diff options
Diffstat (limited to 'compiler/rustc_ast_lowering/src')
| -rw-r--r-- | compiler/rustc_ast_lowering/src/expr.rs | 15 | ||||
| -rw-r--r-- | compiler/rustc_ast_lowering/src/format.rs | 215 | ||||
| -rw-r--r-- | compiler/rustc_ast_lowering/src/item.rs | 28 | ||||
| -rw-r--r-- | compiler/rustc_ast_lowering/src/lib.rs | 33 | ||||
| -rw-r--r-- | compiler/rustc_ast_lowering/src/stability.rs | 9 |
5 files changed, 145 insertions, 155 deletions
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 718edad0cc6..c2140514e31 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -4,6 +4,7 @@ use std::sync::Arc; use rustc_ast::ptr::P as AstP; use rustc_ast::*; use rustc_ast_pretty::pprust::expr_to_string; +use rustc_attr_data_structures::{AttributeKind, find_attr}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir as hir; use rustc_hir::HirId; @@ -831,7 +832,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ) { if self.tcx.features().async_fn_track_caller() && let Some(attrs) = self.attrs.get(&outer_hir_id.local_id) - && attrs.into_iter().any(|attr| attr.has_name(sym::track_caller)) + && find_attr!(*attrs, AttributeKind::TrackCaller(_)) { let unstable_span = self.mark_span_with_reason( DesugaringKind::Async, @@ -2289,12 +2290,12 @@ impl<'hir> LoweringContext<'_, 'hir> { 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) + let array = self.arena.alloc(self.expr(span, hir::ExprKind::Array(elements))); + self.expr_ref(span, array) + } + + pub(super) fn expr_ref(&mut self, span: Span, expr: &'hir hir::Expr<'hir>) -> hir::Expr<'hir> { + self.expr(span, hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, expr)) } pub(super) fn expr(&mut self, span: Span, kind: hir::ExprKind<'hir>) -> hir::Expr<'hir> { diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs index 17b443b8ecc..943cde90dd2 100644 --- a/compiler/rustc_ast_lowering/src/format.rs +++ b/compiler/rustc_ast_lowering/src/format.rs @@ -1,12 +1,10 @@ -use core::ops::ControlFlow; use std::borrow::Cow; -use rustc_ast::visit::Visitor; use rustc_ast::*; use rustc_data_structures::fx::FxIndexMap; use rustc_hir as hir; use rustc_session::config::FmtDebug; -use rustc_span::{Ident, Span, Symbol, sym}; +use rustc_span::{DesugaringKind, Ident, Span, Symbol, sym}; use super::LoweringContext; @@ -16,6 +14,13 @@ impl<'hir> LoweringContext<'_, 'hir> { // format_args!() had any arguments _before_ flattening/inlining. let allow_const = fmt.arguments.all_args().is_empty(); let mut fmt = Cow::Borrowed(fmt); + + let sp = self.mark_span_with_reason( + DesugaringKind::FormatLiteral { source: fmt.is_source_literal }, + sp, + sp.ctxt().outer_expn_data().allow_internal_unstable, + ); + if self.tcx.sess.opts.unstable_opts.flatten_format_args { fmt = flatten_format_args(fmt); fmt = self.inline_literals(fmt); @@ -476,77 +481,52 @@ fn expand_format_args<'hir>( return hir::ExprKind::Call(new, new_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 Argument 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 arguments.is_empty() { + let (let_statements, args) = if arguments.is_empty() { // Generate: - // &<core::fmt::Argument>::none() - // - // Note: - // `none()` just returns `[]`. We use `none()` rather than `[]` to limit the lifetime. - // - // This makes sure that this still fails to compile, even when the argument is inlined: + // [] + (vec![], ctx.arena.alloc(ctx.expr(macsp, hir::ExprKind::Array(&[])))) + } else if argmap.len() == 1 && arguments.len() == 1 { + // Only one argument, so we don't need to make the `args` tuple. // - // ``` - // let f = format_args!("{}", "a"); - // println!("{f}"); // error E0716 - // ``` - // - // Cases where keeping the object around is allowed, such as `format_args!("a")`, - // are handled above by the `allow_const` case. - let none_fn = ctx.arena.alloc(ctx.expr_lang_item_type_relative( - macsp, - hir::LangItem::FormatArgument, - sym::none, - )); - let none = ctx.expr_call(macsp, none_fn, &[]); - ctx.expr(macsp, hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, none)) - } else if use_simple_array { // Generate: - // &[ - // <core::fmt::Argument>::new_display(&arg0), - // <core::fmt::Argument>::new_lower_hex(&arg1), - // <core::fmt::Argument>::new_debug(&arg2), - // … - // ] - let elements = ctx.arena.alloc_from_iter(arguments.iter().zip(argmap).map( - |(arg, ((_, ty), placeholder_span))| { + // super let args = [<core::fmt::Argument>::new_display(&arg)]; + let args = ctx.arena.alloc_from_iter(argmap.iter().map( + |(&(arg_index, ty), &placeholder_span)| { + let arg = &arguments[arg_index]; let placeholder_span = placeholder_span.unwrap_or(arg.expr.span).with_ctxt(macsp.ctxt()); - let arg_span = match arg.kind { - FormatArgumentKind::Captured(_) => placeholder_span, - _ => arg.expr.span.with_ctxt(macsp.ctxt()), - }; let arg = ctx.lower_expr(&arg.expr); - let ref_arg = ctx.arena.alloc(ctx.expr( - arg_span, - hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, arg), - )); + let ref_arg = ctx.arena.alloc(ctx.expr_ref(arg.span.with_ctxt(macsp.ctxt()), arg)); make_argument(ctx, placeholder_span, ref_arg, ty) }, )); - ctx.expr_array_ref(macsp, elements) + let args = ctx.arena.alloc(ctx.expr(macsp, hir::ExprKind::Array(args))); + let args_ident = Ident::new(sym::args, macsp); + let (args_pat, args_hir_id) = ctx.pat_ident(macsp, args_ident); + let let_statement = ctx.stmt_super_let_pat(macsp, args_pat, Some(args)); + (vec![let_statement], ctx.arena.alloc(ctx.expr_ident_mut(macsp, args_ident, args_hir_id))) } else { // Generate: - // &match (&arg0, &arg1, &…) { - // args => [ - // <core::fmt::Argument>::new_display(args.0), - // <core::fmt::Argument>::new_lower_hex(args.1), - // <core::fmt::Argument>::new_debug(args.0), - // … - // ] - // } + // super let args = (&arg0, &arg1, &…); let args_ident = Ident::new(sym::args, macsp); let (args_pat, args_hir_id) = ctx.pat_ident(macsp, args_ident); + let elements = ctx.arena.alloc_from_iter(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), + ) + })); + let args_tuple = ctx.arena.alloc(ctx.expr(macsp, hir::ExprKind::Tup(elements))); + let let_statement_1 = ctx.stmt_super_let_pat(macsp, args_pat, Some(args_tuple)); + + // Generate: + // super let args = [ + // <core::fmt::Argument>::new_display(args.0), + // <core::fmt::Argument>::new_lower_hex(args.1), + // <core::fmt::Argument>::new_debug(args.0), + // … + // ]; let args = ctx.arena.alloc_from_iter(argmap.iter().map( |(&(arg_index, ty), &placeholder_span)| { let arg = &arguments[arg_index]; @@ -567,58 +547,47 @@ fn expand_format_args<'hir>( make_argument(ctx, placeholder_span, arg, ty) }, )); - let elements = ctx.arena.alloc_from_iter(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), - ) - })); - let args_tuple = ctx.arena.alloc(ctx.expr(macsp, hir::ExprKind::Tup(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), + let args = ctx.arena.alloc(ctx.expr(macsp, hir::ExprKind::Array(args))); + let (args_pat, args_hir_id) = ctx.pat_ident(macsp, args_ident); + let let_statement_2 = ctx.stmt_super_let_pat(macsp, args_pat, Some(args)); + ( + vec![let_statement_1, let_statement_2], + ctx.arena.alloc(ctx.expr_ident_mut(macsp, args_ident, args_hir_id)), ) }; - if let Some(format_options) = format_options { + // Generate: + // &args + let args = ctx.expr_ref(macsp, args); + + let call = if let Some(format_options) = format_options { // Generate: - // <core::fmt::Arguments>::new_v1_formatted( - // lit_pieces, - // args, - // format_options, - // unsafe { ::core::fmt::UnsafeArg::new() } - // ) + // unsafe { + // <core::fmt::Arguments>::new_v1_formatted( + // lit_pieces, + // args, + // format_options, + // ) + // } 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 args = ctx.arena.alloc_from_iter([lit_pieces, args, format_options]); + let call = ctx.expr_call(macsp, new_v1_formatted, args); 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) + hir::ExprKind::Block( + ctx.arena.alloc(hir::Block { + stmts: &[], + expr: Some(call), + hir_id, + rules: hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::CompilerGenerated), + span: macsp, + targeted_by_break: false, + }), + None, + ) } else { // Generate: // <core::fmt::Arguments>::new_v1( @@ -632,35 +601,21 @@ fn expand_format_args<'hir>( )); 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; - - impl Visitor<'_> for MayContainYieldPoint { - type Result = ControlFlow<()>; - - fn visit_expr(&mut self, e: &ast::Expr) -> ControlFlow<()> { - if let ast::ExprKind::Await(_, _) | ast::ExprKind::Yield(_) = e.kind { - ControlFlow::Break(()) - } else { - visit::walk_expr(self, e) - } - } - - fn visit_mac_call(&mut self, _: &ast::MacCall) -> ControlFlow<()> { - // Macros should be expanded at this point. - unreachable!("unexpanded macro in ast lowering"); - } + }; - fn visit_item(&mut self, _: &ast::Item) -> ControlFlow<()> { - // Do not recurse into nested items. - ControlFlow::Continue(()) - } + if !let_statements.is_empty() { + // Generate: + // { + // super let … + // super let … + // <core::fmt::Arguments>::new_…(…) + // } + let call = ctx.arena.alloc(ctx.expr(macsp, call)); + let block = ctx.block_all(macsp, ctx.arena.alloc_from_iter(let_statements), Some(call)); + hir::ExprKind::Block(block, None) + } else { + call } - - MayContainYieldPoint.visit_expr(e).is_break() } fn for_all_argument_indexes(template: &mut [FormatArgsPiece], mut f: impl FnMut(&mut usize)) { diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index ef27d0ef69b..8acb5105773 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -2,7 +2,7 @@ use rustc_abi::ExternAbi; use rustc_ast::ptr::P; use rustc_ast::visit::AssocCtxt; use rustc_ast::*; -use rustc_errors::ErrorGuaranteed; +use rustc_errors::{E0570, ErrorGuaranteed, struct_span_code_err}; use rustc_hir::def::{DefKind, PerNS, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId}; use rustc_hir::{self as hir, HirId, LifetimeSource, PredicateOrigin}; @@ -1644,9 +1644,29 @@ impl<'hir> LoweringContext<'_, 'hir> { self.error_on_invalid_abi(abi_str); ExternAbi::Rust }); - let sess = self.tcx.sess; - let features = self.tcx.features(); - gate_unstable_abi(sess, features, span, extern_abi); + let tcx = self.tcx; + + // we can't do codegen for unsupported ABIs, so error now so we won't get farther + if !tcx.sess.target.is_abi_supported(extern_abi) { + let mut err = struct_span_code_err!( + tcx.dcx(), + span, + E0570, + "{extern_abi} is not a supported ABI for the current target", + ); + + if let ExternAbi::Stdcall { unwind } = extern_abi { + let c_abi = ExternAbi::C { unwind }; + let system_abi = ExternAbi::System { unwind }; + err.help(format!("if you need `extern {extern_abi}` on win32 and `extern {c_abi}` everywhere else, \ + use `extern {system_abi}`" + )); + } + err.emit(); + } + // Show required feature gate even if we already errored, as the user is likely to build the code + // for the actually intended target next and then they will need the feature gate. + gate_unstable_abi(tcx.sess, tcx.features(), span, extern_abi); extern_abi } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 3b99a653417..26d7c0cd6d3 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -48,7 +48,7 @@ use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::spawn; use rustc_data_structures::tagged_ptr::TaggedRef; -use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, StashKey}; +use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle}; use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId}; use rustc_hir::lints::DelayedLint; @@ -60,7 +60,7 @@ use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_macros::extension; use rustc_middle::span_bug; use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; -use rustc_session::parse::{add_feature_diagnostics, feature_err}; +use rustc_session::parse::add_feature_diagnostics; use rustc_span::symbol::{Ident, Symbol, kw, sym}; use rustc_span::{DUMMY_SP, DesugaringKind, Span}; use smallvec::SmallVec; @@ -2109,15 +2109,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // `ExprKind::Paren(ExprKind::Underscore)` and should also be lowered to `GenericArg::Infer` match c.value.peel_parens().kind { ExprKind::Underscore => { - if !self.tcx.features().generic_arg_infer() { - feature_err( - &self.tcx.sess, - sym::generic_arg_infer, - c.value.span, - fluent_generated::ast_lowering_underscore_array_length_unstable, - ) - .stash(c.value.span, StashKey::UnderscoreForArrayLengths); - } let ct_kind = hir::ConstArgKind::Infer(self.lower_span(c.value.span), ()); self.arena.alloc(hir::ConstArg { hir_id: self.lower_node_id(c.id), kind: ct_kind }) } @@ -2301,6 +2292,26 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.stmt(span, hir::StmtKind::Let(self.arena.alloc(local))) } + fn stmt_super_let_pat( + &mut self, + span: Span, + pat: &'hir hir::Pat<'hir>, + init: Option<&'hir hir::Expr<'hir>>, + ) -> hir::Stmt<'hir> { + let hir_id = self.next_id(); + let local = hir::LetStmt { + super_: Some(span), + hir_id, + init, + pat, + els: None, + source: hir::LocalSource::Normal, + span: self.lower_span(span), + ty: None, + }; + self.stmt(span, hir::StmtKind::Let(self.arena.alloc(local))) + } + fn block_expr(&mut self, expr: &'hir hir::Expr<'hir>) -> &'hir hir::Block<'hir> { self.block_all(expr.span, &[], Some(expr)) } diff --git a/compiler/rustc_ast_lowering/src/stability.rs b/compiler/rustc_ast_lowering/src/stability.rs index b8fa2dd3dd6..6752218fa0d 100644 --- a/compiler/rustc_ast_lowering/src/stability.rs +++ b/compiler/rustc_ast_lowering/src/stability.rs @@ -96,6 +96,9 @@ pub fn extern_abi_stability(abi: ExternAbi) -> Result<(), UnstableAbi> { ExternAbi::RustCold => { Err(UnstableAbi { abi, feature: sym::rust_cold_cc, explain: GateReason::Experimental }) } + ExternAbi::RustInvalid => { + Err(UnstableAbi { abi, feature: sym::rustc_attrs, explain: GateReason::ImplDetail }) + } ExternAbi::GpuKernel => Err(UnstableAbi { abi, feature: sym::abi_gpu_kernel, @@ -124,12 +127,12 @@ pub fn extern_abi_stability(abi: ExternAbi) -> Result<(), UnstableAbi> { feature: sym::abi_riscv_interrupt, explain: GateReason::Experimental, }), - ExternAbi::CCmseNonSecureCall => Err(UnstableAbi { + ExternAbi::CmseNonSecureCall => Err(UnstableAbi { abi, - feature: sym::abi_c_cmse_nonsecure_call, + feature: sym::abi_cmse_nonsecure_call, explain: GateReason::Experimental, }), - ExternAbi::CCmseNonSecureEntry => Err(UnstableAbi { + ExternAbi::CmseNonSecureEntry => Err(UnstableAbi { abi, feature: sym::cmse_nonsecure_entry, explain: GateReason::Experimental, |
