diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-19 09:26:03 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-19 09:26:03 +0000 |
commit | 9918693037dce8aa4bb6f08741b6812923486c18 (patch) | |
tree | 21d2b40bec7e6a7ea664acee056eb3d08e15a1cf /compiler/rustc_ast_lowering | |
parent | Releasing progress-linux version 1.75.0+dfsg1-5~progress7.99u1. (diff) | |
download | rustc-9918693037dce8aa4bb6f08741b6812923486c18.tar.xz rustc-9918693037dce8aa4bb6f08741b6812923486c18.zip |
Merging upstream version 1.76.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_ast_lowering')
-rw-r--r-- | compiler/rustc_ast_lowering/messages.ftl | 13 | ||||
-rw-r--r-- | compiler/rustc_ast_lowering/src/asm.rs | 119 | ||||
-rw-r--r-- | compiler/rustc_ast_lowering/src/errors.rs | 26 | ||||
-rw-r--r-- | compiler/rustc_ast_lowering/src/expr.rs | 458 | ||||
-rw-r--r-- | compiler/rustc_ast_lowering/src/format.rs | 10 | ||||
-rw-r--r-- | compiler/rustc_ast_lowering/src/index.rs | 17 | ||||
-rw-r--r-- | compiler/rustc_ast_lowering/src/item.rs | 343 | ||||
-rw-r--r-- | compiler/rustc_ast_lowering/src/lib.rs | 328 | ||||
-rw-r--r-- | compiler/rustc_ast_lowering/src/lifetime_collector.rs | 2 | ||||
-rw-r--r-- | compiler/rustc_ast_lowering/src/pat.rs | 3 | ||||
-rw-r--r-- | compiler/rustc_ast_lowering/src/path.rs | 22 |
11 files changed, 790 insertions, 551 deletions
diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index 91591a716..6bde4f2d8 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -91,6 +91,10 @@ ast_lowering_invalid_register = ast_lowering_invalid_register_class = invalid register class `{$reg_class}`: {$error} +ast_lowering_match_arm_with_no_body = + `match` arm with no body + .suggestion = add a body after the pattern + ast_lowering_misplaced_assoc_ty_binding = associated type bounds are only allowed in where clauses and function signatures, not in {$position} @@ -104,6 +108,15 @@ ast_lowering_misplaced_impl_trait = ast_lowering_misplaced_relax_trait_bound = `?Trait` bounds are only permitted at the point where a type parameter is declared +ast_lowering_never_pattern_with_body = + a never pattern is always unreachable + .label = this will never be executed + .suggestion = remove this expression + +ast_lowering_never_pattern_with_guard = + a guard on a never pattern will never be run + .suggestion = remove this guard + ast_lowering_not_supported_for_lifetime_binder_async_closure = `for<...>` binders on `async` closures are not currently supported diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index a1e626996..4c81983c2 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -14,8 +14,8 @@ use rustc_ast::*; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::definitions::DefPathData; use rustc_session::parse::feature_err; +use rustc_span::symbol::kw; use rustc_span::{sym, Span}; use rustc_target::asm; use std::collections::hash_map::Entry; @@ -227,7 +227,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.create_def( parent_def_id.def_id, node_id, - DefPathData::AnonConst, + kw::Empty, + DefKind::AnonConst, *op_sp, ); let anon_const = AnonConst { id: node_id, value: P(expr) }; @@ -335,67 +336,81 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymFn { .. } | hir::InlineAsmOperand::SymStatic { .. } => { - unreachable!() + unreachable!("{op:?} is not a register operand"); } }; // Flag to output the error only once per operand let mut skip = false; - reg.overlapping_regs(|r| { - let mut check = |used_regs: &mut FxHashMap<asm::InlineAsmReg, usize>, - input| { - match used_regs.entry(r) { - Entry::Occupied(o) => { - if skip { - return; - } - skip = true; - let idx2 = *o.get(); - let (ref op2, op_sp2) = operands[idx2]; - let Some(asm::InlineAsmRegOrRegClass::Reg(reg2)) = op2.reg() - else { - unreachable!(); - }; + let mut check = |used_regs: &mut FxHashMap<asm::InlineAsmReg, usize>, + input, + r: asm::InlineAsmReg| { + match used_regs.entry(r) { + Entry::Occupied(o) => { + if skip { + return; + } + skip = true; - let in_out = match (op, op2) { - ( - hir::InlineAsmOperand::In { .. }, - hir::InlineAsmOperand::Out { late, .. }, - ) - | ( - hir::InlineAsmOperand::Out { late, .. }, - hir::InlineAsmOperand::In { .. }, - ) => { - assert!(!*late); - let out_op_sp = if input { op_sp2 } else { op_sp }; - Some(out_op_sp) - } - _ => None, - }; + let idx2 = *o.get(); + let (ref op2, op_sp2) = operands[idx2]; - sess.emit_err(RegisterConflict { - op_span1: op_sp, - op_span2: op_sp2, - reg1_name: reg.name(), - reg2_name: reg2.name(), - in_out, - }); - } - Entry::Vacant(v) => { - if r == reg { - v.insert(idx); + let in_out = match (op, op2) { + ( + hir::InlineAsmOperand::In { .. }, + hir::InlineAsmOperand::Out { late, .. }, + ) + | ( + hir::InlineAsmOperand::Out { late, .. }, + hir::InlineAsmOperand::In { .. }, + ) => { + assert!(!*late); + let out_op_sp = if input { op_sp2 } else { op_sp }; + Some(out_op_sp) + } + _ => None, + }; + let reg_str = |idx| -> &str { + // HIR asm doesn't preserve the original alias string of the explicit register, + // so we have to retrieve it from AST + let (op, _): &(InlineAsmOperand, Span) = &asm.operands[idx]; + if let Some(ast::InlineAsmRegOrRegClass::Reg(reg_sym)) = + op.reg() + { + reg_sym.as_str() + } else { + unreachable!("{op:?} is not a register operand"); } + }; + + sess.emit_err(RegisterConflict { + op_span1: op_sp, + op_span2: op_sp2, + reg1_name: reg_str(idx), + reg2_name: reg_str(idx2), + in_out, + }); + } + Entry::Vacant(v) => { + if r == reg { + v.insert(idx); } } - }; + } + }; + let mut overlapping_with = vec![]; + reg.overlapping_regs(|r| { + overlapping_with.push(r); + }); + for r in overlapping_with { if input { - check(&mut used_input_regs, true); + check(&mut used_input_regs, true, r); } if output { - check(&mut used_output_regs, false); + check(&mut used_output_regs, false, r); } - }); + } } } } @@ -410,12 +425,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { continue; } - let mut output_used = false; + let mut overlapping_with = vec![]; clobber.overlapping_regs(|reg| { - if used_output_regs.contains_key(®) { - output_used = true; - } + overlapping_with.push(reg); }); + let output_used = + overlapping_with.iter().any(|reg| used_output_regs.contains_key(®)); if !output_used { operands.push(( diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index 6e1a9eff5..11bb55971 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -340,6 +340,32 @@ pub struct NotSupportedForLifetimeBinderAsyncClosure { pub span: Span, } +#[derive(Diagnostic)] +#[diag(ast_lowering_match_arm_with_no_body)] +pub struct MatchArmWithNoBody { + #[primary_span] + pub span: Span, + #[suggestion(code = " => todo!(),", applicability = "has-placeholders")] + pub suggestion: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_lowering_never_pattern_with_body)] +pub struct NeverPatternWithBody { + #[primary_span] + #[label] + #[suggestion(code = "", applicability = "maybe-incorrect")] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(ast_lowering_never_pattern_with_guard)] +pub struct NeverPatternWithGuard { + #[primary_span] + #[suggestion(code = "", applicability = "maybe-incorrect")] + pub span: Span, +} + #[derive(Diagnostic, Clone, Copy)] #[diag(ast_lowering_arbitrary_expression_in_pattern)] pub struct ArbitraryExpressionInPattern { diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 0fff9a6be..704f124db 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1,22 +1,22 @@ use super::errors::{ AsyncCoroutinesNotSupported, AsyncNonMoveClosureNotSupported, AwaitOnlyInAsyncFnAndBlocks, BaseExpressionDoubleDot, ClosureCannotBeStatic, CoroutineTooManyParameters, - FunctionalRecordUpdateDestructuringAssignment, InclusiveRangeWithNoEnd, - NotSupportedForLifetimeBinderAsyncClosure, UnderscoreExprLhsAssign, + FunctionalRecordUpdateDestructuringAssignment, InclusiveRangeWithNoEnd, MatchArmWithNoBody, + NeverPatternWithBody, NeverPatternWithGuard, NotSupportedForLifetimeBinderAsyncClosure, + UnderscoreExprLhsAssign, }; use super::ResolverAstLoweringExt; use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs}; use crate::{FnDeclKind, ImplTraitPosition}; -use rustc_ast::attr; use rustc_ast::ptr::P as AstP; use rustc_ast::*; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir as hir; -use rustc_hir::def::Res; -use rustc_hir::definitions::DefPathData; +use rustc_hir::def::{DefKind, Res}; +use rustc_middle::span_bug; use rustc_session::errors::report_lit_error; use rustc_span::source_map::{respan, Spanned}; -use rustc_span::symbol::{sym, Ident, Symbol}; +use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::DUMMY_SP; use rustc_span::{DesugaringKind, Span}; use thin_vec::{thin_vec, ThinVec}; @@ -42,8 +42,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } // Merge attributes into the inner expression. if !e.attrs.is_empty() { - let old_attrs = - self.attrs.get(&ex.hir_id.local_id).map(|la| *la).unwrap_or(&[]); + let old_attrs = self.attrs.get(&ex.hir_id.local_id).copied().unwrap_or(&[]); self.attrs.insert( ex.hir_id.local_id, &*self.arena.alloc_from_iter( @@ -73,7 +72,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let kind = match &e.kind { ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)), ExprKind::ConstBlock(c) => { - let c = self.with_new_scopes(|this| hir::ConstBlock { + let c = self.with_new_scopes(c.value.span, |this| hir::ConstBlock { def_id: this.local_def_id(c.id), hir_id: this.lower_node_id(c.id), body: this.lower_const_body(c.value.span, Some(&c.value)), @@ -190,46 +189,43 @@ impl<'hir> LoweringContext<'_, 'hir> { None, e.span, hir::CoroutineSource::Block, - |this| this.with_new_scopes(|this| this.lower_block_expr(block)), + |this| this.with_new_scopes(e.span, |this| this.lower_block_expr(block)), ), ExprKind::Await(expr, await_kw_span) => self.lower_expr_await(*await_kw_span, expr), ExprKind::Closure(box Closure { binder, capture_clause, constness, - asyncness, + coroutine_kind, movability, fn_decl, body, fn_decl_span, fn_arg_span, - }) => { - if let Async::Yes { closure_id, .. } = asyncness { - self.lower_expr_async_closure( - binder, - *capture_clause, - e.id, - hir_id, - *closure_id, - fn_decl, - body, - *fn_decl_span, - *fn_arg_span, - ) - } else { - self.lower_expr_closure( - binder, - *capture_clause, - e.id, - *constness, - *movability, - fn_decl, - body, - *fn_decl_span, - *fn_arg_span, - ) - } - } + }) => match coroutine_kind { + Some(coroutine_kind) => self.lower_expr_coroutine_closure( + binder, + *capture_clause, + e.id, + hir_id, + *coroutine_kind, + fn_decl, + body, + *fn_decl_span, + *fn_arg_span, + ), + None => self.lower_expr_closure( + binder, + *capture_clause, + e.id, + *constness, + *movability, + fn_decl, + body, + *fn_decl_span, + *fn_arg_span, + ), + }, ExprKind::Block(blk, opt_label) => { let opt_label = self.lower_label(*opt_label); hir::ExprKind::Block(self.lower_block(blk, opt_label.is_some()), opt_label) @@ -324,11 +320,20 @@ impl<'hir> LoweringContext<'_, 'hir> { None, e.span, hir::CoroutineSource::Block, - |this| this.with_new_scopes(|this| this.lower_block_expr(block)), + |this| this.with_new_scopes(e.span, |this| this.lower_block_expr(block)), ), + ExprKind::Gen(capture_clause, block, GenBlockKind::AsyncGen) => self + .make_async_gen_expr( + *capture_clause, + e.id, + None, + e.span, + hir::CoroutineSource::Block, + |this| this.with_new_scopes(e.span, |this| this.lower_block_expr(block)), + ), ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()), ExprKind::Err => hir::ExprKind::Err( - self.tcx.sess.delay_span_bug(e.span, "lowered ExprKind::Err"), + self.tcx.sess.span_delayed_bug(e.span, "lowered ExprKind::Err"), ), ExprKind::Try(sub_expr) => self.lower_expr_try(e.span, sub_expr), @@ -351,30 +356,8 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - fn lower_binop(&mut self, b: BinOp) -> hir::BinOp { - Spanned { - node: match b.node { - BinOpKind::Add => hir::BinOpKind::Add, - BinOpKind::Sub => hir::BinOpKind::Sub, - BinOpKind::Mul => hir::BinOpKind::Mul, - BinOpKind::Div => hir::BinOpKind::Div, - BinOpKind::Rem => hir::BinOpKind::Rem, - BinOpKind::And => hir::BinOpKind::And, - BinOpKind::Or => hir::BinOpKind::Or, - BinOpKind::BitXor => hir::BinOpKind::BitXor, - BinOpKind::BitAnd => hir::BinOpKind::BitAnd, - BinOpKind::BitOr => hir::BinOpKind::BitOr, - BinOpKind::Shl => hir::BinOpKind::Shl, - BinOpKind::Shr => hir::BinOpKind::Shr, - BinOpKind::Eq => hir::BinOpKind::Eq, - BinOpKind::Lt => hir::BinOpKind::Lt, - BinOpKind::Le => hir::BinOpKind::Le, - BinOpKind::Ne => hir::BinOpKind::Ne, - BinOpKind::Ge => hir::BinOpKind::Ge, - BinOpKind::Gt => hir::BinOpKind::Gt, - }, - span: self.lower_span(b.span), - } + fn lower_binop(&mut self, b: BinOp) -> BinOp { + Spanned { node: b.node, span: self.lower_span(b.span) } } fn lower_legacy_const_generics( @@ -396,7 +379,13 @@ impl<'hir> LoweringContext<'_, 'hir> { let node_id = self.next_node_id(); // Add a definition for the in-band const def. - self.create_def(parent_def_id.def_id, node_id, DefPathData::AnonConst, f.span); + self.create_def( + parent_def_id.def_id, + node_id, + kw::Empty, + DefKind::AnonConst, + f.span, + ); let anon_const = AnonConst { id: node_id, value: arg }; generic_args.push(AngleBracketedArg::Arg(GenericArg::Const(anon_const))); @@ -525,7 +514,7 @@ impl<'hir> LoweringContext<'_, 'hir> { this.mark_span_with_reason( DesugaringKind::TryBlock, expr.span, - this.allow_try_trait.clone(), + Some(this.allow_try_trait.clone()), ), expr, ) @@ -533,7 +522,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let try_span = this.mark_span_with_reason( DesugaringKind::TryBlock, this.tcx.sess.source_map().end_point(body.span), - this.allow_try_trait.clone(), + Some(this.allow_try_trait.clone()), ); (try_span, this.expr_unit(try_span)) @@ -561,13 +550,13 @@ impl<'hir> LoweringContext<'_, 'hir> { expr: &'hir hir::Expr<'hir>, overall_span: Span, ) -> &'hir hir::Expr<'hir> { - let constructor = self.arena.alloc(self.expr_lang_item_path(method_span, lang_item, None)); + let constructor = self.arena.alloc(self.expr_lang_item_path(method_span, lang_item)); self.expr_call(overall_span, constructor, std::slice::from_ref(expr)) } fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> { let pat = self.lower_pat(&arm.pat); - let guard = arm.guard.as_ref().map(|cond| { + let mut guard = arm.guard.as_ref().map(|cond| { if let ExprKind::Let(pat, scrutinee, span, is_recovered) = &cond.kind { hir::Guard::IfLet(self.arena.alloc(hir::Let { hir_id: self.next_id(), @@ -582,14 +571,46 @@ impl<'hir> LoweringContext<'_, 'hir> { } }); let hir_id = self.next_id(); + let span = self.lower_span(arm.span); self.lower_attrs(hir_id, &arm.attrs); - hir::Arm { - hir_id, - pat, - guard, - body: self.lower_expr(&arm.body), - span: self.lower_span(arm.span), - } + let is_never_pattern = pat.is_never_pattern(); + let body = if let Some(body) = &arm.body + && !is_never_pattern + { + self.lower_expr(body) + } else { + // Either `body.is_none()` or `is_never_pattern` here. + if !is_never_pattern { + if self.tcx.features().never_patterns { + // If the feature is off we already emitted the error after parsing. + let suggestion = span.shrink_to_hi(); + self.tcx.sess.emit_err(MatchArmWithNoBody { span, suggestion }); + } + } else if let Some(body) = &arm.body { + self.tcx.sess.emit_err(NeverPatternWithBody { span: body.span }); + guard = None; + } else if let Some(g) = &arm.guard { + self.tcx.sess.emit_err(NeverPatternWithGuard { span: g.span }); + guard = None; + } + + // We add a fake `loop {}` arm body so that it typecks to `!`. + // FIXME(never_patterns): Desugar into a call to `unreachable_unchecked`. + let block = self.arena.alloc(hir::Block { + stmts: &[], + expr: None, + hir_id: self.next_id(), + rules: hir::BlockCheckMode::DefaultBlock, + span, + targeted_by_break: false, + }); + self.arena.alloc(hir::Expr { + hir_id: self.next_id(), + kind: hir::ExprKind::Loop(block, None, hir::LoopSource::Loop, span), + span, + }) + }; + hir::Arm { hir_id, pat, guard, body, span } } /// Lower an `async` construct to a coroutine that implements `Future`. @@ -613,9 +634,12 @@ impl<'hir> LoweringContext<'_, 'hir> { let output = ret_ty.unwrap_or_else(|| hir::FnRetTy::DefaultReturn(self.lower_span(span))); // Resume argument type: `ResumeTy` - let unstable_span = - self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone()); - let resume_ty = hir::QPath::LangItem(hir::LangItem::ResumeTy, unstable_span, None); + let unstable_span = self.mark_span_with_reason( + DesugaringKind::Async, + self.lower_span(span), + Some(self.allow_gen_future.clone()), + ); + let resume_ty = hir::QPath::LangItem(hir::LangItem::ResumeTy, unstable_span); let input_ty = hir::Ty { hir_id: self.next_id(), kind: hir::TyKind::Path(resume_ty), @@ -721,6 +745,87 @@ impl<'hir> LoweringContext<'_, 'hir> { })) } + /// Lower a `async gen` construct to a generator that implements `AsyncIterator`. + /// + /// This results in: + /// + /// ```text + /// static move? |_task_context| -> () { + /// <body> + /// } + /// ``` + pub(super) fn make_async_gen_expr( + &mut self, + capture_clause: CaptureBy, + closure_node_id: NodeId, + _yield_ty: Option<hir::FnRetTy<'hir>>, + span: Span, + async_coroutine_source: hir::CoroutineSource, + body: impl FnOnce(&mut Self) -> hir::Expr<'hir>, + ) -> hir::ExprKind<'hir> { + let output = hir::FnRetTy::DefaultReturn(self.lower_span(span)); + + // Resume argument type: `ResumeTy` + let unstable_span = self.mark_span_with_reason( + DesugaringKind::Async, + self.lower_span(span), + Some(self.allow_gen_future.clone()), + ); + let resume_ty = hir::QPath::LangItem(hir::LangItem::ResumeTy, unstable_span); + let input_ty = hir::Ty { + hir_id: self.next_id(), + kind: hir::TyKind::Path(resume_ty), + span: unstable_span, + }; + + // The closure/coroutine `FnDecl` takes a single (resume) argument of type `input_ty`. + let fn_decl = self.arena.alloc(hir::FnDecl { + inputs: arena_vec![self; input_ty], + output, + c_variadic: false, + implicit_self: hir::ImplicitSelfKind::None, + lifetime_elision_allowed: false, + }); + + // Lower the argument pattern/ident. The ident is used again in the `.await` lowering. + let (pat, task_context_hid) = self.pat_ident_binding_mode( + span, + Ident::with_dummy_span(sym::_task_context), + hir::BindingAnnotation::MUT, + ); + let param = hir::Param { + hir_id: self.next_id(), + pat, + ty_span: self.lower_span(span), + span: self.lower_span(span), + }; + let params = arena_vec![self; param]; + + let body = self.lower_body(move |this| { + this.coroutine_kind = Some(hir::CoroutineKind::AsyncGen(async_coroutine_source)); + + let old_ctx = this.task_context; + this.task_context = Some(task_context_hid); + let res = body(this); + this.task_context = old_ctx; + (params, res) + }); + + // `static |_task_context| -> <ret_ty> { body }`: + hir::ExprKind::Closure(self.arena.alloc(hir::Closure { + def_id: self.local_def_id(closure_node_id), + binder: hir::ClosureBinder::Default, + capture_clause, + bound_generic_params: &[], + fn_decl, + body, + fn_decl_span: self.lower_span(span), + fn_arg_span: None, + movability: Some(hir::Movability::Static), + constness: hir::Constness::NotConst, + })) + } + /// Forwards a possible `#[track_caller]` annotation from `outer_hir_id` to /// `inner_hir_id` in case the `async_fn_track_caller` feature is enabled. pub(super) fn maybe_forward_track_caller( @@ -736,7 +841,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let unstable_span = self.mark_span_with_reason( DesugaringKind::Async, span, - self.allow_gen_future.clone(), + Some(self.allow_gen_future.clone()), ); self.lower_attrs( inner_hir_id, @@ -770,20 +875,23 @@ impl<'hir> LoweringContext<'_, 'hir> { /// ``` fn lower_expr_await(&mut self, await_kw_span: Span, expr: &Expr) -> hir::ExprKind<'hir> { let full_span = expr.span.to(await_kw_span); - match self.coroutine_kind { - Some(hir::CoroutineKind::Async(_)) => {} + + let is_async_gen = match self.coroutine_kind { + Some(hir::CoroutineKind::Async(_)) => false, + Some(hir::CoroutineKind::AsyncGen(_)) => true, Some(hir::CoroutineKind::Coroutine) | Some(hir::CoroutineKind::Gen(_)) | None => { - self.tcx.sess.emit_err(AwaitOnlyInAsyncFnAndBlocks { + return hir::ExprKind::Err(self.tcx.sess.emit_err(AwaitOnlyInAsyncFnAndBlocks { await_kw_span, item_span: self.current_item, - }); + })); } - } + }; + let span = self.mark_span_with_reason(DesugaringKind::Await, await_kw_span, None); let gen_future_span = self.mark_span_with_reason( DesugaringKind::Await, full_span, - self.allow_gen_future.clone(), + Some(self.allow_gen_future.clone()), ); let expr = self.lower_expr_mut(expr); let expr_hir_id = expr.hir_id; @@ -792,8 +900,11 @@ impl<'hir> LoweringContext<'_, 'hir> { // debuggers and debugger extensions expect it to be called `__awaitee`. They use // this name to identify what is being awaited by a suspended async functions. let awaitee_ident = Ident::with_dummy_span(sym::__awaitee); - let (awaitee_pat, awaitee_pat_hid) = - self.pat_ident_binding_mode(span, awaitee_ident, hir::BindingAnnotation::MUT); + let (awaitee_pat, awaitee_pat_hid) = self.pat_ident_binding_mode( + gen_future_span, + awaitee_ident, + hir::BindingAnnotation::MUT, + ); let task_context_ident = Ident::with_dummy_span(sym::_task_context); @@ -806,29 +917,27 @@ impl<'hir> LoweringContext<'_, 'hir> { let poll_expr = { let awaitee = self.expr_ident(span, awaitee_ident, awaitee_pat_hid); let ref_mut_awaitee = self.expr_mut_addr_of(span, awaitee); - let task_context = if let Some(task_context_hid) = self.task_context { - self.expr_ident_mut(span, task_context_ident, task_context_hid) - } else { - // Use of `await` outside of an async context, we cannot use `task_context` here. - self.expr_err(span, self.tcx.sess.delay_span_bug(span, "no task_context hir id")) + + let Some(task_context_hid) = self.task_context else { + unreachable!("use of `await` outside of an async context."); }; + + let task_context = self.expr_ident_mut(span, task_context_ident, task_context_hid); + let new_unchecked = self.expr_call_lang_item_fn_mut( span, hir::LangItem::PinNewUnchecked, arena_vec![self; ref_mut_awaitee], - Some(expr_hir_id), ); let get_context = self.expr_call_lang_item_fn_mut( gen_future_span, hir::LangItem::GetContext, arena_vec![self; task_context], - Some(expr_hir_id), ); let call = self.expr_call_lang_item_fn( span, hir::LangItem::FuturePoll, arena_vec![self; new_unchecked, get_context], - Some(expr_hir_id), ); self.arena.alloc(self.expr_unsafe(call)) }; @@ -841,12 +950,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (x_pat, x_pat_hid) = self.pat_ident(gen_future_span, x_ident); let x_expr = self.expr_ident(gen_future_span, x_ident, x_pat_hid); let ready_field = self.single_pat_field(gen_future_span, x_pat); - let ready_pat = self.pat_lang_item_variant( - span, - hir::LangItem::PollReady, - ready_field, - Some(expr_hir_id), - ); + let ready_pat = self.pat_lang_item_variant(span, hir::LangItem::PollReady, ready_field); let break_x = self.with_loop_scope(loop_node_id, move |this| { let expr_break = hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr)); @@ -857,12 +961,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // `::std::task::Poll::Pending => {}` let pending_arm = { - let pending_pat = self.pat_lang_item_variant( - span, - hir::LangItem::PollPending, - &[], - Some(expr_hir_id), - ); + let pending_pat = self.pat_lang_item_variant(span, hir::LangItem::PollPending, &[]); let empty_block = self.expr_block_empty(span); self.arm(pending_pat, empty_block) }; @@ -877,25 +976,30 @@ impl<'hir> LoweringContext<'_, 'hir> { self.stmt_expr(span, match_expr) }; - // task_context = yield (); + // Depending on `async` of `async gen`: + // async - task_context = yield (); + // async gen - task_context = yield ASYNC_GEN_PENDING; let yield_stmt = { - let unit = self.expr_unit(span); + let yielded = if is_async_gen { + self.arena.alloc(self.expr_lang_item_path(span, hir::LangItem::AsyncGenPending)) + } else { + self.expr_unit(span) + }; + let yield_expr = self.expr( span, - hir::ExprKind::Yield(unit, hir::YieldSource::Await { expr: Some(expr_hir_id) }), + hir::ExprKind::Yield(yielded, hir::YieldSource::Await { expr: Some(expr_hir_id) }), ); let yield_expr = self.arena.alloc(yield_expr); - if let Some(task_context_hid) = self.task_context { - let lhs = self.expr_ident(span, task_context_ident, task_context_hid); - let assign = - self.expr(span, hir::ExprKind::Assign(lhs, yield_expr, self.lower_span(span))); - self.stmt_expr(span, assign) - } else { - // Use of `await` outside of an async context. Return `yield_expr` so that we can - // proceed with type checking. - self.stmt(span, hir::StmtKind::Semi(yield_expr)) - } + let Some(task_context_hid) = self.task_context else { + unreachable!("use of `await` outside of an async context."); + }; + + let lhs = self.expr_ident(span, task_context_ident, task_context_hid); + let assign = + self.expr(span, hir::ExprKind::Assign(lhs, yield_expr, self.lower_span(span))); + self.stmt_expr(span, assign) }; let loop_block = self.block_all(span, arena_vec![self; inner_match_stmt, yield_stmt], None); @@ -920,7 +1024,6 @@ impl<'hir> LoweringContext<'_, 'hir> { span, hir::LangItem::IntoFutureIntoFuture, arena_vec![self; expr], - Some(expr_hir_id), ); // match <into_future_expr> { @@ -947,9 +1050,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ) -> hir::ExprKind<'hir> { let (binder_clause, generic_params) = self.lower_closure_binder(binder); - let (body_id, coroutine_option) = self.with_new_scopes(move |this| { - let prev = this.current_item; - this.current_item = Some(fn_decl_span); + let (body_id, coroutine_option) = self.with_new_scopes(fn_decl_span, move |this| { let mut coroutine_kind = None; let body_id = this.lower_fn_body(decl, |this| { let e = this.lower_expr_mut(body); @@ -957,8 +1058,7 @@ impl<'hir> LoweringContext<'_, 'hir> { e }); let coroutine_option = - this.coroutine_movability_for_fn(&decl, fn_decl_span, coroutine_kind, movability); - this.current_item = prev; + this.coroutine_movability_for_fn(decl, fn_decl_span, coroutine_kind, movability); (body_id, coroutine_option) }); @@ -996,7 +1096,11 @@ impl<'hir> LoweringContext<'_, 'hir> { } Some(movability) } - Some(hir::CoroutineKind::Gen(_)) | Some(hir::CoroutineKind::Async(_)) => { + Some( + hir::CoroutineKind::Gen(_) + | hir::CoroutineKind::Async(_) + | hir::CoroutineKind::AsyncGen(_), + ) => { panic!("non-`async`/`gen` closure body turned `async`/`gen` during lowering"); } None => { @@ -1023,18 +1127,22 @@ impl<'hir> LoweringContext<'_, 'hir> { (binder, params) } - fn lower_expr_async_closure( + fn lower_expr_coroutine_closure( &mut self, binder: &ClosureBinder, capture_clause: CaptureBy, closure_id: NodeId, closure_hir_id: hir::HirId, - inner_closure_id: NodeId, + coroutine_kind: CoroutineKind, decl: &FnDecl, body: &Expr, fn_decl_span: Span, fn_arg_span: Span, ) -> hir::ExprKind<'hir> { + let CoroutineKind::Async { closure_id: inner_closure_id, .. } = coroutine_kind else { + span_bug!(fn_decl_span, "`async gen` and `gen` closures are not supported, yet"); + }; + if let &ClosureBinder::For { span, .. } = binder { self.tcx.sess.emit_err(NotSupportedForLifetimeBinderAsyncClosure { span }); } @@ -1044,7 +1152,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let outer_decl = FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) }; - let body = self.with_new_scopes(|this| { + let body = self.with_new_scopes(fn_decl_span, |this| { // FIXME(cramertj): allow `async` non-`move` closures with arguments. if capture_clause == CaptureBy::Ref && !decl.inputs.is_empty() { this.tcx.sess.emit_err(AsyncNonMoveClosureNotSupported { fn_decl_span }); @@ -1055,7 +1163,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let body_id = this.lower_fn_body(&outer_decl, |this| { let async_ret_ty = if let FnRetTy::Ty(ty) = &decl.output { let itctx = ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock); - Some(hir::FnRetTy::Return(this.lower_ty(&ty, &itctx))) + Some(hir::FnRetTy::Return(this.lower_ty(ty, &itctx))) } else { None }; @@ -1066,7 +1174,7 @@ impl<'hir> LoweringContext<'_, 'hir> { async_ret_ty, body.span, hir::CoroutineSource::Closure, - |this| this.with_new_scopes(|this| this.lower_expr_mut(body)), + |this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)), ); let hir_id = this.lower_node_id(inner_closure_id); this.maybe_forward_track_caller(body.span, closure_hir_id, hir_id); @@ -1113,6 +1221,8 @@ impl<'hir> LoweringContext<'_, 'hir> { | ExprKind::Struct(..) | ExprKind::Tup(..) | ExprKind::Underscore => false, + // Check for unit struct constructor. + ExprKind::Path(..) => lower_ctx.extract_unit_struct_path(lhs).is_none(), // Check for tuple struct constructor. ExprKind::Call(callee, ..) => lower_ctx.extract_tuple_struct_path(callee).is_none(), ExprKind::Paren(e) => { @@ -1149,12 +1259,10 @@ impl<'hir> LoweringContext<'_, 'hir> { ); // `a = lhs1; b = lhs2;`. - let stmts = self - .arena - .alloc_from_iter(std::iter::once(destructure_let).chain(assignments.into_iter())); + let stmts = self.arena.alloc_from_iter(std::iter::once(destructure_let).chain(assignments)); // Wrap everything in a block. - hir::ExprKind::Block(&self.block_all(whole_span, stmts, None), None) + hir::ExprKind::Block(self.block_all(whole_span, stmts, None), None) } /// If the given expression is a path to a tuple struct, returns that path. @@ -1377,8 +1485,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_expr_range_closed(&mut self, span: Span, e1: &Expr, e2: &Expr) -> hir::ExprKind<'hir> { let e1 = self.lower_expr_mut(e1); let e2 = self.lower_expr_mut(e2); - let fn_path = - hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, self.lower_span(span), None); + let fn_path = hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, self.lower_span(span)); let fn_expr = self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path))); hir::ExprKind::Call(fn_expr, arena_vec![self; e1, e2]) } @@ -1411,7 +1518,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let fields = self.arena.alloc_from_iter( e1.iter().map(|e| (sym::start, e)).chain(e2.iter().map(|e| (sym::end, e))).map( |(s, e)| { - let expr = self.lower_expr(&e); + let expr = self.lower_expr(e); let ident = Ident::new(s, self.lower_span(e.span)); self.expr_field(ident, expr, e.span) }, @@ -1419,7 +1526,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ); hir::ExprKind::Struct( - self.arena.alloc(hir::QPath::LangItem(lang_item, self.lower_span(span), None)), + self.arena.alloc(hir::QPath::LangItem(lang_item, self.lower_span(span))), fields, None, ) @@ -1504,10 +1611,13 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn lower_expr_yield(&mut self, span: Span, opt_expr: Option<&Expr>) -> hir::ExprKind<'hir> { - match self.coroutine_kind { - Some(hir::CoroutineKind::Gen(_)) => {} + let is_async_gen = match self.coroutine_kind { + Some(hir::CoroutineKind::Gen(_)) => false, + Some(hir::CoroutineKind::AsyncGen(_)) => true, Some(hir::CoroutineKind::Async(_)) => { - self.tcx.sess.emit_err(AsyncCoroutinesNotSupported { span }); + return hir::ExprKind::Err( + self.tcx.sess.emit_err(AsyncCoroutinesNotSupported { span }), + ); } Some(hir::CoroutineKind::Coroutine) | None => { if !self.tcx.features().coroutines { @@ -1519,14 +1629,37 @@ impl<'hir> LoweringContext<'_, 'hir> { ) .emit(); } - self.coroutine_kind = Some(hir::CoroutineKind::Coroutine) + self.coroutine_kind = Some(hir::CoroutineKind::Coroutine); + false } - } + }; - let expr = + let yielded = opt_expr.as_ref().map(|x| self.lower_expr(x)).unwrap_or_else(|| self.expr_unit(span)); - hir::ExprKind::Yield(expr, hir::YieldSource::Yield) + if is_async_gen { + // `yield $expr` is transformed into `task_context = yield async_gen_ready($expr)`. + // This ensures that we store our resumed `ResumeContext` correctly, and also that + // the apparent value of the `yield` expression is `()`. + let wrapped_yielded = self.expr_call_lang_item_fn( + span, + hir::LangItem::AsyncGenReady, + std::slice::from_ref(yielded), + ); + let yield_expr = self.arena.alloc( + self.expr(span, hir::ExprKind::Yield(wrapped_yielded, hir::YieldSource::Yield)), + ); + + let Some(task_context_hid) = self.task_context else { + unreachable!("use of `await` outside of an async context."); + }; + let task_context_ident = Ident::with_dummy_span(sym::_task_context); + let lhs = self.expr_ident(span, task_context_ident, task_context_hid); + + hir::ExprKind::Assign(lhs, yield_expr, self.lower_span(span)) + } else { + hir::ExprKind::Yield(yielded, hir::YieldSource::Yield) + } } /// Desugar `ExprForLoop` from: `[opt_ident]: for <pat> in <head> <body>` into: @@ -1588,7 +1721,6 @@ impl<'hir> LoweringContext<'_, 'hir> { head_span, hir::LangItem::IteratorNext, arena_vec![self; ref_mut_iter], - None, ); let arms = arena_vec![self; none_arm, some_arm]; @@ -1617,7 +1749,6 @@ impl<'hir> LoweringContext<'_, 'hir> { head_span, hir::LangItem::IntoIterIntoIter, arena_vec![self; head], - None, ) }; @@ -1655,13 +1786,13 @@ impl<'hir> LoweringContext<'_, 'hir> { let unstable_span = self.mark_span_with_reason( DesugaringKind::QuestionMark, span, - self.allow_try_trait.clone(), + Some(self.allow_try_trait.clone()), ); let try_span = self.tcx.sess.source_map().end_point(span); let try_span = self.mark_span_with_reason( DesugaringKind::QuestionMark, try_span, - self.allow_try_trait.clone(), + Some(self.allow_try_trait.clone()), ); // `Try::branch(<expr>)` @@ -1673,7 +1804,6 @@ impl<'hir> LoweringContext<'_, 'hir> { unstable_span, hir::LangItem::TryTraitBranch, arena_vec![self; sub_expr], - None, ) }; @@ -1755,7 +1885,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let unstable_span = self.mark_span_with_reason( DesugaringKind::YeetExpr, span, - self.allow_try_trait.clone(), + Some(self.allow_try_trait.clone()), ); let from_yeet_expr = self.wrap_in_try_constructor( @@ -1878,9 +2008,8 @@ impl<'hir> LoweringContext<'_, 'hir> { span: Span, lang_item: hir::LangItem, args: &'hir [hir::Expr<'hir>], - hir_id: Option<hir::HirId>, ) -> hir::Expr<'hir> { - let path = self.arena.alloc(self.expr_lang_item_path(span, lang_item, hir_id)); + let path = self.arena.alloc(self.expr_lang_item_path(span, lang_item)); self.expr_call_mut(span, path, args) } @@ -1889,21 +2018,12 @@ impl<'hir> LoweringContext<'_, 'hir> { span: Span, lang_item: hir::LangItem, args: &'hir [hir::Expr<'hir>], - hir_id: Option<hir::HirId>, ) -> &'hir hir::Expr<'hir> { - self.arena.alloc(self.expr_call_lang_item_fn_mut(span, lang_item, args, hir_id)) + self.arena.alloc(self.expr_call_lang_item_fn_mut(span, lang_item, args)) } - fn expr_lang_item_path( - &mut self, - span: Span, - lang_item: hir::LangItem, - hir_id: Option<hir::HirId>, - ) -> hir::Expr<'hir> { - self.expr( - span, - hir::ExprKind::Path(hir::QPath::LangItem(lang_item, self.lower_span(span), hir_id)), - ) + fn expr_lang_item_path(&mut self, span: Span, lang_item: hir::LangItem) -> hir::Expr<'hir> { + self.expr(span, hir::ExprKind::Path(hir::QPath::LangItem(lang_item, self.lower_span(span)))) } /// `<LangItem>::name` @@ -1916,7 +2036,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let path = hir::ExprKind::Path(hir::QPath::TypeRelative( self.arena.alloc(self.ty( span, - hir::TyKind::Path(hir::QPath::LangItem(lang_item, self.lower_span(span), None)), + hir::TyKind::Path(hir::QPath::LangItem(lang_item, self.lower_span(span))), )), self.arena.alloc(hir::PathSegment::new( Ident::new(name, span), diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs index c7d0719e7..6a82005c4 100644 --- a/compiler/rustc_ast_lowering/src/format.rs +++ b/compiler/rustc_ast_lowering/src/format.rs @@ -1,6 +1,6 @@ use super::LoweringContext; use rustc_ast as ast; -use rustc_ast::visit::{self, Visitor}; +use rustc_ast::visit::Visitor; use rustc_ast::*; use rustc_data_structures::fx::FxIndexMap; use rustc_hir as hir; @@ -267,7 +267,7 @@ fn make_count<'hir>( ctx.expr( sp, hir::ExprKind::Err( - ctx.tcx.sess.delay_span_bug(sp, "lowered bad format_args count"), + ctx.tcx.sess.span_delayed_bug(sp, "lowered bad format_args count"), ), ) } @@ -306,7 +306,7 @@ fn make_format_spec<'hir>( } Err(_) => ctx.expr( sp, - hir::ExprKind::Err(ctx.tcx.sess.delay_span_bug(sp, "lowered bad format_args count")), + hir::ExprKind::Err(ctx.tcx.sess.span_delayed_bug(sp, "lowered bad format_args count")), ), }; let &FormatOptions { @@ -338,8 +338,8 @@ fn make_format_spec<'hir>( | ((debug_hex == Some(FormatDebugHex::Lower)) as u32) << 4 | ((debug_hex == Some(FormatDebugHex::Upper)) as u32) << 5; let flags = ctx.expr_u32(sp, flags); - let precision = make_count(ctx, sp, &precision, argmap); - let width = make_count(ctx, sp, &width, argmap); + let precision = make_count(ctx, sp, precision, argmap); + let width = make_count(ctx, sp, width, argmap); let format_placeholder_new = ctx.arena.alloc(ctx.expr_lang_item_type_relative( sp, hir::LangItem::FormatPlaceholder, diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index eff362f3f..993ddf00e 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -1,8 +1,7 @@ -use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sorted_map::SortedMap; use rustc_hir as hir; -use rustc_hir::def_id::LocalDefId; -use rustc_hir::intravisit::{self, Visitor}; +use rustc_hir::def_id::{LocalDefId, LocalDefIdMap}; +use rustc_hir::intravisit::Visitor; use rustc_hir::*; use rustc_index::{Idx, IndexVec}; use rustc_middle::span_bug; @@ -10,14 +9,14 @@ use rustc_middle::ty::TyCtxt; use rustc_span::{Span, DUMMY_SP}; /// A visitor that walks over the HIR and collects `Node`s into a HIR map. -pub(super) struct NodeCollector<'a, 'hir> { +struct NodeCollector<'a, 'hir> { tcx: TyCtxt<'hir>, bodies: &'a SortedMap<ItemLocalId, &'hir Body<'hir>>, /// Outputs nodes: IndexVec<ItemLocalId, Option<ParentedNode<'hir>>>, - parenting: FxHashMap<LocalDefId, ItemLocalId>, + parenting: LocalDefIdMap<ItemLocalId>, /// The parent of this node parent_node: hir::ItemLocalId, @@ -30,7 +29,7 @@ pub(super) fn index_hir<'hir>( tcx: TyCtxt<'hir>, item: hir::OwnerNode<'hir>, bodies: &SortedMap<ItemLocalId, &'hir Body<'hir>>, -) -> (IndexVec<ItemLocalId, Option<ParentedNode<'hir>>>, FxHashMap<LocalDefId, ItemLocalId>) { +) -> (IndexVec<ItemLocalId, Option<ParentedNode<'hir>>>, LocalDefIdMap<ItemLocalId>) { let mut nodes = IndexVec::new(); // This node's parent should never be accessed: the owner's parent is computed by the // hir_owner_parent query. Make it invalid (= ItemLocalId::MAX) to force an ICE whenever it is @@ -42,12 +41,12 @@ pub(super) fn index_hir<'hir>( parent_node: ItemLocalId::new(0), nodes, bodies, - parenting: FxHashMap::default(), + parenting: Default::default(), }; match item { OwnerNode::Crate(citem) => { - collector.visit_mod(&citem, citem.spans.inner_span, hir::CRATE_HIR_ID) + collector.visit_mod(citem, citem.spans.inner_span, hir::CRATE_HIR_ID) } OwnerNode::Item(item) => collector.visit_item(item), OwnerNode::TraitItem(item) => collector.visit_trait_item(item), @@ -89,7 +88,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { } } - self.nodes.insert(hir_id.local_id, ParentedNode { parent: self.parent_node, node: node }); + self.nodes.insert(hir_id.local_id, ParentedNode { parent: self.parent_node, node }); } fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_node_id: HirId, f: F) { diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 9a70e6d7c..5bddbe5f4 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -3,11 +3,9 @@ use super::ResolverAstLoweringExt; use super::{AstOwner, ImplTraitContext, ImplTraitPosition}; use super::{FnDeclKind, LoweringContext, ParamMode}; -use hir::definitions::DefPathData; use rustc_ast::ptr::P; use rustc_ast::visit::AssocCtxt; use rustc_ast::*; -use rustc_data_structures::sorted_map::SortedMap; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -55,42 +53,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { owner: NodeId, f: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::OwnerNode<'hir>, ) { - let allow_gen_future = Some(if self.tcx.features().async_fn_track_caller { - [sym::gen_future, sym::closure_track_caller][..].into() - } else { - [sym::gen_future][..].into() - }); - let mut lctx = LoweringContext { - // Pseudo-globals. - tcx: self.tcx, - resolver: self.resolver, - arena: self.tcx.hir_arena, - - // HirId handling. - bodies: Vec::new(), - attrs: SortedMap::default(), - children: Vec::default(), - current_hir_id_owner: hir::CRATE_OWNER_ID, - item_local_id_counter: hir::ItemLocalId::new(0), - node_id_to_local_id: Default::default(), - trait_map: Default::default(), - - // Lowering state. - catch_scope: None, - loop_scope: None, - is_in_loop_condition: false, - is_in_trait_impl: false, - is_in_dyn_type: false, - coroutine_kind: None, - task_context: None, - current_item: None, - impl_trait_defs: Vec::new(), - impl_trait_bounds: Vec::new(), - allow_try_trait: Some([sym::try_trait_v2, sym::yeet_desugar_details][..].into()), - allow_gen_future, - generics_def_id_map: Default::default(), - host_param_id: None, - }; + let mut lctx = LoweringContext::new(self.tcx, self.resolver); lctx.with_hir_id_owner(owner, |lctx| f(lctx)); for (def_id, info) in lctx.children { @@ -136,39 +99,9 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { fn lower_assoc_item(&mut self, item: &AssocItem, ctxt: AssocCtxt) { let def_id = self.resolver.node_id_to_def_id[&item.id]; - let parent_id = self.tcx.local_parent(def_id); let parent_hir = self.lower_node(parent_id).unwrap(); - self.with_lctx(item.id, |lctx| { - // Evaluate with the lifetimes in `params` in-scope. - // This is used to track which lifetimes have already been defined, - // and which need to be replicated when lowering an async fn. - - match parent_hir.node().expect_item().kind { - hir::ItemKind::Impl(impl_) => { - lctx.is_in_trait_impl = impl_.of_trait.is_some(); - } - hir::ItemKind::Trait(_, _, generics, _, _) if lctx.tcx.features().effects => { - lctx.host_param_id = generics - .params - .iter() - .find(|param| { - parent_hir - .attrs - .get(param.hir_id.local_id) - .iter() - .any(|attr| attr.has_name(sym::rustc_host)) - }) - .map(|param| param.def_id); - } - _ => {} - } - - match ctxt { - AssocCtxt::Trait => hir::OwnerNode::TraitItem(lctx.lower_trait_item(item)), - AssocCtxt::Impl => hir::OwnerNode::ImplItem(lctx.lower_impl_item(item)), - } - }) + self.with_lctx(item.id, |lctx| lctx.lower_assoc_item(item, ctxt, parent_hir)) } fn lower_foreign_item(&mut self, item: &ForeignItem) { @@ -268,27 +201,30 @@ impl<'hir> LoweringContext<'_, 'hir> { body, .. }) => { - self.with_new_scopes(|this| { - this.current_item = Some(ident.span); - + self.with_new_scopes(ident.span, |this| { // Note: we don't need to change the return type from `T` to // `impl Future<Output = T>` here because lower_body // only cares about the input argument patterns in the function // declaration (decl), not the return types. - let asyncness = header.asyncness; - let body_id = this.lower_maybe_async_body( + let coroutine_kind = header.coroutine_kind; + let body_id = this.lower_maybe_coroutine_body( span, hir_id, - &decl, - asyncness, + decl, + coroutine_kind, body.as_deref(), ); let itctx = ImplTraitContext::Universal; let (generics, decl) = this.lower_generics(generics, header.constness, id, &itctx, |this| { - let ret_id = asyncness.opt_return_id(); - this.lower_fn_decl(&decl, id, *fn_sig_span, FnDeclKind::Fn, ret_id) + this.lower_fn_decl( + decl, + id, + *fn_sig_span, + FnDeclKind::Fn, + coroutine_kind, + ) }); let sig = hir::FnSig { decl, @@ -329,7 +265,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| match ty { None => { - let guar = this.tcx.sess.delay_span_bug( + let guar = this.tcx.sess.span_delayed_bug( span, "expected to lower type alias type, but it was missing", ); @@ -485,7 +421,14 @@ impl<'hir> LoweringContext<'_, 'hir> { } ItemKind::MacroDef(MacroDef { body, macro_rules }) => { let body = P(self.lower_delim_args(body)); - let macro_kind = self.resolver.decl_macro_kind(self.local_def_id(id)); + let def_id = self.local_def_id(id); + let def_kind = self.tcx.def_kind(def_id); + let DefKind::Macro(macro_kind) = def_kind else { + unreachable!( + "expected DefKind::Macro for macro item, found {}", + def_kind.descr(def_id.to_def_id()) + ); + }; let macro_def = self.arena.alloc(ast::MacroDef { body, macro_rules: *macro_rules }); hir::ItemKind::Macro(macro_def, macro_kind) } @@ -614,6 +557,41 @@ impl<'hir> LoweringContext<'_, 'hir> { } } + fn lower_assoc_item( + &mut self, + item: &AssocItem, + ctxt: AssocCtxt, + parent_hir: &'hir hir::OwnerInfo<'hir>, + ) -> hir::OwnerNode<'hir> { + // Evaluate with the lifetimes in `params` in-scope. + // This is used to track which lifetimes have already been defined, + // and which need to be replicated when lowering an async fn. + + match parent_hir.node().expect_item().kind { + hir::ItemKind::Impl(impl_) => { + self.is_in_trait_impl = impl_.of_trait.is_some(); + } + hir::ItemKind::Trait(_, _, generics, _, _) if self.tcx.features().effects => { + self.host_param_id = generics + .params + .iter() + .find(|param| { + matches!( + param.kind, + hir::GenericParamKind::Const { is_host_effect: true, .. } + ) + }) + .map(|param| param.def_id); + } + _ => {} + } + + match ctxt { + AssocCtxt::Trait => hir::OwnerNode::TraitItem(self.lower_trait_item(item)), + AssocCtxt::Impl => hir::OwnerNode::ImplItem(self.lower_impl_item(item)), + } + } + fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> { let hir_id = self.lower_node_id(i.id); let owner_id = hir_id.expect_owner(); @@ -683,11 +661,12 @@ impl<'hir> LoweringContext<'_, 'hir> { vdata: &VariantData, ) -> hir::VariantData<'hir> { match vdata { - VariantData::Struct(fields, recovered) => hir::VariantData::Struct( - self.arena + VariantData::Struct { fields, recovered } => hir::VariantData::Struct { + fields: self + .arena .alloc_from_iter(fields.iter().enumerate().map(|f| self.lower_field_def(f))), - *recovered, - ), + recovered: *recovered, + }, VariantData::Tuple(fields, id) => { let ctor_id = self.lower_node_id(*id); self.alias_attrs(ctor_id, parent_id); @@ -744,7 +723,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, kind, has_default) = match &i.kind { AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => { let (generics, kind) = self.lower_generics( - &generics, + generics, Const::No, i.id, &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), @@ -761,27 +740,30 @@ impl<'hir> LoweringContext<'_, 'hir> { (generics, kind, expr.is_some()) } AssocItemKind::Fn(box Fn { sig, generics, body: None, .. }) => { - let asyncness = sig.header.asyncness; let names = self.lower_fn_params_to_names(&sig.decl); let (generics, sig) = self.lower_method_sig( generics, sig, i.id, FnDeclKind::Trait, - asyncness.opt_return_id(), + sig.header.coroutine_kind, ); (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false) } AssocItemKind::Fn(box Fn { sig, generics, body: Some(body), .. }) => { - let asyncness = sig.header.asyncness; - let body_id = - self.lower_maybe_async_body(i.span, hir_id, &sig.decl, asyncness, Some(&body)); + let body_id = self.lower_maybe_coroutine_body( + i.span, + hir_id, + &sig.decl, + sig.header.coroutine_kind, + Some(body), + ); let (generics, sig) = self.lower_method_sig( generics, sig, i.id, FnDeclKind::Trait, - asyncness.opt_return_id(), + sig.header.coroutine_kind, ); (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), true) } @@ -857,7 +839,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, kind) = match &i.kind { AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => self.lower_generics( - &generics, + generics, Const::No, i.id, &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), @@ -870,13 +852,11 @@ impl<'hir> LoweringContext<'_, 'hir> { }, ), AssocItemKind::Fn(box Fn { sig, generics, body, .. }) => { - self.current_item = Some(i.span); - let asyncness = sig.header.asyncness; - let body_id = self.lower_maybe_async_body( + let body_id = self.lower_maybe_coroutine_body( i.span, hir_id, &sig.decl, - asyncness, + sig.header.coroutine_kind, body.as_deref(), ); let (generics, sig) = self.lower_method_sig( @@ -884,7 +864,7 @@ impl<'hir> LoweringContext<'_, 'hir> { sig, i.id, if self.is_in_trait_impl { FnDeclKind::Impl } else { FnDeclKind::Inherent }, - asyncness.opt_return_id(), + sig.header.coroutine_kind, ); (generics, hir::ImplItemKind::Fn(sig, body_id)) @@ -899,7 +879,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| match ty { None => { - let guar = this.tcx.sess.delay_span_bug( + let guar = this.tcx.sess.span_delayed_bug( i.span, "expected to lower associated type, but it was missing", ); @@ -1032,7 +1012,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_block_expr_opt(&mut self, span: Span, block: Option<&Block>) -> hir::Expr<'hir> { match block { Some(block) => self.lower_block_expr(block), - None => self.expr_err(span, self.tcx.sess.delay_span_bug(span, "no block")), + None => self.expr_err(span, self.tcx.sess.span_delayed_bug(span, "no block")), } } @@ -1042,24 +1022,26 @@ impl<'hir> LoweringContext<'_, 'hir> { &[], match expr { Some(expr) => this.lower_expr_mut(expr), - None => this.expr_err(span, this.tcx.sess.delay_span_bug(span, "no block")), + None => this.expr_err(span, this.tcx.sess.span_delayed_bug(span, "no block")), }, ) }) } - fn lower_maybe_async_body( + /// Takes what may be the body of an `async fn` or a `gen fn` and wraps it in an `async {}` or + /// `gen {}` block as appropriate. + fn lower_maybe_coroutine_body( &mut self, span: Span, fn_id: hir::HirId, decl: &FnDecl, - asyncness: Async, + coroutine_kind: Option<CoroutineKind>, body: Option<&Block>, ) -> hir::BodyId { - let (closure_id, body) = match (asyncness, body) { - (Async::Yes { closure_id, .. }, Some(body)) => (closure_id, body), - _ => return self.lower_fn_body_block(span, decl, body), + let (Some(coroutine_kind), Some(body)) = (coroutine_kind, body) else { + return self.lower_fn_body_block(span, decl, body); }; + let closure_id = coroutine_kind.closure_id(); self.lower_body(|this| { let mut parameters: Vec<hir::Param<'_>> = Vec::new(); @@ -1200,44 +1182,63 @@ impl<'hir> LoweringContext<'_, 'hir> { parameters.push(new_parameter); } - let async_expr = this.make_async_expr( - CaptureBy::Value { move_kw: rustc_span::DUMMY_SP }, - closure_id, - None, - body.span, - hir::CoroutineSource::Fn, - |this| { - // Create a block from the user's function body: - let user_body = this.lower_block_expr(body); + let mkbody = |this: &mut LoweringContext<'_, 'hir>| { + // Create a block from the user's function body: + let user_body = this.lower_block_expr(body); - // Transform into `drop-temps { <user-body> }`, an expression: - let desugared_span = - this.mark_span_with_reason(DesugaringKind::Async, user_body.span, None); - let user_body = - this.expr_drop_temps(desugared_span, this.arena.alloc(user_body)); + // Transform into `drop-temps { <user-body> }`, an expression: + let desugared_span = + this.mark_span_with_reason(DesugaringKind::Async, user_body.span, None); + let user_body = this.expr_drop_temps(desugared_span, this.arena.alloc(user_body)); - // As noted above, create the final block like - // - // ``` - // { - // let $param_pattern = $raw_param; - // ... - // drop-temps { <user-body> } - // } - // ``` - let body = this.block_all( - desugared_span, - this.arena.alloc_from_iter(statements), - Some(user_body), - ); + // As noted above, create the final block like + // + // ``` + // { + // let $param_pattern = $raw_param; + // ... + // drop-temps { <user-body> } + // } + // ``` + let body = this.block_all( + desugared_span, + this.arena.alloc_from_iter(statements), + Some(user_body), + ); - this.expr_block(body) - }, - ); + this.expr_block(body) + }; + // FIXME(gen_blocks): Consider unifying the `make_*_expr` functions. + let coroutine_expr = match coroutine_kind { + CoroutineKind::Async { .. } => this.make_async_expr( + CaptureBy::Value { move_kw: rustc_span::DUMMY_SP }, + closure_id, + None, + body.span, + hir::CoroutineSource::Fn, + mkbody, + ), + CoroutineKind::Gen { .. } => this.make_gen_expr( + CaptureBy::Value { move_kw: rustc_span::DUMMY_SP }, + closure_id, + None, + body.span, + hir::CoroutineSource::Fn, + mkbody, + ), + CoroutineKind::AsyncGen { .. } => this.make_async_gen_expr( + CaptureBy::Value { move_kw: rustc_span::DUMMY_SP }, + closure_id, + None, + body.span, + hir::CoroutineSource::Fn, + mkbody, + ), + }; let hir_id = this.lower_node_id(closure_id); this.maybe_forward_track_caller(body.span, fn_id, hir_id); - let expr = hir::Expr { hir_id, kind: async_expr, span: this.lower_span(body.span) }; + let expr = hir::Expr { hir_id, kind: coroutine_expr, span: this.lower_span(body.span) }; (this.arena.alloc_from_iter(parameters), expr) }) @@ -1249,21 +1250,26 @@ impl<'hir> LoweringContext<'_, 'hir> { sig: &FnSig, id: NodeId, kind: FnDeclKind, - is_async: Option<(NodeId, Span)>, + coroutine_kind: Option<CoroutineKind>, ) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) { let header = self.lower_fn_header(sig.header); let itctx = ImplTraitContext::Universal; let (generics, decl) = self.lower_generics(generics, sig.header.constness, id, &itctx, |this| { - this.lower_fn_decl(&sig.decl, id, sig.span, kind, is_async) + this.lower_fn_decl(&sig.decl, id, sig.span, kind, coroutine_kind) }); (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) }) } fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader { + let asyncness = if let Some(CoroutineKind::Async { span, .. }) = h.coroutine_kind { + hir::IsAsync::Async(span) + } else { + hir::IsAsync::NotAsync + }; hir::FnHeader { unsafety: self.lower_unsafety(h.unsafety), - asyncness: self.lower_asyncness(h.asyncness), + asyncness: asyncness, constness: self.lower_constness(h.constness), abi: self.lower_extern(h.ext), } @@ -1305,13 +1311,6 @@ impl<'hir> LoweringContext<'_, 'hir> { }); } - fn lower_asyncness(&mut self, a: Async) -> hir::IsAsync { - match a { - Async::Yes { span, .. } => hir::IsAsync::Async(span), - Async::No => hir::IsAsync::NotAsync, - } - } - pub(super) fn lower_constness(&mut self, c: Const) -> hir::Constness { match c { Const::Yes(_) => hir::Constness::Const, @@ -1389,26 +1388,18 @@ impl<'hir> LoweringContext<'_, 'hir> { let host_param_parts = if let Const::Yes(span) = constness && self.tcx.features().effects { - if let Some(param) = - generics.params.iter().find(|x| x.attrs.iter().any(|x| x.has_name(sym::rustc_host))) - { - // user has manually specified a `rustc_host` param, in this case, we set - // the param id so that lowering logic can use that. But we don't create - // another host param, so this gives `None`. - self.host_param_id = Some(self.local_def_id(param.id)); - None - } else { - let param_node_id = self.next_node_id(); - let hir_id = self.next_id(); - let def_id = self.create_def( - self.local_def_id(parent_node_id), - param_node_id, - DefPathData::TypeNs(sym::host), - span, - ); - self.host_param_id = Some(def_id); - Some((span, hir_id, def_id)) - } + let span = self.lower_span(span); + let param_node_id = self.next_node_id(); + let hir_id = self.next_id(); + let def_id = self.create_def( + self.local_def_id(parent_node_id), + param_node_id, + sym::host, + DefKind::ConstParam, + span, + ); + self.host_param_id = Some(def_id); + Some((span, hir_id, def_id)) } else { None }; @@ -1462,8 +1453,8 @@ impl<'hir> LoweringContext<'_, 'hir> { if let Some((span, hir_id, def_id)) = host_param_parts { let const_node_id = self.next_node_id(); - let anon_const: LocalDefId = - self.create_def(def_id, const_node_id, DefPathData::AnonConst, span); + let anon_const = + self.create_def(def_id, const_node_id, kw::Empty, DefKind::AnonConst, span); let const_id = self.next_id(); let const_expr_id = self.next_id(); @@ -1472,19 +1463,6 @@ impl<'hir> LoweringContext<'_, 'hir> { self.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id))); self.children.push((anon_const, hir::MaybeOwner::NonOwner(const_id))); - let attr_id = self.tcx.sess.parse_sess.attr_id_generator.mk_attr_id(); - - let attrs = self.arena.alloc_from_iter([Attribute { - kind: AttrKind::Normal(P(NormalAttr::from_ident(Ident::new( - sym::rustc_host, - span, - )))), - span, - id: attr_id, - style: AttrStyle::Outer, - }]); - self.attrs.insert(hir_id.local_id, attrs); - let const_body = self.lower_body(|this| { ( &[], @@ -1526,6 +1504,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir_id: const_id, body: const_body, }), + is_host_effect: true, }, colon_span: None, pure_wrt_drop: false, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index a88493acf..47b929816 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -30,12 +30,11 @@ //! get confused if the spans from leaf AST nodes occur in multiple places //! in the HIR, especially for multiple identifiers. -#![cfg_attr(not(bootstrap), allow(internal_features))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] -#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![allow(internal_features)] +#![feature(rustdoc_internals)] +#![doc(rust_logo)] #![feature(box_patterns)] #![feature(let_chains)] -#![feature(never_type)] #![recursion_limit = "256"] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] @@ -45,32 +44,24 @@ extern crate tracing; use crate::errors::{AssocTyParentheses, AssocTyParenthesesSub, MisplacedImplTrait}; +use rustc_ast::node_id::NodeMap; use rustc_ast::ptr::P; -use rustc_ast::visit; use rustc_ast::{self as ast, *}; use rustc_ast_pretty::pprust; use rustc_data_structures::captures::Captures; use rustc_data_structures::fingerprint::Fingerprint; -use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; -use rustc_errors::{ - DiagnosticArgFromDisplay, DiagnosticMessage, Handler, StashKey, SubdiagnosticMessage, -}; -use rustc_fluent_macro::fluent_messages; +use rustc_errors::{DiagnosticArgFromDisplay, StashKey}; use rustc_hir as hir; use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; -use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; -use rustc_hir::definitions::DefPathData; -use rustc_hir::{ConstArg, GenericArg, ItemLocalId, ParamName, TraitCandidate}; +use rustc_hir::def_id::{LocalDefId, LocalDefIdMap, CRATE_DEF_ID, LOCAL_CRATE}; +use rustc_hir::{ConstArg, GenericArg, ItemLocalMap, ParamName, TraitCandidate}; use rustc_index::{Idx, IndexSlice, IndexVec}; -use rustc_middle::{ - span_bug, - ty::{ResolverAstLowering, TyCtxt}, -}; +use rustc_middle::span_bug; +use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; use rustc_session::parse::{add_feature_diagnostics, feature_err}; -use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{DesugaringKind, Span, DUMMY_SP}; use smallvec::SmallVec; @@ -94,7 +85,7 @@ mod lifetime_collector; mod pat; mod path; -fluent_messages! { "../messages.ftl" } +rustc_fluent_macro::fluent_messages! { "../messages.ftl" } struct LoweringContext<'a, 'hir> { tcx: TyCtxt<'hir>, @@ -128,26 +119,70 @@ struct LoweringContext<'a, 'hir> { current_hir_id_owner: hir::OwnerId, item_local_id_counter: hir::ItemLocalId, - trait_map: FxHashMap<ItemLocalId, Box<[TraitCandidate]>>, + trait_map: ItemLocalMap<Box<[TraitCandidate]>>, impl_trait_defs: Vec<hir::GenericParam<'hir>>, impl_trait_bounds: Vec<hir::WherePredicate<'hir>>, /// NodeIds that are lowered inside the current HIR owner. - node_id_to_local_id: FxHashMap<NodeId, hir::ItemLocalId>, + node_id_to_local_id: NodeMap<hir::ItemLocalId>, - allow_try_trait: Option<Lrc<[Symbol]>>, - allow_gen_future: Option<Lrc<[Symbol]>>, + allow_try_trait: Lrc<[Symbol]>, + allow_gen_future: Lrc<[Symbol]>, + allow_async_iterator: Lrc<[Symbol]>, /// Mapping from generics `def_id`s to TAIT generics `def_id`s. /// For each captured lifetime (e.g., 'a), we create a new lifetime parameter that is a generic /// defined on the TAIT, so we have type Foo<'a1> = ... and we establish a mapping in this /// field from the original parameter 'a to the new parameter 'a1. - generics_def_id_map: Vec<FxHashMap<LocalDefId, LocalDefId>>, + generics_def_id_map: Vec<LocalDefIdMap<LocalDefId>>, host_param_id: Option<LocalDefId>, } +impl<'a, 'hir> LoweringContext<'a, 'hir> { + fn new(tcx: TyCtxt<'hir>, resolver: &'a mut ResolverAstLowering) -> Self { + Self { + // Pseudo-globals. + tcx, + resolver: resolver, + arena: tcx.hir_arena, + + // HirId handling. + bodies: Vec::new(), + attrs: SortedMap::default(), + children: Vec::default(), + current_hir_id_owner: hir::CRATE_OWNER_ID, + item_local_id_counter: hir::ItemLocalId::new(0), + node_id_to_local_id: Default::default(), + trait_map: Default::default(), + + // Lowering state. + catch_scope: None, + loop_scope: None, + is_in_loop_condition: false, + is_in_trait_impl: false, + is_in_dyn_type: false, + coroutine_kind: None, + task_context: None, + current_item: None, + impl_trait_defs: Vec::new(), + impl_trait_bounds: Vec::new(), + allow_try_trait: [sym::try_trait_v2, sym::yeet_desugar_details].into(), + allow_gen_future: if tcx.features().async_fn_track_caller { + [sym::gen_future, sym::closure_track_caller].into() + } else { + [sym::gen_future].into() + }, + // FIXME(gen_blocks): how does `closure_track_caller`/`async_fn_track_caller` + // interact with `gen`/`async gen` blocks + allow_async_iterator: [sym::gen_future, sym::async_iterator].into(), + generics_def_id_map: Default::default(), + host_param_id: None, + } + } +} + trait ResolverAstLoweringExt { fn legacy_const_generic_args(&self, expr: &Expr) -> Option<Vec<usize>>; fn get_partial_res(&self, id: NodeId) -> Option<PartialRes>; @@ -156,7 +191,6 @@ trait ResolverAstLoweringExt { fn get_lifetime_res(&self, id: NodeId) -> Option<LifetimeRes>; fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)>; fn remap_extra_lifetime_params(&mut self, from: NodeId, to: NodeId); - fn decl_macro_kind(&self, def_id: LocalDefId) -> MacroKind; } impl ResolverAstLoweringExt for ResolverAstLowering { @@ -220,10 +254,6 @@ impl ResolverAstLoweringExt for ResolverAstLowering { let lifetimes = self.extra_lifetime_params_map.remove(&from).unwrap_or_default(); self.extra_lifetime_params_map.insert(to, lifetimes); } - - fn decl_macro_kind(&self, def_id: LocalDefId) -> MacroKind { - self.builtin_macro_kinds.get(&def_id).copied().unwrap_or(MacroKind::Bang) - } } /// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree, @@ -350,7 +380,7 @@ enum AstOwner<'a> { } fn index_crate<'a>( - node_id_to_def_id: &FxHashMap<NodeId, LocalDefId>, + node_id_to_def_id: &NodeMap<LocalDefId>, krate: &'a Crate, ) -> IndexVec<LocalDefId, AstOwner<'a>> { let mut indexer = Indexer { node_id_to_def_id, index: IndexVec::new() }; @@ -360,7 +390,7 @@ fn index_crate<'a>( return indexer.index; struct Indexer<'s, 'a> { - node_id_to_def_id: &'s FxHashMap<NodeId, LocalDefId>, + node_id_to_def_id: &'s NodeMap<LocalDefId>, index: IndexVec<LocalDefId, AstOwner<'a>>, } @@ -421,6 +451,7 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> { tcx.ensure_with_value().output_filenames(()); tcx.ensure_with_value().early_lint_checks(()); tcx.ensure_with_value().debugger_visualizers(LOCAL_CRATE); + tcx.ensure_with_value().get_lang_items(()); let (mut resolver, krate) = tcx.resolver_for_lowering(()).steal(); let ast_index = index_crate(&resolver.node_id_to_def_id, &krate); @@ -443,11 +474,6 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> { drop(ast_index); sess.time("drop_ast", || drop(krate)); - // Discard hygiene data, which isn't required after lowering to HIR. - if !sess.opts.unstable_opts.keep_hygiene_data { - rustc_span::hygiene::clear_syntax_context_map(); - } - // Don't hash unless necessary, because it's expensive. let opt_hir_hash = if tcx.needs_crate_hash() { Some(compute_hir_hash(tcx, &owners)) } else { None }; @@ -474,19 +500,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, parent: LocalDefId, node_id: ast::NodeId, - data: DefPathData, + name: Symbol, + def_kind: DefKind, span: Span, ) -> LocalDefId { debug_assert_ne!(node_id, ast::DUMMY_NODE_ID); assert!( self.opt_local_def_id(node_id).is_none(), - "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}", + "adding a def'n for node-id {:?} and def kind {:?} but a previous def'n exists: {:?}", node_id, - data, + def_kind, self.tcx.hir().def_key(self.local_def_id(node_id)), ); - let def_id = self.tcx.at(span).create_def(parent, data).def_id(); + let def_id = self.tcx.at(span).create_def(parent, name, def_kind).def_id(); debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id); self.resolver.node_id_to_def_id.insert(node_id, def_id); @@ -504,7 +531,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// Given the id of some node in the AST, finds the `LocalDefId` associated with it by the name /// resolver (if any). fn orig_opt_local_def_id(&self, node: NodeId) -> Option<LocalDefId> { - self.resolver.node_id_to_def_id.get(&node).map(|local_def_id| *local_def_id) + self.resolver.node_id_to_def_id.get(&node).copied() } /// Given the id of some node in the AST, finds the `LocalDefId` associated with it by the name @@ -547,7 +574,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.generics_def_id_map .iter() .rev() - .find_map(|map| map.get(&local_def_id).map(|local_def_id| *local_def_id)) + .find_map(|map| map.get(&local_def_id).copied()) .unwrap_or(local_def_id) } @@ -615,7 +642,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// `'a` declared on the TAIT, instead of the function. fn with_remapping<R>( &mut self, - remap: FxHashMap<LocalDefId, LocalDefId>, + remap: LocalDefIdMap<LocalDefId>, f: impl FnOnce(&mut Self) -> R, ) -> R { self.generics_def_id_map.push(remap); @@ -737,8 +764,26 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.resolver.get_import_res(id).present_items() } - fn diagnostic(&self) -> &Handler { - self.tcx.sess.diagnostic() + fn make_lang_item_path( + &mut self, + lang_item: hir::LangItem, + span: Span, + args: Option<&'hir hir::GenericArgs<'hir>>, + ) -> &'hir hir::Path<'hir> { + let def_id = self.tcx.require_lang_item(lang_item, Some(span)); + let def_kind = self.tcx.def_kind(def_id); + let res = Res::Def(def_kind, def_id); + self.arena.alloc(hir::Path { + span, + res, + segments: self.arena.alloc_from_iter([hir::PathSegment { + ident: Ident::new(lang_item.name(), span), + hir_id: self.next_id(), + res, + args, + infer_args: false, + }]), + }) } /// Reuses the span but adds information like the kind of the desugaring and features that are @@ -787,7 +832,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let _def_id = self.create_def( self.current_hir_id_owner.def_id, param, - DefPathData::LifetimeNs(kw::UnderscoreLifetime), + kw::UnderscoreLifetime, + DefKind::LifetimeParam, ident.span, ); debug!(?_def_id); @@ -851,7 +897,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { result } - fn with_new_scopes<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T { + fn with_new_scopes<T>(&mut self, scope_span: Span, f: impl FnOnce(&mut Self) -> T) -> T { + let current_item = self.current_item; + self.current_item = Some(scope_span); + let was_in_loop_condition = self.is_in_loop_condition; self.is_in_loop_condition = false; @@ -863,6 +912,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.is_in_loop_condition = was_in_loop_condition; + self.current_item = current_item; + ret } @@ -1162,7 +1213,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { itctx: &ImplTraitContext, ) -> hir::GenericArg<'hir> { match arg { - ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<)), + ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(lt)), ast::GenericArg::Type(ty) => { match &ty.kind { TyKind::Infer if self.tcx.features().generic_arg_infer => { @@ -1199,7 +1250,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let def_id = self.create_def( parent_def_id.def_id, node_id, - DefPathData::AnonConst, + kw::Empty, + DefKind::AnonConst, span, ); @@ -1211,7 +1263,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { tokens: None, }; - let ct = self.with_new_scopes(|this| hir::AnonConst { + let ct = self.with_new_scopes(span, |this| hir::AnonConst { def_id, hir_id: this.lower_node_id(node_id), body: this.lower_const_body(path_expr.span, Some(&path_expr)), @@ -1226,10 +1278,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } _ => {} } - GenericArg::Type(self.lower_ty(&ty, itctx)) + GenericArg::Type(self.lower_ty(ty, itctx)) } ast::GenericArg::Const(ct) => GenericArg::Const(ConstArg { - value: self.lower_anon_const(&ct), + value: self.lower_anon_const(ct), span: self.lower_span(ct.value.span), is_desugared_from_effects: false, }), @@ -1272,7 +1324,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let lifetime_bound = this.elided_dyn_bound(t.span); (bounds, lifetime_bound) }); - let kind = hir::TyKind::TraitObject(bounds, &lifetime_bound, TraitObjectSyntax::None); + let kind = hir::TyKind::TraitObject(bounds, lifetime_bound, TraitObjectSyntax::None); return hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.next_id() }; } @@ -1293,7 +1345,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let kind = match &t.kind { TyKind::Infer => hir::TyKind::Infer, TyKind::Err => { - hir::TyKind::Err(self.tcx.sess.delay_span_bug(t.span, "TyKind::Err lowered")) + hir::TyKind::Err(self.tcx.sess.span_delayed_bug(t.span, "TyKind::Err lowered")) } // FIXME(unnamed_fields): IMPLEMENTATION IN PROGRESS #[allow(rustc::untranslatable_diagnostic)] @@ -1374,7 +1426,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { GenericBound::Trait( ty, modifier @ (TraitBoundModifier::None - | TraitBoundModifier::MaybeConst + | TraitBoundModifier::MaybeConst(_) | TraitBoundModifier::Negative), ) => { Some(this.lower_poly_trait_ref(ty, itctx, modifier.to_constness())) @@ -1436,7 +1488,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.create_def( self.current_hir_id_owner.def_id, *def_node_id, - DefPathData::TypeNs(ident.name), + ident.name, + DefKind::TyParam, span, ); let (param, bounds, path) = self.lower_universal_param_and_bounds( @@ -1476,7 +1529,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } TyKind::MacCall(_) => panic!("`TyKind::MacCall` should have been expanded by now"), TyKind::CVarArgs => { - let guar = self.tcx.sess.delay_span_bug( + let guar = self.tcx.sess.span_delayed_bug( t.span, "`TyKind::CVarArgs` should have been handled elsewhere", ); @@ -1542,8 +1595,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { Vec::new() } hir::OpaqueTyOrigin::FnReturn(..) => { - if let FnDeclKind::Impl | FnDeclKind::Trait = - fn_kind.expect("expected RPITs to be lowered with a FnKind") + if matches!( + fn_kind.expect("expected RPITs to be lowered with a FnKind"), + FnDeclKind::Impl | FnDeclKind::Trait + ) || self.tcx.features().lifetime_capture_rules_2024 + || span.at_least_rust_2024() { // return-position impl trait in trait was decided to capture all // in-scope lifetimes, which we collect for all opaques during resolution. @@ -1556,7 +1612,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // in fn return position, like the `fn test<'a>() -> impl Debug + 'a` // example, we only need to duplicate lifetimes that appear in the // bounds, since those are the only ones that are captured by the opaque. - lifetime_collector::lifetimes_in_bounds(&self.resolver, bounds) + lifetime_collector::lifetimes_in_bounds(self.resolver, bounds) } } hir::OpaqueTyOrigin::AsyncFn(..) => { @@ -1589,14 +1645,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let opaque_ty_def_id = self.create_def( self.current_hir_id_owner.def_id, opaque_ty_node_id, - DefPathData::ImplTrait, + kw::Empty, + DefKind::OpaqueTy, opaque_ty_span, ); debug!(?opaque_ty_def_id); // Map from captured (old) lifetime to synthetic (new) lifetime. // Used to resolve lifetimes in the bounds of the opaque. - let mut captured_to_synthesized_mapping = FxHashMap::default(); + let mut captured_to_synthesized_mapping = LocalDefIdMap::default(); // List of (early-bound) synthetic lifetimes that are owned by the opaque. // This is used to create the `hir::Generics` owned by the opaque. let mut synthesized_lifetime_definitions = vec![]; @@ -1618,7 +1675,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } else { self.tcx .sess - .delay_span_bug(lifetime.ident.span, "no def-id for fresh lifetime"); + .span_delayed_bug(lifetime.ident.span, "no def-id for fresh lifetime"); continue; } } @@ -1643,8 +1700,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let duplicated_lifetime_def_id = self.create_def( opaque_ty_def_id, duplicated_lifetime_node_id, - DefPathData::LifetimeNs(lifetime.ident.name), - lifetime.ident.span, + lifetime.ident.name, + DefKind::LifetimeParam, + self.lower_span(lifetime.ident.span), ); captured_to_synthesized_mapping.insert(old_def_id, duplicated_lifetime_def_id); // FIXME: Instead of doing this, we could move this whole loop @@ -1653,7 +1711,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { synthesized_lifetime_definitions.push(( duplicated_lifetime_node_id, duplicated_lifetime_def_id, - lifetime.ident, + self.lower_ident(lifetime.ident), )); // Now make an arg that we can use for the generic params of the opaque tykind. @@ -1747,13 +1805,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { })) } - // Lowers a function declaration. - // - // `decl`: the unlowered (AST) function declaration. - // `fn_node_id`: `impl Trait` arguments are lowered into generic parameters on the given `NodeId`. - // `make_ret_async`: if `Some`, converts `-> T` into `-> impl Future<Output = T>` in the - // return type. This is used for `async fn` declarations. The `NodeId` is the ID of the - // return type `impl Trait` item, and the `Span` points to the `async` keyword. + /// Lowers a function declaration. + /// + /// `decl`: the unlowered (AST) function declaration. + /// + /// `fn_node_id`: `impl Trait` arguments are lowered into generic parameters on the given + /// `NodeId`. + /// + /// `transform_return_type`: if `Some`, applies some conversion to the return type, such as is + /// needed for `async fn` and `gen fn`. See [`CoroutineKind`] for more details. #[instrument(level = "debug", skip(self))] fn lower_fn_decl( &mut self, @@ -1761,7 +1821,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn_node_id: NodeId, fn_span: Span, kind: FnDeclKind, - make_ret_async: Option<(NodeId, Span)>, + coro: Option<CoroutineKind>, ) -> &'hir hir::FnDecl<'hir> { let c_variadic = decl.c_variadic(); @@ -1790,11 +1850,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.lower_ty_direct(¶m.ty, &itctx) })); - let output = if let Some((ret_id, _span)) = make_ret_async { - let fn_def_id = self.local_def_id(fn_node_id); - self.lower_async_fn_ret_ty(&decl.output, fn_def_id, ret_id, kind, fn_span) - } else { - match &decl.output { + let output = match coro { + Some(coro) => { + let fn_def_id = self.local_def_id(fn_node_id); + self.lower_coroutine_fn_ret_ty(&decl.output, fn_def_id, coro, kind, fn_span) + } + None => match &decl.output { FnRetTy::Ty(ty) => { let context = if kind.return_impl_trait_allowed() { let fn_def_id = self.local_def_id(fn_node_id); @@ -1818,7 +1879,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::FnRetTy::Return(self.lower_ty(ty, &context)) } FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(*span)), - } + }, }; self.arena.alloc(hir::FnDecl { @@ -1857,16 +1918,26 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // `fn_node_id`: `NodeId` of the parent function (used to create child impl trait definition) // `opaque_ty_node_id`: `NodeId` of the opaque `impl Trait` type that should be created #[instrument(level = "debug", skip(self))] - fn lower_async_fn_ret_ty( + fn lower_coroutine_fn_ret_ty( &mut self, output: &FnRetTy, fn_def_id: LocalDefId, - opaque_ty_node_id: NodeId, + coro: CoroutineKind, fn_kind: FnDeclKind, fn_span: Span, ) -> hir::FnRetTy<'hir> { let span = self.lower_span(fn_span); - let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::Async, span, None); + + let (opaque_ty_node_id, allowed_features) = match coro { + CoroutineKind::Async { return_impl_trait_id, .. } => (return_impl_trait_id, None), + CoroutineKind::Gen { return_impl_trait_id, .. } => (return_impl_trait_id, None), + CoroutineKind::AsyncGen { return_impl_trait_id, .. } => { + (return_impl_trait_id, Some(self.allow_async_iterator.clone())) + } + }; + + let opaque_ty_span = + self.mark_span_with_reason(DesugaringKind::Async, span, allowed_features); let captured_lifetimes: Vec<_> = self .resolver @@ -1883,15 +1954,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span, opaque_ty_span, |this| { - let future_bound = this.lower_async_fn_output_type_to_future_bound( + let bound = this.lower_coroutine_fn_output_type_to_bound( output, - span, + coro, + opaque_ty_span, ImplTraitContext::ReturnPositionOpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), fn_kind, }, ); - arena_vec![this; future_bound] + arena_vec![this; bound] }, ); @@ -1900,10 +1972,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } /// Transforms `-> T` into `Future<Output = T>`. - fn lower_async_fn_output_type_to_future_bound( + fn lower_coroutine_fn_output_type_to_bound( &mut self, output: &FnRetTy, - span: Span, + coro: CoroutineKind, + opaque_ty_span: Span, nested_impl_trait_context: ImplTraitContext, ) -> hir::GenericBound<'hir> { // Compute the `T` in `Future<Output = T>` from the return type. @@ -1917,20 +1990,34 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { FnRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])), }; - // "<Output = T>" - let future_args = self.arena.alloc(hir::GenericArgs { + // "<$assoc_ty_name = T>" + let (assoc_ty_name, trait_lang_item) = match coro { + CoroutineKind::Async { .. } => (sym::Output, hir::LangItem::Future), + CoroutineKind::Gen { .. } => (sym::Item, hir::LangItem::Iterator), + CoroutineKind::AsyncGen { .. } => (sym::Item, hir::LangItem::AsyncIterator), + }; + + let bound_args = self.arena.alloc(hir::GenericArgs { args: &[], - bindings: arena_vec![self; self.output_ty_binding(span, output_ty)], + bindings: arena_vec![self; self.assoc_ty_binding(assoc_ty_name, opaque_ty_span, output_ty)], parenthesized: hir::GenericArgsParentheses::No, span_ext: DUMMY_SP, }); - hir::GenericBound::LangItemTrait( - // ::std::future::Future<future_params> - hir::LangItem::Future, - self.lower_span(span), - self.next_id(), - future_args, + hir::GenericBound::Trait( + hir::PolyTraitRef { + bound_generic_params: &[], + trait_ref: hir::TraitRef { + path: self.make_lang_item_path( + trait_lang_item, + opaque_ty_span, + Some(bound_args), + ), + hir_ref_id: self.next_id(), + }, + span: opaque_ty_span, + }, + hir::TraitBoundModifier::None, ) } @@ -2072,14 +2159,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { (hir::ParamName::Plain(self.lower_ident(param.ident)), kind) } GenericParamKind::Const { ty, kw_span: _, default } => { - let ty = self.lower_ty( - &ty, - &ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault), - ); + let ty = self + .lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault)); let default = default.as_ref().map(|def| self.lower_anon_const(def)); ( hir::ParamName::Plain(self.lower_ident(param.ident)), - hir::GenericParamKind::Const { ty, default }, + hir::GenericParamKind::Const { ty, default, is_host_effect: false }, ) } } @@ -2200,7 +2285,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { match c.value.kind { ExprKind::Underscore => { if self.tcx.features().generic_arg_infer { - hir::ArrayLen::Infer(self.lower_node_id(c.id), c.value.span) + hir::ArrayLen::Infer(self.lower_node_id(c.id), self.lower_span(c.value.span)) } else { feature_err( &self.tcx.sess.parse_sess, @@ -2217,7 +2302,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn lower_anon_const(&mut self, c: &AnonConst) -> hir::AnonConst { - self.with_new_scopes(|this| hir::AnonConst { + self.with_new_scopes(c.value.span, |this| hir::AnonConst { def_id: this.local_def_id(c.id), hir_id: this.lower_node_id(c.id), body: this.lower_const_body(c.value.span, Some(&c.value)), @@ -2234,7 +2319,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_trait_bound_modifier(&mut self, f: TraitBoundModifier) -> hir::TraitBoundModifier { match f { TraitBoundModifier::None => hir::TraitBoundModifier::None, - TraitBoundModifier::MaybeConst => hir::TraitBoundModifier::MaybeConst, + TraitBoundModifier::MaybeConst(_) => hir::TraitBoundModifier::MaybeConst, TraitBoundModifier::Negative => { if self.tcx.features().negative_bounds { @@ -2311,21 +2396,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn pat_cf_continue(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> { let field = self.single_pat_field(span, pat); - self.pat_lang_item_variant(span, hir::LangItem::ControlFlowContinue, field, None) + self.pat_lang_item_variant(span, hir::LangItem::ControlFlowContinue, field) } fn pat_cf_break(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> { let field = self.single_pat_field(span, pat); - self.pat_lang_item_variant(span, hir::LangItem::ControlFlowBreak, field, None) + self.pat_lang_item_variant(span, hir::LangItem::ControlFlowBreak, field) } fn pat_some(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> { let field = self.single_pat_field(span, pat); - self.pat_lang_item_variant(span, hir::LangItem::OptionSome, field, None) + self.pat_lang_item_variant(span, hir::LangItem::OptionSome, field) } fn pat_none(&mut self, span: Span) -> &'hir hir::Pat<'hir> { - self.pat_lang_item_variant(span, hir::LangItem::OptionNone, &[], None) + self.pat_lang_item_variant(span, hir::LangItem::OptionNone, &[]) } fn single_pat_field( @@ -2348,9 +2433,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: Span, lang_item: hir::LangItem, fields: &'hir [hir::PatField<'hir>], - hir_id: Option<hir::HirId>, ) -> &'hir hir::Pat<'hir> { - let qpath = hir::QPath::LangItem(lang_item, self.lower_span(span), hir_id); + let qpath = hir::QPath::LangItem(lang_item, self.lower_span(span)); self.pat(span, hir::PatKind::Struct(qpath, fields, false)) } @@ -2482,9 +2566,10 @@ impl<'hir> GenericArgsCtor<'hir> { let hir_id = lcx.next_id(); let Some(host_param_id) = lcx.host_param_id else { - lcx.tcx - .sess - .delay_span_bug(span, "no host param id for call in const yet no errors reported"); + lcx.tcx.sess.span_delayed_bug( + span, + "no host param id for call in const yet no errors reported", + ); return; }; @@ -2507,17 +2592,14 @@ impl<'hir> GenericArgsCtor<'hir> { }) }); - let attr_id = lcx.tcx.sess.parse_sess.attr_id_generator.mk_attr_id(); - let attr = lcx.arena.alloc(Attribute { - kind: AttrKind::Normal(P(NormalAttr::from_ident(Ident::new(sym::rustc_host, span)))), + let def_id = lcx.create_def( + lcx.current_hir_id_owner.def_id, + id, + kw::Empty, + DefKind::AnonConst, span, - id: attr_id, - style: AttrStyle::Outer, - }); - lcx.attrs.insert(hir_id.local_id, std::slice::from_ref(attr)); + ); - let def_id = - lcx.create_def(lcx.current_hir_id_owner.def_id, id, DefPathData::AnonConst, span); lcx.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id))); self.args.push(hir::GenericArg::Const(hir::ConstArg { value: hir::AnonConst { def_id, hir_id, body }, diff --git a/compiler/rustc_ast_lowering/src/lifetime_collector.rs b/compiler/rustc_ast_lowering/src/lifetime_collector.rs index d66bba517..4b1c057cd 100644 --- a/compiler/rustc_ast_lowering/src/lifetime_collector.rs +++ b/compiler/rustc_ast_lowering/src/lifetime_collector.rs @@ -108,7 +108,7 @@ impl<'ast> Visitor<'ast> for LifetimeCollectVisitor<'ast> { } } -pub fn lifetimes_in_bounds( +pub(crate) fn lifetimes_in_bounds( resolver: &ResolverAstLowering, bounds: &GenericBounds, ) -> Vec<Lifetime> { diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index a30f264bc..017314ee4 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -18,12 +18,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.arena.alloc(self.lower_pat_mut(pattern)) } - pub(crate) fn lower_pat_mut(&mut self, mut pattern: &Pat) -> hir::Pat<'hir> { + fn lower_pat_mut(&mut self, mut pattern: &Pat) -> hir::Pat<'hir> { ensure_sufficient_stack(|| { // loop here to avoid recursion let node = loop { match &pattern.kind { PatKind::Wild => break hir::PatKind::Wild, + PatKind::Never => break hir::PatKind::Never, PatKind::Ident(binding_mode, ident, sub) => { let lower_sub = |this: &mut Self| sub.as_ref().map(|s| this.lower_pat(s)); break self.lower_pat_ident(pattern, *binding_mode, *ident, lower_sub); diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 899f92a99..5ceeb72f2 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -9,6 +9,7 @@ use rustc_ast::{self as ast, *}; use rustc_hir as hir; use rustc_hir::def::{DefKind, PartialRes, Res}; use rustc_hir::GenericArg; +use rustc_middle::span_bug; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{BytePos, Span, DUMMY_SP}; @@ -139,7 +140,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // We should've returned in the for loop above. - self.diagnostic().span_bug( + self.tcx.sess.dcx().span_bug( p.span, format!( "lower_qpath: no final extension segment in {}..{}", @@ -285,7 +286,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let (start, end) = match self.resolver.get_lifetime_res(segment_id) { Some(LifetimeRes::ElidedAnchor { start, end }) => (start, end), None => return, - Some(_) => panic!(), + Some(res) => { + span_bug!(path_span, "expected an elided lifetime to insert. found {res:?}") + } }; let expected_lifetimes = end.as_usize() - start.as_usize(); debug!(expected_lifetimes); @@ -372,10 +375,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // ``` FnRetTy::Ty(ty) if matches!(itctx, ImplTraitContext::ReturnPositionOpaqueTy { .. }) => { if self.tcx.features().impl_trait_in_fn_trait_return { - self.lower_ty(&ty, itctx) + self.lower_ty(ty, itctx) } else { self.lower_ty( - &ty, + ty, &ImplTraitContext::FeatureGated( ImplTraitPosition::FnTraitReturn, sym::impl_trait_in_fn_trait_return, @@ -384,12 +387,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } FnRetTy::Ty(ty) => { - self.lower_ty(&ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn)) + self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn)) } FnRetTy::Default(_) => self.arena.alloc(self.ty_tup(*span, &[])), }; let args = smallvec![GenericArg::Type(self.arena.alloc(self.ty_tup(*inputs_span, inputs)))]; - let binding = self.output_ty_binding(output_ty.span, output_ty); + let binding = self.assoc_ty_binding(sym::Output, output_ty.span, output_ty); ( GenericArgsCtor { args, @@ -401,13 +404,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) } - /// An associated type binding `Output = $ty`. - pub(crate) fn output_ty_binding( + /// An associated type binding `$assoc_ty_name = $ty`. + pub(crate) fn assoc_ty_binding( &mut self, + assoc_ty_name: rustc_span::Symbol, span: Span, ty: &'hir hir::Ty<'hir>, ) -> hir::TypeBinding<'hir> { - let ident = Ident::with_dummy_span(hir::FN_OUTPUT_NAME); + let ident = Ident::with_dummy_span(assoc_ty_name); let kind = hir::TypeBindingKind::Equality { term: ty.into() }; let args = arena_vec![self;]; let bindings = arena_vec![self;]; |