diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:41 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:41 +0000 |
commit | 4f9fe856a25ab29345b90e7725509e9ee38a37be (patch) | |
tree | e4ffd8a9374cae7b21f7cbfb352927e0e074aff6 /compiler/rustc_ast_lowering | |
parent | Adding upstream version 1.68.2+dfsg1. (diff) | |
download | rustc-4f9fe856a25ab29345b90e7725509e9ee38a37be.tar.xz rustc-4f9fe856a25ab29345b90e7725509e9ee38a37be.zip |
Adding upstream version 1.69.0+dfsg1.upstream/1.69.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/Cargo.toml | 4 | ||||
-rw-r--r-- | compiler/rustc_ast_lowering/locales/en-US.ftl | 141 | ||||
-rw-r--r-- | compiler/rustc_ast_lowering/src/errors.rs | 9 | ||||
-rw-r--r-- | compiler/rustc_ast_lowering/src/expr.rs | 125 | ||||
-rw-r--r-- | compiler/rustc_ast_lowering/src/format.rs | 411 | ||||
-rw-r--r-- | compiler/rustc_ast_lowering/src/index.rs | 13 | ||||
-rw-r--r-- | compiler/rustc_ast_lowering/src/item.rs | 90 | ||||
-rw-r--r-- | compiler/rustc_ast_lowering/src/lib.rs | 238 | ||||
-rw-r--r-- | compiler/rustc_ast_lowering/src/pat.rs | 4 |
9 files changed, 856 insertions, 179 deletions
diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml index 6a59b9e61..eb2e82d79 100644 --- a/compiler/rustc_ast_lowering/Cargo.toml +++ b/compiler/rustc_ast_lowering/Cargo.toml @@ -7,7 +7,6 @@ edition = "2021" doctest = false [dependencies] -rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_data_structures = { path = "../rustc_data_structures" } @@ -16,10 +15,9 @@ rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_middle = { path = "../rustc_middle" } rustc_macros = { path = "../rustc_macros" } -rustc_query_system = { path = "../rustc_query_system" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -thin-vec = "0.2.9" +thin-vec = "0.2.12" tracing = "0.1" diff --git a/compiler/rustc_ast_lowering/locales/en-US.ftl b/compiler/rustc_ast_lowering/locales/en-US.ftl new file mode 100644 index 000000000..3ccd84398 --- /dev/null +++ b/compiler/rustc_ast_lowering/locales/en-US.ftl @@ -0,0 +1,141 @@ +ast_lowering_generic_type_with_parentheses = + parenthesized type parameters may only be used with a `Fn` trait + .label = only `Fn` traits may use parentheses + +ast_lowering_use_angle_brackets = use angle brackets instead + +ast_lowering_invalid_abi = + invalid ABI: found `{$abi}` + .label = invalid ABI + .note = invoke `{$command}` for a full list of supported calling conventions. + +ast_lowering_invalid_abi_suggestion = did you mean + +ast_lowering_assoc_ty_parentheses = + parenthesized generic arguments cannot be used in associated type constraints + +ast_lowering_remove_parentheses = remove these parentheses + +ast_lowering_misplaced_impl_trait = + `impl Trait` only allowed in function and inherent method return types, not in {$position} + +ast_lowering_misplaced_assoc_ty_binding = + associated type bounds are only allowed in where clauses and function signatures, not in {$position} + +ast_lowering_underscore_expr_lhs_assign = + in expressions, `_` can only be used on the left-hand side of an assignment + .label = `_` not allowed here + +ast_lowering_base_expression_double_dot = + base expression required after `..` + .label = add a base expression here + +ast_lowering_await_only_in_async_fn_and_blocks = + `await` is only allowed inside `async` functions and blocks + .label = only allowed inside `async` functions and blocks + +ast_lowering_this_not_async = this is not `async` + +ast_lowering_generator_too_many_parameters = + too many parameters for a generator (expected 0 or 1 parameters) + +ast_lowering_closure_cannot_be_static = closures cannot be static + +ast_lowering_async_non_move_closure_not_supported = + `async` non-`move` closures with parameters are not currently supported + .help = consider using `let` statements to manually capture variables by reference before entering an `async move` closure + +ast_lowering_functional_record_update_destructuring_assignment = + functional record updates are not allowed in destructuring assignments + .suggestion = consider removing the trailing pattern + +ast_lowering_async_generators_not_supported = + `async` generators are not yet supported + +ast_lowering_inline_asm_unsupported_target = + inline assembly is unsupported on this target + +ast_lowering_att_syntax_only_x86 = + the `att_syntax` option is only supported on x86 + +ast_lowering_abi_specified_multiple_times = + `{$prev_name}` ABI specified multiple times + .label = previously specified here + .note = these ABIs are equivalent on the current target + +ast_lowering_clobber_abi_not_supported = + `clobber_abi` is not supported on this target + +ast_lowering_invalid_abi_clobber_abi = + invalid ABI for `clobber_abi` + .note = the following ABIs are supported on this target: {$supported_abis} + +ast_lowering_invalid_register = + invalid register `{$reg}`: {$error} + +ast_lowering_invalid_register_class = + invalid register class `{$reg_class}`: {$error} + +ast_lowering_invalid_asm_template_modifier_reg_class = + invalid asm template modifier for this register class + +ast_lowering_argument = argument + +ast_lowering_template_modifier = template modifier + +ast_lowering_support_modifiers = + the `{$class_name}` register class supports the following template modifiers: {$modifiers} + +ast_lowering_does_not_support_modifiers = + the `{$class_name}` register class does not support template modifiers + +ast_lowering_invalid_asm_template_modifier_const = + asm template modifiers are not allowed for `const` arguments + +ast_lowering_invalid_asm_template_modifier_sym = + asm template modifiers are not allowed for `sym` arguments + +ast_lowering_register_class_only_clobber = + register class `{$reg_class_name}` can only be used as a clobber, not as an input or output + +ast_lowering_register_conflict = + register `{$reg1_name}` conflicts with register `{$reg2_name}` + .help = use `lateout` instead of `out` to avoid conflict + +ast_lowering_register1 = register `{$reg1_name}` + +ast_lowering_register2 = register `{$reg2_name}` + +ast_lowering_sub_tuple_binding = + `{$ident_name} @` is not allowed in a {$ctx} + .label = this is only allowed in slice patterns + .help = remove this and bind each tuple field independently + +ast_lowering_sub_tuple_binding_suggestion = if you don't need to use the contents of {$ident}, discard the tuple's remaining fields + +ast_lowering_extra_double_dot = + `..` can only be used once per {$ctx} pattern + .label = can only be used once per {$ctx} pattern + +ast_lowering_previously_used_here = previously used here + +ast_lowering_misplaced_double_dot = + `..` patterns are not allowed here + .note = only allowed in tuple, tuple struct, and slice patterns + +ast_lowering_misplaced_relax_trait_bound = + `?Trait` bounds are only permitted at the point where a type parameter is declared + +ast_lowering_not_supported_for_lifetime_binder_async_closure = + `for<...>` binders on `async` closures are not currently supported + +ast_lowering_arbitrary_expression_in_pattern = + arbitrary expressions aren't allowed in patterns + +ast_lowering_inclusive_range_with_no_end = inclusive range with no end + +ast_lowering_trait_fn_async = + functions in traits cannot be declared `async` + .label = `async` because of this + .note = `async` trait functions are not currently supported + .note2 = consider using the `async-trait` crate: https://crates.io/crates/async-trait diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index 21c6a2d26..5e6b6050b 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -79,11 +79,12 @@ pub struct MisplacedImplTrait<'a> { pub position: DiagnosticArgFromDisplay<'a>, } -#[derive(Diagnostic, Clone, Copy)] -#[diag(ast_lowering_rustc_box_attribute_error)] -pub struct RustcBoxAttributeError { +#[derive(Diagnostic)] +#[diag(ast_lowering_misplaced_assoc_ty_binding)] +pub struct MisplacedAssocTyBinding<'a> { #[primary_span] pub span: Span, + pub position: DiagnosticArgFromDisplay<'a>, } #[derive(Diagnostic, Clone, Copy)] @@ -339,7 +340,7 @@ pub struct InclusiveRangeWithNoEnd { #[derive(Diagnostic, Clone, Copy)] #[diag(ast_lowering_trait_fn_async, code = "E0706")] #[note] -#[note(note2)] +#[note(ast_lowering_note2)] pub struct TraitFnAsync { #[primary_span] pub fn_span: Span, diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index c3611b2f5..ffb30b1b3 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -2,7 +2,7 @@ use super::errors::{ AsyncGeneratorsNotSupported, AsyncNonMoveClosureNotSupported, AwaitOnlyInAsyncFnAndBlocks, BaseExpressionDoubleDot, ClosureCannotBeStatic, FunctionalRecordUpdateDestructuringAssignemnt, GeneratorTooManyParameters, InclusiveRangeWithNoEnd, NotSupportedForLifetimeBinderAsyncClosure, - RustcBoxAttributeError, UnderscoreExprLhsAssign, + UnderscoreExprLhsAssign, }; use super::ResolverAstLoweringExt; use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs}; @@ -16,9 +16,9 @@ use rustc_hir::def::Res; use rustc_hir::definitions::DefPathData; use rustc_session::errors::report_lit_error; use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned}; -use rustc_span::symbol::{sym, Ident}; +use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::DUMMY_SP; -use thin_vec::thin_vec; +use thin_vec::{thin_vec, ThinVec}; impl<'hir> LoweringContext<'_, 'hir> { fn lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> &'hir [hir::Expr<'hir>] { @@ -83,15 +83,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } ExprKind::Tup(elts) => hir::ExprKind::Tup(self.lower_exprs(elts)), ExprKind::Call(f, args) => { - if e.attrs.get(0).map_or(false, |a| a.has_name(sym::rustc_box)) { - if let [inner] = &args[..] && e.attrs.len() == 1 { - let kind = hir::ExprKind::Box(self.lower_expr(&inner)); - return hir::Expr { hir_id, kind, span: self.lower_span(e.span) }; - } else { - self.tcx.sess.emit_err(RustcBoxAttributeError { span: e.span }); - hir::ExprKind::Err - } - } else if let Some(legacy_args) = self.resolver.legacy_const_generic_args(f) { + if let Some(legacy_args) = self.resolver.legacy_const_generic_args(f) { self.lower_legacy_const_generics((**f).clone(), args.clone(), &legacy_args) } else { let f = self.lower_expr(f); @@ -139,13 +131,13 @@ impl<'hir> LoweringContext<'_, 'hir> { ExprKind::Cast(expr, ty) => { let expr = self.lower_expr(expr); let ty = - self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Cast)); hir::ExprKind::Cast(expr, ty) } ExprKind::Type(expr, ty) => { let expr = self.lower_expr(expr); let ty = - self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Cast)); hir::ExprKind::Type(expr, ty) } ExprKind::AddrOf(k, m, ohs) => { @@ -266,8 +258,8 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_expr_range(e.span, e1.as_deref(), e2.as_deref(), *lims) } ExprKind::Underscore => { - self.tcx.sess.emit_err(UnderscoreExprLhsAssign { span: e.span }); - hir::ExprKind::Err + let guar = self.tcx.sess.emit_err(UnderscoreExprLhsAssign { span: e.span }); + hir::ExprKind::Err(guar) } ExprKind::Path(qself, path) => { let qpath = self.lower_qpath( @@ -294,12 +286,14 @@ impl<'hir> LoweringContext<'_, 'hir> { ExprKind::InlineAsm(asm) => { hir::ExprKind::InlineAsm(self.lower_inline_asm(e.span, asm)) } + ExprKind::FormatArgs(fmt) => self.lower_format_args(e.span, fmt), ExprKind::Struct(se) => { let rest = match &se.rest { StructRest::Base(e) => Some(self.lower_expr(e)), StructRest::Rest(sp) => { - self.tcx.sess.emit_err(BaseExpressionDoubleDot { span: *sp }); - Some(&*self.arena.alloc(self.expr_err(*sp))) + let guar = + self.tcx.sess.emit_err(BaseExpressionDoubleDot { span: *sp }); + Some(&*self.arena.alloc(self.expr_err(*sp, guar))) } StructRest::None => None, }; @@ -317,7 +311,9 @@ impl<'hir> LoweringContext<'_, 'hir> { ) } ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()), - ExprKind::Err => hir::ExprKind::Err, + ExprKind::Err => hir::ExprKind::Err( + self.tcx.sess.delay_span_bug(e.span, "lowered ExprKind::Err"), + ), ExprKind::Try(sub_expr) => self.lower_expr_try(e.span, sub_expr), ExprKind::Paren(_) | ExprKind::ForLoop(..) => unreachable!("already handled"), @@ -366,7 +362,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_legacy_const_generics( &mut self, mut f: Expr, - args: Vec<AstP<Expr>>, + args: ThinVec<AstP<Expr>>, legacy_args_idx: &[usize], ) -> hir::ExprKind<'hir> { let ExprKind::Path(None, path) = &mut f.kind else { @@ -375,7 +371,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // Split the arguments into const generics and normal arguments let mut real_args = vec![]; - let mut generic_args = vec![]; + let mut generic_args = ThinVec::new(); for (idx, arg) in args.into_iter().enumerate() { if legacy_args_idx.contains(&idx) { let parent_def_id = self.current_hir_id_owner; @@ -760,7 +756,7 @@ impl<'hir> LoweringContext<'_, 'hir> { 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.expr_err(span, self.tcx.sess.delay_span_bug(span, "no task_context hir id")) }; let new_unchecked = self.expr_call_lang_item_fn_mut( span, @@ -1735,7 +1731,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.expr(span, hir::ExprKind::DropTemps(expr)) } - fn expr_match( + pub(super) fn expr_match( &mut self, span: Span, arg: &'hir hir::Expr<'hir>, @@ -1763,7 +1759,44 @@ impl<'hir> LoweringContext<'_, 'hir> { self.arena.alloc(self.expr(sp, hir::ExprKind::Tup(&[]))) } - fn expr_call_mut( + pub(super) fn expr_usize(&mut self, sp: Span, value: usize) -> hir::Expr<'hir> { + self.expr( + sp, + hir::ExprKind::Lit(hir::Lit { + span: sp, + node: ast::LitKind::Int( + value as u128, + ast::LitIntType::Unsigned(ast::UintTy::Usize), + ), + }), + ) + } + + pub(super) fn expr_u32(&mut self, sp: Span, value: u32) -> hir::Expr<'hir> { + self.expr( + sp, + hir::ExprKind::Lit(hir::Lit { + span: sp, + node: ast::LitKind::Int(value.into(), ast::LitIntType::Unsigned(ast::UintTy::U32)), + }), + ) + } + + pub(super) fn expr_char(&mut self, sp: Span, value: char) -> hir::Expr<'hir> { + self.expr(sp, hir::ExprKind::Lit(hir::Lit { span: sp, node: ast::LitKind::Char(value) })) + } + + pub(super) fn expr_str(&mut self, sp: Span, value: Symbol) -> hir::Expr<'hir> { + self.expr( + sp, + hir::ExprKind::Lit(hir::Lit { + span: sp, + node: ast::LitKind::Str(value, ast::StrStyle::Cooked), + }), + ) + } + + pub(super) fn expr_call_mut( &mut self, span: Span, e: &'hir hir::Expr<'hir>, @@ -1772,7 +1805,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.expr(span, hir::ExprKind::Call(e, args)) } - fn expr_call( + pub(super) fn expr_call( &mut self, span: Span, e: &'hir hir::Expr<'hir>, @@ -1814,6 +1847,27 @@ impl<'hir> LoweringContext<'_, 'hir> { ) } + /// `<LangItem>::name` + pub(super) fn expr_lang_item_type_relative( + &mut self, + span: Span, + lang_item: hir::LangItem, + name: Symbol, + ) -> hir::Expr<'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)), + )), + self.arena.alloc(hir::PathSegment::new( + Ident::new(name, span), + self.next_id(), + Res::Err, + )), + )); + self.expr(span, path) + } + pub(super) fn expr_ident( &mut self, sp: Span, @@ -1872,12 +1926,25 @@ impl<'hir> LoweringContext<'_, 'hir> { self.expr(b.span, hir::ExprKind::Block(b, None)) } + pub(super) fn expr_array_ref( + &mut self, + span: Span, + elements: &'hir [hir::Expr<'hir>], + ) -> hir::Expr<'hir> { + let addrof = hir::ExprKind::AddrOf( + hir::BorrowKind::Ref, + hir::Mutability::Not, + self.arena.alloc(self.expr(span, hir::ExprKind::Array(elements))), + ); + self.expr(span, addrof) + } + pub(super) fn expr(&mut self, span: Span, kind: hir::ExprKind<'hir>) -> hir::Expr<'hir> { let hir_id = self.next_id(); hir::Expr { hir_id, kind, span: self.lower_span(span) } } - fn expr_field( + pub(super) fn expr_field( &mut self, ident: Ident, expr: &'hir hir::Expr<'hir>, @@ -1892,7 +1959,11 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - fn arm(&mut self, pat: &'hir hir::Pat<'hir>, expr: &'hir hir::Expr<'hir>) -> hir::Arm<'hir> { + pub(super) fn arm( + &mut self, + pat: &'hir hir::Pat<'hir>, + expr: &'hir hir::Expr<'hir>, + ) -> hir::Arm<'hir> { hir::Arm { hir_id: self.next_id(), pat, diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs new file mode 100644 index 000000000..4095e225a --- /dev/null +++ b/compiler/rustc_ast_lowering/src/format.rs @@ -0,0 +1,411 @@ +use super::LoweringContext; +use rustc_ast as ast; +use rustc_ast::visit::{self, Visitor}; +use rustc_ast::*; +use rustc_data_structures::fx::FxIndexSet; +use rustc_hir as hir; +use rustc_span::{ + sym, + symbol::{kw, Ident}, + Span, +}; + +impl<'hir> LoweringContext<'_, 'hir> { + pub(crate) fn lower_format_args(&mut self, sp: Span, fmt: &FormatArgs) -> hir::ExprKind<'hir> { + expand_format_args(self, sp, fmt) + } +} + +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +enum ArgumentType { + Format(FormatTrait), + Usize, +} + +/// Generate a hir expression representing an argument to a format_args invocation. +/// +/// Generates: +/// +/// ```text +/// <core::fmt::ArgumentV1>::new_…(arg) +/// ``` +fn make_argument<'hir>( + ctx: &mut LoweringContext<'_, 'hir>, + sp: Span, + arg: &'hir hir::Expr<'hir>, + ty: ArgumentType, +) -> hir::Expr<'hir> { + use ArgumentType::*; + use FormatTrait::*; + let new_fn = ctx.arena.alloc(ctx.expr_lang_item_type_relative( + sp, + hir::LangItem::FormatArgument, + match ty { + Format(Display) => sym::new_display, + Format(Debug) => sym::new_debug, + Format(LowerExp) => sym::new_lower_exp, + Format(UpperExp) => sym::new_upper_exp, + Format(Octal) => sym::new_octal, + Format(Pointer) => sym::new_pointer, + Format(Binary) => sym::new_binary, + Format(LowerHex) => sym::new_lower_hex, + Format(UpperHex) => sym::new_upper_hex, + Usize => sym::from_usize, + }, + )); + ctx.expr_call_mut(sp, new_fn, std::slice::from_ref(arg)) +} + +/// Generate a hir expression for a format_args Count. +/// +/// Generates: +/// +/// ```text +/// <core::fmt::rt::v1::Count>::Is(…) +/// ``` +/// +/// or +/// +/// ```text +/// <core::fmt::rt::v1::Count>::Param(…) +/// ``` +/// +/// or +/// +/// ```text +/// <core::fmt::rt::v1::Count>::Implied +/// ``` +fn make_count<'hir>( + ctx: &mut LoweringContext<'_, 'hir>, + sp: Span, + count: &Option<FormatCount>, + argmap: &mut FxIndexSet<(usize, ArgumentType)>, +) -> hir::Expr<'hir> { + match count { + Some(FormatCount::Literal(n)) => { + let count_is = ctx.arena.alloc(ctx.expr_lang_item_type_relative( + sp, + hir::LangItem::FormatCount, + sym::Is, + )); + let value = ctx.arena.alloc_from_iter([ctx.expr_usize(sp, *n)]); + ctx.expr_call_mut(sp, count_is, value) + } + Some(FormatCount::Argument(arg)) => { + if let Ok(arg_index) = arg.index { + let (i, _) = argmap.insert_full((arg_index, ArgumentType::Usize)); + let count_param = ctx.arena.alloc(ctx.expr_lang_item_type_relative( + sp, + hir::LangItem::FormatCount, + sym::Param, + )); + let value = ctx.arena.alloc_from_iter([ctx.expr_usize(sp, i)]); + ctx.expr_call_mut(sp, count_param, value) + } else { + ctx.expr( + sp, + hir::ExprKind::Err( + ctx.tcx.sess.delay_span_bug(sp, "lowered bad format_args count"), + ), + ) + } + } + None => ctx.expr_lang_item_type_relative(sp, hir::LangItem::FormatCount, sym::Implied), + } +} + +/// Generate a hir expression for a format_args placeholder specification. +/// +/// Generates +/// +/// ```text +/// <core::fmt::rt::v1::Argument::new( +/// …usize, // position +/// '…', // fill +/// <core::fmt::rt::v1::Alignment>::…, // alignment +/// …u32, // flags +/// <core::fmt::rt::v1::Count::…>, // width +/// <core::fmt::rt::v1::Count::…>, // precision +/// ) +/// ``` +fn make_format_spec<'hir>( + ctx: &mut LoweringContext<'_, 'hir>, + sp: Span, + placeholder: &FormatPlaceholder, + argmap: &mut FxIndexSet<(usize, ArgumentType)>, +) -> hir::Expr<'hir> { + let position = match placeholder.argument.index { + Ok(arg_index) => { + let (i, _) = + argmap.insert_full((arg_index, ArgumentType::Format(placeholder.format_trait))); + ctx.expr_usize(sp, i) + } + Err(_) => ctx.expr( + sp, + hir::ExprKind::Err(ctx.tcx.sess.delay_span_bug(sp, "lowered bad format_args count")), + ), + }; + let &FormatOptions { + ref width, + ref precision, + alignment, + fill, + sign, + alternate, + zero_pad, + debug_hex, + } = &placeholder.format_options; + let fill = ctx.expr_char(sp, fill.unwrap_or(' ')); + let align = ctx.expr_lang_item_type_relative( + sp, + hir::LangItem::FormatAlignment, + match alignment { + Some(FormatAlignment::Left) => sym::Left, + Some(FormatAlignment::Right) => sym::Right, + Some(FormatAlignment::Center) => sym::Center, + None => sym::Unknown, + }, + ); + // This needs to match `FlagV1` in library/core/src/fmt/mod.rs. + let flags: u32 = ((sign == Some(FormatSign::Plus)) as u32) + | ((sign == Some(FormatSign::Minus)) as u32) << 1 + | (alternate as u32) << 2 + | (zero_pad as u32) << 3 + | ((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 format_placeholder_new = ctx.arena.alloc(ctx.expr_lang_item_type_relative( + sp, + hir::LangItem::FormatPlaceholder, + sym::new, + )); + let args = ctx.arena.alloc_from_iter([position, fill, align, flags, precision, width]); + ctx.expr_call_mut(sp, format_placeholder_new, args) +} + +fn expand_format_args<'hir>( + ctx: &mut LoweringContext<'_, 'hir>, + macsp: Span, + fmt: &FormatArgs, +) -> hir::ExprKind<'hir> { + let lit_pieces = + ctx.arena.alloc_from_iter(fmt.template.iter().enumerate().filter_map(|(i, piece)| { + match piece { + &FormatArgsPiece::Literal(s) => Some(ctx.expr_str(fmt.span, s)), + &FormatArgsPiece::Placeholder(_) => { + // Inject empty string before placeholders when not already preceded by a literal piece. + if i == 0 || matches!(fmt.template[i - 1], FormatArgsPiece::Placeholder(_)) { + Some(ctx.expr_str(fmt.span, kw::Empty)) + } else { + None + } + } + } + })); + let lit_pieces = ctx.expr_array_ref(fmt.span, lit_pieces); + + // Whether we'll use the `Arguments::new_v1_formatted` form (true), + // or the `Arguments::new_v1` form (false). + let mut use_format_options = false; + + // Create a list of all _unique_ (argument, format trait) combinations. + // E.g. "{0} {0:x} {0} {1}" -> [(0, Display), (0, LowerHex), (1, Display)] + let mut argmap = FxIndexSet::default(); + for piece in &fmt.template { + let FormatArgsPiece::Placeholder(placeholder) = piece else { continue }; + if placeholder.format_options != Default::default() { + // Can't use basic form if there's any formatting options. + use_format_options = true; + } + if let Ok(index) = placeholder.argument.index { + if !argmap.insert((index, ArgumentType::Format(placeholder.format_trait))) { + // Duplicate (argument, format trait) combination, + // which we'll only put once in the args array. + use_format_options = true; + } + } + } + + let format_options = use_format_options.then(|| { + // Generate: + // &[format_spec_0, format_spec_1, format_spec_2] + let elements: Vec<_> = fmt + .template + .iter() + .filter_map(|piece| { + let FormatArgsPiece::Placeholder(placeholder) = piece else { return None }; + Some(make_format_spec(ctx, macsp, placeholder, &mut argmap)) + }) + .collect(); + ctx.expr_array_ref(macsp, ctx.arena.alloc_from_iter(elements)) + }); + + let arguments = fmt.arguments.all_args(); + + // If the args array contains exactly all the original arguments once, + // in order, we can use a simple array instead of a `match` construction. + // However, if there's a yield point in any argument except the first one, + // we don't do this, because an ArgumentV1 cannot be kept across yield points. + // + // This is an optimization, speeding up compilation about 1-2% in some cases. + // See https://github.com/rust-lang/rust/pull/106770#issuecomment-1380790609 + let use_simple_array = argmap.len() == arguments.len() + && argmap.iter().enumerate().all(|(i, &(j, _))| i == j) + && arguments.iter().skip(1).all(|arg| !may_contain_yield_point(&arg.expr)); + + let args = if use_simple_array { + // Generate: + // &[ + // <core::fmt::ArgumentV1>::new_display(&arg0), + // <core::fmt::ArgumentV1>::new_lower_hex(&arg1), + // <core::fmt::ArgumentV1>::new_debug(&arg2), + // … + // ] + let elements: Vec<_> = arguments + .iter() + .zip(argmap) + .map(|(arg, (_, ty))| { + let sp = arg.expr.span.with_ctxt(macsp.ctxt()); + let arg = ctx.lower_expr(&arg.expr); + let ref_arg = ctx.arena.alloc(ctx.expr( + sp, + hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, arg), + )); + make_argument(ctx, sp, ref_arg, ty) + }) + .collect(); + ctx.expr_array_ref(macsp, ctx.arena.alloc_from_iter(elements)) + } else { + // Generate: + // &match (&arg0, &arg1, &…) { + // args => [ + // <core::fmt::ArgumentV1>::new_display(args.0), + // <core::fmt::ArgumentV1>::new_lower_hex(args.1), + // <core::fmt::ArgumentV1>::new_debug(args.0), + // … + // ] + // } + let args_ident = Ident::new(sym::args, macsp); + let (args_pat, args_hir_id) = ctx.pat_ident(macsp, args_ident); + let args = ctx.arena.alloc_from_iter(argmap.iter().map(|&(arg_index, ty)| { + if let Some(arg) = arguments.get(arg_index) { + let sp = arg.expr.span.with_ctxt(macsp.ctxt()); + let args_ident_expr = ctx.expr_ident(macsp, args_ident, args_hir_id); + let arg = ctx.arena.alloc(ctx.expr( + sp, + hir::ExprKind::Field( + args_ident_expr, + Ident::new(sym::integer(arg_index), macsp), + ), + )); + make_argument(ctx, sp, arg, ty) + } else { + ctx.expr( + macsp, + hir::ExprKind::Err( + ctx.tcx.sess.delay_span_bug(macsp, format!("no arg at {arg_index}")), + ), + ) + } + })); + let elements: Vec<_> = arguments + .iter() + .map(|arg| { + let arg_expr = ctx.lower_expr(&arg.expr); + ctx.expr( + arg.expr.span.with_ctxt(macsp.ctxt()), + hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, arg_expr), + ) + }) + .collect(); + let args_tuple = ctx + .arena + .alloc(ctx.expr(macsp, hir::ExprKind::Tup(ctx.arena.alloc_from_iter(elements)))); + let array = ctx.arena.alloc(ctx.expr(macsp, hir::ExprKind::Array(args))); + let match_arms = ctx.arena.alloc_from_iter([ctx.arm(args_pat, array)]); + let match_expr = ctx.arena.alloc(ctx.expr_match( + macsp, + args_tuple, + match_arms, + hir::MatchSource::FormatArgs, + )); + ctx.expr( + macsp, + hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, match_expr), + ) + }; + + if let Some(format_options) = format_options { + // Generate: + // <core::fmt::Arguments>::new_v1_formatted( + // lit_pieces, + // args, + // format_options, + // unsafe { ::core::fmt::UnsafeArg::new() } + // ) + let new_v1_formatted = ctx.arena.alloc(ctx.expr_lang_item_type_relative( + macsp, + hir::LangItem::FormatArguments, + sym::new_v1_formatted, + )); + let unsafe_arg_new = ctx.arena.alloc(ctx.expr_lang_item_type_relative( + macsp, + hir::LangItem::FormatUnsafeArg, + sym::new, + )); + let unsafe_arg_new_call = ctx.expr_call(macsp, unsafe_arg_new, &[]); + let hir_id = ctx.next_id(); + let unsafe_arg = ctx.expr_block(ctx.arena.alloc(hir::Block { + stmts: &[], + expr: Some(unsafe_arg_new_call), + hir_id, + rules: hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::CompilerGenerated), + span: macsp, + targeted_by_break: false, + })); + let args = ctx.arena.alloc_from_iter([lit_pieces, args, format_options, unsafe_arg]); + hir::ExprKind::Call(new_v1_formatted, args) + } else { + // Generate: + // <core::fmt::Arguments>::new_v1( + // lit_pieces, + // args, + // ) + let new_v1 = ctx.arena.alloc(ctx.expr_lang_item_type_relative( + macsp, + hir::LangItem::FormatArguments, + sym::new_v1, + )); + let new_args = ctx.arena.alloc_from_iter([lit_pieces, args]); + hir::ExprKind::Call(new_v1, new_args) + } +} + +fn may_contain_yield_point(e: &ast::Expr) -> bool { + struct MayContainYieldPoint(bool); + + impl Visitor<'_> for MayContainYieldPoint { + fn visit_expr(&mut self, e: &ast::Expr) { + if let ast::ExprKind::Await(_) | ast::ExprKind::Yield(_) = e.kind { + self.0 = true; + } else { + visit::walk_expr(self, e); + } + } + + fn visit_mac_call(&mut self, _: &ast::MacCall) { + // Macros should be expanded at this point. + unreachable!("unexpanded macro in ast lowering"); + } + + fn visit_item(&mut self, _: &ast::Item) { + // Do not recurse into nested items. + } + } + + let mut visitor = MayContainYieldPoint(false); + visitor.visit_expr(e); + visitor.0 +} diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index 63033085b..f7fe0d771 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -275,19 +275,6 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { }); } - fn visit_fn( - &mut self, - fk: intravisit::FnKind<'hir>, - fd: &'hir FnDecl<'hir>, - b: BodyId, - _: Span, - id: HirId, - ) { - assert_eq!(self.owner, id.owner); - assert_eq!(self.parent_node, id.local_id); - intravisit::walk_fn(self, fk, fd, b, id); - } - fn visit_block(&mut self, block: &'hir Block<'hir>) { self.insert(block.span, block.hir_id, Node::Block(block)); self.with_parent(block.hir_id, |this| { diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 5d2589cb2..41295f2b7 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -7,13 +7,14 @@ 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}; use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; use rustc_hir::PredicateOrigin; use rustc_index::vec::{Idx, IndexVec}; use rustc_middle::ty::{DefIdTree, ResolverAstLowering, TyCtxt}; -use rustc_span::lev_distance::find_best_match_for_name; +use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::source_map::DesugaringKind; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{Span, Symbol}; @@ -67,7 +68,6 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { current_hir_id_owner: hir::CRATE_OWNER_ID, item_local_id_counter: hir::ItemLocalId::new(0), node_id_to_local_id: Default::default(), - local_id_to_def_id: SortedMap::new(), trait_map: Default::default(), // Lowering state. @@ -285,7 +285,7 @@ impl<'hir> LoweringContext<'_, 'hir> { .alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))), }, ItemKind::GlobalAsm(asm) => hir::ItemKind::GlobalAsm(self.lower_inline_asm(span, asm)), - ItemKind::TyAlias(box TyAlias { generics, where_clauses, ty: Some(ty), .. }) => { + ItemKind::TyAlias(box TyAlias { generics, where_clauses, ty, .. }) => { // We lower // // type Foo = impl Trait @@ -300,18 +300,16 @@ impl<'hir> LoweringContext<'_, 'hir> { &generics, id, &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), - |this| this.lower_ty(ty, &ImplTraitContext::TypeAliasesOpaqueTy), - ); - hir::ItemKind::TyAlias(ty, generics) - } - ItemKind::TyAlias(box TyAlias { generics, where_clauses, ty: None, .. }) => { - let mut generics = generics.clone(); - add_ty_alias_where_clause(&mut generics, *where_clauses, true); - let (generics, ty) = self.lower_generics( - &generics, - id, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), - |this| this.arena.alloc(this.ty(span, hir::TyKind::Err)), + |this| match ty { + None => { + let guar = this.tcx.sess.delay_span_bug( + span, + "expected to lower type alias type, but it was missing", + ); + this.arena.alloc(this.ty(span, hir::TyKind::Err(guar))) + } + Some(ty) => this.lower_ty(ty, &ImplTraitContext::TypeAliasesOpaqueTy), + }, ); hir::ItemKind::TyAlias(ty, generics) } @@ -379,8 +377,10 @@ impl<'hir> LoweringContext<'_, 'hir> { ) }); - let lowered_ty = this - .lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let lowered_ty = this.lower_ty( + ty, + &ImplTraitContext::Disallowed(ImplTraitPosition::ImplSelf), + ); (trait_ref, lowered_ty) }); @@ -459,7 +459,7 @@ impl<'hir> LoweringContext<'_, 'hir> { span: Span, body: Option<&Expr>, ) -> (&'hir hir::Ty<'hir>, hir::BodyId) { - let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy)); (ty, self.lower_const_body(span, body)) } @@ -609,8 +609,8 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ForeignItemKind::Fn(fn_dec, fn_args, generics) } ForeignItemKind::Static(t, m, _) => { - let ty = - self.lower_ty(t, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let ty = self + .lower_ty(t, &ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy)); hir::ForeignItemKind::Static(ty, *m) } ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type, @@ -680,11 +680,11 @@ impl<'hir> LoweringContext<'_, 'hir> { qself, path, ParamMode::ExplicitNamed, // no `'_` in declarations (Issue #61124) - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &ImplTraitContext::Disallowed(ImplTraitPosition::FieldTy), ); self.arena.alloc(t) } else { - self.lower_ty(&f.ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)) + self.lower_ty(&f.ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FieldTy)) }; let hir_id = self.lower_node_id(f.id); self.lower_attrs(hir_id, &f.attrs); @@ -709,7 +709,8 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, kind, has_default) = match &i.kind { AssocItemKind::Const(_, ty, default) => { - let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let ty = + self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy)); let body = default.as_ref().map(|x| self.lower_const_body(i.span, Some(x))); (hir::Generics::empty(), hir::TraitItemKind::Const(ty, body), body.is_some()) } @@ -747,7 +748,10 @@ impl<'hir> LoweringContext<'_, 'hir> { &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { let ty = ty.as_ref().map(|x| { - this.lower_ty(x, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)) + this.lower_ty( + x, + &ImplTraitContext::Disallowed(ImplTraitPosition::AssocTy), + ) }); hir::TraitItemKind::Type( this.lower_param_bounds( @@ -793,8 +797,8 @@ impl<'hir> LoweringContext<'_, 'hir> { } /// Construct `ExprKind::Err` for the given `span`. - pub(crate) fn expr_err(&mut self, span: Span) -> hir::Expr<'hir> { - self.expr(span, hir::ExprKind::Err) + pub(crate) fn expr_err(&mut self, span: Span, guar: ErrorGuaranteed) -> hir::Expr<'hir> { + self.expr(span, hir::ExprKind::Err(guar)) } fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> { @@ -806,7 +810,8 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, kind) = match &i.kind { AssocItemKind::Const(_, ty, expr) => { - let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); + let ty = + self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy)); ( hir::Generics::empty(), hir::ImplItemKind::Const(ty, self.lower_const_body(i.span, expr.as_deref())), @@ -841,7 +846,11 @@ impl<'hir> LoweringContext<'_, 'hir> { &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| match ty { None => { - let ty = this.arena.alloc(this.ty(i.span, hir::TyKind::Err)); + let guar = this.tcx.sess.delay_span_bug( + i.span, + "expected to lower associated type, but it was missing", + ); + let ty = this.arena.alloc(this.ty(i.span, hir::TyKind::Err(guar))); hir::ImplItemKind::Type(ty) } Some(ty) => { @@ -967,7 +976,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), + None => self.expr_err(span, self.tcx.sess.delay_span_bug(span, "no block")), } } @@ -977,7 +986,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &[], match expr { Some(expr) => this.lower_expr_mut(expr), - None => this.expr_err(span), + None => this.expr_err(span, this.tcx.sess.delay_span_bug(span, "no block")), }, ) }) @@ -1330,13 +1339,19 @@ impl<'hir> LoweringContext<'_, 'hir> { .map(|predicate| self.lower_where_predicate(predicate)), ); - let mut params: SmallVec<[hir::GenericParam<'hir>; 4]> = - self.lower_generic_params_mut(&generics.params).collect(); + let mut params: SmallVec<[hir::GenericParam<'hir>; 4]> = self + .lower_generic_params_mut(&generics.params, hir::GenericParamSource::Generics) + .collect(); // Introduce extra lifetimes if late resolution tells us to. let extra_lifetimes = self.resolver.take_extra_lifetime_params(parent_node_id); params.extend(extra_lifetimes.into_iter().filter_map(|(ident, node_id, res)| { - self.lifetime_res_to_generic_param(ident, node_id, res) + self.lifetime_res_to_generic_param( + ident, + node_id, + res, + hir::GenericParamSource::Generics, + ) })); let has_where_clause_predicates = !generics.where_clause.predicates.is_empty(); @@ -1440,9 +1455,10 @@ impl<'hir> LoweringContext<'_, 'hir> { span, }) => hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { hir_id: self.next_id(), - bound_generic_params: self.lower_generic_params(bound_generic_params), + bound_generic_params: self + .lower_generic_params(bound_generic_params, hir::GenericParamSource::Binder), bounded_ty: self - .lower_ty(bounded_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)), + .lower_ty(bounded_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Bound)), bounds: self.arena.alloc_from_iter(bounds.iter().map(|bound| { self.lower_param_bound( bound, @@ -1466,9 +1482,9 @@ impl<'hir> LoweringContext<'_, 'hir> { WherePredicate::EqPredicate(WhereEqPredicate { lhs_ty, rhs_ty, span }) => { hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { lhs_ty: self - .lower_ty(lhs_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)), + .lower_ty(lhs_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Bound)), rhs_ty: self - .lower_ty(rhs_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)), + .lower_ty(rhs_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Bound)), span: self.lower_span(*span), }) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index bc6d2cf12..b20157f2c 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -52,23 +52,28 @@ 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, Handler, StashKey}; +use rustc_errors::{ + DiagnosticArgFromDisplay, DiagnosticMessage, Handler, StashKey, SubdiagnosticMessage, +}; use rustc_hir as hir; use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; use rustc_hir::definitions::DefPathData; use rustc_hir::{ConstArg, GenericArg, ItemLocalId, ParamName, TraitCandidate}; use rustc_index::vec::{Idx, IndexVec}; -use rustc_middle::span_bug; -use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; +use rustc_macros::fluent_messages; +use rustc_middle::{ + span_bug, + ty::{ResolverAstLowering, TyCtxt}, +}; use rustc_session::parse::feature_err; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::DesugaringKind; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; - use smallvec::SmallVec; use std::collections::hash_map::Entry; +use thin_vec::ThinVec; macro_rules! arena_vec { ($this:expr; $($x:expr),*) => ( @@ -80,12 +85,15 @@ mod asm; mod block; mod errors; mod expr; +mod format; mod index; mod item; mod lifetime_collector; mod pat; mod path; +fluent_messages! { "../locales/en-US.ftl" } + struct LoweringContext<'a, 'hir> { tcx: TyCtxt<'hir>, resolver: &'a mut ResolverAstLowering, @@ -118,7 +126,6 @@ struct LoweringContext<'a, 'hir> { current_hir_id_owner: hir::OwnerId, item_local_id_counter: hir::ItemLocalId, - local_id_to_def_id: SortedMap<ItemLocalId, LocalDefId>, trait_map: FxHashMap<ItemLocalId, Box<[TraitCandidate]>>, impl_trait_defs: Vec<hir::GenericParam<'hir>>, @@ -253,7 +260,6 @@ enum ImplTraitContext { enum ImplTraitPosition { Path, Variable, - Type, Trait, AsyncBlock, Bound, @@ -270,30 +276,43 @@ enum ImplTraitPosition { FnTraitReturn, TraitReturn, ImplReturn, + GenericDefault, + ConstTy, + StaticTy, + AssocTy, + FieldTy, + Cast, + ImplSelf, } impl std::fmt::Display for ImplTraitPosition { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let name = match self { - ImplTraitPosition::Path => "path", - ImplTraitPosition::Variable => "variable binding", - ImplTraitPosition::Type => "type", - ImplTraitPosition::Trait => "trait", - ImplTraitPosition::AsyncBlock => "async block", - ImplTraitPosition::Bound => "bound", - ImplTraitPosition::Generic => "generic", - ImplTraitPosition::ExternFnParam => "`extern fn` param", - ImplTraitPosition::ClosureParam => "closure param", - ImplTraitPosition::PointerParam => "`fn` pointer param", - ImplTraitPosition::FnTraitParam => "`Fn` trait param", - ImplTraitPosition::TraitParam => "trait method param", - ImplTraitPosition::ImplParam => "`impl` method param", - ImplTraitPosition::ExternFnReturn => "`extern fn` return", - ImplTraitPosition::ClosureReturn => "closure return", - ImplTraitPosition::PointerReturn => "`fn` pointer return", - ImplTraitPosition::FnTraitReturn => "`Fn` trait return", - ImplTraitPosition::TraitReturn => "trait method return", - ImplTraitPosition::ImplReturn => "`impl` method return", + ImplTraitPosition::Path => "paths", + ImplTraitPosition::Variable => "variable bindings", + ImplTraitPosition::Trait => "traits", + ImplTraitPosition::AsyncBlock => "async blocks", + ImplTraitPosition::Bound => "bounds", + ImplTraitPosition::Generic => "generics", + ImplTraitPosition::ExternFnParam => "`extern fn` params", + ImplTraitPosition::ClosureParam => "closure params", + ImplTraitPosition::PointerParam => "`fn` pointer params", + ImplTraitPosition::FnTraitParam => "`Fn` trait params", + ImplTraitPosition::TraitParam => "trait method params", + ImplTraitPosition::ImplParam => "`impl` method params", + ImplTraitPosition::ExternFnReturn => "`extern fn` return types", + ImplTraitPosition::ClosureReturn => "closure return types", + ImplTraitPosition::PointerReturn => "`fn` pointer return types", + ImplTraitPosition::FnTraitReturn => "`Fn` trait return types", + ImplTraitPosition::TraitReturn => "trait method return types", + ImplTraitPosition::ImplReturn => "`impl` method return types", + ImplTraitPosition::GenericDefault => "generic parameter defaults", + ImplTraitPosition::ConstTy => "const types", + ImplTraitPosition::StaticTy => "static types", + ImplTraitPosition::AssocTy => "associated types", + ImplTraitPosition::FieldTy => "field types", + ImplTraitPosition::Cast => "cast types", + ImplTraitPosition::ImplSelf => "impl headers", }; write!(f, "{name}") @@ -416,6 +435,7 @@ fn compute_hir_hash( pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> { let sess = tcx.sess; + tcx.ensure().output_filenames(()); let (mut resolver, krate) = tcx.resolver_for_lowering(()).steal(); let ast_index = index_crate(&resolver.node_id_to_def_id, &krate); @@ -565,7 +585,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let current_attrs = std::mem::take(&mut self.attrs); let current_bodies = std::mem::take(&mut self.bodies); let current_node_ids = std::mem::take(&mut self.node_id_to_local_id); - let current_id_to_def_id = std::mem::take(&mut self.local_id_to_def_id); let current_trait_map = std::mem::take(&mut self.trait_map); let current_owner = std::mem::replace(&mut self.current_hir_id_owner, hir::OwnerId { def_id }); @@ -592,7 +611,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.attrs = current_attrs; self.bodies = current_bodies; self.node_id_to_local_id = current_node_ids; - self.local_id_to_def_id = current_id_to_def_id; self.trait_map = current_trait_map; self.current_hir_id_owner = current_owner; self.item_local_id_counter = current_local_counter; @@ -627,7 +645,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn make_owner_info(&mut self, node: hir::OwnerNode<'hir>) -> &'hir hir::OwnerInfo<'hir> { let attrs = std::mem::take(&mut self.attrs); let mut bodies = std::mem::take(&mut self.bodies); - let local_id_to_def_id = std::mem::take(&mut self.local_id_to_def_id); let trait_map = std::mem::take(&mut self.trait_map); #[cfg(debug_assertions)] @@ -643,13 +660,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let (hash_including_bodies, hash_without_bodies) = self.hash_owner(node, &bodies); let (nodes, parenting) = index::index_hir(self.tcx.sess, &*self.tcx.definitions_untracked(), node, &bodies); - let nodes = hir::OwnerNodes { - hash_including_bodies, - hash_without_bodies, - nodes, - bodies, - local_id_to_def_id, - }; + let nodes = hir::OwnerNodes { hash_including_bodies, hash_without_bodies, nodes, bodies }; let attrs = { let hash = self.tcx.with_stable_hashing_context(|mut hcx| { let mut stable_hasher = StableHasher::new(); @@ -708,7 +719,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { assert_ne!(local_id, hir::ItemLocalId::new(0)); if let Some(def_id) = self.opt_local_def_id(ast_node_id) { self.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id))); - self.local_id_to_def_id.insert(local_id, def_id); } if let Some(traits) = self.resolver.trait_map.remove(&ast_node_id) { @@ -794,6 +804,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ident: Ident, node_id: NodeId, res: LifetimeRes, + source: hir::GenericParamSource, ) -> Option<hir::GenericParam<'hir>> { let (name, kind) = match res { LifetimeRes::Param { .. } => { @@ -827,6 +838,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { pure_wrt_drop: false, kind: hir::GenericParamKind::Lifetime { kind }, colon_span: None, + source, }) } @@ -842,11 +854,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { binder: NodeId, generic_params: &[GenericParam], ) -> &'hir [hir::GenericParam<'hir>] { - let mut generic_params: Vec<_> = self.lower_generic_params_mut(generic_params).collect(); + let mut generic_params: Vec<_> = self + .lower_generic_params_mut(generic_params, hir::GenericParamSource::Binder) + .collect(); let extra_lifetimes = self.resolver.take_extra_lifetime_params(binder); debug!(?extra_lifetimes); generic_params.extend(extra_lifetimes.into_iter().filter_map(|(ident, node_id, res)| { - self.lifetime_res_to_generic_param(ident, node_id, res) + self.lifetime_res_to_generic_param(ident, node_id, res, hir::GenericParamSource::Binder) })); let generic_params = self.arena.alloc_from_iter(generic_params); debug!(?generic_params); @@ -992,8 +1006,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } else { self.arena.alloc(hir::GenericArgs::none()) }; - let itctx_tait = &ImplTraitContext::TypeAliasesOpaqueTy; - let kind = match &constraint.kind { AssocConstraintKind::Equality { term } => { let term = match term { @@ -1003,8 +1015,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::TypeBindingKind::Equality { term } } AssocConstraintKind::Bound { bounds } => { + enum DesugarKind<'a> { + ImplTrait, + Error(&'a ImplTraitPosition), + Bound, + } + // Piggy-back on the `impl Trait` context to figure out the correct behavior. - let (desugar_to_impl_trait, itctx) = match itctx { + let desugar_kind = match itctx { // We are in the return position: // // fn foo() -> impl Iterator<Item: Debug> @@ -1013,7 +1031,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // // fn foo() -> impl Iterator<Item = impl Debug> ImplTraitContext::ReturnPositionOpaqueTy { .. } - | ImplTraitContext::TypeAliasesOpaqueTy { .. } => (true, itctx), + | ImplTraitContext::TypeAliasesOpaqueTy { .. } => DesugarKind::ImplTrait, // We are in the argument position, but within a dyn type: // @@ -1022,15 +1040,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // so desugar to // // fn foo(x: dyn Iterator<Item = impl Debug>) - ImplTraitContext::Universal if self.is_in_dyn_type => (true, itctx), + ImplTraitContext::Universal if self.is_in_dyn_type => DesugarKind::ImplTrait, - // In `type Foo = dyn Iterator<Item: Debug>` we desugar to - // `type Foo = dyn Iterator<Item = impl Debug>` but we have to override the - // "impl trait context" to permit `impl Debug` in this position (it desugars - // then to an opaque type). - // - // FIXME: this is only needed until `impl Trait` is allowed in type aliases. - ImplTraitContext::Disallowed(_) if self.is_in_dyn_type => (true, itctx_tait), + ImplTraitContext::Disallowed(position) if self.is_in_dyn_type => { + DesugarKind::Error(position) + } // We are in the parameter position, but not within a dyn type: // @@ -1039,35 +1053,47 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // so we leave it as is and this gets expanded in astconv to a bound like // `<T as Iterator>::Item: Debug` where `T` is the type parameter for the // `impl Iterator`. - _ => (false, itctx), + _ => DesugarKind::Bound, }; - if desugar_to_impl_trait { - // Desugar `AssocTy: Bounds` into `AssocTy = impl Bounds`. We do this by - // constructing the HIR for `impl bounds...` and then lowering that. - - let impl_trait_node_id = self.next_node_id(); - - self.with_dyn_type_scope(false, |this| { - let node_id = this.next_node_id(); - let ty = this.lower_ty( - &Ty { - id: node_id, - kind: TyKind::ImplTrait(impl_trait_node_id, bounds.clone()), - span: this.lower_span(constraint.span), - tokens: None, - }, - itctx, - ); + match desugar_kind { + DesugarKind::ImplTrait => { + // Desugar `AssocTy: Bounds` into `AssocTy = impl Bounds`. We do this by + // constructing the HIR for `impl bounds...` and then lowering that. - hir::TypeBindingKind::Equality { term: ty.into() } - }) - } else { - // Desugar `AssocTy: Bounds` into a type binding where the - // later desugars into a trait predicate. - let bounds = self.lower_param_bounds(bounds, itctx); + let impl_trait_node_id = self.next_node_id(); + + self.with_dyn_type_scope(false, |this| { + let node_id = this.next_node_id(); + let ty = this.lower_ty( + &Ty { + id: node_id, + kind: TyKind::ImplTrait(impl_trait_node_id, bounds.clone()), + span: this.lower_span(constraint.span), + tokens: None, + }, + itctx, + ); + + hir::TypeBindingKind::Equality { term: ty.into() } + }) + } + DesugarKind::Bound => { + // Desugar `AssocTy: Bounds` into a type binding where the + // later desugars into a trait predicate. + let bounds = self.lower_param_bounds(bounds, itctx); - hir::TypeBindingKind::Constraint { bounds } + hir::TypeBindingKind::Constraint { bounds } + } + DesugarKind::Error(position) => { + let guar = self.tcx.sess.emit_err(errors::MisplacedAssocTyBinding { + span: constraint.span, + position: DiagnosticArgFromDisplay(position), + }); + let err_ty = + &*self.arena.alloc(self.ty(constraint.span, hir::TyKind::Err(guar))); + hir::TypeBindingKind::Equality { term: err_ty.into() } + } } } }; @@ -1204,7 +1230,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| { let bound = this.lower_poly_trait_ref( &PolyTraitRef { - bound_generic_params: vec![], + bound_generic_params: ThinVec::new(), trait_ref: TraitRef { path: path.clone(), ref_id: t.id }, span: t.span }, @@ -1234,7 +1260,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_ty_direct(&mut self, t: &Ty, itctx: &ImplTraitContext) -> hir::Ty<'hir> { let kind = match &t.kind { TyKind::Infer => hir::TyKind::Infer, - TyKind::Err => hir::TyKind::Err, + TyKind::Err => { + hir::TyKind::Err(self.tcx.sess.delay_span_bug(t.span, "TyKind::Err lowered")) + } TyKind::Slice(ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)), TyKind::Ptr(mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)), TyKind::Ref(region, mt) => { @@ -1351,8 +1379,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span, ); let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span); - let (param, bounds, path) = - self.lower_generic_and_bounds(*def_node_id, span, ident, bounds); + let (param, bounds, path) = self.lower_universal_param_and_bounds( + *def_node_id, + span, + ident, + bounds, + ); self.impl_trait_defs.push(param); if let Some(bounds) = bounds { self.impl_trait_bounds.push(bounds); @@ -1360,7 +1392,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { path } ImplTraitContext::FeatureGated(position, feature) => { - self.tcx + let guar = self + .tcx .sess .create_feature_err( MisplacedImplTrait { @@ -1370,24 +1403,24 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { *feature, ) .emit(); - hir::TyKind::Err + hir::TyKind::Err(guar) } ImplTraitContext::Disallowed(position) => { - self.tcx.sess.emit_err(MisplacedImplTrait { + let guar = self.tcx.sess.emit_err(MisplacedImplTrait { span: t.span, position: DiagnosticArgFromDisplay(position), }); - hir::TyKind::Err + hir::TyKind::Err(guar) } } } TyKind::MacCall(_) => panic!("`TyKind::MacCall` should have been expanded by now"), TyKind::CVarArgs => { - self.tcx.sess.delay_span_bug( + let guar = self.tcx.sess.delay_span_bug( t.span, "`TyKind::CVarArgs` should have been handled elsewhere", ); - hir::TyKind::Err + hir::TyKind::Err(guar) } }; @@ -1505,6 +1538,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { pure_wrt_drop: false, kind: hir::GenericParamKind::Lifetime { kind }, colon_span: None, + source: hir::GenericParamSource::Generics, } }, )); @@ -1573,7 +1607,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::OwnerNode::Item(self.arena.alloc(opaque_ty_item)) } - /// Given a `parent_def_id`, a list of `lifetimes_in_bounds and a `remapping` hash to be + /// Given a `parent_def_id`, a list of `lifetimes_in_bounds` and a `remapping` hash to be /// filled, this function creates new definitions for `Param` and `Fresh` lifetimes, inserts the /// new definition, adds it to the remapping with the definition of the given lifetime and /// returns a list of lifetimes to be lowered afterwards. @@ -1962,6 +1996,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { pure_wrt_drop: false, kind: hir::GenericParamKind::Lifetime { kind }, colon_span: None, + source: hir::GenericParamSource::Generics, } }, )); @@ -2127,16 +2162,25 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_generic_params_mut<'s>( &'s mut self, params: &'s [GenericParam], + source: hir::GenericParamSource, ) -> impl Iterator<Item = hir::GenericParam<'hir>> + Captures<'a> + Captures<'s> { - params.iter().map(move |param| self.lower_generic_param(param)) + params.iter().map(move |param| self.lower_generic_param(param, source)) } - fn lower_generic_params(&mut self, params: &[GenericParam]) -> &'hir [hir::GenericParam<'hir>] { - self.arena.alloc_from_iter(self.lower_generic_params_mut(params)) + fn lower_generic_params( + &mut self, + params: &[GenericParam], + source: hir::GenericParamSource, + ) -> &'hir [hir::GenericParam<'hir>] { + self.arena.alloc_from_iter(self.lower_generic_params_mut(params, source)) } #[instrument(level = "trace", skip(self))] - fn lower_generic_param(&mut self, param: &GenericParam) -> hir::GenericParam<'hir> { + fn lower_generic_param( + &mut self, + param: &GenericParam, + source: hir::GenericParamSource, + ) -> hir::GenericParam<'hir> { let (name, kind) = self.lower_generic_param_kind(param); let hir_id = self.lower_node_id(param.id); @@ -2149,6 +2193,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { pure_wrt_drop: self.tcx.sess.contains_name(¶m.attrs, sym::may_dangle), kind, colon_span: param.colon_span.map(|s| self.lower_span(s)), + source, } } @@ -2175,7 +2220,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { GenericParamKind::Type { default, .. } => { let kind = hir::GenericParamKind::Type { default: default.as_ref().map(|x| { - self.lower_ty(x, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)) + self.lower_ty( + x, + &ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault), + ) }), synthetic: false, }; @@ -2183,7 +2231,10 @@ 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::Type)); + 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)), @@ -2235,7 +2286,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } #[instrument(level = "debug", skip(self), ret)] - fn lower_generic_and_bounds( + fn lower_universal_param_and_bounds( &mut self, node_id: NodeId, span: Span, @@ -2255,6 +2306,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span, kind: hir::GenericParamKind::Type { default: None, synthetic: true }, colon_span: None, + source: hir::GenericParamSource::Generics, }; let preds = self.lower_generic_bound_predicate( diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index 06d885a45..2509b7056 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -330,8 +330,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ExprKind::Path(..) if allow_paths => {} ExprKind::Unary(UnOp::Neg, inner) if matches!(inner.kind, ExprKind::Lit(_)) => {} _ => { - self.tcx.sess.emit_err(ArbitraryExpressionInPattern { span: expr.span }); - return self.arena.alloc(self.expr_err(expr.span)); + let guar = self.tcx.sess.emit_err(ArbitraryExpressionInPattern { span: expr.span }); + return self.arena.alloc(self.expr_err(expr.span, guar)); } } self.lower_expr(expr) |