summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_ast_lowering/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_ast_lowering/src')
-rw-r--r--compiler/rustc_ast_lowering/src/asm.rs119
-rw-r--r--compiler/rustc_ast_lowering/src/errors.rs26
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs458
-rw-r--r--compiler/rustc_ast_lowering/src/format.rs10
-rw-r--r--compiler/rustc_ast_lowering/src/index.rs17
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs343
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs328
-rw-r--r--compiler/rustc_ast_lowering/src/lifetime_collector.rs2
-rw-r--r--compiler/rustc_ast_lowering/src/pat.rs3
-rw-r--r--compiler/rustc_ast_lowering/src/path.rs22
10 files changed, 777 insertions, 551 deletions
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(&reg) {
- output_used = true;
- }
+ overlapping_with.push(reg);
});
+ let output_used =
+ overlapping_with.iter().any(|reg| used_output_regs.contains_key(&reg));
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(&lt)),
+ 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(&param.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;];