diff --git a/.mailmap b/.mailmap index 3b57f88ecabd..b9fb7be0403c 100644 --- a/.mailmap +++ b/.mailmap @@ -34,10 +34,13 @@ Alona Enraght-Moony Alona Enraght-Moony Amanda Stjerna Amanda Stjerna +Amanieu d'Antras Amos Onn Ana-Maria Mihalache Anatoly Ikorsky Andre Bogus +Andre Bogus +Andre Bogus Andrea Ciliberti Andreas Gal Andreas Jonson @@ -116,6 +119,7 @@ Carol Willing Chandler Deng Charles Lew CrLF0710 Chris C Cerami Chris C Cerami +Chris Denton Chris Denton Chris Denton Chris Gregory Chris Pardy @@ -403,6 +407,8 @@ Urgau <3616612+Urgau@users.noreply.github.com> Lucy Lukas H. Lukas Lueg +Lukas Wirth +Lukas Wirth Luke Metz Luqman Aden Luqman Aden @@ -493,6 +499,7 @@ Nicolas Abram Nicole Mazzuca Niko Matsakis Niko Matsakis +Niko Matsakis Noratrieb <48135649+Noratrieb@users.noreply.github.com> Noratrieb <48135649+Noratrieb@users.noreply.github.com> <48135649+Nilstrieb@users.noreply.github.com> Noratrieb <48135649+Noratrieb@users.noreply.github.com> diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 6b51cbd7fbeb..4489a424c0d5 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1450,11 +1450,20 @@ impl Expr { } pub fn precedence(&self) -> ExprPrecedence { + fn prefix_attrs_precedence(attrs: &AttrVec) -> ExprPrecedence { + for attr in attrs { + if let AttrStyle::Outer = attr.style { + return ExprPrecedence::Prefix; + } + } + ExprPrecedence::Unambiguous + } + match &self.kind { ExprKind::Closure(closure) => { match closure.fn_decl.output { FnRetTy::Default(_) => ExprPrecedence::Jump, - FnRetTy::Ty(_) => ExprPrecedence::Unambiguous, + FnRetTy::Ty(_) => prefix_attrs_precedence(&self.attrs), } } @@ -1463,7 +1472,7 @@ impl Expr { | ExprKind::Yield(YieldKind::Prefix(value)) | ExprKind::Yeet(value) => match value { Some(_) => ExprPrecedence::Jump, - None => ExprPrecedence::Unambiguous, + None => prefix_attrs_precedence(&self.attrs), }, ExprKind::Become(_) => ExprPrecedence::Jump, @@ -1490,7 +1499,7 @@ impl Expr { | ExprKind::Let(..) | ExprKind::Unary(..) => ExprPrecedence::Prefix, - // Never need parens + // Need parens if and only if there are prefix attributes. ExprKind::Array(_) | ExprKind::Await(..) | ExprKind::Use(..) @@ -1525,7 +1534,7 @@ impl Expr { | ExprKind::While(..) | ExprKind::Yield(YieldKind::Postfix(..)) | ExprKind::Err(_) - | ExprKind::Dummy => ExprPrecedence::Unambiguous, + | ExprKind::Dummy => prefix_attrs_precedence(&self.attrs), } } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index c88aa5c33ea9..1449a4a5fb30 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -1700,7 +1700,8 @@ fn visit_nested_use_tree<'a, V: Visitor<'a>>( } pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) -> V::Result { - let Stmt { id: _, kind, span: _ } = statement; + let Stmt { id, kind, span: _ } = statement; + try_visit!(visit_id(visitor, id)); match kind { StmtKind::Let(local) => try_visit!(visitor.visit_local(local)), StmtKind::Item(item) => try_visit!(visitor.visit_item(item)), diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index e2d291a536da..49110c93954a 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -145,6 +145,7 @@ impl<'hir> LoweringContext<'_, 'hir> { kind, vis_span, span: self.lower_span(i.span), + has_delayed_lints: !self.delayed_lints.is_empty(), }; self.arena.alloc(item) } @@ -599,6 +600,7 @@ impl<'hir> LoweringContext<'_, 'hir> { kind, vis_span, span: this.lower_span(use_tree.span), + has_delayed_lints: !this.delayed_lints.is_empty(), }; hir::OwnerNode::Item(this.arena.alloc(item)) }); @@ -697,6 +699,7 @@ impl<'hir> LoweringContext<'_, 'hir> { kind, vis_span: self.lower_span(i.vis.span), span: self.lower_span(i.span), + has_delayed_lints: !self.delayed_lints.is_empty(), }; self.arena.alloc(item) } @@ -941,6 +944,7 @@ impl<'hir> LoweringContext<'_, 'hir> { kind, span: self.lower_span(i.span), defaultness: hir::Defaultness::Default { has_value: has_default }, + has_delayed_lints: !self.delayed_lints.is_empty(), }; self.arena.alloc(item) } @@ -1100,6 +1104,7 @@ impl<'hir> LoweringContext<'_, 'hir> { vis_span: self.lower_span(i.vis.span), span: self.lower_span(i.span), defaultness, + has_delayed_lints: !self.delayed_lints.is_empty(), }; self.arena.alloc(item) } diff --git a/compiler/rustc_attr_data_structures/src/attributes.rs b/compiler/rustc_attr_data_structures/src/attributes.rs index 845e4d5e5d0f..8f95a0178090 100644 --- a/compiler/rustc_attr_data_structures/src/attributes.rs +++ b/compiler/rustc_attr_data_structures/src/attributes.rs @@ -130,24 +130,54 @@ impl Deprecation { } } -/// Represent parsed, *built in*, inert attributes. +/// Represents parsed *built-in* inert attributes. /// -/// That means attributes that are not actually ever expanded. -/// For more information on this, see the module docs on the [`rustc_attr_parsing`] crate. -/// They're instead used as markers, to guide the compilation process in various way in most every stage of the compiler. -/// These are kept around after the AST, into the HIR and further on. +/// ## Overview +/// These attributes are markers that guide the compilation process and are never expanded into other code. +/// They persist throughout the compilation phases, from AST to HIR and beyond. /// -/// The word "parsed" could be a little misleading here, because the parser already parses -/// attributes early on. However, the result, an [`ast::Attribute`] -/// is only parsed at a high level, still containing a token stream in many cases. That is -/// because the structure of the contents varies from attribute to attribute. -/// With a parsed attribute I mean that each attribute is processed individually into a -/// final structure, which on-site (the place where the attribute is useful for, think the -/// the place where `must_use` is checked) little to no extra parsing or validating needs to -/// happen. +/// ## Attribute Processing +/// While attributes are initially parsed by [`rustc_parse`] into [`ast::Attribute`], they still contain raw token streams +/// because different attributes have different internal structures. This enum represents the final, +/// fully parsed form of these attributes, where each variant contains contains all the information and +/// structure relevant for the specific attribute. /// -/// For more docs, look in [`rustc_attr_parsing`]. +/// Some attributes can be applied multiple times to the same item, and they are "collapsed" into a single +/// semantic attribute. For example: +/// ```rust +/// #[repr(C)] +/// #[repr(packed)] +/// struct S { } +/// ``` +/// This is equivalent to `#[repr(C, packed)]` and results in a single [`AttributeKind::Repr`] containing +/// both `C` and `packed` annotations. This collapsing happens during parsing and is reflected in the +/// data structures defined in this enum. /// +/// ## Usage +/// These parsed attributes are used throughout the compiler to: +/// - Control code generation (e.g., `#[repr]`) +/// - Mark API stability (`#[stable]`, `#[unstable]`) +/// - Provide documentation (`#[doc]`) +/// - Guide compiler behavior (e.g., `#[allow_internal_unstable]`) +/// +/// ## Note on Attribute Organization +/// Some attributes like `InlineAttr`, `OptimizeAttr`, and `InstructionSetAttr` are defined separately +/// from this enum because they are used in specific compiler phases (like code generation) and don't +/// need to persist throughout the entire compilation process. They are typically processed and +/// converted into their final form earlier in the compilation pipeline. +/// +/// For example: +/// - `InlineAttr` is used during code generation to control function inlining +/// - `OptimizeAttr` is used to control optimization levels +/// - `InstructionSetAttr` is used for target-specific code generation +/// +/// These attributes are handled by their respective compiler passes in the [`rustc_codegen_ssa`] crate +/// and don't need to be preserved in the same way as the attributes in this enum. +/// +/// For more details on attribute parsing, see the [`rustc_attr_parsing`] crate. +/// +/// [`rustc_parse`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/index.html +/// [`rustc_codegen_ssa`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/index.html /// [`rustc_attr_parsing`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_attr_parsing/index.html #[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute)] pub enum AttributeKind { @@ -158,6 +188,9 @@ pub enum AttributeKind { /// Represents `#[allow_internal_unstable]`. AllowInternalUnstable(ThinVec<(Symbol, Span)>), + /// Represents `#[rustc_as_ptr]` (used by the `dangling_pointers_from_temporaries` lint). + AsPtr(Span), + /// Represents `#[rustc_default_body_unstable]`. BodyStability { stability: DefaultBodyStability, diff --git a/compiler/rustc_attr_data_structures/src/lib.rs b/compiler/rustc_attr_data_structures/src/lib.rs index b0fc19d1cd7b..f8355be09adf 100644 --- a/compiler/rustc_attr_data_structures/src/lib.rs +++ b/compiler/rustc_attr_data_structures/src/lib.rs @@ -1,3 +1,7 @@ +//! Data structures for representing parsed attributes in the Rust compiler. +//! For detailed documentation about attribute processing, +//! see [rustc_attr_parsing](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_attr_parsing/index.html). + // tidy-alphabetical-start #![allow(internal_features)] #![doc(rust_logo)] diff --git a/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs b/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs new file mode 100644 index 000000000000..32a20d4c5b5e --- /dev/null +++ b/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs @@ -0,0 +1,21 @@ +use rustc_attr_data_structures::AttributeKind; +use rustc_span::{Symbol, sym}; + +use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser}; +use crate::context::{AcceptContext, Stage}; +use crate::parser::ArgParser; + +pub(crate) struct AsPtrParser; + +impl SingleAttributeParser for AsPtrParser { + const PATH: &[Symbol] = &[sym::rustc_as_ptr]; + + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst; + + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + + fn convert(cx: &mut AcceptContext<'_, '_, S>, _args: &ArgParser<'_>) -> Option { + // FIXME: check that there's no args (this is currently checked elsewhere) + Some(AttributeKind::AsPtr(cx.attr_span)) + } +} diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index caf55e6685ef..df488c89a34f 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -29,6 +29,7 @@ pub(crate) mod allow_unstable; pub(crate) mod cfg; pub(crate) mod confusables; pub(crate) mod deprecation; +pub(crate) mod lint_helpers; pub(crate) mod repr; pub(crate) mod stability; pub(crate) mod transparency; diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 47f72232828e..3193d8975e9f 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -18,6 +18,7 @@ use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym}; use crate::attributes::allow_unstable::{AllowConstFnUnstableParser, AllowInternalUnstableParser}; use crate::attributes::confusables::ConfusablesParser; use crate::attributes::deprecation::DeprecationParser; +use crate::attributes::lint_helpers::AsPtrParser; use crate::attributes::repr::ReprParser; use crate::attributes::stability::{ BodyStabilityParser, ConstStabilityIndirectParser, ConstStabilityParser, StabilityParser, @@ -102,6 +103,7 @@ attribute_parsers!( // tidy-alphabetical-end // tidy-alphabetical-start + Single, Single, Single, Single, diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index 7511a55b03ae..57db2e9fb574 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -2,7 +2,7 @@ use std::fmt; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::graph; -use rustc_index::bit_set::DenseBitSet; +use rustc_index::bit_set::{DenseBitSet, MixedBitSet}; use rustc_middle::mir::{ self, BasicBlock, Body, CallReturnPlaces, Location, Place, TerminatorEdges, }; @@ -548,7 +548,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> { } } -type BorrowsDomain = DenseBitSet; +type BorrowsDomain = MixedBitSet; /// Forward dataflow computation of the set of borrows that are in scope at a particular location. /// - we gen the introduced loans @@ -564,7 +564,7 @@ impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> { fn bottom_value(&self, _: &mir::Body<'tcx>) -> Self::Domain { // bottom = nothing is reserved or activated yet; - DenseBitSet::new_empty(self.borrow_set.len()) + MixedBitSet::new_empty(self.borrow_set.len()) } fn initialize_start_block(&self, _: &mir::Body<'tcx>, _: &mut Self::Domain) { diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index a845431facac..c4b0f503664e 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -342,6 +342,10 @@ impl<'tcx> BorrowExplanation<'tcx> { } } } else if let LocalInfo::BlockTailTemp(info) = local_decl.local_info() { + let sp = info + .span + .find_ancestor_in_same_ctxt(local_decl.source_info.span) + .unwrap_or(info.span); if info.tail_result_is_ignored { // #85581: If the first mutable borrow's scope contains // the second borrow, this suggestion isn't helpful. @@ -349,7 +353,7 @@ impl<'tcx> BorrowExplanation<'tcx> { old.to(info.span.shrink_to_hi()).contains(new) }) { err.span_suggestion_verbose( - info.span.shrink_to_hi(), + sp.shrink_to_hi(), "consider adding semicolon after the expression so its \ temporaries are dropped sooner, before the local variables \ declared by the block are dropped", @@ -368,8 +372,8 @@ impl<'tcx> BorrowExplanation<'tcx> { local variable `x` and then make `x` be the expression at the \ end of the block", vec![ - (info.span.shrink_to_lo(), "let x = ".to_string()), - (info.span.shrink_to_hi(), "; x".to_string()), + (sp.shrink_to_lo(), "let x = ".to_string()), + (sp.shrink_to_hi(), "; x".to_string()), ], Applicability::MaybeIncorrect, ); diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index e6eae7d4f5a2..4d85f1090201 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -29,7 +29,7 @@ use rustc_errors::LintDiagnostic; use rustc_hir as hir; use rustc_hir::CRATE_HIR_ID; use rustc_hir::def_id::LocalDefId; -use rustc_index::bit_set::{DenseBitSet, MixedBitSet}; +use rustc_index::bit_set::MixedBitSet; use rustc_index::{IndexSlice, IndexVec}; use rustc_infer::infer::{ InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, TyCtxtInferExt, @@ -1151,11 +1151,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { &self, location: Location, state: &'s BorrowckDomain, - ) -> Cow<'s, DenseBitSet> { + ) -> Cow<'s, MixedBitSet> { if let Some(polonius) = &self.polonius_output { // Use polonius output if it has been enabled. let location = self.location_table.start_index(location); - let mut polonius_output = DenseBitSet::new_empty(self.borrow_set.len()); + let mut polonius_output = MixedBitSet::new_empty(self.borrow_set.len()); for &idx in polonius.errors_at(location) { polonius_output.insert(idx); } diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index b439fa34f5b1..b067578794b3 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -118,10 +118,7 @@ pub(crate) fn expand_test_or_bench( let (item, is_stmt) = match item { Annotatable::Item(i) => (i, false), - Annotatable::Stmt(stmt) if matches!(stmt.kind, ast::StmtKind::Item(_)) => { - // FIXME: Use an 'if let' guard once they are implemented - if let ast::StmtKind::Item(i) = stmt.kind { (i, true) } else { unreachable!() } - } + Annotatable::Stmt(box ast::Stmt { kind: ast::StmtKind::Item(i), .. }) => (i, true), other => { not_testable_error(cx, attr_sp, None); return vec![other]; diff --git a/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs b/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs index 6d8614aca693..cd0afee0cfb2 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs @@ -1,6 +1,6 @@ //! Argument passing -use cranelift_codegen::ir::{ArgumentExtension, ArgumentPurpose}; +use cranelift_codegen::ir::ArgumentPurpose; use rustc_abi::{Reg, RegKind}; use rustc_target::callconv::{ ArgAbi, ArgAttributes, ArgExtension as RustcArgExtension, CastTarget, PassMode, @@ -32,16 +32,26 @@ fn reg_to_abi_param(reg: Reg) -> AbiParam { AbiParam::new(clif_ty) } -fn apply_arg_attrs_to_abi_param(mut param: AbiParam, arg_attrs: ArgAttributes) -> AbiParam { +fn apply_attrs_to_abi_param(param: AbiParam, arg_attrs: ArgAttributes) -> AbiParam { match arg_attrs.arg_ext { - RustcArgExtension::None => {} - RustcArgExtension::Zext => param.extension = ArgumentExtension::Uext, - RustcArgExtension::Sext => param.extension = ArgumentExtension::Sext, + RustcArgExtension::None => param, + RustcArgExtension::Zext => param.uext(), + RustcArgExtension::Sext => param.sext(), } - param } -fn cast_target_to_abi_params(cast: &CastTarget) -> SmallVec<[AbiParam; 2]> { +fn cast_target_to_abi_params(cast: &CastTarget) -> SmallVec<[(Size, AbiParam); 2]> { + if let Some(offset_from_start) = cast.rest_offset { + assert!(cast.prefix[1..].iter().all(|p| p.is_none())); + assert_eq!(cast.rest.unit.size, cast.rest.total); + let first = cast.prefix[0].unwrap(); + let second = cast.rest.unit; + return smallvec![ + (Size::ZERO, reg_to_abi_param(first)), + (offset_from_start, reg_to_abi_param(second)) + ]; + } + let (rest_count, rem_bytes) = if cast.rest.unit.size.bytes() == 0 { (0, 0) } else { @@ -56,25 +66,32 @@ fn cast_target_to_abi_params(cast: &CastTarget) -> SmallVec<[AbiParam; 2]> { // different types in Cranelift IR. Instead a single array of primitive types is used. // Create list of fields in the main structure - let mut args = cast + let args = cast .prefix .iter() .flatten() .map(|®| reg_to_abi_param(reg)) - .chain((0..rest_count).map(|_| reg_to_abi_param(cast.rest.unit))) - .collect::>(); + .chain((0..rest_count).map(|_| reg_to_abi_param(cast.rest.unit))); + + let mut res = SmallVec::new(); + let mut offset = Size::ZERO; + + for arg in args { + res.push((offset, arg)); + offset += Size::from_bytes(arg.value_type.bytes()); + } // Append final integer if rem_bytes != 0 { // Only integers can be really split further. assert_eq!(cast.rest.unit.kind, RegKind::Integer); - args.push(reg_to_abi_param(Reg { - kind: RegKind::Integer, - size: Size::from_bytes(rem_bytes), - })); + res.push(( + offset, + reg_to_abi_param(Reg { kind: RegKind::Integer, size: Size::from_bytes(rem_bytes) }), + )); } - args + res } impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> { @@ -82,7 +99,7 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> { match self.mode { PassMode::Ignore => smallvec![], PassMode::Direct(attrs) => match self.layout.backend_repr { - BackendRepr::Scalar(scalar) => smallvec![apply_arg_attrs_to_abi_param( + BackendRepr::Scalar(scalar) => smallvec![apply_attrs_to_abi_param( AbiParam::new(scalar_to_clif_type(tcx, scalar)), attrs )], @@ -97,34 +114,34 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> { let a = scalar_to_clif_type(tcx, a); let b = scalar_to_clif_type(tcx, b); smallvec![ - apply_arg_attrs_to_abi_param(AbiParam::new(a), attrs_a), - apply_arg_attrs_to_abi_param(AbiParam::new(b), attrs_b), + apply_attrs_to_abi_param(AbiParam::new(a), attrs_a), + apply_attrs_to_abi_param(AbiParam::new(b), attrs_b), ] } _ => unreachable!("{:?}", self.layout.backend_repr), }, PassMode::Cast { ref cast, pad_i32 } => { assert!(!pad_i32, "padding support not yet implemented"); - cast_target_to_abi_params(cast) + cast_target_to_abi_params(cast).into_iter().map(|(_, param)| param).collect() } PassMode::Indirect { attrs, meta_attrs: None, on_stack } => { if on_stack { // Abi requires aligning struct size to pointer size let size = self.layout.size.align_to(tcx.data_layout.pointer_align.abi); let size = u32::try_from(size.bytes()).unwrap(); - smallvec![apply_arg_attrs_to_abi_param( + smallvec![apply_attrs_to_abi_param( AbiParam::special(pointer_ty(tcx), ArgumentPurpose::StructArgument(size),), attrs )] } else { - smallvec![apply_arg_attrs_to_abi_param(AbiParam::new(pointer_ty(tcx)), attrs)] + smallvec![apply_attrs_to_abi_param(AbiParam::new(pointer_ty(tcx)), attrs)] } } PassMode::Indirect { attrs, meta_attrs: Some(meta_attrs), on_stack } => { assert!(!on_stack); smallvec![ - apply_arg_attrs_to_abi_param(AbiParam::new(pointer_ty(tcx)), attrs), - apply_arg_attrs_to_abi_param(AbiParam::new(pointer_ty(tcx)), meta_attrs), + apply_attrs_to_abi_param(AbiParam::new(pointer_ty(tcx)), attrs), + apply_attrs_to_abi_param(AbiParam::new(pointer_ty(tcx)), meta_attrs), ] } } @@ -133,30 +150,47 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> { fn get_abi_return(&self, tcx: TyCtxt<'tcx>) -> (Option, Vec) { match self.mode { PassMode::Ignore => (None, vec![]), - PassMode::Direct(_) => match self.layout.backend_repr { - BackendRepr::Scalar(scalar) => { - (None, vec![AbiParam::new(scalar_to_clif_type(tcx, scalar))]) - } + PassMode::Direct(attrs) => match self.layout.backend_repr { + BackendRepr::Scalar(scalar) => ( + None, + vec![apply_attrs_to_abi_param( + AbiParam::new(scalar_to_clif_type(tcx, scalar)), + attrs, + )], + ), BackendRepr::SimdVector { .. } => { let vector_ty = crate::intrinsics::clif_vector_type(tcx, self.layout); - (None, vec![AbiParam::new(vector_ty)]) + (None, vec![apply_attrs_to_abi_param(AbiParam::new(vector_ty), attrs)]) } _ => unreachable!("{:?}", self.layout.backend_repr), }, - PassMode::Pair(_, _) => match self.layout.backend_repr { + PassMode::Pair(attrs_a, attrs_b) => match self.layout.backend_repr { BackendRepr::ScalarPair(a, b) => { let a = scalar_to_clif_type(tcx, a); let b = scalar_to_clif_type(tcx, b); - (None, vec![AbiParam::new(a), AbiParam::new(b)]) + ( + None, + vec![ + apply_attrs_to_abi_param(AbiParam::new(a), attrs_a), + apply_attrs_to_abi_param(AbiParam::new(b), attrs_b), + ], + ) } _ => unreachable!("{:?}", self.layout.backend_repr), }, - PassMode::Cast { ref cast, .. } => { - (None, cast_target_to_abi_params(cast).into_iter().collect()) - } - PassMode::Indirect { attrs: _, meta_attrs: None, on_stack } => { + PassMode::Cast { ref cast, .. } => ( + None, + cast_target_to_abi_params(cast).into_iter().map(|(_, param)| param).collect(), + ), + PassMode::Indirect { attrs, meta_attrs: None, on_stack } => { assert!(!on_stack); - (Some(AbiParam::special(pointer_ty(tcx), ArgumentPurpose::StructReturn)), vec![]) + ( + Some(apply_attrs_to_abi_param( + AbiParam::special(pointer_ty(tcx), ArgumentPurpose::StructReturn), + attrs, + )), + vec![], + ) } PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => { unreachable!("unsized return value") @@ -172,12 +206,14 @@ pub(super) fn to_casted_value<'tcx>( ) -> SmallVec<[Value; 2]> { let (ptr, meta) = arg.force_stack(fx); assert!(meta.is_none()); - let mut offset = 0; cast_target_to_abi_params(cast) .into_iter() - .map(|param| { - let val = ptr.offset_i64(fx, offset).load(fx, param.value_type, MemFlags::new()); - offset += i64::from(param.value_type.bytes()); + .map(|(offset, param)| { + let val = ptr.offset_i64(fx, offset.bytes() as i64).load( + fx, + param.value_type, + MemFlags::new(), + ); val }) .collect() @@ -190,7 +226,7 @@ pub(super) fn from_casted_value<'tcx>( cast: &CastTarget, ) -> CValue<'tcx> { let abi_params = cast_target_to_abi_params(cast); - let abi_param_size: u32 = abi_params.iter().map(|param| param.value_type.bytes()).sum(); + let abi_param_size: u32 = abi_params.iter().map(|(_, param)| param.value_type.bytes()).sum(); let layout_size = u32::try_from(layout.size.bytes()).unwrap(); let ptr = fx.create_stack_slot( // Stack slot size may be bigger for example `[u8; 3]` which is packed into an `i32`. @@ -199,16 +235,13 @@ pub(super) fn from_casted_value<'tcx>( std::cmp::max(abi_param_size, layout_size), u32::try_from(layout.align.abi.bytes()).unwrap(), ); - let mut offset = 0; let mut block_params_iter = block_params.iter().copied(); - for param in abi_params { - let val = ptr.offset_i64(fx, offset).store( + for (offset, _) in abi_params { + ptr.offset_i64(fx, offset.bytes() as i64).store( fx, block_params_iter.next().unwrap(), MemFlags::new(), - ); - offset += i64::from(param.value_type.bytes()); - val + ) } assert_eq!(block_params_iter.next(), None, "Leftover block param"); CValue::by_ref(ptr, layout) diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index 5d07c94859f3..442151fe32de 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -11,7 +11,6 @@ use std::thread::JoinHandle; use cranelift_object::{ObjectBuilder, ObjectModule}; use rustc_codegen_ssa::assert_module_sources::CguReuse; use rustc_codegen_ssa::back::link::ensure_removed; -use rustc_codegen_ssa::back::metadata::create_compressed_metadata_file; use rustc_codegen_ssa::base::determine_cgu_reuse; use rustc_codegen_ssa::{ CodegenResults, CompiledModule, CrateInfo, ModuleKind, errors as ssa_errors, @@ -19,7 +18,6 @@ use rustc_codegen_ssa::{ use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{IntoDynSyncSend, par_map}; -use rustc_metadata::EncodedMetadata; use rustc_metadata::fs::copy_to_stdout; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; @@ -61,8 +59,6 @@ impl HashStable for OngoingModuleCodegen { pub(crate) struct OngoingCodegen { modules: Vec, allocator_module: Option, - metadata_module: Option, - metadata: EncodedMetadata, crate_info: CrateInfo, concurrency_limiter: ConcurrencyLimiter, } @@ -134,8 +130,6 @@ impl OngoingCodegen { let codegen_results = CodegenResults { modules, allocator_module: self.allocator_module, - metadata_module: self.metadata_module, - metadata: self.metadata, crate_info: self.crate_info, }; @@ -646,42 +640,6 @@ fn module_codegen( })) } -fn emit_metadata_module(tcx: TyCtxt<'_>, metadata: &EncodedMetadata) -> CompiledModule { - use rustc_middle::mir::mono::CodegenUnitNameBuilder; - - let _timer = tcx.sess.timer("write compressed metadata"); - - let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx); - let metadata_cgu_name = cgu_name_builder - .build_cgu_name(LOCAL_CRATE, ["crate"], Some("metadata")) - .as_str() - .to_string(); - - let tmp_file = tcx.output_filenames(()).temp_path_for_cgu( - OutputType::Metadata, - &metadata_cgu_name, - tcx.sess.invocation_temp.as_deref(), - ); - - let symbol_name = rustc_middle::middle::exported_symbols::metadata_symbol_name(tcx); - let obj = create_compressed_metadata_file(tcx.sess, metadata, &symbol_name); - - if let Err(err) = std::fs::write(&tmp_file, obj) { - tcx.dcx().fatal(format!("error writing metadata object file: {}", err)); - } - - CompiledModule { - name: metadata_cgu_name, - kind: ModuleKind::Metadata, - object: Some(tmp_file), - dwarf_object: None, - bytecode: None, - assembly: None, - llvm_ir: None, - links_from_incr_cache: Vec::new(), - } -} - fn emit_allocator_module(tcx: TyCtxt<'_>) -> Option { let mut allocator_module = make_module(tcx.sess, "allocator_shim".to_string()); let created_alloc_shim = crate::allocator::codegen(tcx, &mut allocator_module); @@ -706,11 +664,7 @@ fn emit_allocator_module(tcx: TyCtxt<'_>) -> Option { } } -pub(crate) fn run_aot( - tcx: TyCtxt<'_>, - metadata: EncodedMetadata, - need_metadata_module: bool, -) -> Box { +pub(crate) fn run_aot(tcx: TyCtxt<'_>) -> Box { // FIXME handle `-Ctarget-cpu=native` let target_cpu = match tcx.sess.opts.cg.target_cpu { Some(ref name) => name, @@ -726,8 +680,6 @@ pub(crate) fn run_aot( return Box::new(OngoingCodegen { modules: vec![], allocator_module: None, - metadata_module: None, - metadata, crate_info: CrateInfo::new(tcx, target_cpu), concurrency_limiter: ConcurrencyLimiter::new(0), }); @@ -787,14 +739,9 @@ pub(crate) fn run_aot( let allocator_module = emit_allocator_module(tcx); - let metadata_module = - if need_metadata_module { Some(emit_metadata_module(tcx, &metadata)) } else { None }; - Box::new(OngoingCodegen { modules, allocator_module, - metadata_module, - metadata, crate_info: CrateInfo::new(tcx, target_cpu), concurrency_limiter: concurrency_limiter.0, }) diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 8ef623cde005..07ea29f3024e 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -46,7 +46,6 @@ use cranelift_codegen::isa::TargetIsa; use cranelift_codegen::settings::{self, Configurable}; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::{CodegenResults, TargetConfig}; -use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_session::Session; use rustc_session::config::OutputFilenames; @@ -238,12 +237,7 @@ impl CodegenBackend for CraneliftCodegenBackend { println!("Cranelift version: {}", cranelift_codegen::VERSION); } - fn codegen_crate( - &self, - tcx: TyCtxt<'_>, - metadata: EncodedMetadata, - need_metadata_module: bool, - ) -> Box { + fn codegen_crate(&self, tcx: TyCtxt<'_>) -> Box { info!("codegen crate {}", tcx.crate_name(LOCAL_CRATE)); let config = self.config.clone().unwrap_or_else(|| { BackendConfig::from_opts(&tcx.sess.opts.cg.llvm_args) @@ -256,7 +250,7 @@ impl CodegenBackend for CraneliftCodegenBackend { #[cfg(not(feature = "jit"))] tcx.dcx().fatal("jit support was disabled when compiling rustc_codegen_cranelift"); } else { - driver::aot::run_aot(tcx, metadata, need_metadata_module) + driver::aot::run_aot(tcx) } } diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index 1bd892121008..68c6156fa4b1 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -30,7 +30,7 @@ use rustc_middle::ty::{self, AtomicOrdering, Instance, Ty, TyCtxt}; use rustc_span::Span; use rustc_span::def_id::DefId; use rustc_target::callconv::FnAbi; -use rustc_target::spec::{HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, Target, WasmCAbi, X86Abi}; +use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, X86Abi}; use crate::common::{SignType, TypeReflection, type_is_pointer}; use crate::context::CodegenCx; @@ -2394,12 +2394,6 @@ impl<'tcx> HasTargetSpec for Builder<'_, '_, 'tcx> { } } -impl<'tcx> HasWasmCAbiOpt for Builder<'_, '_, 'tcx> { - fn wasm_c_abi_opt(&self) -> WasmCAbi { - self.cx.wasm_c_abi_opt() - } -} - impl<'tcx> HasX86AbiOpt for Builder<'_, '_, 'tcx> { fn x86_abi_opt(&self) -> X86Abi { self.cx.x86_abi_opt() diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs index c6c43201f216..4955e039e7b7 100644 --- a/compiler/rustc_codegen_gcc/src/context.rs +++ b/compiler/rustc_codegen_gcc/src/context.rs @@ -19,9 +19,7 @@ use rustc_middle::ty::{self, ExistentialTraitRef, Instance, Ty, TyCtxt}; use rustc_session::Session; use rustc_span::source_map::respan; use rustc_span::{DUMMY_SP, Span}; -use rustc_target::spec::{ - HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, Target, TlsModel, WasmCAbi, X86Abi, -}; +use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, TlsModel, X86Abi}; #[cfg(feature = "master")] use crate::abi::conv_to_fn_attribute; @@ -512,12 +510,6 @@ impl<'gcc, 'tcx> HasTargetSpec for CodegenCx<'gcc, 'tcx> { } } -impl<'gcc, 'tcx> HasWasmCAbiOpt for CodegenCx<'gcc, 'tcx> { - fn wasm_c_abi_opt(&self) -> WasmCAbi { - self.tcx.sess.opts.unstable_opts.wasm_c_abi - } -} - impl<'gcc, 'tcx> HasX86AbiOpt for CodegenCx<'gcc, 'tcx> { fn x86_abi_opt(&self) -> X86Abi { X86Abi { diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index 9e05b8f23aad..c921851b42b9 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -626,7 +626,7 @@ impl<'gcc, 'tcx> ArgAbiExt<'gcc, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> { bx.lifetime_start(llscratch, scratch_size); // ... where we first store the value... - bx.store(val, llscratch, scratch_align); + rustc_codegen_ssa::mir::store_cast(bx, cast, val, llscratch, scratch_align); // ... and then memcpy it to the intended destination. bx.memcpy( diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index 0591ffa42e4a..dbecbc426182 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -48,7 +48,6 @@ extern crate rustc_index; #[cfg(feature = "master")] extern crate rustc_interface; extern crate rustc_macros; -extern crate rustc_metadata; extern crate rustc_middle; extern crate rustc_session; extern crate rustc_span; @@ -106,7 +105,6 @@ use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen, TargetCon use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sync::IntoDynSyncSend; use rustc_errors::DiagCtxtHandle; -use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::ty::TyCtxt; use rustc_middle::util::Providers; @@ -230,20 +228,9 @@ impl CodegenBackend for GccCodegenBackend { providers.global_backend_features = |tcx, ()| gcc_util::global_gcc_features(tcx.sess, true) } - fn codegen_crate( - &self, - tcx: TyCtxt<'_>, - metadata: EncodedMetadata, - need_metadata_module: bool, - ) -> Box { + fn codegen_crate(&self, tcx: TyCtxt<'_>) -> Box { let target_cpu = target_cpu(tcx.sess); - let res = codegen_crate( - self.clone(), - tcx, - target_cpu.to_string(), - metadata, - need_metadata_module, - ); + let res = codegen_crate(self.clone(), tcx, target_cpu.to_string()); Box::new(res) } diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index aba63d75f1df..4b07c8aef915 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -229,7 +229,7 @@ impl<'ll, 'tcx> ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> { let llscratch = bx.alloca(scratch_size, scratch_align); bx.lifetime_start(llscratch, scratch_size); // ...store the value... - bx.store(val, llscratch, scratch_align); + rustc_codegen_ssa::mir::store_cast(bx, cast, val, llscratch, scratch_align); // ... and then memcpy it to the intended destination. bx.memcpy( dst.val.llval, diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 4185aef8b31c..9ddadcf16aa3 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -1021,6 +1021,15 @@ fn llvm_fixup_input<'ll, 'tcx>( ) if element.primitive() == Primitive::Float(Float::F16) => { bx.bitcast(value, bx.type_vector(bx.type_i16(), count)) } + (LoongArch(LoongArchInlineAsmRegClass::freg), BackendRepr::Scalar(s)) + if s.primitive() == Primitive::Float(Float::F16) => + { + // Smaller floats are always "NaN-boxed" inside larger floats on LoongArch. + let value = bx.bitcast(value, bx.type_i16()); + let value = bx.zext(value, bx.type_i32()); + let value = bx.or(value, bx.const_u32(0xFFFF_0000)); + bx.bitcast(value, bx.type_f32()) + } (Mips(MipsInlineAsmRegClass::reg), BackendRepr::Scalar(s)) => { match s.primitive() { // MIPS only supports register-length arithmetics. @@ -1178,6 +1187,13 @@ fn llvm_fixup_output<'ll, 'tcx>( ) if element.primitive() == Primitive::Float(Float::F16) => { bx.bitcast(value, bx.type_vector(bx.type_f16(), count)) } + (LoongArch(LoongArchInlineAsmRegClass::freg), BackendRepr::Scalar(s)) + if s.primitive() == Primitive::Float(Float::F16) => + { + let value = bx.bitcast(value, bx.type_i32()); + let value = bx.trunc(value, bx.type_i16()); + bx.bitcast(value, bx.type_f16()) + } (Mips(MipsInlineAsmRegClass::reg), BackendRepr::Scalar(s)) => { match s.primitive() { // MIPS only supports register-length arithmetics. @@ -1318,6 +1334,11 @@ fn llvm_fixup_output_type<'ll, 'tcx>( ) if element.primitive() == Primitive::Float(Float::F16) => { cx.type_vector(cx.type_i16(), count) } + (LoongArch(LoongArchInlineAsmRegClass::freg), BackendRepr::Scalar(s)) + if s.primitive() == Primitive::Float(Float::F16) => + { + cx.type_f32() + } (Mips(MipsInlineAsmRegClass::reg), BackendRepr::Scalar(s)) => { match s.primitive() { // MIPS only supports register-length arithmetics. diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 09cb74d9dcb0..5e9594dd06bb 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -507,7 +507,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { let name = format!("llvm.{}{oop_str}.with.overflow", if signed { 's' } else { 'u' }); - let res = self.call_intrinsic(&name, &[self.type_ix(width)], &[lhs, rhs]); + let res = self.call_intrinsic(name, &[self.type_ix(width)], &[lhs, rhs]); (self.extract_value(res, 0), self.extract_value(res, 1)) } @@ -1038,7 +1038,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { let size = ty.primitive_size(self.tcx); let name = if ty.is_signed() { "llvm.scmp" } else { "llvm.ucmp" }; - Some(self.call_intrinsic(&name, &[self.type_i8(), self.type_ix(size.bits())], &[lhs, rhs])) + Some(self.call_intrinsic(name, &[self.type_i8(), self.type_ix(size.bits())], &[lhs, rhs])) } /* Miscellaneous instructions */ @@ -1393,7 +1393,8 @@ impl<'ll> StaticBuilderMethods for Builder<'_, 'll, '_> { // Forward to the `get_static` method of `CodegenCx` let global = self.cx().get_static(def_id); if self.cx().tcx.is_thread_local_static(def_id) { - let pointer = self.call_intrinsic("llvm.threadlocal.address", &[], &[global]); + let pointer = + self.call_intrinsic("llvm.threadlocal.address", &[self.val_ty(global)], &[global]); // Cast to default address space if globals are in a different addrspace self.pointercast(pointer, self.type_ptr()) } else { @@ -1590,15 +1591,15 @@ impl<'a, 'll, CX: Borrow>> GenericBuilder<'a, 'll, CX> { impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { pub(crate) fn call_intrinsic( &mut self, - base_name: &str, + base_name: impl Into>, type_params: &[&'ll Type], args: &[&'ll Value], ) -> &'ll Value { - let (ty, f) = self.cx.get_intrinsic(base_name, type_params); + let (ty, f) = self.cx.get_intrinsic(base_name.into(), type_params); self.call(ty, None, None, f, args, None, None) } - fn call_lifetime_intrinsic(&mut self, intrinsic: &str, ptr: &'ll Value, size: Size) { + fn call_lifetime_intrinsic(&mut self, intrinsic: &'static str, ptr: &'ll Value, size: Size) { let size = size.bytes(); if size == 0 { return; @@ -1608,7 +1609,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { return; } - self.call_intrinsic(intrinsic, &[self.type_ptr()], &[self.cx.const_u64(size), ptr]); + self.call_intrinsic(intrinsic, &[self.val_ty(ptr)], &[self.cx.const_u64(size), ptr]); } } impl<'a, 'll, CX: Borrow>> GenericBuilder<'a, 'll, CX> { diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index f36f3b2b16b8..bff95ea46fa7 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -1,4 +1,4 @@ -use std::borrow::Borrow; +use std::borrow::{Borrow, Cow}; use std::cell::{Cell, RefCell}; use std::ffi::{CStr, c_char, c_uint}; use std::marker::PhantomData; @@ -138,7 +138,7 @@ pub(crate) struct FullCx<'ll, 'tcx> { pub rust_try_fn: Cell>, intrinsics: - RefCell), (&'ll Type, &'ll Value)>>, + RefCell, SmallVec<[&'ll Type; 2]>), (&'ll Type, &'ll Value)>>, /// A counter that is used for generating local symbol names local_gen_sym_counter: Cell, @@ -845,45 +845,16 @@ impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { impl<'ll> CodegenCx<'ll, '_> { pub(crate) fn get_intrinsic( &self, - base_name: &str, + base_name: Cow<'static, str>, type_params: &[&'ll Type], ) -> (&'ll Type, &'ll Value) { - if let Some(v) = - self.intrinsics.borrow().get(&(base_name, SmallVec::from_slice(type_params))) - { - return *v; - } - - self.declare_intrinsic(base_name, type_params) - } - - fn insert_intrinsic( - &self, - base_name: &'static str, - type_params: &[&'ll Type], - args: Option<&[&'ll llvm::Type]>, - ret: &'ll llvm::Type, - ) -> (&'ll llvm::Type, &'ll llvm::Value) { - let fn_ty = if let Some(args) = args { - self.type_func(args, ret) - } else { - self.type_variadic_func(&[], ret) - }; - - let intrinsic = llvm::Intrinsic::lookup(base_name.as_bytes()) - .expect("Unknown LLVM intrinsic `{base_name}`"); - - let full_name = if intrinsic.is_overloaded() { - &intrinsic.overloaded_name(self.llmod, type_params) - } else { - base_name - }; - - let f = self.declare_cfn(full_name, llvm::UnnamedAddr::No, fn_ty); - self.intrinsics + *self + .intrinsics .borrow_mut() - .insert((base_name, SmallVec::from_slice(type_params)), (fn_ty, f)); - (fn_ty, f) + .entry((base_name, SmallVec::from_slice(type_params))) + .or_insert_with_key(|(base_name, type_params)| { + self.declare_intrinsic(base_name, type_params) + }) } fn declare_intrinsic( @@ -891,155 +862,22 @@ impl<'ll> CodegenCx<'ll, '_> { base_name: &str, type_params: &[&'ll Type], ) -> (&'ll Type, &'ll Value) { - macro_rules! param { - ($index:literal) => { - type_params[$index] - }; - ($other:expr) => { - $other - }; - } - macro_rules! ifn { - ($name:expr, fn(...) -> $ret:expr) => ( - if base_name == $name { - return self.insert_intrinsic($name, type_params, None, param!($ret)); - } - ); - ($name:expr, fn($($arg:expr),*) -> $ret:expr) => ( - if base_name == $name { - return self.insert_intrinsic($name, type_params, Some(&[$(param!($arg)),*]), param!($ret)); - } - ); - } - macro_rules! mk_struct { - ($($field_ty:expr),*) => (self.type_struct( &[$(param!($field_ty)),*], false)) - } - - let same_width_vector = |index, element_ty| { - self.type_vector(element_ty, self.vector_length(type_params[index]) as u64) - }; - - let ptr = self.type_ptr(); - let void = self.type_void(); - let i1 = self.type_i1(); - let t_i32 = self.type_i32(); - let t_i64 = self.type_i64(); - let t_isize = self.type_isize(); - let t_metadata = self.type_metadata(); - let t_token = self.type_token(); - - ifn!("llvm.wasm.get.exception", fn(t_token) -> ptr); - ifn!("llvm.wasm.get.ehselector", fn(t_token) -> t_i32); - - ifn!("llvm.wasm.trunc.unsigned", fn(1) -> 0); - ifn!("llvm.wasm.trunc.signed", fn(1) -> 0); - ifn!("llvm.fptosi.sat", fn(1) -> 0); - ifn!("llvm.fptoui.sat", fn(1) -> 0); - - ifn!("llvm.trap", fn() -> void); - ifn!("llvm.debugtrap", fn() -> void); - ifn!("llvm.frameaddress", fn(t_i32) -> ptr); - - ifn!("llvm.powi", fn(0, 1) -> 0); - ifn!("llvm.pow", fn(0, 0) -> 0); - ifn!("llvm.sqrt", fn(0) -> 0); - ifn!("llvm.sin", fn(0) -> 0); - ifn!("llvm.cos", fn(0) -> 0); - ifn!("llvm.exp", fn(0) -> 0); - ifn!("llvm.exp2", fn(0) -> 0); - ifn!("llvm.log", fn(0) -> 0); - ifn!("llvm.log10", fn(0) -> 0); - ifn!("llvm.log2", fn(0) -> 0); - ifn!("llvm.fma", fn(0, 0, 0) -> 0); - ifn!("llvm.fmuladd", fn(0, 0, 0) -> 0); - ifn!("llvm.fabs", fn(0) -> 0); - ifn!("llvm.minnum", fn(0, 0) -> 0); - ifn!("llvm.minimum", fn(0, 0) -> 0); - ifn!("llvm.maxnum", fn(0, 0) -> 0); - ifn!("llvm.maximum", fn(0, 0) -> 0); - ifn!("llvm.floor", fn(0) -> 0); - ifn!("llvm.ceil", fn(0) -> 0); - ifn!("llvm.trunc", fn(0) -> 0); - ifn!("llvm.copysign", fn(0, 0) -> 0); - ifn!("llvm.round", fn(0) -> 0); - ifn!("llvm.rint", fn(0) -> 0); - ifn!("llvm.nearbyint", fn(0) -> 0); - - ifn!("llvm.ctpop", fn(0) -> 0); - ifn!("llvm.ctlz", fn(0, i1) -> 0); - ifn!("llvm.cttz", fn(0, i1) -> 0); - ifn!("llvm.bswap", fn(0) -> 0); - ifn!("llvm.bitreverse", fn(0) -> 0); - ifn!("llvm.fshl", fn(0, 0, 0) -> 0); - ifn!("llvm.fshr", fn(0, 0, 0) -> 0); - - ifn!("llvm.sadd.with.overflow", fn(0, 0) -> mk_struct! {0, i1}); - ifn!("llvm.uadd.with.overflow", fn(0, 0) -> mk_struct! {0, i1}); - ifn!("llvm.ssub.with.overflow", fn(0, 0) -> mk_struct! {0, i1}); - ifn!("llvm.usub.with.overflow", fn(0, 0) -> mk_struct! {0, i1}); - ifn!("llvm.smul.with.overflow", fn(0, 0) -> mk_struct! {0, i1}); - ifn!("llvm.umul.with.overflow", fn(0, 0) -> mk_struct! {0, i1}); - - ifn!("llvm.sadd.sat", fn(0, 0) -> 0); - ifn!("llvm.uadd.sat", fn(0, 0) -> 0); - ifn!("llvm.ssub.sat", fn(0, 0) -> 0); - ifn!("llvm.usub.sat", fn(0, 0) -> 0); - - ifn!("llvm.scmp", fn(1, 1) -> 0); - ifn!("llvm.ucmp", fn(1, 1) -> 0); - - ifn!("llvm.lifetime.start", fn(t_i64, 0) -> void); - ifn!("llvm.lifetime.end", fn(t_i64, 0) -> void); - - ifn!("llvm.is.constant", fn(0) -> i1); - ifn!("llvm.expect", fn(0, 0) -> 0); - - ifn!("llvm.eh.typeid.for", fn(0) -> t_i32); - ifn!("llvm.localescape", fn(...) -> void); - ifn!("llvm.localrecover", fn(ptr, ptr, t_i32) -> ptr); - - ifn!("llvm.assume", fn(i1) -> void); - ifn!("llvm.prefetch", fn(0, t_i32, t_i32, t_i32) -> void); - // This isn't an "LLVM intrinsic", but LLVM's optimization passes // recognize it like one (including turning it into `bcmp` sometimes) // and we use it to implement intrinsics like `raw_eq` and `compare_bytes` if base_name == "memcmp" { - let fn_ty = self.type_func(&[ptr, ptr, t_isize], self.type_int()); + let fn_ty = self + .type_func(&[self.type_ptr(), self.type_ptr(), self.type_isize()], self.type_int()); let f = self.declare_cfn("memcmp", llvm::UnnamedAddr::No, fn_ty); - self.intrinsics.borrow_mut().insert(("memcmp", SmallVec::new()), (fn_ty, f)); return (fn_ty, f); } - // variadic intrinsics - ifn!("llvm.va_start", fn(0) -> void); - ifn!("llvm.va_end", fn(0) -> void); - ifn!("llvm.va_copy", fn(0, 0) -> void); + let intrinsic = llvm::Intrinsic::lookup(base_name.as_bytes()) + .unwrap_or_else(|| bug!("Unknown intrinsic: `{base_name}`")); + let f = intrinsic.get_declaration(self.llmod, &type_params); - if self.sess().instrument_coverage() { - ifn!("llvm.instrprof.increment", fn(ptr, t_i64, t_i32, t_i32) -> void); - ifn!("llvm.instrprof.mcdc.parameters", fn(ptr, t_i64, t_i32) -> void); - ifn!("llvm.instrprof.mcdc.tvbitmap.update", fn(ptr, t_i64, t_i32, ptr) -> void); - } - - ifn!("llvm.type.test", fn(ptr, t_metadata) -> i1); - ifn!("llvm.type.checked.load", fn(ptr, t_i32, t_metadata) -> mk_struct! {ptr, i1}); - - if self.sess().opts.debuginfo != DebugInfo::None { - ifn!("llvm.dbg.declare", fn(t_metadata, t_metadata, t_metadata) -> void); - ifn!("llvm.dbg.value", fn(t_metadata, t_metadata, t_metadata) -> void); - } - - ifn!("llvm.ptrmask", fn(0, 1) -> 0); - ifn!("llvm.threadlocal.address", fn(ptr) -> ptr); - - ifn!("llvm.masked.load", fn(1, t_i32, same_width_vector(0, i1), 0) -> 0); - ifn!("llvm.masked.store", fn(0, 1, t_i32, same_width_vector(0, i1)) -> void); - ifn!("llvm.masked.gather", fn(1, t_i32, same_width_vector(0, i1), 0) -> 0); - ifn!("llvm.masked.scatter", fn(0, 1, t_i32, same_width_vector(0, i1)) -> void); - - bug!("Unknown intrinsic: `{base_name}`") + (self.get_type_of_global(f), f) } pub(crate) fn eh_catch_typeinfo(&self) -> &'ll Value { diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 497c31706ec8..f7f062849a8b 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -154,8 +154,6 @@ fn call_simple_intrinsic<'ll, 'tcx>( sym::roundf64 => ("llvm.round", &[bx.type_f64()]), sym::roundf128 => ("llvm.round", &[bx.type_f128()]), - sym::ptr_mask => ("llvm.ptrmask", &[bx.type_ptr(), bx.type_isize()]), - _ => return None, }; Some(bx.call_intrinsic( @@ -181,6 +179,14 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { let simple = call_simple_intrinsic(self, name, args); let llval = match name { _ if simple.is_some() => simple.unwrap(), + sym::ptr_mask => { + let ptr = args[0].immediate(); + self.call_intrinsic( + "llvm.ptrmask", + &[self.val_ty(ptr), self.type_isize()], + &[ptr, args[1].immediate()], + ) + } sym::is_val_statically_known => { if let OperandValue::Immediate(imm) = args[0].val { self.call_intrinsic( @@ -232,11 +238,14 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { return Ok(()); } sym::breakpoint => self.call_intrinsic("llvm.debugtrap", &[], &[]), - sym::va_copy => self.call_intrinsic( - "llvm.va_copy", - &[self.type_ptr()], - &[args[0].immediate(), args[1].immediate()], - ), + sym::va_copy => { + let dest = args[0].immediate(); + self.call_intrinsic( + "llvm.va_copy", + &[self.val_ty(dest)], + &[dest, args[1].immediate()], + ) + } sym::va_arg => { match result.layout.backend_repr { BackendRepr::Scalar(scalar) => { @@ -309,15 +318,11 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { sym::prefetch_write_instruction => (1, 0), _ => bug!(), }; + let ptr = args[0].immediate(); self.call_intrinsic( "llvm.prefetch", - &[self.type_ptr()], - &[ - args[0].immediate(), - self.const_i32(rw), - args[1].immediate(), - self.const_i32(cache_type), - ], + &[self.val_ty(ptr)], + &[ptr, self.const_i32(rw), args[1].immediate(), self.const_i32(cache_type)], ) } sym::carrying_mul_add => { @@ -378,7 +383,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { sym::ctlz | sym::cttz => { let y = self.const_bool(false); let ret = self.call_intrinsic( - &format!("llvm.{name}"), + format!("llvm.{name}"), &[llty], &[args[0].immediate(), y], ); @@ -423,7 +428,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { // always uses `u32`. let raw_shift = self.intcast(raw_shift, self.val_ty(val), false); - self.call_intrinsic(&llvm_name, &[llty], &[val, val, raw_shift]) + self.call_intrinsic(llvm_name, &[llty], &[val, val, raw_shift]) } sym::saturating_add | sym::saturating_sub => { let is_add = name == sym::saturating_add; @@ -434,7 +439,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { if signed { 's' } else { 'u' }, if is_add { "add" } else { "sub" }, ); - self.call_intrinsic(&llvm_name, &[llty], &[lhs, rhs]) + self.call_intrinsic(llvm_name, &[llty], &[lhs, rhs]) } _ => bug!(), } @@ -637,11 +642,11 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { } fn va_start(&mut self, va_list: &'ll Value) -> &'ll Value { - self.call_intrinsic("llvm.va_start", &[self.type_ptr()], &[va_list]) + self.call_intrinsic("llvm.va_start", &[self.val_ty(va_list)], &[va_list]) } fn va_end(&mut self, va_list: &'ll Value) -> &'ll Value { - self.call_intrinsic("llvm.va_end", &[self.type_ptr()], &[va_list]) + self.call_intrinsic("llvm.va_end", &[self.val_ty(va_list)], &[va_list]) } } @@ -1018,7 +1023,7 @@ fn codegen_emcc_try<'ll, 'tcx>( let selector = bx.extract_value(vals, 1); // Check if the typeid we got is the one for a Rust panic. - let rust_typeid = bx.call_intrinsic("llvm.eh.typeid.for", &[bx.type_ptr()], &[tydesc]); + let rust_typeid = bx.call_intrinsic("llvm.eh.typeid.for", &[bx.val_ty(tydesc)], &[tydesc]); let is_rust_panic = bx.icmp(IntPredicate::IntEQ, selector, rust_typeid); let is_rust_panic = bx.zext(is_rust_panic, bx.type_bool()); @@ -2393,7 +2398,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( ); let vec_ty = bx.cx.type_vector(elem_ty, in_len as u64); - return Ok(bx.call_intrinsic(&llvm_intrinsic, &[vec_ty], &[lhs, rhs])); + return Ok(bx.call_intrinsic(llvm_intrinsic, &[vec_ty], &[lhs, rhs])); } span_bug!(span, "unknown SIMD intrinsic"); diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 6890923a5946..cdfffbe47bfa 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -340,18 +340,11 @@ impl CodegenBackend for LlvmCodegenBackend { target_config(sess) } - fn codegen_crate<'tcx>( - &self, - tcx: TyCtxt<'tcx>, - metadata: EncodedMetadata, - need_metadata_module: bool, - ) -> Box { + fn codegen_crate<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Box { Box::new(rustc_codegen_ssa::base::codegen_crate( LlvmCodegenBackend(()), tcx, crate::llvm_util::target_cpu(tcx.sess).to_string(), - metadata, - need_metadata_module, )) } @@ -376,14 +369,20 @@ impl CodegenBackend for LlvmCodegenBackend { (codegen_results, work_products) } - fn link(&self, sess: &Session, codegen_results: CodegenResults, outputs: &OutputFilenames) { + fn link( + &self, + sess: &Session, + codegen_results: CodegenResults, + metadata: EncodedMetadata, + outputs: &OutputFilenames, + ) { use rustc_codegen_ssa::back::link::link_binary; use crate::back::archive::LlvmArchiveBuilderBuilder; // Run the linker on any artifacts that resulted from the LLVM run. // This should produce either a finished executable or library. - link_binary(sess, &LlvmArchiveBuilderBuilder, codegen_results, outputs); + link_binary(sess, &LlvmArchiveBuilderBuilder, codegen_results, metadata, outputs); } } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 59c61db5fcdc..91ada856d597 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1078,8 +1078,6 @@ unsafe extern "C" { // Operations on other types pub(crate) fn LLVMVoidTypeInContext(C: &Context) -> &Type; - pub(crate) fn LLVMTokenTypeInContext(C: &Context) -> &Type; - pub(crate) fn LLVMMetadataTypeInContext(C: &Context) -> &Type; // Operations on all values pub(crate) fn LLVMTypeOf(Val: &Value) -> &Type; @@ -1198,14 +1196,12 @@ unsafe extern "C" { // Operations about llvm intrinsics pub(crate) fn LLVMLookupIntrinsicID(Name: *const c_char, NameLen: size_t) -> c_uint; - pub(crate) fn LLVMIntrinsicIsOverloaded(ID: NonZero) -> Bool; - pub(crate) fn LLVMIntrinsicCopyOverloadedName2<'a>( + pub(crate) fn LLVMGetIntrinsicDeclaration<'a>( Mod: &'a Module, ID: NonZero, ParamTypes: *const &'a Type, ParamCount: size_t, - NameLength: *mut size_t, - ) -> *mut c_char; + ) -> &'a Value; // Operations on parameters pub(crate) fn LLVMIsAArgument(Val: &Value) -> Option<&Value>; diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index bc3538c768de..661174a80dfb 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -2,9 +2,9 @@ use std::ffi::{CStr, CString}; use std::num::NonZero; +use std::ptr; use std::str::FromStr; use std::string::FromUtf8Error; -use std::{ptr, slice}; use libc::c_uint; use rustc_abi::{Align, Size, WrappingRange}; @@ -339,34 +339,14 @@ impl Intrinsic { NonZero::new(id).map(|id| Self { id }) } - pub(crate) fn is_overloaded(self) -> bool { - unsafe { LLVMIntrinsicIsOverloaded(self.id) == True } - } - - pub(crate) fn overloaded_name<'ll>( + pub(crate) fn get_declaration<'ll>( self, llmod: &'ll Module, type_params: &[&'ll Type], - ) -> String { - let mut len = 0; - let ptr = unsafe { - LLVMIntrinsicCopyOverloadedName2( - llmod, - self.id, - type_params.as_ptr(), - type_params.len(), - &mut len, - ) - }; - - let slice = unsafe { slice::from_raw_parts_mut(ptr.cast(), len) }; - let copied = str::from_utf8(slice).expect("Non-UTF8 intrinsic name").to_string(); - + ) -> &'ll Value { unsafe { - libc::free(ptr.cast()); + LLVMGetIntrinsicDeclaration(llmod, self.id, type_params.as_ptr(), type_params.len()) } - - copied } } diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs index 2364ad0c9d23..453eca2bbe17 100644 --- a/compiler/rustc_codegen_llvm/src/type_.rs +++ b/compiler/rustc_codegen_llvm/src/type_.rs @@ -58,13 +58,6 @@ impl<'ll, CX: Borrow>> GenericCx<'ll, CX> { pub(crate) fn type_void(&self) -> &'ll Type { unsafe { llvm::LLVMVoidTypeInContext(self.llcx()) } } - pub(crate) fn type_token(&self) -> &'ll Type { - unsafe { llvm::LLVMTokenTypeInContext(self.llcx()) } - } - - pub(crate) fn type_metadata(&self) -> &'ll Type { - unsafe { llvm::LLVMMetadataTypeInContext(self.llcx()) } - } ///x Creates an integer type with the given number of bits, e.g., i24 pub(crate) fn type_ix(&self, num_bits: u64) -> &'ll Type { diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index 91f6af7fb939..5322fe58cf33 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -198,8 +198,6 @@ codegen_ssa_linking_failed = linking with `{$linker_path}` failed: {$exit_status codegen_ssa_malformed_cgu_name = found malformed codegen unit name `{$user_path}`. codegen units names must always start with the name of the crate (`{$crate_name}` in this case). -codegen_ssa_metadata_object_file_write = error writing metadata object file: {$error} - codegen_ssa_missing_cpp_build_tool_component = or a necessary component may be missing from the "C++ build tools" workload codegen_ssa_missing_features = add the missing features in a `target_feature` attribute diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index 1e1bdfb5977a..84a56f6b0b55 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -14,11 +14,12 @@ use object::read::macho::FatArch; use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::memmap::Mmap; use rustc_fs_util::TempDirBuilder; +use rustc_metadata::EncodedMetadata; use rustc_session::Session; use rustc_span::Symbol; use tracing::trace; -use super::metadata::search_for_section; +use super::metadata::{create_compressed_metadata_file, search_for_section}; use crate::common; // Re-exporting for rustc_codegen_llvm::back::archive pub use crate::errors::{ArchiveBuildFailure, ExtractBundledLibsError, UnknownArchiveKind}; @@ -58,6 +59,15 @@ impl From for COFFShortExport { pub trait ArchiveBuilderBuilder { fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box; + fn create_dylib_metadata_wrapper( + &self, + sess: &Session, + metadata: &EncodedMetadata, + symbol_name: &str, + ) -> Vec { + create_compressed_metadata_file(sess, metadata, symbol_name) + } + /// Creates a DLL Import Library . /// and returns the path on disk to that import library. /// This functions doesn't take `self` so that it can be called from diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 18b76b337576..8c52ed6ed123 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -23,7 +23,8 @@ use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_macros::LintDiagnostic; use rustc_metadata::fs::{METADATA_FILENAME, copy_to_stdout, emit_wrapper_file}; use rustc_metadata::{ - NativeLibSearchFallback, find_native_static_library, walk_native_lib_search_dirs, + EncodedMetadata, NativeLibSearchFallback, find_native_static_library, + walk_native_lib_search_dirs, }; use rustc_middle::bug; use rustc_middle::lint::lint_level; @@ -91,6 +92,7 @@ pub fn link_binary( sess: &Session, archive_builder_builder: &dyn ArchiveBuilderBuilder, codegen_results: CodegenResults, + metadata: EncodedMetadata, outputs: &OutputFilenames, ) { let _timer = sess.timer("link_binary"); @@ -142,6 +144,7 @@ pub fn link_binary( sess, archive_builder_builder, &codegen_results, + &metadata, RlibFlavor::Normal, &path, ) @@ -152,6 +155,7 @@ pub fn link_binary( sess, archive_builder_builder, &codegen_results, + &metadata, &out_filename, &path, ); @@ -163,6 +167,7 @@ pub fn link_binary( crate_type, &out_filename, &codegen_results, + &metadata, path.as_ref(), ); } @@ -226,11 +231,7 @@ pub fn link_binary( let remove_temps_from_module = |module: &CompiledModule| maybe_remove_temps_from_module(false, false, module); - // Otherwise, always remove the metadata and allocator module temporaries. - if let Some(ref metadata_module) = codegen_results.metadata_module { - remove_temps_from_module(metadata_module); - } - + // Otherwise, always remove the allocator module temporaries. if let Some(ref allocator_module) = codegen_results.allocator_module { remove_temps_from_module(allocator_module); } @@ -312,6 +313,7 @@ fn link_rlib<'a>( sess: &'a Session, archive_builder_builder: &dyn ArchiveBuilderBuilder, codegen_results: &CodegenResults, + metadata: &EncodedMetadata, flavor: RlibFlavor, tmpdir: &MaybeTempDir, ) -> Box { @@ -319,12 +321,9 @@ fn link_rlib<'a>( let trailing_metadata = match flavor { RlibFlavor::Normal => { - let (metadata, metadata_position) = create_wrapper_file( - sess, - ".rmeta".to_string(), - codegen_results.metadata.stub_or_full(), - ); - let metadata = emit_wrapper_file(sess, &metadata, tmpdir, METADATA_FILENAME); + let (metadata, metadata_position) = + create_wrapper_file(sess, ".rmeta".to_string(), metadata.stub_or_full()); + let metadata = emit_wrapper_file(sess, &metadata, tmpdir.as_ref(), METADATA_FILENAME); match metadata_position { MetadataPosition::First => { // Most of the time metadata in rlib files is wrapped in a "dummy" object @@ -392,7 +391,7 @@ fn link_rlib<'a>( let src = read(path) .unwrap_or_else(|e| sess.dcx().emit_fatal(errors::ReadFileError { message: e })); let (data, _) = create_wrapper_file(sess, ".bundled_lib".to_string(), &src); - let wrapper_file = emit_wrapper_file(sess, &data, tmpdir, filename.as_str()); + let wrapper_file = emit_wrapper_file(sess, &data, tmpdir.as_ref(), filename.as_str()); packed_bundled_libs.push(wrapper_file); } else { let path = find_native_static_library(lib.name.as_str(), lib.verbatim, sess); @@ -473,6 +472,7 @@ fn link_staticlib( sess: &Session, archive_builder_builder: &dyn ArchiveBuilderBuilder, codegen_results: &CodegenResults, + metadata: &EncodedMetadata, out_filename: &Path, tempdir: &MaybeTempDir, ) { @@ -481,6 +481,7 @@ fn link_staticlib( sess, archive_builder_builder, codegen_results, + metadata, RlibFlavor::StaticlibBase, tempdir, ); @@ -694,6 +695,7 @@ fn link_natively( crate_type: CrateType, out_filename: &Path, codegen_results: &CodegenResults, + metadata: &EncodedMetadata, tmpdir: &Path, ) { info!("preparing {:?} to {:?}", crate_type, out_filename); @@ -718,6 +720,7 @@ fn link_natively( tmpdir, temp_filename, codegen_results, + metadata, self_contained_components, ); @@ -2095,17 +2098,25 @@ fn add_local_crate_allocator_objects(cmd: &mut dyn Linker, codegen_results: &Cod /// Add object files containing metadata for the current crate. fn add_local_crate_metadata_objects( cmd: &mut dyn Linker, + sess: &Session, + archive_builder_builder: &dyn ArchiveBuilderBuilder, crate_type: CrateType, + tmpdir: &Path, codegen_results: &CodegenResults, + metadata: &EncodedMetadata, ) { // When linking a dynamic library, we put the metadata into a section of the // executable. This metadata is in a separate object file from the main - // object file, so we link that in here. - if matches!(crate_type, CrateType::Dylib | CrateType::ProcMacro) - && let Some(m) = &codegen_results.metadata_module - && let Some(obj) = &m.object - { - cmd.add_object(obj); + // object file, so we create and link it in here. + if matches!(crate_type, CrateType::Dylib | CrateType::ProcMacro) { + let data = archive_builder_builder.create_dylib_metadata_wrapper( + sess, + &metadata, + &codegen_results.crate_info.metadata_symbol, + ); + let obj = emit_wrapper_file(sess, &data, tmpdir, "rmeta.o"); + + cmd.add_object(&obj); } } @@ -2195,6 +2206,7 @@ fn linker_with_args( tmpdir: &Path, out_filename: &Path, codegen_results: &CodegenResults, + metadata: &EncodedMetadata, self_contained_components: LinkSelfContainedComponents, ) -> Command { let self_contained_crt_objects = self_contained_components.is_crt_objects_enabled(); @@ -2269,7 +2281,15 @@ fn linker_with_args( // in this DAG so far because they can only depend on other native libraries // and such dependencies are also required to be specified. add_local_crate_regular_objects(cmd, codegen_results); - add_local_crate_metadata_objects(cmd, crate_type, codegen_results); + add_local_crate_metadata_objects( + cmd, + sess, + archive_builder_builder, + crate_type, + tmpdir, + codegen_results, + metadata, + ); add_local_crate_allocator_objects(cmd, codegen_results); // Avoid linking to dynamic libraries unless they satisfy some undefined symbols diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index a41ca8ce28bc..bbf9cceef2a0 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -24,7 +24,6 @@ use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_incremental::{ copy_cgu_workproduct_to_incr_comp_cache_dir, in_incr_comp_dir, in_incr_comp_dir_sess, }; -use rustc_metadata::EncodedMetadata; use rustc_metadata::fs::copy_to_stdout; use rustc_middle::bug; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; @@ -142,7 +141,6 @@ impl ModuleConfig { || match kind { ModuleKind::Regular => sess.opts.output_types.contains_key(&OutputType::Object), ModuleKind::Allocator => false, - ModuleKind::Metadata => sess.opts.output_types.contains_key(&OutputType::Metadata), }; let emit_obj = if !should_emit_obj { @@ -350,7 +348,6 @@ pub struct CodegenContext { pub output_filenames: Arc, pub invocation_temp: Option, pub regular_module_config: Arc, - pub metadata_module_config: Arc, pub allocator_module_config: Arc, pub tm_factory: TargetMachineFactoryFn, pub msvc_imps_needed: bool, @@ -395,7 +392,6 @@ impl CodegenContext { pub fn config(&self, kind: ModuleKind) -> &ModuleConfig { match kind { ModuleKind::Regular => &self.regular_module_config, - ModuleKind::Metadata => &self.metadata_module_config, ModuleKind::Allocator => &self.allocator_module_config, } } @@ -474,8 +470,6 @@ pub(crate) fn start_async_codegen( backend: B, tcx: TyCtxt<'_>, target_cpu: String, - metadata: EncodedMetadata, - metadata_module: Option, ) -> OngoingCodegen { let (coordinator_send, coordinator_receive) = channel(); @@ -485,7 +479,6 @@ pub(crate) fn start_async_codegen( let crate_info = CrateInfo::new(tcx, target_cpu); let regular_config = ModuleConfig::new(ModuleKind::Regular, tcx, no_builtins); - let metadata_config = ModuleConfig::new(ModuleKind::Metadata, tcx, no_builtins); let allocator_config = ModuleConfig::new(ModuleKind::Allocator, tcx, no_builtins); let (shared_emitter, shared_emitter_main) = SharedEmitter::new(); @@ -499,15 +492,12 @@ pub(crate) fn start_async_codegen( codegen_worker_send, coordinator_receive, Arc::new(regular_config), - Arc::new(metadata_config), Arc::new(allocator_config), coordinator_send.clone(), ); OngoingCodegen { backend, - metadata, - metadata_module, crate_info, codegen_worker_receive, @@ -843,12 +833,6 @@ pub(crate) fn compute_per_cgu_lto_type( sess_crate_types: &[CrateType], module_kind: ModuleKind, ) -> ComputedLtoType { - // Metadata modules never participate in LTO regardless of the lto - // settings. - if module_kind == ModuleKind::Metadata { - return ComputedLtoType::No; - } - // If the linker does LTO, we don't have to do it. Note that we // keep doing full LTO, if it is requested, as not to break the // assumption that the output will be a single module. @@ -1029,10 +1013,7 @@ fn finish_intra_module_work( let dcx = cgcx.create_dcx(); let dcx = dcx.handle(); - if !cgcx.opts.unstable_opts.combine_cgu - || module.kind == ModuleKind::Metadata - || module.kind == ModuleKind::Allocator - { + if !cgcx.opts.unstable_opts.combine_cgu || module.kind == ModuleKind::Allocator { let module = B::codegen(cgcx, dcx, module, module_config)?; Ok(WorkItemResult::Finished(module)) } else { @@ -1123,7 +1104,6 @@ fn start_executing_work( codegen_worker_send: Sender, coordinator_receive: Receiver>, regular_config: Arc, - metadata_config: Arc, allocator_config: Arc, tx_to_llvm_workers: Sender>, ) -> thread::JoinHandle> { @@ -1216,7 +1196,6 @@ fn start_executing_work( diag_emitter: shared_emitter.clone(), output_filenames: Arc::clone(tcx.output_filenames(())), regular_module_config: regular_config, - metadata_module_config: metadata_config, allocator_module_config: allocator_config, tm_factory: backend.target_machine_factory(tcx.sess, ol, backend_features), msvc_imps_needed: msvc_imps_needed(tcx), @@ -1673,7 +1652,6 @@ fn start_executing_work( assert!(compiled_allocator_module.is_none()); compiled_allocator_module = Some(compiled_module); } - ModuleKind::Metadata => bug!("Should be handled separately"), } } Ok(WorkItemResult::NeedsLink(module)) => { @@ -2055,8 +2033,6 @@ impl Drop for Coordinator { pub struct OngoingCodegen { pub backend: B, - pub metadata: EncodedMetadata, - pub metadata_module: Option, pub crate_info: CrateInfo, pub codegen_worker_receive: Receiver, pub shared_emitter_main: SharedEmitterMain, @@ -2096,12 +2072,10 @@ impl OngoingCodegen { ( CodegenResults { - metadata: self.metadata, crate_info: self.crate_info, modules: compiled_modules.modules, allocator_module: compiled_modules.allocator_module, - metadata_module: self.metadata_module, }, work_products, ) diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index c2d6a26de0fd..a3d6c73ba856 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -15,11 +15,10 @@ use rustc_data_structures::unord::UnordMap; use rustc_hir::ItemId; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::lang_items::LangItem; -use rustc_metadata::EncodedMetadata; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::middle::debugger_visualizer::{DebuggerVisualizerFile, DebuggerVisualizerType}; -use rustc_middle::middle::exported_symbols::SymbolExportKind; -use rustc_middle::middle::{exported_symbols, lang_items}; +use rustc_middle::middle::exported_symbols::{self, SymbolExportKind}; +use rustc_middle::middle::lang_items; use rustc_middle::mir::BinOp; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem, MonoItemPartitions}; @@ -28,7 +27,7 @@ use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_session::Session; -use rustc_session::config::{self, CrateType, EntryFnType, OutputType}; +use rustc_session::config::{self, CrateType, EntryFnType}; use rustc_span::{DUMMY_SP, Symbol, sym}; use rustc_symbol_mangling::mangle_internal_symbol; use rustc_trait_selection::infer::{BoundRegionConversionTime, TyCtxtInferExt}; @@ -37,7 +36,6 @@ use tracing::{debug, info}; use crate::assert_module_sources::CguReuse; use crate::back::link::are_upstream_rust_objects_already_included; -use crate::back::metadata::create_compressed_metadata_file; use crate::back::write::{ ComputedLtoType, OngoingCodegen, compute_per_cgu_lto_type, start_async_codegen, submit_codegened_module_to_llvm, submit_post_lto_module_to_llvm, submit_pre_lto_module_to_llvm, @@ -48,8 +46,7 @@ use crate::mir::operand::OperandValue; use crate::mir::place::PlaceRef; use crate::traits::*; use crate::{ - CachedModuleCodegen, CodegenLintLevels, CompiledModule, CrateInfo, ModuleCodegen, ModuleKind, - errors, meth, mir, + CachedModuleCodegen, CodegenLintLevels, CrateInfo, ModuleCodegen, ModuleKind, errors, meth, mir, }; pub(crate) fn bin_op_to_icmp_predicate(op: BinOp, signed: bool) -> IntPredicate { @@ -669,12 +666,10 @@ pub fn codegen_crate( backend: B, tcx: TyCtxt<'_>, target_cpu: String, - metadata: EncodedMetadata, - need_metadata_module: bool, ) -> OngoingCodegen { // Skip crate items and just output metadata in -Z no-codegen mode. if tcx.sess.opts.unstable_opts.no_codegen || !tcx.sess.opts.output_types.should_codegen() { - let ongoing_codegen = start_async_codegen(backend, tcx, target_cpu, metadata, None); + let ongoing_codegen = start_async_codegen(backend, tcx, target_cpu); ongoing_codegen.codegen_finished(tcx); @@ -707,39 +702,7 @@ pub fn codegen_crate( } } - let metadata_module = need_metadata_module.then(|| { - // Emit compressed metadata object. - let metadata_cgu_name = - cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("metadata")).to_string(); - tcx.sess.time("write_compressed_metadata", || { - let file_name = tcx.output_filenames(()).temp_path_for_cgu( - OutputType::Metadata, - &metadata_cgu_name, - tcx.sess.invocation_temp.as_deref(), - ); - let data = create_compressed_metadata_file( - tcx.sess, - &metadata, - &exported_symbols::metadata_symbol_name(tcx), - ); - if let Err(error) = std::fs::write(&file_name, data) { - tcx.dcx().emit_fatal(errors::MetadataObjectFileWrite { error }); - } - CompiledModule { - name: metadata_cgu_name, - kind: ModuleKind::Metadata, - object: Some(file_name), - dwarf_object: None, - bytecode: None, - assembly: None, - llvm_ir: None, - links_from_incr_cache: Vec::new(), - } - }) - }); - - let ongoing_codegen = - start_async_codegen(backend.clone(), tcx, target_cpu, metadata, metadata_module); + let ongoing_codegen = start_async_codegen(backend.clone(), tcx, target_cpu); // Codegen an allocator shim, if necessary. if let Some(kind) = allocator_kind_for_codegen(tcx) { @@ -1010,6 +973,7 @@ impl CrateInfo { windows_subsystem, natvis_debugger_visualizers: Default::default(), lint_levels: CodegenLintLevels::from_tcx(tcx), + metadata_symbol: exported_symbols::metadata_symbol_name(tcx), }; info.native_libraries.reserve(n_crates); diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index f843347db925..bac02bdf983a 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -777,12 +777,6 @@ pub(crate) struct MultipleMainFunctions { pub span: Span, } -#[derive(Diagnostic)] -#[diag(codegen_ssa_metadata_object_file_write)] -pub(crate) struct MetadataObjectFileWrite { - pub error: Error, -} - #[derive(Diagnostic)] #[diag(codegen_ssa_invalid_windows_subsystem)] pub(crate) struct InvalidWindowsSubsystem { diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 84919645cf07..523c9f2ad1ce 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -31,6 +31,7 @@ use rustc_data_structures::unord::UnordMap; use rustc_hir::CRATE_HIR_ID; use rustc_hir::def_id::CrateNum; use rustc_macros::{Decodable, Encodable, HashStable}; +use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::WorkProduct; use rustc_middle::lint::LevelAndSource; use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; @@ -169,7 +170,6 @@ pub(crate) struct CachedModuleCodegen { #[derive(Copy, Clone, Debug, PartialEq, Encodable, Decodable)] pub enum ModuleKind { Regular, - Metadata, Allocator, } @@ -233,6 +233,7 @@ pub struct CrateInfo { pub windows_subsystem: Option, pub natvis_debugger_visualizers: BTreeSet, pub lint_levels: CodegenLintLevels, + pub metadata_symbol: String, } /// Target-specific options that get set in `cfg(...)`. @@ -257,8 +258,6 @@ pub struct TargetConfig { pub struct CodegenResults { pub modules: Vec, pub allocator_module: Option, - pub metadata_module: Option, - pub metadata: rustc_metadata::EncodedMetadata, pub crate_info: CrateInfo, } @@ -303,6 +302,7 @@ impl CodegenResults { sess: &Session, rlink_file: &Path, codegen_results: &CodegenResults, + metadata: &EncodedMetadata, outputs: &OutputFilenames, ) -> Result { let mut encoder = FileEncoder::new(rlink_file)?; @@ -312,6 +312,7 @@ impl CodegenResults { encoder.emit_raw_bytes(&RLINK_VERSION.to_be_bytes()); encoder.emit_str(sess.cfg_version); Encodable::encode(codegen_results, &mut encoder); + Encodable::encode(metadata, &mut encoder); Encodable::encode(outputs, &mut encoder); encoder.finish().map_err(|(_path, err)| err) } @@ -319,7 +320,7 @@ impl CodegenResults { pub fn deserialize_rlink( sess: &Session, data: Vec, - ) -> Result<(Self, OutputFilenames), CodegenErrors> { + ) -> Result<(Self, EncodedMetadata, OutputFilenames), CodegenErrors> { // The Decodable machinery is not used here because it panics if the input data is invalid // and because its internal representation may change. if !data.starts_with(RLINK_MAGIC) { @@ -350,8 +351,9 @@ impl CodegenResults { } let codegen_results = CodegenResults::decode(&mut decoder); + let metadata = EncodedMetadata::decode(&mut decoder); let outputs = OutputFilenames::decode(&mut decoder); - Ok((codegen_results, outputs)) + Ok((codegen_results, metadata, outputs)) } } diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 43b87171d510..3df97429e093 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -1,6 +1,6 @@ use std::cmp; -use rustc_abi::{BackendRepr, ExternAbi, HasDataLayout, Reg, Size, WrappingRange}; +use rustc_abi::{Align, BackendRepr, ExternAbi, HasDataLayout, Reg, Size, WrappingRange}; use rustc_ast as ast; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_data_structures::packed::Pu128; @@ -13,7 +13,7 @@ use rustc_middle::{bug, span_bug}; use rustc_session::config::OptLevel; use rustc_span::Span; use rustc_span::source_map::Spanned; -use rustc_target::callconv::{ArgAbi, FnAbi, PassMode}; +use rustc_target::callconv::{ArgAbi, CastTarget, FnAbi, PassMode}; use tracing::{debug, info}; use super::operand::OperandRef; @@ -558,8 +558,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } ZeroSized => bug!("ZST return value shouldn't be in PassMode::Cast"), }; - let ty = bx.cast_backend_type(cast_ty); - bx.load(ty, llslot, self.fn_abi.ret.layout.align.abi) + load_cast(bx, cast_ty, llslot, self.fn_abi.ret.layout.align.abi) } }; bx.ret(llval); @@ -1618,8 +1617,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { MemFlags::empty(), ); // ...and then load it with the ABI type. - let cast_ty = bx.cast_backend_type(cast); - llval = bx.load(cast_ty, llscratch, scratch_align); + llval = load_cast(bx, cast, llscratch, scratch_align); bx.lifetime_end(llscratch, scratch_size); } else { // We can't use `PlaceRef::load` here because the argument @@ -1969,3 +1967,47 @@ enum ReturnDest<'tcx, V> { /// Store a direct return value to an operand local place. DirectOperand(mir::Local), } + +fn load_cast<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( + bx: &mut Bx, + cast: &CastTarget, + ptr: Bx::Value, + align: Align, +) -> Bx::Value { + let cast_ty = bx.cast_backend_type(cast); + if let Some(offset_from_start) = cast.rest_offset { + assert!(cast.prefix[1..].iter().all(|p| p.is_none())); + assert_eq!(cast.rest.unit.size, cast.rest.total); + let first_ty = bx.reg_backend_type(&cast.prefix[0].unwrap()); + let second_ty = bx.reg_backend_type(&cast.rest.unit); + let first = bx.load(first_ty, ptr, align); + let second_ptr = bx.inbounds_ptradd(ptr, bx.const_usize(offset_from_start.bytes())); + let second = bx.load(second_ty, second_ptr, align.restrict_for_offset(offset_from_start)); + let res = bx.cx().const_poison(cast_ty); + let res = bx.insert_value(res, first, 0); + bx.insert_value(res, second, 1) + } else { + bx.load(cast_ty, ptr, align) + } +} + +pub fn store_cast<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( + bx: &mut Bx, + cast: &CastTarget, + value: Bx::Value, + ptr: Bx::Value, + align: Align, +) { + if let Some(offset_from_start) = cast.rest_offset { + assert!(cast.prefix[1..].iter().all(|p| p.is_none())); + assert_eq!(cast.rest.unit.size, cast.rest.total); + assert!(cast.prefix[0].is_some()); + let first = bx.extract_value(value, 0); + let second = bx.extract_value(value, 1); + bx.store(first, ptr, align); + let second_ptr = bx.inbounds_ptradd(ptr, bx.const_usize(offset_from_start.bytes())); + bx.store(second, second_ptr, align.restrict_for_offset(offset_from_start)); + } else { + bx.store(value, ptr, align); + }; +} diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 96a04473aba2..66c4af4c935b 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -26,6 +26,7 @@ pub mod place; mod rvalue; mod statement; +pub use self::block::store_cast; use self::debuginfo::{FunctionDebugContext, PerLocalVarDebugInfo}; use self::operand::{OperandRef, OperandValue}; use self::place::PlaceRef; @@ -259,7 +260,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } PassMode::Cast { ref cast, .. } => { debug!("alloc: {:?} (return place) -> place", local); - let size = cast.size(&start_bx); + let size = cast.size(&start_bx).max(layout.size); return LocalRef::Place(PlaceRef::alloca_size(&mut start_bx, size, layout)); } _ => {} diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs index 46fb9a895133..b805dc094e91 100644 --- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs +++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs @@ -1,14 +1,13 @@ use rustc_abi::{BackendRepr, Float, Integer, Primitive, RegKind}; use rustc_attr_data_structures::InstructionSetAttr; -use rustc_hir::def_id::DefId; use rustc_middle::mir::mono::{Linkage, MonoItemData, Visibility}; use rustc_middle::mir::{InlineAsmOperand, START_BLOCK}; use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout}; use rustc_middle::ty::{Instance, Ty, TyCtxt, TypeVisitableExt}; -use rustc_middle::{bug, span_bug, ty}; +use rustc_middle::{bug, ty}; use rustc_span::sym; use rustc_target::callconv::{ArgAbi, FnAbi, PassMode}; -use rustc_target::spec::{BinaryFormat, WasmCAbi}; +use rustc_target::spec::BinaryFormat; use crate::common; use crate::mir::AsmCodegenMethods; @@ -287,12 +286,7 @@ fn prefix_and_suffix<'tcx>( writeln!(begin, "{}", arch_prefix).unwrap(); } writeln!(begin, "{asm_name}:").unwrap(); - writeln!( - begin, - ".functype {asm_name} {}", - wasm_functype(tcx, fn_abi, instance.def_id()) - ) - .unwrap(); + writeln!(begin, ".functype {asm_name} {}", wasm_functype(tcx, fn_abi)).unwrap(); writeln!(end).unwrap(); // .size is ignored for function symbols, so we can skip it @@ -333,7 +327,7 @@ fn prefix_and_suffix<'tcx>( /// The webassembly type signature for the given function. /// /// Used by the `.functype` directive on wasm targets. -fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, def_id: DefId) -> String { +fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> String { let mut signature = String::with_capacity(64); let ptr_type = match tcx.data_layout.pointer_size.bits() { @@ -342,17 +336,6 @@ fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, def_id other => bug!("wasm pointer size cannot be {other} bits"), }; - // FIXME: remove this once the wasm32-unknown-unknown ABI is fixed - // please also add `wasm32-unknown-unknown` back in `tests/assembly/wasm32-naked-fn.rs` - // basically the commit introducing this comment should be reverted - if let PassMode::Pair { .. } = fn_abi.ret.mode { - let _ = WasmCAbi::Legacy { with_lint: true }; - span_bug!( - tcx.def_span(def_id), - "cannot return a pair (the wasm32-unknown-unknown ABI is broken, see https://github.com/rust-lang/rust/issues/115666" - ); - } - let hidden_return = matches!(fn_abi.ret.mode, PassMode::Indirect { .. }); signature.push('('); @@ -366,7 +349,7 @@ fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, def_id let mut it = fn_abi.args.iter().peekable(); while let Some(arg_abi) = it.next() { - wasm_type(tcx, &mut signature, arg_abi, ptr_type, def_id); + wasm_type(&mut signature, arg_abi, ptr_type); if it.peek().is_some() { signature.push_str(", "); } @@ -375,7 +358,7 @@ fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, def_id signature.push_str(") -> ("); if !hidden_return { - wasm_type(tcx, &mut signature, &fn_abi.ret, ptr_type, def_id); + wasm_type(&mut signature, &fn_abi.ret, ptr_type); } signature.push(')'); @@ -383,27 +366,13 @@ fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, def_id signature } -fn wasm_type<'tcx>( - tcx: TyCtxt<'tcx>, - signature: &mut String, - arg_abi: &ArgAbi<'_, Ty<'tcx>>, - ptr_type: &'static str, - def_id: DefId, -) { +fn wasm_type<'tcx>(signature: &mut String, arg_abi: &ArgAbi<'_, Ty<'tcx>>, ptr_type: &'static str) { match arg_abi.mode { PassMode::Ignore => { /* do nothing */ } PassMode::Direct(_) => { let direct_type = match arg_abi.layout.backend_repr { BackendRepr::Scalar(scalar) => wasm_primitive(scalar.primitive(), ptr_type), BackendRepr::SimdVector { .. } => "v128", - BackendRepr::Memory { .. } => { - // FIXME: remove this branch once the wasm32-unknown-unknown ABI is fixed - let _ = WasmCAbi::Legacy { with_lint: true }; - span_bug!( - tcx.def_span(def_id), - "cannot use memory args (the wasm32-unknown-unknown ABI is broken, see https://github.com/rust-lang/rust/issues/115666" - ); - } other => unreachable!("unexpected BackendRepr: {:?}", other), }; diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index 95bf3b16685b..29ec7eb1da3b 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -74,12 +74,7 @@ pub trait CodegenBackend { fn provide(&self, _providers: &mut Providers) {} - fn codegen_crate<'tcx>( - &self, - tcx: TyCtxt<'tcx>, - metadata: EncodedMetadata, - need_metadata_module: bool, - ) -> Box; + fn codegen_crate<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Box; /// This is called on the returned `Box` from [`codegen_crate`](Self::codegen_crate) /// @@ -94,8 +89,14 @@ pub trait CodegenBackend { ) -> (CodegenResults, FxIndexMap); /// This is called on the returned [`CodegenResults`] from [`join_codegen`](Self::join_codegen). - fn link(&self, sess: &Session, codegen_results: CodegenResults, outputs: &OutputFilenames) { - link_binary(sess, &ArArchiveBuilderBuilder, codegen_results, outputs); + fn link( + &self, + sess: &Session, + codegen_results: CodegenResults, + metadata: EncodedMetadata, + outputs: &OutputFilenames, + ) { + link_binary(sess, &ArArchiveBuilderBuilder, codegen_results, metadata, outputs); } } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 0cd9e36a9277..d53126d04143 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -557,27 +557,34 @@ fn process_rlink(sess: &Session, compiler: &interface::Compiler) { let rlink_data = fs::read(file).unwrap_or_else(|err| { dcx.emit_fatal(RlinkUnableToRead { err }); }); - let (codegen_results, outputs) = match CodegenResults::deserialize_rlink(sess, rlink_data) { - Ok((codegen, outputs)) => (codegen, outputs), - Err(err) => { - match err { - CodegenErrors::WrongFileType => dcx.emit_fatal(RLinkWrongFileType), - CodegenErrors::EmptyVersionNumber => dcx.emit_fatal(RLinkEmptyVersionNumber), - CodegenErrors::EncodingVersionMismatch { version_array, rlink_version } => dcx - .emit_fatal(RLinkEncodingVersionMismatch { version_array, rlink_version }), - CodegenErrors::RustcVersionMismatch { rustc_version } => { - dcx.emit_fatal(RLinkRustcVersionMismatch { - rustc_version, - current_version: sess.cfg_version, - }) - } - CodegenErrors::CorruptFile => { - dcx.emit_fatal(RlinkCorruptFile { file }); - } - }; - } - }; - compiler.codegen_backend.link(sess, codegen_results, &outputs); + let (codegen_results, metadata, outputs) = + match CodegenResults::deserialize_rlink(sess, rlink_data) { + Ok((codegen, metadata, outputs)) => (codegen, metadata, outputs), + Err(err) => { + match err { + CodegenErrors::WrongFileType => dcx.emit_fatal(RLinkWrongFileType), + CodegenErrors::EmptyVersionNumber => { + dcx.emit_fatal(RLinkEmptyVersionNumber) + } + CodegenErrors::EncodingVersionMismatch { version_array, rlink_version } => { + dcx.emit_fatal(RLinkEncodingVersionMismatch { + version_array, + rlink_version, + }) + } + CodegenErrors::RustcVersionMismatch { rustc_version } => { + dcx.emit_fatal(RLinkRustcVersionMismatch { + rustc_version, + current_version: sess.cfg_version, + }) + } + CodegenErrors::CorruptFile => { + dcx.emit_fatal(RlinkCorruptFile { file }); + } + }; + } + }; + compiler.codegen_backend.link(sess, codegen_results, metadata, &outputs); } else { dcx.emit_fatal(RlinkNotAFile {}); } diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 311dadb53c42..7a29f8c9fbde 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -35,6 +35,7 @@ use crate::base::ast::MetaItemInner; use crate::errors; use crate::expand::{self, AstFragment, Invocation}; use crate::module::DirOwnership; +use crate::stats::MacroStat; // When adding new variants, make sure to // adjust the `visit_*` / `flat_map_*` calls in `InvocationCollector` @@ -1191,7 +1192,7 @@ pub struct ExtCtxt<'a> { /// not to expand it again. pub(super) expanded_inert_attrs: MarkedAttrs, /// `-Zmacro-stats` data. - pub macro_stats: FxHashMap<(Symbol, MacroKind), crate::stats::MacroStat>, // njn: quals + pub macro_stats: FxHashMap<(Symbol, MacroKind), MacroStat>, } impl<'a> ExtCtxt<'a> { diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 73a21789c5d2..7d6e471e7e95 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -887,7 +887,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_legacy_const_generics, Normal, template!(List: "N"), ErrorFollowing, EncodeCrossCrate::Yes, ), - // Do not const-check this function's body. It will always get replaced during CTFE. + // Do not const-check this function's body. It will always get replaced during CTFE via `hook_special_const_fn`. rustc_attr!( rustc_do_not_const_check, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes, "`#[rustc_do_not_const_check]` skips const-check for this function's body", diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 336bf0d93fd0..556f50a85af7 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2285,12 +2285,23 @@ pub struct Expr<'hir> { } impl Expr<'_> { - pub fn precedence(&self) -> ExprPrecedence { + pub fn precedence( + &self, + for_each_attr: &dyn Fn(HirId, &mut dyn FnMut(&Attribute)), + ) -> ExprPrecedence { + let prefix_attrs_precedence = || -> ExprPrecedence { + let mut has_outer_attr = false; + for_each_attr(self.hir_id, &mut |attr: &Attribute| { + has_outer_attr |= matches!(attr.style(), AttrStyle::Outer) + }); + if has_outer_attr { ExprPrecedence::Prefix } else { ExprPrecedence::Unambiguous } + }; + match &self.kind { ExprKind::Closure(closure) => { match closure.fn_decl.output { FnRetTy::DefaultReturn(_) => ExprPrecedence::Jump, - FnRetTy::Return(_) => ExprPrecedence::Unambiguous, + FnRetTy::Return(_) => prefix_attrs_precedence(), } } @@ -2315,7 +2326,7 @@ impl Expr<'_> { | ExprKind::Let(..) | ExprKind::Unary(..) => ExprPrecedence::Prefix, - // Never need parens + // Need parens if and only if there are prefix attributes. ExprKind::Array(_) | ExprKind::Block(..) | ExprKind::Call(..) @@ -2337,9 +2348,9 @@ impl Expr<'_> { | ExprKind::Type(..) | ExprKind::UnsafeBinderCast(..) | ExprKind::Use(..) - | ExprKind::Err(_) => ExprPrecedence::Unambiguous, + | ExprKind::Err(_) => prefix_attrs_precedence(), - ExprKind::DropTemps(expr, ..) => expr.precedence(), + ExprKind::DropTemps(expr, ..) => expr.precedence(for_each_attr), } } @@ -3064,6 +3075,7 @@ pub struct TraitItem<'hir> { pub kind: TraitItemKind<'hir>, pub span: Span, pub defaultness: Defaultness, + pub has_delayed_lints: bool, } macro_rules! expect_methods_self_kind { @@ -3168,6 +3180,7 @@ pub struct ImplItem<'hir> { pub defaultness: Defaultness, pub span: Span, pub vis_span: Span, + pub has_delayed_lints: bool, } impl<'hir> ImplItem<'hir> { @@ -4087,6 +4100,7 @@ pub struct Item<'hir> { pub kind: ItemKind<'hir>, pub span: Span, pub vis_span: Span, + pub has_delayed_lints: bool, } impl<'hir> Item<'hir> { @@ -4492,6 +4506,7 @@ pub struct ForeignItem<'hir> { pub owner_id: OwnerId, pub span: Span, pub vis_span: Span, + pub has_delayed_lints: bool, } impl ForeignItem<'_> { @@ -4974,7 +4989,7 @@ mod size_asserts { static_assert_size!(Expr<'_>, 64); static_assert_size!(ExprKind<'_>, 48); static_assert_size!(FnDecl<'_>, 40); - static_assert_size!(ForeignItem<'_>, 88); + static_assert_size!(ForeignItem<'_>, 96); static_assert_size!(ForeignItemKind<'_>, 56); static_assert_size!(GenericArg<'_>, 16); static_assert_size!(GenericBound<'_>, 64); diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index bebac3a4b782..57e49625148c 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -537,7 +537,7 @@ pub fn walk_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Param<'v>) -> } pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::Result { - let Item { owner_id: _, kind, span: _, vis_span: _ } = item; + let Item { owner_id: _, kind, span: _, vis_span: _, has_delayed_lints: _ } = item; try_visit!(visitor.visit_id(item.hir_id())); match *kind { ItemKind::ExternCrate(orig_name, ident) => { @@ -656,7 +656,8 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>( visitor: &mut V, foreign_item: &'v ForeignItem<'v>, ) -> V::Result { - let ForeignItem { ident, kind, owner_id: _, span: _, vis_span: _ } = foreign_item; + let ForeignItem { ident, kind, owner_id: _, span: _, vis_span: _, has_delayed_lints: _ } = + foreign_item; try_visit!(visitor.visit_id(foreign_item.hir_id())); try_visit!(visitor.visit_ident(*ident)); @@ -1205,7 +1206,15 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>( visitor: &mut V, trait_item: &'v TraitItem<'v>, ) -> V::Result { - let TraitItem { ident, generics, ref defaultness, ref kind, span, owner_id: _ } = *trait_item; + let TraitItem { + ident, + generics, + ref defaultness, + ref kind, + span, + owner_id: _, + has_delayed_lints: _, + } = *trait_item; let hir_id = trait_item.hir_id(); try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_generics(&generics)); @@ -1261,6 +1270,7 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>( ref defaultness, span: _, vis_span: _, + has_delayed_lints: _, } = *impl_item; try_visit!(visitor.visit_ident(ident)); diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index f768bd157abc..bd2252c1bf8f 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -46,6 +46,9 @@ hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the {$ hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion = use a fully qualified path with explicit lifetimes +hir_analysis_async_drop_without_sync_drop = `AsyncDrop` impl without `Drop` impl + .help = type implementing `AsyncDrop` trait must also implement `Drop` trait to be used in sync context and unwinds + hir_analysis_auto_deref_reached_recursion_limit = reached the recursion limit while auto-dereferencing `{$ty}` .label = deref recursion limit reached .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`) diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index c5c7e6b2aa72..de8cbc3a57ff 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -113,7 +113,15 @@ pub fn provide(providers: &mut Providers) { } fn adt_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option { - tcx.calculate_dtor(def_id, always_applicable::check_drop_impl) + let dtor = tcx.calculate_dtor(def_id, always_applicable::check_drop_impl); + if dtor.is_none() && tcx.features().async_drop() { + if let Some(async_dtor) = adt_async_destructor(tcx, def_id) { + // When type has AsyncDrop impl, but doesn't have Drop impl, generate error + let span = tcx.def_span(async_dtor.impl_did); + tcx.dcx().emit_err(errors::AsyncDropWithoutSyncDrop { span }); + } + } + dtor } fn adt_async_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option { diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 8de2aec95a7b..318aaab50f4d 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1712,3 +1712,11 @@ pub(crate) struct AbiCustomClothedFunction { )] pub naked_span: Span, } + +#[derive(Diagnostic)] +#[diag(hir_analysis_async_drop_without_sync_drop)] +#[help] +pub(crate) struct AsyncDropWithoutSyncDrop { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 4f699462ac34..7c8c9425a03d 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -193,13 +193,41 @@ pub fn check_crate(tcx: TyCtxt<'_>) { let _: R = tcx.ensure_ok().crate_inherent_impls_overlap_check(()); }); - for owner_id in tcx.hir_crate_items(()).owners() { - if let Some(delayed_lints) = tcx.opt_ast_lowering_delayed_lints(owner_id) { - for lint in &delayed_lints.lints { - emit_delayed_lint(lint, tcx); + tcx.sess.time("emit_ast_lowering_delayed_lints", || { + // sanity check in debug mode that all lints are really noticed + // and we really will emit them all in the loop right below. + // + // during ast lowering, when creating items, foreign items, trait items and impl items + // we store in them whether they have any lints in their owner node that should be + // picked up by `hir_crate_items`. However, theoretically code can run between that + // boolean being inserted into the item and the owner node being created. + // We don't want any new lints to be emitted there + // (though honestly, you have to really try to manage to do that but still), + // but this check is there to catch that. + #[cfg(debug_assertions)] + { + // iterate over all owners + for owner_id in tcx.hir_crate_items(()).owners() { + // if it has delayed lints + if let Some(delayed_lints) = tcx.opt_ast_lowering_delayed_lints(owner_id) { + if !delayed_lints.lints.is_empty() { + // assert that delayed_lint_items also picked up this item to have lints + assert!( + tcx.hir_crate_items(()).delayed_lint_items().any(|i| i == owner_id) + ); + } + } } } - } + + for owner_id in tcx.hir_crate_items(()).delayed_lint_items() { + if let Some(delayed_lints) = tcx.opt_ast_lowering_delayed_lints(owner_id) { + for lint in &delayed_lints.lints { + emit_delayed_lint(lint, tcx); + } + } + } + }); tcx.par_hir_body_owners(|item_def_id| { let def_kind = tcx.def_kind(item_def_id); diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index b23b3125c59a..fc507285860e 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -80,6 +80,13 @@ impl<'a> State<'a> { (self.attrs)(id) } + fn precedence(&self, expr: &hir::Expr<'_>) -> ExprPrecedence { + let for_each_attr = |id: HirId, callback: &mut dyn FnMut(&hir::Attribute)| { + self.attrs(id).iter().for_each(callback); + }; + expr.precedence(&for_each_attr) + } + fn print_attrs_as_inner(&mut self, attrs: &[hir::Attribute]) { self.print_either_attributes(attrs, ast::AttrStyle::Inner) } @@ -1164,7 +1171,7 @@ impl<'a> State<'a> { } self.space(); self.word_space("="); - let npals = || parser::needs_par_as_let_scrutinee(init.precedence()); + let npals = || parser::needs_par_as_let_scrutinee(self.precedence(init)); self.print_expr_cond_paren(init, Self::cond_needs_par(init) || npals()) } @@ -1265,7 +1272,7 @@ impl<'a> State<'a> { fn print_expr_call(&mut self, func: &hir::Expr<'_>, args: &[hir::Expr<'_>]) { let needs_paren = match func.kind { hir::ExprKind::Field(..) => true, - _ => func.precedence() < ExprPrecedence::Unambiguous, + _ => self.precedence(func) < ExprPrecedence::Unambiguous, }; self.print_expr_cond_paren(func, needs_paren); @@ -1279,7 +1286,10 @@ impl<'a> State<'a> { args: &[hir::Expr<'_>], ) { let base_args = args; - self.print_expr_cond_paren(receiver, receiver.precedence() < ExprPrecedence::Unambiguous); + self.print_expr_cond_paren( + receiver, + self.precedence(receiver) < ExprPrecedence::Unambiguous, + ); self.word("."); self.print_ident(segment.ident); @@ -1293,8 +1303,8 @@ impl<'a> State<'a> { fn print_expr_binary(&mut self, op: hir::BinOpKind, lhs: &hir::Expr<'_>, rhs: &hir::Expr<'_>) { let binop_prec = op.precedence(); - let left_prec = lhs.precedence(); - let right_prec = rhs.precedence(); + let left_prec = self.precedence(lhs); + let right_prec = self.precedence(rhs); let (mut left_needs_paren, right_needs_paren) = match op.fixity() { Fixity::Left => (left_prec < binop_prec, right_prec <= binop_prec), @@ -1323,7 +1333,7 @@ impl<'a> State<'a> { fn print_expr_unary(&mut self, op: hir::UnOp, expr: &hir::Expr<'_>) { self.word(op.as_str()); - self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Prefix); + self.print_expr_cond_paren(expr, self.precedence(expr) < ExprPrecedence::Prefix); } fn print_expr_addr_of( @@ -1340,7 +1350,7 @@ impl<'a> State<'a> { self.print_mutability(mutability, true); } } - self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Prefix); + self.print_expr_cond_paren(expr, self.precedence(expr) < ExprPrecedence::Prefix); } fn print_literal(&mut self, lit: &hir::Lit) { @@ -1483,7 +1493,7 @@ impl<'a> State<'a> { self.print_literal(lit); } hir::ExprKind::Cast(expr, ty) => { - self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Cast); + self.print_expr_cond_paren(expr, self.precedence(expr) < ExprPrecedence::Cast); self.space(); self.word_space("as"); self.print_type(ty); @@ -1580,24 +1590,30 @@ impl<'a> State<'a> { self.print_block(blk, cb, ib); } hir::ExprKind::Assign(lhs, rhs, _) => { - self.print_expr_cond_paren(lhs, lhs.precedence() <= ExprPrecedence::Assign); + self.print_expr_cond_paren(lhs, self.precedence(lhs) <= ExprPrecedence::Assign); self.space(); self.word_space("="); - self.print_expr_cond_paren(rhs, rhs.precedence() < ExprPrecedence::Assign); + self.print_expr_cond_paren(rhs, self.precedence(rhs) < ExprPrecedence::Assign); } hir::ExprKind::AssignOp(op, lhs, rhs) => { - self.print_expr_cond_paren(lhs, lhs.precedence() <= ExprPrecedence::Assign); + self.print_expr_cond_paren(lhs, self.precedence(lhs) <= ExprPrecedence::Assign); self.space(); self.word_space(op.node.as_str()); - self.print_expr_cond_paren(rhs, rhs.precedence() < ExprPrecedence::Assign); + self.print_expr_cond_paren(rhs, self.precedence(rhs) < ExprPrecedence::Assign); } hir::ExprKind::Field(expr, ident) => { - self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Unambiguous); + self.print_expr_cond_paren( + expr, + self.precedence(expr) < ExprPrecedence::Unambiguous, + ); self.word("."); self.print_ident(ident); } hir::ExprKind::Index(expr, index, _) => { - self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Unambiguous); + self.print_expr_cond_paren( + expr, + self.precedence(expr) < ExprPrecedence::Unambiguous, + ); self.word("["); self.print_expr(index); self.word("]"); @@ -1611,7 +1627,7 @@ impl<'a> State<'a> { } if let Some(expr) = opt_expr { self.space(); - self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Jump); + self.print_expr_cond_paren(expr, self.precedence(expr) < ExprPrecedence::Jump); } } hir::ExprKind::Continue(destination) => { @@ -1625,13 +1641,13 @@ impl<'a> State<'a> { self.word("return"); if let Some(expr) = result { self.word(" "); - self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Jump); + self.print_expr_cond_paren(expr, self.precedence(expr) < ExprPrecedence::Jump); } } hir::ExprKind::Become(result) => { self.word("become"); self.word(" "); - self.print_expr_cond_paren(result, result.precedence() < ExprPrecedence::Jump); + self.print_expr_cond_paren(result, self.precedence(result) < ExprPrecedence::Jump); } hir::ExprKind::InlineAsm(asm) => { self.word("asm!"); @@ -1669,7 +1685,7 @@ impl<'a> State<'a> { } hir::ExprKind::Yield(expr, _) => { self.word_space("yield"); - self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Jump); + self.print_expr_cond_paren(expr, self.precedence(expr) < ExprPrecedence::Jump); } hir::ExprKind::Err(_) => { self.popen(); diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index e915b4fc626f..80bff09d0a43 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -620,7 +620,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; if let Ok(rest_snippet) = rest_snippet { - let sugg = if callee_expr.precedence() >= ExprPrecedence::Unambiguous { + let sugg = if self.precedence(callee_expr) >= ExprPrecedence::Unambiguous { vec![ (up_to_rcvr_span, "".to_string()), (rest_span, format!(".{}({rest_snippet}", segment.ident)), diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index e17cfc15a43d..6f8abc1e67d2 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -1100,7 +1100,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { } fn lossy_provenance_ptr2int_lint(&self, fcx: &FnCtxt<'a, 'tcx>, t_c: ty::cast::IntTy) { - let expr_prec = self.expr.precedence(); + let expr_prec = fcx.precedence(self.expr); let needs_parens = expr_prec < ExprPrecedence::Unambiguous; let needs_cast = !matches!(t_c, ty::cast::IntTy::U(ty::UintTy::Usize)); diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 30bf557dc93a..55c39d960e7c 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -6,6 +6,7 @@ //! See [`rustc_hir_analysis::check`] for more context on type checking in general. use rustc_abi::{ExternAbi, FIRST_VARIANT, FieldIdx}; +use rustc_ast::util::parser::ExprPrecedence; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::unord::UnordMap; @@ -17,7 +18,7 @@ use rustc_errors::{ use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; -use rustc_hir::{ExprKind, HirId, QPath}; +use rustc_hir::{Attribute, ExprKind, HirId, QPath}; use rustc_hir_analysis::NoVariantNamed; use rustc_hir_analysis::hir_ty_lowering::{FeedConstTy, HirTyLowerer as _}; use rustc_infer::infer; @@ -54,6 +55,30 @@ use crate::{ }; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { + pub(crate) fn precedence(&self, expr: &hir::Expr<'_>) -> ExprPrecedence { + let for_each_attr = |id: HirId, callback: &mut dyn FnMut(&Attribute)| { + for attr in self.tcx.hir_attrs(id) { + // For the purpose of rendering suggestions, disregard attributes + // that originate from desugaring of any kind. For example, `x?` + // desugars to `#[allow(unreachable_code)] match ...`. Failing to + // ignore the prefix attribute in the desugaring would cause this + // suggestion: + // + // let y: u32 = x?.try_into().unwrap(); + // ++++++++++++++++++++ + // + // to be rendered as: + // + // let y: u32 = (x?).try_into().unwrap(); + // + +++++++++++++++++++++ + if attr.span().desugaring_kind().is_none() { + callback(attr); + } + } + }; + expr.precedence(&for_each_attr) + } + /// Check an expr with an expectation type, and also demand that the expr's /// evaluated type is a subtype of the expectation at the end. This is a /// *hard* requirement. diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 66af085cfd48..7e5f1d97a8bf 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -399,7 +399,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // so we remove the user's `clone` call. { vec![(receiver_method.ident.span, conversion_method_name.to_string())] - } else if expr.precedence() < ExprPrecedence::Unambiguous { + } else if self.precedence(expr) < ExprPrecedence::Unambiguous { vec![ (expr.span.shrink_to_lo(), "(".to_string()), (expr.span.shrink_to_hi(), format!(").{}()", conversion_method_name)), @@ -1395,7 +1395,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { let span = expr.span.find_oldest_ancestor_in_same_ctxt(); - let mut sugg = if expr.precedence() >= ExprPrecedence::Unambiguous { + let mut sugg = if self.precedence(expr) >= ExprPrecedence::Unambiguous { vec![(span.shrink_to_hi(), ".into()".to_owned())] } else { vec![ @@ -3106,7 +3106,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "change the type of the numeric literal from `{checked_ty}` to `{expected_ty}`", ); - let close_paren = if expr.precedence() < ExprPrecedence::Unambiguous { + let close_paren = if self.precedence(expr) < ExprPrecedence::Unambiguous { sugg.push((expr.span.shrink_to_lo(), "(".to_string())); ")" } else { @@ -3131,7 +3131,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let len = src.trim_end_matches(&checked_ty.to_string()).len(); span.with_lo(span.lo() + BytePos(len as u32)) }, - if expr.precedence() < ExprPrecedence::Unambiguous { + if self.precedence(expr) < ExprPrecedence::Unambiguous { // Readd `)` format!("{expected_ty})") } else { diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 0238d6a39475..02d1ebdb31a9 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -18,6 +18,7 @@ use rustc_hir::def_id::{LOCAL_CRATE, StableCrateId, StableCrateIdMap}; use rustc_hir::definitions::Definitions; use rustc_incremental::setup_dep_graph; use rustc_lint::{BufferedEarlyLint, EarlyCheckNode, LintStore, unerased_lint_store}; +use rustc_metadata::EncodedMetadata; use rustc_metadata::creader::CStore; use rustc_middle::arena::Arena; use rustc_middle::dep_graph::DepsType; @@ -1174,7 +1175,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) { pub(crate) fn start_codegen<'tcx>( codegen_backend: &dyn CodegenBackend, tcx: TyCtxt<'tcx>, -) -> Box { +) -> (Box, EncodedMetadata) { // Hook for tests. if let Some((def_id, _)) = tcx.entry_fn(()) && tcx.has_attr(def_id, sym::rustc_delayed_bug_from_inside_query) @@ -1197,11 +1198,9 @@ pub(crate) fn start_codegen<'tcx>( info!("Pre-codegen\n{:?}", tcx.debug_stats()); - let (metadata, need_metadata_module) = rustc_metadata::fs::encode_and_write_metadata(tcx); + let metadata = rustc_metadata::fs::encode_and_write_metadata(tcx); - let codegen = tcx.sess.time("codegen_crate", move || { - codegen_backend.codegen_crate(tcx, metadata, need_metadata_module) - }); + let codegen = tcx.sess.time("codegen_crate", move || codegen_backend.codegen_crate(tcx)); info!("Post-codegen\n{:?}", tcx.debug_stats()); @@ -1211,7 +1210,7 @@ pub(crate) fn start_codegen<'tcx>( tcx.sess.code_stats.print_type_sizes(); } - codegen + (codegen, metadata) } /// Compute and validate the crate name. diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index c8914c9be9c0..9a474b910f68 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -5,6 +5,7 @@ use rustc_codegen_ssa::CodegenResults; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::svh::Svh; use rustc_hir::def_id::LOCAL_CRATE; +use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::DepGraph; use rustc_middle::ty::TyCtxt; use rustc_session::Session; @@ -18,6 +19,7 @@ pub struct Linker { output_filenames: Arc, // Only present when incr. comp. is enabled. crate_hash: Option, + metadata: EncodedMetadata, ongoing_codegen: Box, } @@ -26,7 +28,7 @@ impl Linker { tcx: TyCtxt<'_>, codegen_backend: &dyn CodegenBackend, ) -> Linker { - let ongoing_codegen = passes::start_codegen(codegen_backend, tcx); + let (ongoing_codegen, metadata) = passes::start_codegen(codegen_backend, tcx); Linker { dep_graph: tcx.dep_graph.clone(), @@ -36,6 +38,7 @@ impl Linker { } else { None }, + metadata, ongoing_codegen, } } @@ -75,6 +78,7 @@ impl Linker { sess, &rlink_file, &codegen_results, + &self.metadata, &*self.output_filenames, ) .unwrap_or_else(|error| { @@ -84,6 +88,6 @@ impl Linker { } let _timer = sess.prof.verbose_generic_activity("link_crate"); - codegen_backend.link(sess, codegen_results, &self.output_filenames) + codegen_backend.link(sess, codegen_results, self.metadata, &self.output_filenames) } } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 5419d688caae..82823581c121 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -27,7 +27,7 @@ use rustc_span::source_map::{RealFileLoader, SourceMapInputs}; use rustc_span::{FileName, SourceFileHashAlgorithm, sym}; use rustc_target::spec::{ CodeModel, FramePointer, LinkerFlavorCli, MergeFunctions, OnBrokenPipe, PanicStrategy, - RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel, WasmCAbi, + RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel, }; use crate::interface::{initialize_checked_jobserver, parse_cfg}; @@ -882,7 +882,6 @@ fn test_unstable_options_tracking_hash() { tracked!(verify_llvm_ir, true); tracked!(virtual_function_elimination, true); tracked!(wasi_exec_model, Some(WasiExecModel::Reactor)); - tracked!(wasm_c_abi, WasmCAbi::Spec); // tidy-alphabetical-end macro_rules! tracked_no_crate_hash { diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 5679d4566dcd..b6bf45dfbcfb 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -7,6 +7,7 @@ use std::cell::Cell; use std::slice; use rustc_ast::BindingMode; +use rustc_ast::util::parser::ExprPrecedence; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sync; use rustc_data_structures::unord::UnordMap; @@ -850,6 +851,20 @@ impl<'tcx> LateContext<'tcx> { }) } + /// Returns the effective precedence of an expression for the purpose of + /// rendering diagnostic. This is not the same as the precedence that would + /// be used for pretty-printing HIR by rustc_hir_pretty. + pub fn precedence(&self, expr: &hir::Expr<'_>) -> ExprPrecedence { + let for_each_attr = |id: hir::HirId, callback: &mut dyn FnMut(&hir::Attribute)| { + for attr in self.tcx.hir_attrs(id) { + if attr.span().desugaring_kind().is_none() { + callback(attr); + } + } + }; + expr.precedence(&for_each_attr) + } + /// If the given expression is a local binding, find the initializer expression. /// If that initializer expression is another local binding, find its initializer again. /// diff --git a/compiler/rustc_lint/src/dangling.rs b/compiler/rustc_lint/src/dangling.rs index 91c7922638de..c737919db9c2 100644 --- a/compiler/rustc_lint/src/dangling.rs +++ b/compiler/rustc_lint/src/dangling.rs @@ -1,4 +1,5 @@ use rustc_ast::visit::{visit_opt, walk_list}; +use rustc_attr_data_structures::{AttributeKind, find_attr}; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{FnKind, Visitor, walk_expr}; use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, LangItem}; @@ -133,7 +134,7 @@ fn lint_expr(cx: &LateContext<'_>, expr: &Expr<'_>) { && let ty = cx.typeck_results().expr_ty(receiver) && owns_allocation(cx.tcx, ty) && let Some(fn_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) - && cx.tcx.has_attr(fn_id, sym::rustc_as_ptr) + && find_attr!(cx.tcx.get_all_attrs(fn_id), AttributeKind::AsPtr(_)) { // FIXME: use `emit_node_lint` when `#[primary_span]` is added. cx.tcx.emit_node_span_lint( diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 12666d383f93..48e3bbb79fa0 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -33,10 +33,8 @@ pub struct EarlyContextAndPass<'ecx, 'tcx, T: EarlyLintPass> { } impl<'ecx, 'tcx, T: EarlyLintPass> EarlyContextAndPass<'ecx, 'tcx, T> { - // This always-inlined function is for the hot call site. - #[inline(always)] #[allow(rustc::diagnostic_outside_of_impl)] - fn inlined_check_id(&mut self, id: ast::NodeId) { + fn check_id(&mut self, id: ast::NodeId) { for early_lint in self.context.buffered.take(id) { let BufferedEarlyLint { span, node_id: _, lint_id, diagnostic } = early_lint; self.context.opt_span_lint(lint_id.lint, span, |diag| { @@ -45,11 +43,6 @@ impl<'ecx, 'tcx, T: EarlyLintPass> EarlyContextAndPass<'ecx, 'tcx, T> { } } - // This non-inlined function is for the cold call sites. - fn check_id(&mut self, id: ast::NodeId) { - self.inlined_check_id(id) - } - /// Merge the lints specified by any lint attributes into the /// current lint context, call the provided function, then reset the /// lints in effect to their previous state. @@ -61,7 +54,6 @@ impl<'ecx, 'tcx, T: EarlyLintPass> EarlyContextAndPass<'ecx, 'tcx, T> { debug!(?id); let push = self.context.builder.push(attrs, is_crate_node, None); - self.inlined_check_id(id); debug!("early context: enter_attrs({:?})", attrs); lint_callback!(self, check_attributes, attrs); ensure_sufficient_stack(|| f(self)); @@ -136,12 +128,8 @@ impl<'ast, 'ecx, 'tcx, T: EarlyLintPass> ast_visit::Visitor<'ast> // the AST struct that they wrap (e.g. an item) self.with_lint_attrs(s.id, s.attrs(), |cx| { lint_callback!(cx, check_stmt, s); + ast_visit::walk_stmt(cx, s); }); - // The visitor for the AST struct wrapped - // by the statement (e.g. `Item`) will call - // `with_lint_attrs`, so do this walk - // outside of the above `with_lint_attrs` call - ast_visit::walk_stmt(self, s); } fn visit_fn(&mut self, fk: ast_visit::FnKind<'ast>, span: Span, id: ast::NodeId) { diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index e84cdb581b5e..9a1490d3eea3 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -623,6 +623,7 @@ fn register_builtins(store: &mut LintStore) { "converted into hard error, \ see for more information", ); + store.register_removed("wasm_c_abi", "the wasm C ABI has been fixed"); } fn register_internals(store: &mut LintStore) { diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 295dd82fead9..b0ea9689e50d 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -140,7 +140,6 @@ declare_lint_pass! { UNUSED_VARIABLES, USELESS_DEPRECATED, WARNINGS, - WASM_C_ABI, // tidy-alphabetical-end ] } @@ -4100,6 +4099,7 @@ declare_lint! { @future_incompatible = FutureIncompatibleInfo { reason: FutureIncompatibilityReason::EditionAndFutureReleaseSemanticsChange(Edition::Edition2024), reference: "", + report_in_deps: true, }; @edition Edition2024 => Deny; report_in_external_macro @@ -4154,6 +4154,7 @@ declare_lint! { @future_incompatible = FutureIncompatibleInfo { reason: FutureIncompatibilityReason::EditionAndFutureReleaseError(Edition::Edition2024), reference: "", + report_in_deps: true, }; report_in_external_macro } @@ -4980,50 +4981,6 @@ declare_lint! { crate_level_only } -declare_lint! { - /// The `wasm_c_abi` lint detects usage of the `extern "C"` ABI of wasm that is affected - /// by a planned ABI change that has the goal of aligning Rust with the standard C ABI - /// of this target. - /// - /// ### Example - /// - /// ```rust,ignore (needs wasm32-unknown-unknown) - /// #[repr(C)] - /// struct MyType(i32, i32); - /// - /// extern "C" my_fun(x: MyType) {} - /// ``` - /// - /// This will produce: - /// - /// ```text - /// error: this function function definition is affected by the wasm ABI transition: it passes an argument of non-scalar type `MyType` - /// --> $DIR/wasm_c_abi_transition.rs:17:1 - /// | - /// | pub extern "C" fn my_fun(_x: MyType) {} - /// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - /// | - /// = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - /// = note: for more information, see issue #138762 - /// = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target - /// ``` - /// - /// ### Explanation - /// - /// Rust has historically implemented a non-spec-compliant C ABI on wasm32-unknown-unknown. This - /// has caused incompatibilities with other compilers and Wasm targets. In a future version - /// of Rust, this will be fixed, and therefore code relying on the non-spec-compliant C ABI will - /// stop functioning. - pub WASM_C_ABI, - Warn, - "detects code relying on rustc's non-spec-compliant wasm C ABI", - @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseError, - reference: "issue #138762 ", - report_in_deps: true, - }; -} - declare_lint! { /// The `aarch64_softfloat_neon` lint detects usage of `#[target_feature(enable = "neon")]` on /// softfloat aarch64 targets. Enabling this target feature causes LLVM to alter the ABI of diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs index e57534b847ef..1eaad26ff8e8 100644 --- a/compiler/rustc_metadata/src/fs.rs +++ b/compiler/rustc_metadata/src/fs.rs @@ -4,9 +4,9 @@ use std::{fs, io}; use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_fs_util::TempDirBuilder; use rustc_middle::ty::TyCtxt; +use rustc_session::Session; use rustc_session::config::{CrateType, OutFileName, OutputType}; use rustc_session::output::filename_for_metadata; -use rustc_session::{MetadataKind, Session}; use crate::errors::{ BinaryOutputToTty, FailedCopyToStdout, FailedCreateEncodedMetadata, FailedCreateFile, @@ -22,13 +22,8 @@ pub const METADATA_FILENAME: &str = "lib.rmeta"; /// building an `.rlib` (stomping over one another), or writing an `.rmeta` into a /// directory being searched for `extern crate` (observing an incomplete file). /// The returned path is the temporary file containing the complete metadata. -pub fn emit_wrapper_file( - sess: &Session, - data: &[u8], - tmpdir: &MaybeTempDir, - name: &str, -) -> PathBuf { - let out_filename = tmpdir.as_ref().join(name); +pub fn emit_wrapper_file(sess: &Session, data: &[u8], tmpdir: &Path, name: &str) -> PathBuf { + let out_filename = tmpdir.join(name); let result = fs::write(&out_filename, data); if let Err(err) = result { @@ -38,7 +33,7 @@ pub fn emit_wrapper_file( out_filename } -pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) { +pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { let out_filename = filename_for_metadata(tcx.sess, tcx.output_filenames(())); // To avoid races with another rustc process scanning the output directory, // we need to write the file somewhere else and atomically move it to its @@ -59,25 +54,20 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) { None }; - // Always create a file at `metadata_filename`, even if we have nothing to write to it. - // This simplifies the creation of the output `out_filename` when requested. - let metadata_kind = tcx.metadata_kind(); - match metadata_kind { - MetadataKind::None => { - std::fs::File::create(&metadata_filename).unwrap_or_else(|err| { - tcx.dcx().emit_fatal(FailedCreateFile { filename: &metadata_filename, err }); + if tcx.needs_metadata() { + encode_metadata(tcx, &metadata_filename, metadata_stub_filename.as_deref()); + } else { + // Always create a file at `metadata_filename`, even if we have nothing to write to it. + // This simplifies the creation of the output `out_filename` when requested. + std::fs::File::create(&metadata_filename).unwrap_or_else(|err| { + tcx.dcx().emit_fatal(FailedCreateFile { filename: &metadata_filename, err }); + }); + if let Some(metadata_stub_filename) = &metadata_stub_filename { + std::fs::File::create(metadata_stub_filename).unwrap_or_else(|err| { + tcx.dcx().emit_fatal(FailedCreateFile { filename: &metadata_stub_filename, err }); }); - if let Some(metadata_stub_filename) = &metadata_stub_filename { - std::fs::File::create(metadata_stub_filename).unwrap_or_else(|err| { - tcx.dcx() - .emit_fatal(FailedCreateFile { filename: &metadata_stub_filename, err }); - }); - } } - MetadataKind::Uncompressed | MetadataKind::Compressed => { - encode_metadata(tcx, &metadata_filename, metadata_stub_filename.as_deref()) - } - }; + } let _prof_timer = tcx.sess.prof.generic_activity("write_crate_metadata"); @@ -118,9 +108,7 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) { tcx.dcx().emit_fatal(FailedCreateEncodedMetadata { err }); }); - let need_metadata_module = metadata_kind == MetadataKind::Compressed; - - (metadata, need_metadata_module) + metadata } #[cfg(not(target_os = "linux"))] diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs index 3de97c8c0d99..e5e1ae508edc 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -1233,6 +1233,7 @@ pub(super) fn hir_module_items(tcx: TyCtxt<'_>, module_id: LocalModDefId) -> Mod body_owners: body_owners.into_boxed_slice(), opaques: opaques.into_boxed_slice(), nested_bodies: nested_bodies.into_boxed_slice(), + delayed_lint_items: Box::new([]), } } @@ -1254,6 +1255,7 @@ pub(crate) fn hir_crate_items(tcx: TyCtxt<'_>, _: ()) -> ModuleItems { body_owners, opaques, nested_bodies, + delayed_lint_items, .. } = collector; @@ -1266,6 +1268,7 @@ pub(crate) fn hir_crate_items(tcx: TyCtxt<'_>, _: ()) -> ModuleItems { body_owners: body_owners.into_boxed_slice(), opaques: opaques.into_boxed_slice(), nested_bodies: nested_bodies.into_boxed_slice(), + delayed_lint_items: delayed_lint_items.into_boxed_slice(), } } @@ -1282,6 +1285,7 @@ struct ItemCollector<'tcx> { body_owners: Vec, opaques: Vec, nested_bodies: Vec, + delayed_lint_items: Vec, } impl<'tcx> ItemCollector<'tcx> { @@ -1297,6 +1301,7 @@ impl<'tcx> ItemCollector<'tcx> { body_owners: Vec::default(), opaques: Vec::default(), nested_bodies: Vec::default(), + delayed_lint_items: Vec::default(), } } } @@ -1314,6 +1319,9 @@ impl<'hir> Visitor<'hir> for ItemCollector<'hir> { } self.items.push(item.item_id()); + if self.crate_collector && item.has_delayed_lints { + self.delayed_lint_items.push(item.item_id().owner_id); + } // Items that are modules are handled here instead of in visit_mod. if let ItemKind::Mod(_, module) = &item.kind { @@ -1329,6 +1337,9 @@ impl<'hir> Visitor<'hir> for ItemCollector<'hir> { fn visit_foreign_item(&mut self, item: &'hir ForeignItem<'hir>) { self.foreign_items.push(item.foreign_item_id()); + if self.crate_collector && item.has_delayed_lints { + self.delayed_lint_items.push(item.foreign_item_id().owner_id); + } intravisit::walk_foreign_item(self, item) } @@ -1362,6 +1373,10 @@ impl<'hir> Visitor<'hir> for ItemCollector<'hir> { } self.trait_items.push(item.trait_item_id()); + if self.crate_collector && item.has_delayed_lints { + self.delayed_lint_items.push(item.trait_item_id().owner_id); + } + intravisit::walk_trait_item(self, item) } @@ -1371,6 +1386,10 @@ impl<'hir> Visitor<'hir> for ItemCollector<'hir> { } self.impl_items.push(item.impl_item_id()); + if self.crate_collector && item.has_delayed_lints { + self.delayed_lint_items.push(item.impl_item_id().owner_id); + } + intravisit::walk_impl_item(self, item) } } diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index cb4760c18de5..9f79ed4b5a52 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -32,6 +32,8 @@ pub struct ModuleItems { opaques: Box<[LocalDefId]>, body_owners: Box<[LocalDefId]>, nested_bodies: Box<[LocalDefId]>, + // only filled with hir_crate_items, not with hir_module_items + delayed_lint_items: Box<[OwnerId]>, } impl ModuleItems { @@ -49,6 +51,10 @@ impl ModuleItems { self.trait_items.iter().copied() } + pub fn delayed_lint_items(&self) -> impl Iterator { + self.delayed_lint_items.iter().copied() + } + /// Returns all items that are associated with some `impl` block (both inherent and trait impl /// blocks). pub fn impl_items(&self) -> impl Iterator { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 15e8c1ef3cc0..63312eff4906 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1,8 +1,64 @@ -//! Defines the various compiler queries. //! -//! For more information on the query system, see -//! ["Queries: demand-driven compilation"](https://rustc-dev-guide.rust-lang.org/query.html). -//! This chapter includes instructions for adding new queries. +//! # The rustc Query System: Query Definitions and Modifiers +//! +//! The core processes in rustc are shipped as queries. Each query is a demand-driven function from some key to a value. +//! The execution result of the function is cached and directly read during the next request, thereby improving compilation efficiency. +//! Some results are saved locally and directly read during the next compilation, which are core of incremental compilation. +//! +//! ## How to Read This Module +//! +//! Each `query` block in this file defines a single query, specifying its key and value types, along with various modifiers. +//! These query definitions are processed by the [`rustc_macros`], which expands them into the necessary boilerplate code +//! for the query system—including the [`Providers`] struct (a function table for all query implementations, where each field is +//! a function pointer to the actual provider), caching, and dependency graph integration. +//! **Note:** The `Providers` struct is not a Rust trait, but a struct generated by the `rustc_macros` to hold all provider functions. +//! The `rustc_macros` also supports a set of **query modifiers** (see below) that control the behavior of each query. +//! +//! The actual provider functions are implemented in various modules and registered into the `Providers` struct +//! during compiler initialization (see [`rustc_interface::passes::DEFAULT_QUERY_PROVIDERS`]). +//! +//! [`rustc_macros`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_macros/index.html +//! [`rustc_interface::passes::DEFAULT_QUERY_PROVIDERS`]: ../../rustc_interface/passes/static.DEFAULT_QUERY_PROVIDERS.html +//! +//! ## Query Modifiers +//! +//! Query modifiers are special flags that alter the behavior of a query. They are parsed and processed by the `rustc_macros` +//! The main modifiers are: +//! +//! - `desc { ... }`: Sets the human-readable description for diagnostics and profiling. Required for every query. +//! - `arena_cache`: Use an arena for in-memory caching of the query result. +//! - `cache_on_disk_if { ... }`: Cache the query result to disk if the provided block evaluates to true. +//! - `fatal_cycle`: If a dependency cycle is detected, abort compilation with a fatal error. +//! - `cycle_delay_bug`: If a dependency cycle is detected, emit a delayed bug instead of aborting immediately. +//! - `cycle_stash`: If a dependency cycle is detected, stash the error for later handling. +//! - `no_hash`: Do not hash the query result for incremental compilation; just mark as dirty if recomputed. +//! - `anon`: Make the query anonymous in the dependency graph (no dep node is created). +//! - `eval_always`: Always evaluate the query, ignoring its dependencies and cached results. +//! - `depth_limit`: Impose a recursion depth limit on the query to prevent stack overflows. +//! - `separate_provide_extern`: Use separate provider functions for local and external crates. +//! - `feedable`: Allow the query result to be set from another query ("fed" externally). +//! - `return_result_from_ensure_ok`: When called via `tcx.ensure_ok()`, return `Result<(), ErrorGuaranteed>` instead of `()`. +//! If the query needs to be executed and returns an error, the error is returned to the caller. +//! Only valid for queries returning `Result<_, ErrorGuaranteed>`. +//! +//! For the up-to-date list, see the `QueryModifiers` struct in +//! [`rustc_macros/src/query.rs`](https://github.com/rust-lang/rust/blob/master/compiler/rustc_macros/src/query.rs) +//! and for more details in incremental compilation, see the +//! [Query modifiers in incremental compilation](https://rustc-dev-guide.rust-lang.org/queries/incremental-compilation-in-detail.html#query-modifiers) section of the rustc-dev-guide. +//! +//! ## Query Expansion and Code Generation +//! +//! The [`rustc_macros::rustc_queries`] macro expands each query definition into: +//! - A method on [`TyCtxt`] (and [`TyCtxtAt`]) for invoking the query. +//! - Provider traits and structs for supplying the query's value. +//! - Caching and dependency graph integration. +//! - Support for incremental compilation, disk caching, and arena allocation as controlled by the modifiers. +//! +//! [`rustc_macros::rustc_queries`]: ../../rustc_macros/macro.rustc_queries.html +//! +//! The macro-based approach allows the query system to be highly flexible and maintainable, while minimizing boilerplate. +//! +//! For more details, see the [rustc-dev-guide](https://rustc-dev-guide.rust-lang.org/query.html). #![allow(unused_parens)] diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs index 145561b76c4e..ef5223de0e82 100644 --- a/compiler/rustc_middle/src/traits/solve.rs +++ b/compiler/rustc_middle/src/traits/solve.rs @@ -49,6 +49,13 @@ impl<'tcx> TypeFoldable> for ExternalConstraints<'tcx> { self, folder: &mut F, ) -> Result { + // Perf testing has found that this check is slightly faster than + // folding and re-interning an empty `ExternalConstraintsData`. + // See: . + if self.is_empty() { + return Ok(self); + } + Ok(FallibleTypeFolder::cx(folder).mk_external_constraints(ExternalConstraintsData { region_constraints: self.region_constraints.clone().try_fold_with(folder)?, opaque_types: self @@ -64,6 +71,13 @@ impl<'tcx> TypeFoldable> for ExternalConstraints<'tcx> { } fn fold_with>>(self, folder: &mut F) -> Self { + // Perf testing has found that this check is slightly faster than + // folding and re-interning an empty `ExternalConstraintsData`. + // See: . + if self.is_empty() { + return self; + } + TypeFolder::cx(folder).mk_external_constraints(ExternalConstraintsData { region_constraints: self.region_constraints.clone().fold_with(folder), opaque_types: self.opaque_types.iter().map(|opaque| opaque.fold_with(folder)).collect(), diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index b4d8b2e71763..fe4dd8d080b6 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -47,7 +47,7 @@ use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; use rustc_session::config::CrateType; use rustc_session::cstore::{CrateStoreDyn, Untracked}; use rustc_session::lint::Lint; -use rustc_session::{Limit, MetadataKind, Session}; +use rustc_session::{Limit, Session}; use rustc_span::def_id::{CRATE_DEF_ID, DefPathHash, StableCrateId}; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym}; use rustc_type_ir::TyKind::*; @@ -1858,23 +1858,14 @@ impl<'tcx> TyCtxt<'tcx> { &self.crate_types } - pub fn metadata_kind(self) -> MetadataKind { - self.crate_types() - .iter() - .map(|ty| match *ty { - CrateType::Executable - | CrateType::Staticlib - | CrateType::Cdylib - | CrateType::Sdylib => MetadataKind::None, - CrateType::Rlib => MetadataKind::Uncompressed, - CrateType::Dylib | CrateType::ProcMacro => MetadataKind::Compressed, - }) - .max() - .unwrap_or(MetadataKind::None) - } - pub fn needs_metadata(self) -> bool { - self.metadata_kind() != MetadataKind::None + self.crate_types().iter().any(|ty| match *ty { + CrateType::Executable + | CrateType::Staticlib + | CrateType::Cdylib + | CrateType::Sdylib => false, + CrateType::Rlib | CrateType::Dylib | CrateType::ProcMacro => true, + }) } pub fn needs_crate_hash(self) -> bool { diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 9bce28456805..13c281a61827 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -16,9 +16,7 @@ use rustc_macros::{HashStable, TyDecodable, TyEncodable, extension}; use rustc_session::config::OptLevel; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym}; use rustc_target::callconv::FnAbi; -use rustc_target::spec::{ - HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, PanicStrategy, Target, WasmCAbi, X86Abi, -}; +use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, PanicStrategy, Target, X86Abi}; use tracing::debug; use {rustc_abi as abi, rustc_hir as hir}; @@ -565,12 +563,6 @@ impl<'tcx> HasTargetSpec for TyCtxt<'tcx> { } } -impl<'tcx> HasWasmCAbiOpt for TyCtxt<'tcx> { - fn wasm_c_abi_opt(&self) -> WasmCAbi { - self.sess.opts.unstable_opts.wasm_c_abi - } -} - impl<'tcx> HasX86AbiOpt for TyCtxt<'tcx> { fn x86_abi_opt(&self) -> X86Abi { X86Abi { @@ -625,12 +617,6 @@ impl<'tcx> HasTargetSpec for LayoutCx<'tcx> { } } -impl<'tcx> HasWasmCAbiOpt for LayoutCx<'tcx> { - fn wasm_c_abi_opt(&self) -> WasmCAbi { - self.calc.cx.wasm_c_abi_opt() - } -} - impl<'tcx> HasX86AbiOpt for LayoutCx<'tcx> { fn x86_abi_opt(&self) -> X86Abi { self.calc.cx.x86_abi_opt() diff --git a/compiler/rustc_mir_transform/src/coroutine/drop.rs b/compiler/rustc_mir_transform/src/coroutine/drop.rs index 6021e795d210..dc68629ec0d0 100644 --- a/compiler/rustc_mir_transform/src/coroutine/drop.rs +++ b/compiler/rustc_mir_transform/src/coroutine/drop.rs @@ -132,6 +132,7 @@ fn build_poll_switch<'tcx>( body: &mut Body<'tcx>, poll_enum: Ty<'tcx>, poll_unit_place: &Place<'tcx>, + fut_pin_place: &Place<'tcx>, ready_block: BasicBlock, yield_block: BasicBlock, ) -> BasicBlock { @@ -162,9 +163,11 @@ fn build_poll_switch<'tcx>( Rvalue::Discriminant(*poll_unit_place), ))), }; + let storage_dead = + Statement { source_info, kind: StatementKind::StorageDead(fut_pin_place.local) }; let unreachable_block = insert_term_block(body, TerminatorKind::Unreachable); body.basic_blocks_mut().push(BasicBlockData { - statements: [discr_assign].to_vec(), + statements: [storage_dead, discr_assign].to_vec(), terminator: Some(Terminator { source_info, kind: TerminatorKind::SwitchInt { @@ -332,10 +335,17 @@ pub(super) fn expand_async_drops<'tcx>( kind: StatementKind::Assign(Box::new((context_ref_place, arg))), }); let yield_block = insert_term_block(body, TerminatorKind::Unreachable); // `kind` replaced later to yield - let switch_block = - build_poll_switch(tcx, body, poll_enum, &poll_unit_place, target, yield_block); let (pin_bb, fut_pin_place) = build_pin_fut(tcx, body, fut_place.clone(), UnwindAction::Continue); + let switch_block = build_poll_switch( + tcx, + body, + poll_enum, + &poll_unit_place, + &fut_pin_place, + target, + yield_block, + ); let call_bb = build_poll_call( tcx, body, @@ -357,16 +367,17 @@ pub(super) fn expand_async_drops<'tcx>( body.local_decls.push(LocalDecl::new(context_mut_ref, source_info.span)), ); let drop_yield_block = insert_term_block(body, TerminatorKind::Unreachable); // `kind` replaced later to yield + let (pin_bb2, fut_pin_place2) = + build_pin_fut(tcx, body, fut_place, UnwindAction::Continue); let drop_switch_block = build_poll_switch( tcx, body, poll_enum, &poll_unit_place, + &fut_pin_place2, drop.unwrap(), drop_yield_block, ); - let (pin_bb2, fut_pin_place2) = - build_pin_fut(tcx, body, fut_place, UnwindAction::Continue); let drop_call_bb = build_poll_call( tcx, body, diff --git a/compiler/rustc_mir_transform/src/elaborate_drop.rs b/compiler/rustc_mir_transform/src/elaborate_drop.rs index 3a5e2620b149..c9bc52c6c7eb 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drop.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drop.rs @@ -390,6 +390,20 @@ where Location { block: self.succ, statement_index: 0 }, StatementKind::StorageDead(fut.local), ); + // StorageDead(fut) in unwind block (at the begin) + if let Unwind::To(block) = unwind { + self.elaborator.patch().add_statement( + Location { block, statement_index: 0 }, + StatementKind::StorageDead(fut.local), + ); + } + // StorageDead(fut) in dropline block (at the begin) + if let Some(block) = dropline { + self.elaborator.patch().add_statement( + Location { block, statement_index: 0 }, + StatementKind::StorageDead(fut.local), + ); + } // #1:pin_obj_bb >>> call Pin::new_unchecked(&mut obj) self.elaborator.patch().patch_terminator( diff --git a/compiler/rustc_monomorphize/messages.ftl b/compiler/rustc_monomorphize/messages.ftl index 35bedf4318ff..2bd19e81b01c 100644 --- a/compiler/rustc_monomorphize/messages.ftl +++ b/compiler/rustc_monomorphize/messages.ftl @@ -60,11 +60,4 @@ monomorphize_start_not_found = using `fn main` requires the standard library monomorphize_symbol_already_defined = symbol `{$symbol}` is already defined -monomorphize_wasm_c_abi_transition = - this function {$is_call -> - [true] call - *[false] definition - } involves an argument of type `{$ty}` which is affected by the wasm ABI transition - .help = the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target - monomorphize_written_to_path = the full type name has been written to '{$path}' diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index acf77b5916e4..938c427b56c8 100644 --- a/compiler/rustc_monomorphize/src/errors.rs +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -100,12 +100,3 @@ pub(crate) struct AbiRequiredTargetFeature<'a> { /// Whether this is a problem at a call site or at a declaration. pub is_call: bool, } - -#[derive(LintDiagnostic)] -#[diag(monomorphize_wasm_c_abi_transition)] -#[help] -pub(crate) struct WasmCAbiTransition<'a> { - pub ty: Ty<'a>, - /// Whether this is a problem at a call site or at a declaration. - pub is_call: bool, -} diff --git a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs index 8dbbb4d1713a..b8c001d357e6 100644 --- a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs +++ b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs @@ -3,13 +3,10 @@ use rustc_abi::{BackendRepr, CanonAbi, RegKind, X86Call}; use rustc_hir::{CRATE_HIR_ID, HirId}; use rustc_middle::mir::{self, Location, traversal}; -use rustc_middle::ty::layout::LayoutCx; -use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt, TypingEnv}; -use rustc_session::lint::builtin::WASM_C_ABI; +use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt}; use rustc_span::def_id::DefId; use rustc_span::{DUMMY_SP, Span, Symbol, sym}; -use rustc_target::callconv::{ArgAbi, FnAbi, PassMode}; -use rustc_target::spec::{HasWasmCAbiOpt, WasmCAbi}; +use rustc_target::callconv::{FnAbi, PassMode}; use crate::errors; @@ -81,73 +78,6 @@ fn do_check_simd_vector_abi<'tcx>( } } -/// Determines whether the given argument is passed the same way on the old and new wasm ABIs. -fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool { - if matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) { - return true; - } - - // Both the old and the new ABIs treat vector types like `v128` the same - // way. - if uses_vector_registers(&arg.mode, &arg.layout.backend_repr) { - return true; - } - - // This matches `unwrap_trivial_aggregate` in the wasm ABI logic. - if arg.layout.is_aggregate() { - let cx = LayoutCx::new(tcx, TypingEnv::fully_monomorphized()); - if let Some(unit) = arg.layout.homogeneous_aggregate(&cx).ok().and_then(|ha| ha.unit()) { - let size = arg.layout.size; - // Ensure there's just a single `unit` element in `arg`. - if unit.size == size { - return true; - } - } - } - - // Zero-sized types are dropped in both ABIs, so they're safe - if arg.layout.is_zst() { - return true; - } - - false -} - -/// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the -/// ABI transition. -fn do_check_wasm_abi<'tcx>( - tcx: TyCtxt<'tcx>, - abi: &FnAbi<'tcx, Ty<'tcx>>, - is_call: bool, - loc: impl Fn() -> (Span, HirId), -) { - // Only proceed for `extern "C" fn` on wasm32-unknown-unknown (same check as what - // `adjust_for_foreign_abi` uses to call `compute_wasm_abi_info`), and only proceed if - // `wasm_c_abi_opt` indicates we should emit the lint. - if !(tcx.sess.target.arch == "wasm32" - && tcx.sess.target.os == "unknown" - && tcx.wasm_c_abi_opt() == WasmCAbi::Legacy { with_lint: true } - && abi.conv == CanonAbi::C) - { - return; - } - // Warn against all types whose ABI will change. Return values are not affected by this change. - for arg_abi in abi.args.iter() { - if wasm_abi_safe(tcx, arg_abi) { - continue; - } - let (span, hir_id) = loc(); - tcx.emit_node_span_lint( - WASM_C_ABI, - hir_id, - span, - errors::WasmCAbiTransition { ty: arg_abi.layout.ty, is_call }, - ); - // Let's only warn once per function. - break; - } -} - /// Checks that the ABI of a given instance of a function does not contain vector-passed arguments /// or return values for which the corresponding target feature is not enabled. fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) { @@ -173,7 +103,6 @@ fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) { ) }; do_check_simd_vector_abi(tcx, abi, instance.def_id(), /*is_call*/ false, loc); - do_check_wasm_abi(tcx, abi, /*is_call*/ false, loc); } /// Checks that a call expression does not try to pass a vector-passed argument which requires a @@ -212,7 +141,6 @@ fn check_call_site_abi<'tcx>( return; }; do_check_simd_vector_abi(tcx, callee_abi, caller.def_id(), /*is_call*/ true, loc); - do_check_wasm_abi(tcx, callee_abi, /*is_call*/ true, loc); } fn check_callees_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, body: &mir::Body<'tcx>) { diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index b49a13ce584f..a64bb4241173 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -686,23 +686,34 @@ impl<'a> Parser<'a> { } if let token::DocComment(kind, style, _) = self.token.kind { - // We have something like `expr //!val` where the user likely meant `expr // !val` - let pos = self.token.span.lo() + BytePos(2); - let span = self.token.span.with_lo(pos).with_hi(pos); - err.span_suggestion_verbose( - span, - format!( - "add a space before {} to write a regular comment", - match (kind, style) { - (token::CommentKind::Line, ast::AttrStyle::Inner) => "`!`", - (token::CommentKind::Block, ast::AttrStyle::Inner) => "`!`", - (token::CommentKind::Line, ast::AttrStyle::Outer) => "the last `/`", - (token::CommentKind::Block, ast::AttrStyle::Outer) => "the last `*`", - }, - ), - " ".to_string(), - Applicability::MachineApplicable, - ); + // This is to avoid suggesting converting a doc comment to a regular comment + // when missing a comma before the doc comment in lists (#142311): + // + // ``` + // enum Foo{ + // A /// xxxxxxx + // B, + // } + // ``` + if !expected.contains(&TokenType::Comma) { + // We have something like `expr //!val` where the user likely meant `expr // !val` + let pos = self.token.span.lo() + BytePos(2); + let span = self.token.span.with_lo(pos).with_hi(pos); + err.span_suggestion_verbose( + span, + format!( + "add a space before {} to write a regular comment", + match (kind, style) { + (token::CommentKind::Line, ast::AttrStyle::Inner) => "`!`", + (token::CommentKind::Block, ast::AttrStyle::Inner) => "`!`", + (token::CommentKind::Line, ast::AttrStyle::Outer) => "the last `/`", + (token::CommentKind::Block, ast::AttrStyle::Outer) => "the last `*`", + }, + ), + " ".to_string(), + Applicability::MaybeIncorrect, + ); + } } let sp = if self.token == token::Eof { @@ -2273,23 +2284,18 @@ impl<'a> Parser<'a> { ), // Also catches `fn foo(&a)`. PatKind::Ref(ref inner_pat, mutab) - if matches!(inner_pat.clone().kind, PatKind::Ident(..)) => + if let PatKind::Ident(_, ident, _) = inner_pat.clone().kind => { - match inner_pat.clone().kind { - PatKind::Ident(_, ident, _) => { - let mutab = mutab.prefix_str(); - ( - ident, - "self: ", - format!("{ident}: &{mutab}TypeName"), - "_: ", - pat.span.shrink_to_lo(), - pat.span, - pat.span.shrink_to_lo(), - ) - } - _ => unreachable!(), - } + let mutab = mutab.prefix_str(); + ( + ident, + "self: ", + format!("{ident}: &{mutab}TypeName"), + "_: ", + pat.span.shrink_to_lo(), + pat.span, + pat.span.shrink_to_lo(), + ) } _ => { // Otherwise, try to get a type and emit a suggestion. diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 4e2be8ff0b81..dddbf65db72e 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -147,6 +147,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::ConstStabilityIndirect | AttributeKind::MacroTransparency(_), ) => { /* do nothing */ } + Attribute::Parsed(AttributeKind::AsPtr(attr_span)) => { + self.check_applied_to_fn_or_method(hir_id, *attr_span, span, target) + } Attribute::Unparsed(_) => { match attr.path().as_slice() { [sym::diagnostic, sym::do_not_recommend, ..] => { @@ -188,26 +191,23 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.check_rustc_std_internal_symbol(attr, span, target) } [sym::naked, ..] => self.check_naked(hir_id, attr, span, target, attrs), - [sym::rustc_as_ptr, ..] => { - self.check_applied_to_fn_or_method(hir_id, attr, span, target) - } [sym::rustc_no_implicit_autorefs, ..] => { - self.check_applied_to_fn_or_method(hir_id, attr, span, target) + self.check_applied_to_fn_or_method(hir_id, attr.span(), span, target) } [sym::rustc_never_returns_null_ptr, ..] => { - self.check_applied_to_fn_or_method(hir_id, attr, span, target) + self.check_applied_to_fn_or_method(hir_id, attr.span(), span, target) } [sym::rustc_legacy_const_generics, ..] => { self.check_rustc_legacy_const_generics(hir_id, attr, span, target, item) } [sym::rustc_lint_query_instability, ..] => { - self.check_applied_to_fn_or_method(hir_id, attr, span, target) + self.check_applied_to_fn_or_method(hir_id, attr.span(), span, target) } [sym::rustc_lint_untracked_query_information, ..] => { - self.check_applied_to_fn_or_method(hir_id, attr, span, target) + self.check_applied_to_fn_or_method(hir_id, attr.span(), span, target) } [sym::rustc_lint_diagnostics, ..] => { - self.check_applied_to_fn_or_method(hir_id, attr, span, target) + self.check_applied_to_fn_or_method(hir_id, attr.span(), span, target) } [sym::rustc_lint_opt_ty, ..] => self.check_rustc_lint_opt_ty(attr, span, target), [sym::rustc_lint_opt_deny_field_access, ..] => { @@ -1825,15 +1825,15 @@ impl<'tcx> CheckAttrVisitor<'tcx> { fn check_applied_to_fn_or_method( &self, hir_id: HirId, - attr: &Attribute, - span: Span, + attr_span: Span, + defn_span: Span, target: Target, ) { let is_function = matches!(target, Target::Fn | Target::Method(..)); if !is_function { self.dcx().emit_err(errors::AttrShouldBeAppliedToFn { - attr_span: attr.span(), - defn_span: span, + attr_span, + defn_span, on_crate: hir_id == CRATE_HIR_ID, }); } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index fa4b024c422f..338d9edcd22f 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -415,24 +415,24 @@ pub(crate) enum AliasPossibility { } #[derive(Copy, Clone, Debug)] -pub(crate) enum PathSource<'a, 'c> { +pub(crate) enum PathSource<'a, 'ast, 'ra> { /// Type paths `Path`. Type, /// Trait paths in bounds or impls. Trait(AliasPossibility), /// Expression paths `path`, with optional parent context. - Expr(Option<&'a Expr>), + Expr(Option<&'ast Expr>), /// Paths in path patterns `Path`. Pat, /// Paths in struct expressions and patterns `Path { .. }`. Struct, /// Paths in tuple struct patterns `Path(..)`. - TupleStruct(Span, &'a [Span]), + TupleStruct(Span, &'ra [Span]), /// `m::A::B` in `::B::C`. /// /// Second field holds the "cause" of this one, i.e. the context within /// which the trait item is resolved. Used for diagnostics. - TraitItem(Namespace, &'c PathSource<'a, 'c>), + TraitItem(Namespace, &'a PathSource<'a, 'ast, 'ra>), /// Paths in delegation item Delegation, /// An arg in a `use<'a, N>` precise-capturing bound. @@ -443,7 +443,7 @@ pub(crate) enum PathSource<'a, 'c> { DefineOpaques, } -impl<'a> PathSource<'a, '_> { +impl PathSource<'_, '_, '_> { fn namespace(self) -> Namespace { match self { PathSource::Type @@ -773,7 +773,7 @@ struct LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } /// Walks the whole crate in DFS order, visiting each item, resolving names as it goes. -impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { +impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { fn visit_attribute(&mut self, _: &'ast Attribute) { // We do not want to resolve expressions that appear in attributes, // as they do not correspond to actual code. @@ -1462,7 +1462,7 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r } } -impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { +impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { fn new(resolver: &'a mut Resolver<'ra, 'tcx>) -> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // During late resolution we only track the module component of the parent scope, // although it may be useful to track other components as well for diagnostics. @@ -2010,7 +2010,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { &mut self, partial_res: PartialRes, path: &[Segment], - source: PathSource<'_, '_>, + source: PathSource<'_, '_, '_>, path_span: Span, ) { let proj_start = path.len() - partial_res.unresolved_segments(); @@ -4161,7 +4161,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { id: NodeId, qself: &Option>, path: &Path, - source: PathSource<'ast, '_>, + source: PathSource<'_, 'ast, '_>, ) { self.smart_resolve_path_fragment( qself, @@ -4178,7 +4178,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { &mut self, qself: &Option>, path: &[Segment], - source: PathSource<'ast, '_>, + source: PathSource<'_, 'ast, '_>, finalize: Finalize, record_partial_res: RecordPartialRes, parent_qself: Option<&QSelf>, @@ -4482,7 +4482,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { span: Span, defer_to_typeck: bool, finalize: Finalize, - source: PathSource<'ast, '_>, + source: PathSource<'_, 'ast, '_>, ) -> Result, Spanned>> { let mut fin_res = None; @@ -4525,7 +4525,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { path: &[Segment], ns: Namespace, finalize: Finalize, - source: PathSource<'ast, '_>, + source: PathSource<'_, 'ast, '_>, ) -> Result, Spanned>> { debug!( "resolve_qpath(qself={:?}, path={:?}, ns={:?}, finalize={:?})", diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 2f6aed35f252..d5dd3bdb6cd8 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -170,12 +170,12 @@ impl TypoCandidate { } } -impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { +impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { fn make_base_error( &mut self, path: &[Segment], span: Span, - source: PathSource<'_, '_>, + source: PathSource<'_, '_, '_>, res: Option, ) -> BaseError { // Make the base error. @@ -421,7 +421,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { path: &[Segment], following_seg: Option<&Segment>, span: Span, - source: PathSource<'_, '_>, + source: PathSource<'_, '_, '_>, res: Option, qself: Option<&QSelf>, ) -> (Diag<'tcx>, Vec) { @@ -539,7 +539,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { path: &[Segment], following_seg: Option<&Segment>, span: Span, - source: PathSource<'_, '_>, + source: PathSource<'_, '_, '_>, res: Option, qself: Option<&QSelf>, ) { @@ -650,7 +650,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { fn try_lookup_name_relaxed( &mut self, err: &mut Diag<'_>, - source: PathSource<'_, '_>, + source: PathSource<'_, '_, '_>, path: &[Segment], following_seg: Option<&Segment>, span: Span, @@ -940,7 +940,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { fn suggest_trait_and_bounds( &mut self, err: &mut Diag<'_>, - source: PathSource<'_, '_>, + source: PathSource<'_, '_, '_>, res: Option, span: Span, base_error: &BaseError, @@ -1017,7 +1017,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { fn suggest_typo( &mut self, err: &mut Diag<'_>, - source: PathSource<'_, '_>, + source: PathSource<'_, '_, '_>, path: &[Segment], following_seg: Option<&Segment>, span: Span, @@ -1063,7 +1063,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { fn suggest_shadowed( &mut self, err: &mut Diag<'_>, - source: PathSource<'_, '_>, + source: PathSource<'_, '_, '_>, path: &[Segment], following_seg: Option<&Segment>, span: Span, @@ -1096,7 +1096,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { fn err_code_special_cases( &mut self, err: &mut Diag<'_>, - source: PathSource<'_, '_>, + source: PathSource<'_, '_, '_>, path: &[Segment], span: Span, ) { @@ -1141,7 +1141,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { fn suggest_self_ty( &mut self, err: &mut Diag<'_>, - source: PathSource<'_, '_>, + source: PathSource<'_, '_, '_>, path: &[Segment], span: Span, ) -> bool { @@ -1164,7 +1164,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { fn suggest_self_value( &mut self, err: &mut Diag<'_>, - source: PathSource<'_, '_>, + source: PathSource<'_, '_, '_>, path: &[Segment], span: Span, ) -> bool { @@ -1332,7 +1332,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { fn suggest_swapping_misplaced_self_ty_and_trait( &mut self, err: &mut Diag<'_>, - source: PathSource<'_, '_>, + source: PathSource<'_, '_, '_>, res: Option, span: Span, ) { @@ -1361,7 +1361,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { &mut self, err: &mut Diag<'_>, res: Option, - source: PathSource<'_, '_>, + source: PathSource<'_, '_, '_>, ) { let PathSource::TupleStruct(_, _) = source else { return }; let Some(Res::Def(DefKind::Fn, _)) = res else { return }; @@ -1373,7 +1373,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { &mut self, err: &mut Diag<'_>, res: Option, - source: PathSource<'_, '_>, + source: PathSource<'_, '_, '_>, span: Span, ) { let PathSource::Trait(_) = source else { return }; @@ -1422,7 +1422,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { fn suggest_pattern_match_with_let( &mut self, err: &mut Diag<'_>, - source: PathSource<'_, '_>, + source: PathSource<'_, '_, '_>, span: Span, ) -> bool { if let PathSource::Expr(_) = source @@ -1448,7 +1448,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { fn get_single_associated_item( &mut self, path: &[Segment], - source: &PathSource<'_, '_>, + source: &PathSource<'_, '_, '_>, filter_fn: &impl Fn(Res) -> bool, ) -> Option { if let crate::PathSource::TraitItem(_, _) = source { @@ -1556,7 +1556,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { /// Check if the source is call expression and the first argument is `self`. If true, /// return the span of whole call and the span for all arguments expect the first one (`self`). - fn call_has_self_arg(&self, source: PathSource<'_, '_>) -> Option<(Span, Option)> { + fn call_has_self_arg(&self, source: PathSource<'_, '_, '_>) -> Option<(Span, Option)> { let mut has_self_arg = None; if let PathSource::Expr(Some(parent)) = source && let ExprKind::Call(_, args) = &parent.kind @@ -1614,7 +1614,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { &mut self, err: &mut Diag<'_>, span: Span, - source: PathSource<'_, '_>, + source: PathSource<'_, '_, '_>, path: &[Segment], res: Res, path_str: &str, @@ -1666,7 +1666,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } }; - let find_span = |source: &PathSource<'_, '_>, err: &mut Diag<'_>| { + let find_span = |source: &PathSource<'_, '_, '_>, err: &mut Diag<'_>| { match source { PathSource::Expr(Some(Expr { span, kind: ExprKind::Call(_, _), .. })) | PathSource::TupleStruct(span, _) => { @@ -2699,7 +2699,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { fn suggest_using_enum_variant( &mut self, err: &mut Diag<'_>, - source: PathSource<'_, '_>, + source: PathSource<'_, '_, '_>, def_id: DefId, span: Span, ) { @@ -2877,7 +2877,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { pub(crate) fn suggest_adding_generic_parameter( &self, path: &[Segment], - source: PathSource<'_, '_>, + source: PathSource<'_, '_, '_>, ) -> Option<(Span, &'static str, String, Applicability)> { let (ident, span) = match path { [segment] diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 8984634e5ec6..406a6bd335a7 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -3066,7 +3066,7 @@ pub(crate) mod dep_tracking { use rustc_target::spec::{ CodeModel, FramePointer, MergeFunctions, OnBrokenPipe, PanicStrategy, RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, SymbolVisibility, TargetTuple, - TlsModel, WasmCAbi, + TlsModel, }; use super::{ @@ -3177,7 +3177,6 @@ pub(crate) mod dep_tracking { Polonius, InliningThreshold, FunctionReturn, - WasmCAbi, Align, ); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 6218521d4f06..f76f258d00de 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -16,7 +16,7 @@ use rustc_span::{RealFileName, SourceFileHashAlgorithm}; use rustc_target::spec::{ CodeModel, FramePointer, LinkerFlavorCli, MergeFunctions, OnBrokenPipe, PanicStrategy, RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, SymbolVisibility, - TargetTuple, TlsModel, WasmCAbi, + TargetTuple, TlsModel, }; use crate::config::*; @@ -802,7 +802,6 @@ mod desc { "either a boolean (`yes`, `no`, `on`, `off`, etc), or a non-negative number"; pub(crate) const parse_llvm_module_flag: &str = ":::. Type must currently be `u32`. Behavior should be one of (`error`, `warning`, `require`, `override`, `append`, `appendunique`, `max`, `min`)"; pub(crate) const parse_function_return: &str = "`keep` or `thunk-extern`"; - pub(crate) const parse_wasm_c_abi: &str = "`legacy` or `spec`"; pub(crate) const parse_mir_include_spans: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), or `nll` (default: `nll`)"; pub(crate) const parse_align: &str = "a number that is a power of 2 between 1 and 2^29"; @@ -1898,16 +1897,6 @@ pub mod parse { true } - pub(crate) fn parse_wasm_c_abi(slot: &mut WasmCAbi, v: Option<&str>) -> bool { - match v { - Some("spec") => *slot = WasmCAbi::Spec, - // Explicitly setting the `-Z` flag suppresses the lint. - Some("legacy") => *slot = WasmCAbi::Legacy { with_lint: false }, - _ => return false, - } - true - } - pub(crate) fn parse_mir_include_spans(slot: &mut MirIncludeSpans, v: Option<&str>) -> bool { *slot = match v { Some("on" | "yes" | "y" | "true") | None => MirIncludeSpans::On, @@ -2642,8 +2631,6 @@ written to standard error output)"), Requires `-Clto[=[fat,yes]]`"), wasi_exec_model: Option = (None, parse_wasi_exec_model, [TRACKED], "whether to build a wasi command or reactor"), - wasm_c_abi: WasmCAbi = (WasmCAbi::Legacy { with_lint: true }, parse_wasm_c_abi, [TRACKED], - "use spec-compliant C ABI for `wasm32-unknown-unknown` (default: legacy)"), write_long_types_to_disk: bool = (true, parse_bool, [UNTRACKED], "whether long type names should be written to files instead of being printed in errors"), // tidy-alphabetical-end diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 6b85e0abc868..b8b4518b14e2 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -215,13 +215,6 @@ pub struct Session { pub invocation_temp: Option, } -#[derive(PartialEq, Eq, PartialOrd, Ord)] -pub enum MetadataKind { - None, - Uncompressed, - Compressed, -} - #[derive(Clone, Copy)] pub enum CodegenUnits { /// Specified by the user. In this case we try fairly hard to produce the diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index ef8c88355f62..baa4c0681e80 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -12,7 +12,8 @@ use rustc_middle::ty::layout::{ }; use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths}; use rustc_middle::ty::{ - GenericPredicates, Instance, List, ScalarInt, TyCtxt, TypeVisitableExt, ValTree, + CoroutineArgsExt, GenericPredicates, Instance, List, ScalarInt, TyCtxt, TypeVisitableExt, + ValTree, }; use rustc_middle::{mir, ty}; use rustc_span::def_id::LOCAL_CRATE; @@ -22,9 +23,9 @@ use stable_mir::mir::mono::{InstanceDef, StaticDef}; use stable_mir::mir::{BinOp, Body, Place, UnOp}; use stable_mir::target::{MachineInfo, MachineSize}; use stable_mir::ty::{ - AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, FieldDef, FnDef, ForeignDef, - ForeignItemKind, GenericArgs, IntrinsicDef, LineInfo, MirConst, PolyFnSig, RigidTy, Span, Ty, - TyConst, TyKind, UintTy, VariantDef, + AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, CoroutineDef, Discr, FieldDef, FnDef, + ForeignDef, ForeignItemKind, GenericArgs, IntrinsicDef, LineInfo, MirConst, PolyFnSig, RigidTy, + Span, Ty, TyConst, TyKind, UintTy, VariantDef, VariantIdx, }; use stable_mir::{Crate, CrateDef, CrateItem, CrateNum, DefId, Error, Filename, ItemKind, Symbol}; @@ -447,6 +448,30 @@ impl<'tcx> SmirCtxt<'tcx> { def.internal(&mut *tables, tcx).variants().len() } + /// Discriminant for a given variant index of AdtDef + pub fn adt_discr_for_variant(&self, adt: AdtDef, variant: VariantIdx) -> Discr { + let mut tables = self.0.borrow_mut(); + let tcx = tables.tcx; + let adt = adt.internal(&mut *tables, tcx); + let variant = variant.internal(&mut *tables, tcx); + adt.discriminant_for_variant(tcx, variant).stable(&mut *tables) + } + + /// Discriminant for a given variand index and args of a coroutine + pub fn coroutine_discr_for_variant( + &self, + coroutine: CoroutineDef, + args: &GenericArgs, + variant: VariantIdx, + ) -> Discr { + let mut tables = self.0.borrow_mut(); + let tcx = tables.tcx; + let coroutine = coroutine.def_id().internal(&mut *tables, tcx); + let args = args.internal(&mut *tables, tcx); + let variant = variant.internal(&mut *tables, tcx); + args.as_coroutine().discriminant_for_variant(coroutine, tcx, variant).stable(&mut *tables) + } + /// The name of a variant. pub fn variant_name(&self, def: VariantDef) -> Symbol { let mut tables = self.0.borrow_mut(); diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index 6a26f5f79974..b4239ddd896e 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -960,3 +960,11 @@ impl<'tcx> Stable<'tcx> for ty::ImplTraitInTraitData { } } } + +impl<'tcx> Stable<'tcx> for rustc_middle::ty::util::Discr<'tcx> { + type T = stable_mir::ty::Discr; + + fn stable(&self, tables: &mut Tables<'_>) -> Self::T { + stable_mir::ty::Discr { val: self.val, ty: self.ty.stable(tables) } + } +} diff --git a/compiler/rustc_smir/src/stable_mir/compiler_interface.rs b/compiler/rustc_smir/src/stable_mir/compiler_interface.rs index 3967ad13eebd..2668fba9f4f6 100644 --- a/compiler/rustc_smir/src/stable_mir/compiler_interface.rs +++ b/compiler/rustc_smir/src/stable_mir/compiler_interface.rs @@ -13,10 +13,10 @@ use stable_mir::mir::mono::{Instance, InstanceDef, StaticDef}; use stable_mir::mir::{BinOp, Body, Place, UnOp}; use stable_mir::target::MachineInfo; use stable_mir::ty::{ - AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, FieldDef, FnDef, ForeignDef, - ForeignItemKind, ForeignModule, ForeignModuleDef, GenericArgs, GenericPredicates, Generics, - ImplDef, ImplTrait, IntrinsicDef, LineInfo, MirConst, PolyFnSig, RigidTy, Span, TraitDecl, - TraitDef, Ty, TyConst, TyConstId, TyKind, UintTy, VariantDef, + AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, CoroutineDef, Discr, FieldDef, FnDef, + ForeignDef, ForeignItemKind, ForeignModule, ForeignModuleDef, GenericArgs, GenericPredicates, + Generics, ImplDef, ImplTrait, IntrinsicDef, LineInfo, MirConst, PolyFnSig, RigidTy, Span, + TraitDecl, TraitDef, Ty, TyConst, TyConstId, TyKind, UintTy, VariantDef, VariantIdx, }; use stable_mir::{ AssocItems, Crate, CrateItem, CrateItems, CrateNum, DefId, Error, Filename, ImplTraitDecls, @@ -230,6 +230,21 @@ impl<'tcx> SmirInterface<'tcx> { self.cx.adt_variants_len(def) } + /// Discriminant for a given variant index of AdtDef + pub(crate) fn adt_discr_for_variant(&self, adt: AdtDef, variant: VariantIdx) -> Discr { + self.cx.adt_discr_for_variant(adt, variant) + } + + /// Discriminant for a given variand index and args of a coroutine + pub(crate) fn coroutine_discr_for_variant( + &self, + coroutine: CoroutineDef, + args: &GenericArgs, + variant: VariantIdx, + ) -> Discr { + self.cx.coroutine_discr_for_variant(coroutine, args, variant) + } + /// The name of a variant. pub(crate) fn variant_name(&self, def: VariantDef) -> Symbol { self.cx.variant_name(def) diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index 2934af31cd5d..4415cd6e2e3b 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -756,6 +756,12 @@ crate_def! { pub CoroutineDef; } +impl CoroutineDef { + pub fn discriminant_for_variant(&self, args: &GenericArgs, idx: VariantIdx) -> Discr { + with(|cx| cx.coroutine_discr_for_variant(*self, args, idx)) + } +} + crate_def! { #[derive(Serialize)] pub CoroutineClosureDef; @@ -831,6 +837,15 @@ impl AdtDef { pub fn repr(&self) -> ReprOptions { with(|cx| cx.adt_repr(*self)) } + + pub fn discriminant_for_variant(&self, idx: VariantIdx) -> Discr { + with(|cx| cx.adt_discr_for_variant(*self, idx)) + } +} + +pub struct Discr { + pub val: u128, + pub ty: Ty, } /// Definition of a variant, which can be either a struct / union field or an enum variant. diff --git a/compiler/rustc_target/src/asm/loongarch.rs b/compiler/rustc_target/src/asm/loongarch.rs index 8783d3953b16..51e7ee8daa43 100644 --- a/compiler/rustc_target/src/asm/loongarch.rs +++ b/compiler/rustc_target/src/asm/loongarch.rs @@ -37,9 +37,11 @@ impl LoongArchInlineAsmRegClass { arch: InlineAsmArch, ) -> &'static [(InlineAsmType, Option)] { match (self, arch) { - (Self::reg, InlineAsmArch::LoongArch64) => types! { _: I8, I16, I32, I64, F32, F64; }, - (Self::reg, InlineAsmArch::LoongArch32) => types! { _: I8, I16, I32, F32; }, - (Self::freg, _) => types! { f: F32; d: F64; }, + (Self::reg, InlineAsmArch::LoongArch64) => { + types! { _: I8, I16, I32, I64, F16, F32, F64; } + } + (Self::reg, InlineAsmArch::LoongArch32) => types! { _: I8, I16, I32, F16, F32; }, + (Self::freg, _) => types! { f: F16, F32; d: F64; }, _ => unreachable!("unsupported register class"), } } diff --git a/compiler/rustc_target/src/callconv/mips64.rs b/compiler/rustc_target/src/callconv/mips64.rs index 89f324bc3130..77c0cf06fc16 100644 --- a/compiler/rustc_target/src/callconv/mips64.rs +++ b/compiler/rustc_target/src/callconv/mips64.rs @@ -2,9 +2,7 @@ use rustc_abi::{ BackendRepr, FieldsShape, Float, HasDataLayout, Primitive, Reg, Size, TyAbiInterface, }; -use crate::callconv::{ - ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, FnAbi, PassMode, Uniform, -}; +use crate::callconv::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Uniform}; fn extend_integer_width_mips(arg: &mut ArgAbi<'_, Ty>, bits: u64) { // Always sign extend u32 values on 64-bit mips @@ -140,16 +138,7 @@ where // Extract first 8 chunks as the prefix let rest_size = size - Size::from_bytes(8) * prefix_index as u64; - arg.cast_to(CastTarget { - prefix, - rest: Uniform::new(Reg::i64(), rest_size), - attrs: ArgAttributes { - regular: ArgAttribute::default(), - arg_ext: ArgExtension::None, - pointee_size: Size::ZERO, - pointee_align: None, - }, - }); + arg.cast_to(CastTarget::prefixed(prefix, Uniform::new(Reg::i64(), rest_size))); } pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index f9ecf02f857f..71cc2a455638 100644 --- a/compiler/rustc_target/src/callconv/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -7,7 +7,7 @@ use rustc_abi::{ use rustc_macros::HashStable_Generic; pub use crate::spec::AbiMap; -use crate::spec::{HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, WasmCAbi}; +use crate::spec::{HasTargetSpec, HasX86AbiOpt}; mod aarch64; mod amdgpu; @@ -197,6 +197,17 @@ impl ArgAttributes { } } +impl From for ArgAttributes { + fn from(value: ArgAttribute) -> Self { + Self { + regular: value, + arg_ext: ArgExtension::None, + pointee_size: Size::ZERO, + pointee_align: None, + } + } +} + /// An argument passed entirely registers with the /// same kind (e.g., HFA / HVA on PPC64 and AArch64). #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)] @@ -251,6 +262,9 @@ impl Uniform { #[derive(Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub struct CastTarget { pub prefix: [Option; 8], + /// The offset of `rest` from the start of the value. Currently only implemented for a `Reg` + /// pair created by the `offset_pair` method. + pub rest_offset: Option, pub rest: Uniform, pub attrs: ArgAttributes, } @@ -263,42 +277,45 @@ impl From for CastTarget { impl From for CastTarget { fn from(uniform: Uniform) -> CastTarget { - CastTarget { - prefix: [None; 8], - rest: uniform, - attrs: ArgAttributes { - regular: ArgAttribute::default(), - arg_ext: ArgExtension::None, - pointee_size: Size::ZERO, - pointee_align: None, - }, - } + Self::prefixed([None; 8], uniform) } } impl CastTarget { - pub fn pair(a: Reg, b: Reg) -> CastTarget { - CastTarget { + pub fn prefixed(prefix: [Option; 8], rest: Uniform) -> Self { + Self { prefix, rest_offset: None, rest, attrs: ArgAttributes::new() } + } + + pub fn offset_pair(a: Reg, offset_from_start: Size, b: Reg) -> Self { + Self { prefix: [Some(a), None, None, None, None, None, None, None], - rest: Uniform::from(b), - attrs: ArgAttributes { - regular: ArgAttribute::default(), - arg_ext: ArgExtension::None, - pointee_size: Size::ZERO, - pointee_align: None, - }, + rest_offset: Some(offset_from_start), + rest: b.into(), + attrs: ArgAttributes::new(), } } + pub fn with_attrs(mut self, attrs: ArgAttributes) -> Self { + self.attrs = attrs; + self + } + + pub fn pair(a: Reg, b: Reg) -> CastTarget { + Self::prefixed([Some(a), None, None, None, None, None, None, None], Uniform::from(b)) + } + /// When you only access the range containing valid data, you can use this unaligned size; /// otherwise, use the safer `size` method. pub fn unaligned_size(&self, _cx: &C) -> Size { // Prefix arguments are passed in specific designated registers - let prefix_size = self - .prefix - .iter() - .filter_map(|x| x.map(|reg| reg.size)) - .fold(Size::ZERO, |acc, size| acc + size); + let prefix_size = if let Some(offset_from_start) = self.rest_offset { + offset_from_start + } else { + self.prefix + .iter() + .filter_map(|x| x.map(|reg| reg.size)) + .fold(Size::ZERO, |acc, size| acc + size) + }; // Remaining arguments are passed in chunks of the unit size let rest_size = self.rest.unit.size * self.rest.total.bytes().div_ceil(self.rest.unit.size.bytes()); @@ -322,9 +339,22 @@ impl CastTarget { /// Checks if these two `CastTarget` are equal enough to be considered "the same for all /// function call ABIs". pub fn eq_abi(&self, other: &Self) -> bool { - let CastTarget { prefix: prefix_l, rest: rest_l, attrs: attrs_l } = self; - let CastTarget { prefix: prefix_r, rest: rest_r, attrs: attrs_r } = other; - prefix_l == prefix_r && rest_l == rest_r && attrs_l.eq_abi(attrs_r) + let CastTarget { + prefix: prefix_l, + rest_offset: rest_offset_l, + rest: rest_l, + attrs: attrs_l, + } = self; + let CastTarget { + prefix: prefix_r, + rest_offset: rest_offset_r, + rest: rest_r, + attrs: attrs_r, + } = other; + prefix_l == prefix_r + && rest_offset_l == rest_offset_r + && rest_l == rest_r + && attrs_l.eq_abi(attrs_r) } } @@ -593,7 +623,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { pub fn adjust_for_foreign_abi(&mut self, cx: &C, abi: ExternAbi) where Ty: TyAbiInterface<'a, C> + Copy, - C: HasDataLayout + HasTargetSpec + HasWasmCAbiOpt + HasX86AbiOpt, + C: HasDataLayout + HasTargetSpec + HasX86AbiOpt, { if abi == ExternAbi::X86Interrupt { if let Some(arg) = self.args.first_mut() { @@ -669,14 +699,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { "hexagon" => hexagon::compute_abi_info(self), "xtensa" => xtensa::compute_abi_info(cx, self), "riscv32" | "riscv64" => riscv::compute_abi_info(cx, self), - "wasm32" => { - if spec.os == "unknown" && matches!(cx.wasm_c_abi_opt(), WasmCAbi::Legacy { .. }) { - wasm::compute_wasm_abi_info(self) - } else { - wasm::compute_c_abi_info(cx, self) - } - } - "wasm64" => wasm::compute_c_abi_info(cx, self), + "wasm32" | "wasm64" => wasm::compute_abi_info(cx, self), "bpf" => bpf::compute_abi_info(self), arch => panic!("no lowering implemented for {arch}"), } diff --git a/compiler/rustc_target/src/callconv/nvptx64.rs b/compiler/rustc_target/src/callconv/nvptx64.rs index a26e7dac5baf..44977de7fcbc 100644 --- a/compiler/rustc_target/src/callconv/nvptx64.rs +++ b/compiler/rustc_target/src/callconv/nvptx64.rs @@ -1,6 +1,6 @@ use rustc_abi::{HasDataLayout, Reg, Size, TyAbiInterface}; -use super::{ArgAttribute, ArgAttributes, ArgExtension, CastTarget}; +use super::CastTarget; use crate::callconv::{ArgAbi, FnAbi, Uniform}; fn classify_ret(ret: &mut ArgAbi<'_, Ty>) { @@ -34,16 +34,10 @@ fn classify_aggregate(arg: &mut ArgAbi<'_, Ty>) { }; if align_bytes == size.bytes() { - arg.cast_to(CastTarget { - prefix: [Some(reg), None, None, None, None, None, None, None], - rest: Uniform::new(Reg::i8(), Size::from_bytes(0)), - attrs: ArgAttributes { - regular: ArgAttribute::default(), - arg_ext: ArgExtension::None, - pointee_size: Size::ZERO, - pointee_align: None, - }, - }); + arg.cast_to(CastTarget::prefixed( + [Some(reg), None, None, None, None, None, None, None], + Uniform::new(Reg::i8(), Size::ZERO), + )); } else { arg.cast_to(Uniform::new(reg, size)); } @@ -78,11 +72,10 @@ where }; if arg.layout.size.bytes() / align_bytes == 1 { // Make sure we pass the struct as array at the LLVM IR level and not as a single integer. - arg.cast_to(CastTarget { - prefix: [Some(unit), None, None, None, None, None, None, None], - rest: Uniform::new(unit, Size::ZERO), - attrs: ArgAttributes::new(), - }); + arg.cast_to(CastTarget::prefixed( + [Some(unit), None, None, None, None, None, None, None], + Uniform::new(unit, Size::ZERO), + )); } else { arg.cast_to(Uniform::new(unit, arg.layout.size)); } diff --git a/compiler/rustc_target/src/callconv/riscv.rs b/compiler/rustc_target/src/callconv/riscv.rs index cd1d3cd1eee0..6a2038f93811 100644 --- a/compiler/rustc_target/src/callconv/riscv.rs +++ b/compiler/rustc_target/src/callconv/riscv.rs @@ -14,16 +14,16 @@ use crate::spec::HasTargetSpec; #[derive(Copy, Clone)] enum RegPassKind { - Float(Reg), - Integer(Reg), + Float { offset_from_start: Size, ty: Reg }, + Integer { offset_from_start: Size, ty: Reg }, Unknown, } #[derive(Copy, Clone)] enum FloatConv { - FloatPair(Reg, Reg), + FloatPair { first_ty: Reg, second_ty_offset_from_start: Size, second_ty: Reg }, Float(Reg), - MixedPair(Reg, Reg), + MixedPair { first_ty: Reg, second_ty_offset_from_start: Size, second_ty: Reg }, } #[derive(Copy, Clone)] @@ -43,6 +43,7 @@ fn should_use_fp_conv_helper<'a, Ty, C>( flen: u64, field1_kind: &mut RegPassKind, field2_kind: &mut RegPassKind, + offset_from_start: Size, ) -> Result<(), CannotUseFpConv> where Ty: TyAbiInterface<'a, C> + Copy, @@ -55,16 +56,16 @@ where } match (*field1_kind, *field2_kind) { (RegPassKind::Unknown, _) => { - *field1_kind = RegPassKind::Integer(Reg { - kind: RegKind::Integer, - size: arg_layout.size, - }); + *field1_kind = RegPassKind::Integer { + offset_from_start, + ty: Reg { kind: RegKind::Integer, size: arg_layout.size }, + }; } - (RegPassKind::Float(_), RegPassKind::Unknown) => { - *field2_kind = RegPassKind::Integer(Reg { - kind: RegKind::Integer, - size: arg_layout.size, - }); + (RegPassKind::Float { .. }, RegPassKind::Unknown) => { + *field2_kind = RegPassKind::Integer { + offset_from_start, + ty: Reg { kind: RegKind::Integer, size: arg_layout.size }, + }; } _ => return Err(CannotUseFpConv), } @@ -75,12 +76,16 @@ where } match (*field1_kind, *field2_kind) { (RegPassKind::Unknown, _) => { - *field1_kind = - RegPassKind::Float(Reg { kind: RegKind::Float, size: arg_layout.size }); + *field1_kind = RegPassKind::Float { + offset_from_start, + ty: Reg { kind: RegKind::Float, size: arg_layout.size }, + }; } (_, RegPassKind::Unknown) => { - *field2_kind = - RegPassKind::Float(Reg { kind: RegKind::Float, size: arg_layout.size }); + *field2_kind = RegPassKind::Float { + offset_from_start, + ty: Reg { kind: RegKind::Float, size: arg_layout.size }, + }; } _ => return Err(CannotUseFpConv), } @@ -102,13 +107,14 @@ where flen, field1_kind, field2_kind, + offset_from_start, ); } return Err(CannotUseFpConv); } } FieldsShape::Array { count, .. } => { - for _ in 0..count { + for i in 0..count { let elem_layout = arg_layout.field(cx, 0); should_use_fp_conv_helper( cx, @@ -117,6 +123,7 @@ where flen, field1_kind, field2_kind, + offset_from_start + elem_layout.size * i, )?; } } @@ -127,7 +134,15 @@ where } for i in arg_layout.fields.index_by_increasing_offset() { let field = arg_layout.field(cx, i); - should_use_fp_conv_helper(cx, &field, xlen, flen, field1_kind, field2_kind)?; + should_use_fp_conv_helper( + cx, + &field, + xlen, + flen, + field1_kind, + field2_kind, + offset_from_start + arg_layout.fields.offset(i), + )?; } } }, @@ -146,14 +161,52 @@ where { let mut field1_kind = RegPassKind::Unknown; let mut field2_kind = RegPassKind::Unknown; - if should_use_fp_conv_helper(cx, arg, xlen, flen, &mut field1_kind, &mut field2_kind).is_err() { + if should_use_fp_conv_helper( + cx, + arg, + xlen, + flen, + &mut field1_kind, + &mut field2_kind, + Size::ZERO, + ) + .is_err() + { return None; } match (field1_kind, field2_kind) { - (RegPassKind::Integer(l), RegPassKind::Float(r)) => Some(FloatConv::MixedPair(l, r)), - (RegPassKind::Float(l), RegPassKind::Integer(r)) => Some(FloatConv::MixedPair(l, r)), - (RegPassKind::Float(l), RegPassKind::Float(r)) => Some(FloatConv::FloatPair(l, r)), - (RegPassKind::Float(f), RegPassKind::Unknown) => Some(FloatConv::Float(f)), + ( + RegPassKind::Integer { offset_from_start, .. } + | RegPassKind::Float { offset_from_start, .. }, + _, + ) if offset_from_start != Size::ZERO => { + panic!("type {:?} has a first field with non-zero offset {offset_from_start:?}", arg.ty) + } + ( + RegPassKind::Integer { ty: first_ty, .. }, + RegPassKind::Float { offset_from_start, ty: second_ty }, + ) => Some(FloatConv::MixedPair { + first_ty, + second_ty_offset_from_start: offset_from_start, + second_ty, + }), + ( + RegPassKind::Float { ty: first_ty, .. }, + RegPassKind::Integer { offset_from_start, ty: second_ty }, + ) => Some(FloatConv::MixedPair { + first_ty, + second_ty_offset_from_start: offset_from_start, + second_ty, + }), + ( + RegPassKind::Float { ty: first_ty, .. }, + RegPassKind::Float { offset_from_start, ty: second_ty }, + ) => Some(FloatConv::FloatPair { + first_ty, + second_ty_offset_from_start: offset_from_start, + second_ty, + }), + (RegPassKind::Float { ty, .. }, RegPassKind::Unknown) => Some(FloatConv::Float(ty)), _ => None, } } @@ -171,11 +224,19 @@ where FloatConv::Float(f) => { arg.cast_to(f); } - FloatConv::FloatPair(l, r) => { - arg.cast_to(CastTarget::pair(l, r)); + FloatConv::FloatPair { first_ty, second_ty_offset_from_start, second_ty } => { + arg.cast_to(CastTarget::offset_pair( + first_ty, + second_ty_offset_from_start, + second_ty, + )); } - FloatConv::MixedPair(l, r) => { - arg.cast_to(CastTarget::pair(l, r)); + FloatConv::MixedPair { first_ty, second_ty_offset_from_start, second_ty } => { + arg.cast_to(CastTarget::offset_pair( + first_ty, + second_ty_offset_from_start, + second_ty, + )); } } return false; @@ -239,15 +300,27 @@ fn classify_arg<'a, Ty, C>( arg.cast_to(f); return; } - Some(FloatConv::FloatPair(l, r)) if *avail_fprs >= 2 => { + Some(FloatConv::FloatPair { first_ty, second_ty_offset_from_start, second_ty }) + if *avail_fprs >= 2 => + { *avail_fprs -= 2; - arg.cast_to(CastTarget::pair(l, r)); + arg.cast_to(CastTarget::offset_pair( + first_ty, + second_ty_offset_from_start, + second_ty, + )); return; } - Some(FloatConv::MixedPair(l, r)) if *avail_fprs >= 1 && *avail_gprs >= 1 => { + Some(FloatConv::MixedPair { first_ty, second_ty_offset_from_start, second_ty }) + if *avail_fprs >= 1 && *avail_gprs >= 1 => + { *avail_gprs -= 1; *avail_fprs -= 1; - arg.cast_to(CastTarget::pair(l, r)); + arg.cast_to(CastTarget::offset_pair( + first_ty, + second_ty_offset_from_start, + second_ty, + )); return; } _ => (), diff --git a/compiler/rustc_target/src/callconv/sparc64.rs b/compiler/rustc_target/src/callconv/sparc64.rs index 7ca0031fc59c..186826c08fcb 100644 --- a/compiler/rustc_target/src/callconv/sparc64.rs +++ b/compiler/rustc_target/src/callconv/sparc64.rs @@ -5,9 +5,7 @@ use rustc_abi::{ TyAndLayout, }; -use crate::callconv::{ - ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, FnAbi, Uniform, -}; +use crate::callconv::{ArgAbi, ArgAttribute, CastTarget, FnAbi, Uniform}; use crate::spec::HasTargetSpec; #[derive(Clone, Debug)] @@ -197,16 +195,10 @@ where rest_size = rest_size - Reg::i32().size; } - arg.cast_to(CastTarget { - prefix: data.prefix, - rest: Uniform::new(Reg::i64(), rest_size), - attrs: ArgAttributes { - regular: data.arg_attribute, - arg_ext: ArgExtension::None, - pointee_size: Size::ZERO, - pointee_align: None, - }, - }); + arg.cast_to( + CastTarget::prefixed(data.prefix, Uniform::new(Reg::i64(), rest_size)) + .with_attrs(data.arg_attribute.into()), + ); return; } } diff --git a/compiler/rustc_target/src/callconv/wasm.rs b/compiler/rustc_target/src/callconv/wasm.rs index 881168c98c32..a308f378ee87 100644 --- a/compiler/rustc_target/src/callconv/wasm.rs +++ b/compiler/rustc_target/src/callconv/wasm.rs @@ -59,7 +59,7 @@ where } /// The purpose of this ABI is to match the C ABI (aka clang) exactly. -pub(crate) fn compute_c_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) +pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout, @@ -75,43 +75,3 @@ where classify_arg(cx, arg); } } - -/// The purpose of this ABI is for matching the WebAssembly standard. This -/// intentionally diverges from the C ABI and is specifically crafted to take -/// advantage of LLVM's support of multiple returns in WebAssembly. -/// -/// This ABI is *bad*! It uses `PassMode::Direct` for `abi::Aggregate` types, which leaks LLVM -/// implementation details into the ABI. It's just hard to fix because ABIs are hard to change. -/// Also see . -pub(crate) fn compute_wasm_abi_info(fn_abi: &mut FnAbi<'_, Ty>) { - if !fn_abi.ret.is_ignore() { - classify_ret_wasm_abi(&mut fn_abi.ret); - } - - for arg in fn_abi.args.iter_mut() { - if arg.is_ignore() { - continue; - } - classify_arg_wasm_abi(arg); - } - - fn classify_ret_wasm_abi(ret: &mut ArgAbi<'_, Ty>) { - if !ret.layout.is_sized() { - // Not touching this... - return; - } - // FIXME: this is bad! https://github.com/rust-lang/rust/issues/115666 - ret.make_direct_deprecated(); - ret.extend_integer_width_to(32); - } - - fn classify_arg_wasm_abi(arg: &mut ArgAbi<'_, Ty>) { - if !arg.layout.is_sized() { - // Not touching this... - return; - } - // FIXME: this is bad! https://github.com/rust-lang/rust/issues/115666 - arg.make_direct_deprecated(); - arg.extend_integer_width_to(32); - } -} diff --git a/compiler/rustc_target/src/callconv/x86_64.rs b/compiler/rustc_target/src/callconv/x86_64.rs index 300b19f62e72..700ee73c8fdc 100644 --- a/compiler/rustc_target/src/callconv/x86_64.rs +++ b/compiler/rustc_target/src/callconv/x86_64.rs @@ -7,6 +7,7 @@ use rustc_abi::{ }; use crate::callconv::{ArgAbi, CastTarget, FnAbi}; +use crate::spec::HasTargetSpec; /// Classification of "eightbyte" components. // N.B., the order of the variants is from general to specific, @@ -175,7 +176,7 @@ const MAX_SSE_REGS: usize = 8; // XMM0-7 pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where Ty: TyAbiInterface<'a, C> + Copy, - C: HasDataLayout, + C: HasDataLayout + HasTargetSpec, { let mut int_regs = MAX_INT_REGS; let mut sse_regs = MAX_SSE_REGS; @@ -236,7 +237,7 @@ where if arg.layout.is_aggregate() { let size = arg.layout.size; arg.cast_to(cast_target(cls, size)); - } else { + } else if is_arg || cx.target_spec().is_like_darwin { arg.extend_integer_width_to(32); } } diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index c360fe63a008..010355abd781 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -2233,22 +2233,6 @@ impl HasTargetSpec for Target { } } -/// Which C ABI to use for `wasm32-unknown-unknown`. -#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub enum WasmCAbi { - /// Spec-compliant C ABI. - Spec, - /// Legacy ABI. Which is non-spec-compliant. - Legacy { - /// Indicates whether the `wasm_c_abi` lint should be emitted. - with_lint: bool, - }, -} - -pub trait HasWasmCAbiOpt { - fn wasm_c_abi_opt(&self) -> WasmCAbi; -} - /// x86 (32-bit) abi options. #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct X86Abi { diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index bb5187e4f5c8..f0ff50318abc 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -403,28 +403,18 @@ fn fn_abi_sanity_check<'tcx>( // For an unsized type we'd only pass the sized prefix, so there is no universe // in which we ever want to allow this. assert!(sized, "`PassMode::Direct` for unsized type in ABI: {:#?}", fn_abi); + // This really shouldn't happen even for sized aggregates, since // `immediate_llvm_type` will use `layout.fields` to turn this Rust type into an // LLVM type. This means all sorts of Rust type details leak into the ABI. - // However wasm sadly *does* currently use this mode for it's "C" ABI so we - // have to allow it -- but we absolutely shouldn't let any more targets do - // that. (Also see .) - // - // The unadjusted ABI also uses Direct for all args and is ill-specified, + // The unadjusted ABI however uses Direct for all args. It is ill-specified, // but unfortunately we need it for calling certain LLVM intrinsics. - - match spec_abi { - ExternAbi::Unadjusted => {} - ExternAbi::C { unwind: _ } - if matches!(&*tcx.sess.target.arch, "wasm32" | "wasm64") => {} - _ => { - panic!( - "`PassMode::Direct` for aggregates only allowed for \"unadjusted\" functions and on wasm\n\ - Problematic type: {:#?}", - arg.layout, - ); - } - } + assert!( + matches!(spec_abi, ExternAbi::Unadjusted), + "`PassMode::Direct` for aggregates only allowed for \"unadjusted\"\n\ + Problematic type: {:#?}", + arg.layout, + ); } } } diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs index f0eb96b47b10..b59b4f928540 100644 --- a/compiler/rustc_type_ir/src/search_graph/mod.rs +++ b/compiler/rustc_type_ir/src/search_graph/mod.rs @@ -842,9 +842,8 @@ impl, X: Cx> SearchGraph { /// evaluating this entry would not have ended up depending on either a goal /// already on the stack or a provisional cache entry. fn candidate_is_applicable( - stack: &Stack, + &self, step_kind_from_parent: PathKind, - provisional_cache: &HashMap>>, nested_goals: &NestedGoals, ) -> bool { // If the global cache entry didn't depend on any nested goals, it always @@ -855,7 +854,7 @@ impl, X: Cx> SearchGraph { // If a nested goal of the global cache entry is on the stack, we would // definitely encounter a cycle. - if stack.iter().any(|e| nested_goals.contains(e.input)) { + if self.stack.iter().any(|e| nested_goals.contains(e.input)) { debug!("cache entry not applicable due to stack"); return false; } @@ -864,7 +863,7 @@ impl, X: Cx> SearchGraph { // would apply for any of its nested goals. #[allow(rustc::potential_query_instability)] for (input, path_from_global_entry) in nested_goals.iter() { - let Some(entries) = provisional_cache.get(&input) else { + let Some(entries) = self.provisional_cache.get(&input) else { continue; }; @@ -890,7 +889,7 @@ impl, X: Cx> SearchGraph { // We check if any of the paths taken while computing the global goal // would end up with an applicable provisional cache entry. let head = heads.highest_cycle_head(); - let head_to_curr = Self::cycle_path_kind(stack, step_kind_from_parent, head); + let head_to_curr = Self::cycle_path_kind(&self.stack, step_kind_from_parent, head); let full_paths = path_from_global_entry.extend_with(head_to_curr); if full_paths.contains(head_to_provisional.into()) { debug!( @@ -918,12 +917,7 @@ impl, X: Cx> SearchGraph { cx.with_global_cache(|cache| { cache .get(cx, input, available_depth, |nested_goals| { - Self::candidate_is_applicable( - &self.stack, - step_kind_from_parent, - &self.provisional_cache, - nested_goals, - ) + self.candidate_is_applicable(step_kind_from_parent, nested_goals) }) .map(|c| c.result) }) @@ -942,12 +936,7 @@ impl, X: Cx> SearchGraph { cx.with_global_cache(|cache| { let CacheData { result, required_depth, encountered_overflow, nested_goals } = cache .get(cx, input, available_depth, |nested_goals| { - Self::candidate_is_applicable( - &self.stack, - step_kind_from_parent, - &self.provisional_cache, - nested_goals, - ) + self.candidate_is_applicable(step_kind_from_parent, nested_goals) })?; // We don't move cycle participants to the global cache, so the diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index 2e05c23a6458..ba777c7c59ad 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -236,6 +236,14 @@ pub struct ExternalConstraintsData { pub normalization_nested_goals: NestedNormalizationGoals, } +impl ExternalConstraintsData { + pub fn is_empty(&self) -> bool { + self.region_constraints.is_empty() + && self.opaque_types.is_empty() + && self.normalization_nested_goals.is_empty() + } +} + #[derive_where(Clone, Hash, PartialEq, Eq, Debug, Default; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] diff --git a/library/backtrace b/library/backtrace index 6c882eb11984..b65ab935fb2e 160000 --- a/library/backtrace +++ b/library/backtrace @@ -1 +1 @@ -Subproject commit 6c882eb11984d737f62e85f36703effaf34c2453 +Subproject commit b65ab935fb2e0d59dba8966ffca09c9cc5a5f57c diff --git a/library/core/src/panic/location.rs b/library/core/src/panic/location.rs index 94cfd667ffae..f1eedede8aab 100644 --- a/library/core/src/panic/location.rs +++ b/library/core/src/panic/location.rs @@ -30,7 +30,7 @@ use crate::fmt; /// Files are compared as strings, not `Path`, which could be unexpected. /// See [`Location::file`]'s documentation for more discussion. #[lang = "panic_location"] -#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +#[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)] #[stable(feature = "panic_hooks", since = "1.10.0")] pub struct Location<'a> { // Note: this filename will have exactly one nul byte at its end, but otherwise @@ -43,6 +43,17 @@ pub struct Location<'a> { col: u32, } +#[stable(feature = "panic_hooks", since = "1.10.0")] +impl fmt::Debug for Location<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Location") + .field("file", &self.file()) + .field("line", &self.line) + .field("column", &self.col) + .finish() + } +} + impl<'a> Location<'a> { /// Returns the source location of the caller of this function. If that function's caller is /// annotated then its call location will be returned, and so on up the stack to the first call diff --git a/library/coretests/tests/panic/location.rs b/library/coretests/tests/panic/location.rs index d20241d83800..5ce0b06e90e1 100644 --- a/library/coretests/tests/panic/location.rs +++ b/library/coretests/tests/panic/location.rs @@ -29,3 +29,11 @@ fn location_const_column() { const COLUMN: u32 = CALLER.column(); assert_eq!(COLUMN, 40); } + +#[test] +fn location_debug() { + let f = format!("{:?}", Location::caller()); + assert!(f.contains(&format!("{:?}", file!()))); + assert!(f.contains("35")); + assert!(f.contains("29")); +} diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs index 75d82d746540..d60a76fff5dc 100644 --- a/library/proc_macro/src/bridge/mod.rs +++ b/library/proc_macro/src/bridge/mod.rs @@ -7,9 +7,6 @@ //! Rust ABIs (e.g., stage0/bin/rustc vs stage1/bin/rustc during bootstrap). #![deny(unsafe_code)] -// proc_macros anyway don't work on wasm hosts so while both sides of this bridge can -// be built with different versions of rustc, the wasm ABI changes don't really matter. -#![allow(wasm_c_abi)] use std::hash::Hash; use std::ops::{Bound, Range}; diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 0cd794fd3efb..865ea620a283 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -121,7 +121,7 @@ pub struct File { /// /// [`try_lock`]: File::try_lock /// [`try_lock_shared`]: File::try_lock_shared -#[unstable(feature = "file_lock", issue = "130994")] +#[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")] pub enum TryLockError { /// The lock could not be acquired due to an I/O error on the file. The standard library will /// not return an [`ErrorKind::WouldBlock`] error inside [`TryLockError::Error`] @@ -366,10 +366,10 @@ pub fn write, C: AsRef<[u8]>>(path: P, contents: C) -> io::Result inner(path.as_ref(), contents.as_ref()) } -#[unstable(feature = "file_lock", issue = "130994")] +#[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")] impl error::Error for TryLockError {} -#[unstable(feature = "file_lock", issue = "130994")] +#[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")] impl fmt::Debug for TryLockError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { @@ -379,7 +379,7 @@ impl fmt::Debug for TryLockError { } } -#[unstable(feature = "file_lock", issue = "130994")] +#[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")] impl fmt::Display for TryLockError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { @@ -390,7 +390,7 @@ impl fmt::Display for TryLockError { } } -#[unstable(feature = "file_lock", issue = "130994")] +#[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")] impl From for io::Error { fn from(err: TryLockError) -> io::Error { match err { @@ -713,7 +713,6 @@ impl File { /// # Examples /// /// ```no_run - /// #![feature(file_lock)] /// use std::fs::File; /// /// fn main() -> std::io::Result<()> { @@ -722,7 +721,7 @@ impl File { /// Ok(()) /// } /// ``` - #[unstable(feature = "file_lock", issue = "130994")] + #[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")] pub fn lock(&self) -> io::Result<()> { self.inner.lock() } @@ -766,7 +765,6 @@ impl File { /// # Examples /// /// ```no_run - /// #![feature(file_lock)] /// use std::fs::File; /// /// fn main() -> std::io::Result<()> { @@ -775,7 +773,7 @@ impl File { /// Ok(()) /// } /// ``` - #[unstable(feature = "file_lock", issue = "130994")] + #[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")] pub fn lock_shared(&self) -> io::Result<()> { self.inner.lock_shared() } @@ -824,7 +822,6 @@ impl File { /// # Examples /// /// ```no_run - /// #![feature(file_lock)] /// use std::fs::{File, TryLockError}; /// /// fn main() -> std::io::Result<()> { @@ -840,7 +837,7 @@ impl File { /// Ok(()) /// } /// ``` - #[unstable(feature = "file_lock", issue = "130994")] + #[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")] pub fn try_lock(&self) -> Result<(), TryLockError> { self.inner.try_lock() } @@ -888,7 +885,6 @@ impl File { /// # Examples /// /// ```no_run - /// #![feature(file_lock)] /// use std::fs::{File, TryLockError}; /// /// fn main() -> std::io::Result<()> { @@ -905,7 +901,7 @@ impl File { /// Ok(()) /// } /// ``` - #[unstable(feature = "file_lock", issue = "130994")] + #[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")] pub fn try_lock_shared(&self) -> Result<(), TryLockError> { self.inner.try_lock_shared() } @@ -933,7 +929,6 @@ impl File { /// # Examples /// /// ```no_run - /// #![feature(file_lock)] /// use std::fs::File; /// /// fn main() -> std::io::Result<()> { @@ -943,7 +938,7 @@ impl File { /// Ok(()) /// } /// ``` - #[unstable(feature = "file_lock", issue = "130994")] + #[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")] pub fn unlock(&self) -> io::Result<()> { self.inner.unlock() } diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 826d9f0f39dc..0469db0814c1 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -1882,6 +1882,19 @@ impl FromStr for PathBuf { #[stable(feature = "rust1", since = "1.0.0")] impl> FromIterator

for PathBuf { + /// Creates a new `PathBuf` from the [`Path`] elements of an iterator. + /// + /// This uses [`push`](Self::push) to add each element, so can be used to adjoin multiple path + /// [components](Components). + /// + /// # Examples + /// ``` + /// # use std::path::PathBuf; + /// let path = PathBuf::from_iter(["/tmp", "foo", "bar"]); + /// assert_eq!(path, PathBuf::from("/tmp/foo/bar")); + /// ``` + /// + /// See documentation for [`push`](Self::push) for more details on how the path is constructed. fn from_iter>(iter: I) -> PathBuf { let mut buf = PathBuf::new(); buf.extend(iter); @@ -1891,6 +1904,20 @@ impl> FromIterator

for PathBuf { #[stable(feature = "rust1", since = "1.0.0")] impl> Extend

for PathBuf { + /// Extends `self` with [`Path`] elements from `iter`. + /// + /// This uses [`push`](Self::push) to add each element, so can be used to adjoin multiple path + /// [components](Components). + /// + /// # Examples + /// ``` + /// # use std::path::PathBuf; + /// let mut path = PathBuf::from("/tmp"); + /// path.extend(["foo", "bar", "file.txt"]); + /// assert_eq!(path, PathBuf::from("/tmp/foo/bar/file.txt")); + /// ``` + /// + /// See documentation for [`push`](Self::push) for more details on how the path is constructed. fn extend>(&mut self, iter: I) { iter.into_iter().for_each(move |p| self.push(p.as_ref())); } diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index 0c8e66335609..a6ca699e2824 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -44,6 +44,7 @@ dependencies = [ "fd-lock", "home", "ignore", + "insta", "junction", "libc", "object", @@ -158,6 +159,18 @@ dependencies = [ "cc", ] +[[package]] +name = "console" +version = "0.15.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "windows-sys 0.59.0", +] + [[package]] name = "cpufeatures" version = "0.2.15" @@ -218,6 +231,12 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + [[package]] name = "errno" version = "0.3.11" @@ -323,6 +342,17 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "insta" +version = "1.43.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "154934ea70c58054b556dd430b99a98c2a7ff5309ac9891597e339b5c28f4371" +dependencies = [ + "console", + "once_cell", + "similar", +] + [[package]] name = "itoa" version = "1.0.11" @@ -675,6 +705,12 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "similar" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" + [[package]] name = "smallvec" version = "1.13.2" diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index b12b3dfc7b2a..9785a306c9b1 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -84,6 +84,7 @@ features = [ [dev-dependencies] pretty_assertions = "1.4" tempfile = "3.15.0" +insta = "1.43" # We care a lot about bootstrap's compile times, so don't include debuginfo for # dependencies, only bootstrap itself. diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md index f9d7c811f600..5ff999f01a95 100644 --- a/src/bootstrap/README.md +++ b/src/bootstrap/README.md @@ -200,6 +200,10 @@ please file issues on the [Rust issue tracker][rust-issue-tracker]. [rust-bootstrap-zulip]: https://rust-lang.zulipchat.com/#narrow/stream/t-infra.2Fbootstrap [rust-issue-tracker]: https://github.com/rust-lang/rust/issues +## Testing + +To run bootstrap tests, execute `x test bootstrap`. If you want to bless snapshot tests, then install `cargo-insta` (`cargo install cargo-insta`) and then run `cargo insta review --manifest-path src/bootstrap/Cargo.toml`. + ## Changelog Because we do not release bootstrap with versions, we also do not maintain CHANGELOG files. To diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index ebb926d81cef..f9f82b800419 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -2009,7 +2009,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the // Note that if we encounter `PATH` we make sure to append to our own `PATH` // rather than stomp over it. if !builder.config.dry_run() && target.is_msvc() { - for (k, v) in builder.cc.borrow()[&target].env() { + for (k, v) in builder.cc[&target].env() { if k != "PATH" { cmd.env(k, v); } @@ -2026,8 +2026,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the // address sanitizer enabled (e.g., ntdll.dll). cmd.env("ASAN_WIN_CONTINUE_ON_INTERCEPTION_FAILURE", "1"); // Add the address sanitizer runtime to the PATH - it is located next to cl.exe. - let asan_runtime_path = - builder.cc.borrow()[&target].path().parent().unwrap().to_path_buf(); + let asan_runtime_path = builder.cc[&target].path().parent().unwrap().to_path_buf(); let old_path = cmd .get_envs() .find_map(|(k, v)| (k == "PATH").then_some(v)) @@ -3059,6 +3058,8 @@ impl Step for Bootstrap { cargo .rustflag("-Cdebuginfo=2") .env("CARGO_TARGET_DIR", builder.out.join("bootstrap")) + // Needed for insta to correctly write pending snapshots to the right directories. + .env("INSTA_WORKSPACE_ROOT", &builder.src) .env("RUSTC_BOOTSTRAP", "1"); // bootstrap tests are racy on directory creation so just run them one at a time. diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index f64d67341cfe..237efaefada3 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -1334,7 +1334,7 @@ impl Builder<'_> { if compiler.host.is_msvc() { let curpaths = env::var_os("PATH").unwrap_or_default(); let curpaths = env::split_paths(&curpaths).collect::>(); - for (k, v) in self.cc.borrow()[&compiler.host].env() { + for (k, v) in self.cc[&compiler.host].env() { if k != "PATH" { continue; } diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index c6cfdb69356c..0e3c3aaee0ff 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -278,9 +278,7 @@ impl Cargo { self.rustdocflags.arg(&arg); } - if !builder.config.dry_run() - && builder.cc.borrow()[&target].args().iter().any(|arg| arg == "-gz") - { + if !builder.config.dry_run() && builder.cc[&target].args().iter().any(|arg| arg == "-gz") { self.rustflags.arg("-Clink-arg=-gz"); } diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index 887db683f789..7433f0b0f3b4 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -5,7 +5,7 @@ use std::fmt::{self, Debug, Write}; use std::hash::Hash; use std::ops::Deref; use std::path::{Path, PathBuf}; -use std::sync::LazyLock; +use std::sync::{LazyLock, OnceLock}; use std::time::{Duration, Instant}; use std::{env, fs}; @@ -60,6 +60,9 @@ pub struct Builder<'a> { /// to do. For example: with `./x check foo bar` we get `paths=["foo", /// "bar"]`. pub paths: Vec, + + /// Cached list of submodules from self.build.src. + submodule_paths_cache: OnceLock>, } impl Deref for Builder<'_> { @@ -687,7 +690,7 @@ impl<'a> ShouldRun<'a> { /// /// [`path`]: ShouldRun::path pub fn paths(mut self, paths: &[&str]) -> Self { - let submodules_paths = build_helper::util::parse_gitmodules(&self.builder.src); + let submodules_paths = self.builder.submodule_paths(); self.paths.insert(PathSet::Set( paths @@ -1180,6 +1183,7 @@ impl<'a> Builder<'a> { stack: RefCell::new(Vec::new()), time_spent_on_dependencies: Cell::new(Duration::new(0, 0)), paths, + submodule_paths_cache: Default::default(), } } @@ -1510,6 +1514,19 @@ impl<'a> Builder<'a> { None } + /// Updates all submodules, and exits with an error if submodule + /// management is disabled and the submodule does not exist. + pub fn require_and_update_all_submodules(&self) { + for submodule in self.submodule_paths() { + self.require_submodule(submodule, None); + } + } + + /// Get all submodules from the src directory. + pub fn submodule_paths(&self) -> &[String] { + self.submodule_paths_cache.get_or_init(|| build_helper::util::parse_gitmodules(&self.src)) + } + /// Ensure that a given step is built, returning its output. This will /// cache the step, so it is safe (and good!) to call this as often as /// needed to ensure that all dependencies are built. diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index a26a96f2815e..d07df7f4a841 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -15,11 +15,12 @@ static TEST_TRIPLE_2: &str = "i686-unknown-hurd-gnu"; static TEST_TRIPLE_3: &str = "i686-unknown-netbsd"; fn configure(cmd: &str, host: &[&str], target: &[&str]) -> Config { - configure_with_args(&[cmd.to_owned()], host, target) + configure_with_args(&[cmd], host, target) } -fn configure_with_args(cmd: &[String], host: &[&str], target: &[&str]) -> Config { - let mut config = Config::parse(Flags::parse(cmd)); +fn configure_with_args(cmd: &[&str], host: &[&str], target: &[&str]) -> Config { + let cmd = cmd.iter().copied().map(String::from).collect::>(); + let mut config = Config::parse(Flags::parse(&cmd)); // don't save toolstates config.save_toolstates = None; config.set_dry_run(DryRun::SelfCheck); @@ -67,7 +68,7 @@ fn run_build(paths: &[PathBuf], config: Config) -> Cache { fn check_cli(paths: [&str; N]) { run_build( &paths.map(PathBuf::from), - configure_with_args(&paths.map(String::from), &[TEST_TRIPLE_1], &[TEST_TRIPLE_1]), + configure_with_args(&paths, &[TEST_TRIPLE_1], &[TEST_TRIPLE_1]), ); } @@ -1000,8 +1001,7 @@ mod sysroot_target_dirs { /// cg_gcc tests instead. #[test] fn test_test_compiler() { - let cmd = &["test", "compiler"].map(str::to_owned); - let config = configure_with_args(cmd, &[TEST_TRIPLE_1], &[TEST_TRIPLE_1]); + let config = configure_with_args(&["test", "compiler"], &[TEST_TRIPLE_1], &[TEST_TRIPLE_1]); let cache = run_build(&config.paths.clone(), config); let compiler = cache.contains::(); @@ -1034,8 +1034,7 @@ fn test_test_coverage() { // Print each test case so that if one fails, the most recently printed // case is the one that failed. println!("Testing case: {cmd:?}"); - let cmd = cmd.iter().copied().map(str::to_owned).collect::>(); - let config = configure_with_args(&cmd, &[TEST_TRIPLE_1], &[TEST_TRIPLE_1]); + let config = configure_with_args(cmd, &[TEST_TRIPLE_1], &[TEST_TRIPLE_1]); let mut cache = run_build(&config.paths.clone(), config); let modes = @@ -1207,8 +1206,7 @@ fn test_get_tool_rustc_compiler() { /// of `Any { .. }`. #[test] fn step_cycle_debug() { - let cmd = ["run", "cyclic-step"].map(str::to_owned); - let config = configure_with_args(&cmd, &[TEST_TRIPLE_1], &[TEST_TRIPLE_1]); + let config = configure_with_args(&["run", "cyclic-step"], &[TEST_TRIPLE_1], &[TEST_TRIPLE_1]); let err = panic::catch_unwind(|| run_build(&config.paths.clone(), config)).unwrap_err(); let err = err.downcast_ref::().unwrap().as_str(); @@ -1233,3 +1231,81 @@ fn any_debug() { // Downcasting to the underlying type should succeed. assert_eq!(x.downcast_ref::(), Some(&MyStruct { x: 7 })); } + +/// The staging tests use insta for snapshot testing. +/// See bootstrap's README on how to bless the snapshots. +mod staging { + use crate::core::builder::tests::{ + TEST_TRIPLE_1, configure, configure_with_args, render_steps, run_build, + }; + + #[test] + fn build_compiler_stage_1() { + let mut cache = run_build( + &["compiler".into()], + configure_with_args(&["build", "--stage", "1"], &[TEST_TRIPLE_1], &[TEST_TRIPLE_1]), + ); + let steps = cache.into_executed_steps(); + insta::assert_snapshot!(render_steps(&steps), @r" + [build] rustc 0 -> std 0 + [build] llvm + [build] rustc 0 -> rustc 1 + [build] rustc 0 -> rustc 1 + "); + } +} + +/// Renders the executed bootstrap steps for usage in snapshot tests with insta. +/// Only renders certain important steps. +/// Each value in `steps` should be a tuple of (Step, step output). +fn render_steps(steps: &[(Box, Box)]) -> String { + steps + .iter() + .filter_map(|(step, output)| { + // FIXME: implement an optional method on Step to produce metadata for test, instead + // of this downcasting + if let Some((rustc, output)) = downcast_step::(step, output) { + Some(format!( + "[build] {} -> {}", + render_compiler(rustc.build_compiler), + // FIXME: return the correct stage from the `Rustc` step, now it behaves weirdly + render_compiler(Compiler::new(rustc.build_compiler.stage + 1, rustc.target)), + )) + } else if let Some((std, output)) = downcast_step::(step, output) { + Some(format!( + "[build] {} -> std {} <{}>", + render_compiler(std.compiler), + std.compiler.stage, + std.target + )) + } else if let Some((llvm, output)) = downcast_step::(step, output) { + Some(format!("[build] llvm <{}>", llvm.target)) + } else { + None + } + }) + .map(|line| { + line.replace(TEST_TRIPLE_1, "target1") + .replace(TEST_TRIPLE_2, "target2") + .replace(TEST_TRIPLE_3, "target3") + }) + .collect::>() + .join("\n") +} + +fn downcast_step<'a, S: Step>( + step: &'a Box, + output: &'a Box, +) -> Option<(&'a S, &'a S::Output)> { + let Some(step) = step.downcast_ref::() else { + return None; + }; + let Some(output) = output.downcast_ref::() else { + return None; + }; + Some((step, output)) +} + +fn render_compiler(compiler: Compiler) -> String { + format!("rustc {} <{}>", compiler.stage, compiler.host) +} diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 970a982dae42..f9980ac5fe12 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1373,12 +1373,13 @@ impl Config { } println!("Updating submodule {relative_path}"); - self.check_run( - helpers::git(Some(&self.src)) - .run_always() - .args(["submodule", "-q", "sync"]) - .arg(relative_path), - ); + + helpers::git(Some(&self.src)) + .allow_failure() + .run_always() + .args(["submodule", "-q", "sync"]) + .arg(relative_path) + .run(self); // Try passing `--progress` to start, then run git again without if that fails. let update = |progress: bool| { @@ -1407,26 +1408,23 @@ impl Config { git.arg(relative_path); git }; - if !self.check_run(&mut update(true)) { - self.check_run(&mut update(false)); + if !update(true).allow_failure().run(self) { + update(false).allow_failure().run(self); } // Save any local changes, but avoid running `git stash pop` if there are none (since it will exit with an error). // diff-index reports the modifications through the exit status - let has_local_modifications = !self.check_run(submodule_git().allow_failure().args([ - "diff-index", - "--quiet", - "HEAD", - ])); + let has_local_modifications = + !submodule_git().allow_failure().args(["diff-index", "--quiet", "HEAD"]).run(self); if has_local_modifications { - self.check_run(submodule_git().args(["stash", "push"])); + submodule_git().allow_failure().args(["stash", "push"]).run(self); } - self.check_run(submodule_git().args(["reset", "-q", "--hard"])); - self.check_run(submodule_git().args(["clean", "-qdfx"])); + submodule_git().allow_failure().args(["reset", "-q", "--hard"]).run(self); + submodule_git().allow_failure().args(["clean", "-qdfx"]).run(self); if has_local_modifications { - self.check_run(submodule_git().args(["stash", "pop"])); + submodule_git().allow_failure().args(["stash", "pop"]).run(self); } } diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index 88a58e580e60..d7c6d8dbcc3f 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -9,8 +9,8 @@ use xz2::bufread::XzDecoder; use crate::core::config::BUILDER_CONFIG_FILENAME; use crate::utils::build_stamp::BuildStamp; -use crate::utils::exec::{BootstrapCommand, command}; -use crate::utils::helpers::{check_run, exe, hex_encode, move_file}; +use crate::utils::exec::command; +use crate::utils::helpers::{exe, hex_encode, move_file}; use crate::{Config, t}; static SHOULD_FIX_BINS_AND_DYLIBS: OnceLock = OnceLock::new(); @@ -65,17 +65,6 @@ impl Config { tmp } - /// Runs a command, printing out nice contextual information if it fails. - /// Returns false if do not execute at all, otherwise returns its - /// `status.success()`. - pub(crate) fn check_run(&self, cmd: &mut BootstrapCommand) -> bool { - if self.dry_run() && !cmd.run_always { - return true; - } - self.verbose(|| println!("running: {cmd:?}")); - check_run(cmd, self.is_verbose()) - } - /// Whether or not `fix_bin_or_dylib` needs to be run; can only be true /// on NixOS fn should_fix_bins_and_dylibs(&self) -> bool { @@ -214,7 +203,7 @@ impl Config { // options should be kept in sync with // src/bootstrap/src/core/download.rs // for consistency - let mut curl = command("curl"); + let mut curl = command("curl").allow_failure(); curl.args([ // follow redirect "--location", @@ -255,7 +244,7 @@ impl Config { curl.arg("--retry-all-errors"); } curl.arg(url); - if !self.check_run(&mut curl) { + if !curl.run(self) { if self.host_target.contains("windows-msvc") { eprintln!("Fallback to PowerShell"); for _ in 0..3 { diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 7254c653a2db..f1628f34ddab 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -17,7 +17,7 @@ //! also check out the `src/bootstrap/README.md` file for more information. #![cfg_attr(test, allow(unused))] -use std::cell::{Cell, RefCell}; +use std::cell::Cell; use std::collections::{BTreeSet, HashMap, HashSet}; use std::fmt::Display; use std::path::{Path, PathBuf}; @@ -189,10 +189,12 @@ pub struct Build { // Runtime state filled in later on // C/C++ compilers and archiver for all targets - cc: RefCell>, - cxx: RefCell>, - ar: RefCell>, - ranlib: RefCell>, + cc: HashMap, + cxx: HashMap, + ar: HashMap, + ranlib: HashMap, + wasi_sdk_path: Option, + // Miscellaneous // allow bidirectional lookups: both name -> path and path -> name crates: HashMap, @@ -466,10 +468,11 @@ impl Build { enzyme_info, in_tree_llvm_info, in_tree_gcc_info, - cc: RefCell::new(HashMap::new()), - cxx: RefCell::new(HashMap::new()), - ar: RefCell::new(HashMap::new()), - ranlib: RefCell::new(HashMap::new()), + cc: HashMap::new(), + cxx: HashMap::new(), + ar: HashMap::new(), + ranlib: HashMap::new(), + wasi_sdk_path: env::var_os("WASI_SDK_PATH").map(PathBuf::from), crates: HashMap::new(), crate_paths: HashMap::new(), is_sudo, @@ -498,7 +501,7 @@ impl Build { } build.verbose(|| println!("finding compilers")); - utils::cc_detect::find(&build); + utils::cc_detect::fill_compilers(&mut build); // When running `setup`, the profile is about to change, so any requirements we have now may // be different on the next invocation. Don't check for them until the next time x.py is // run. This is ok because `setup` never runs any build commands, so it won't fail if commands are missing. @@ -593,14 +596,6 @@ impl Build { } } - /// Updates all submodules, and exits with an error if submodule - /// management is disabled and the submodule does not exist. - pub fn require_and_update_all_submodules(&self) { - for submodule in build_helper::util::parse_gitmodules(&self.src) { - self.require_submodule(submodule, None); - } - } - /// If any submodule has been initialized already, sync it unconditionally. /// This avoids contributors checking in a submodule change by accident. fn update_existing_submodules(&self) { @@ -1143,17 +1138,17 @@ impl Build { if self.config.dry_run() { return PathBuf::new(); } - self.cc.borrow()[&target].path().into() + self.cc[&target].path().into() } /// Returns the internal `cc::Tool` for the C compiler. fn cc_tool(&self, target: TargetSelection) -> Tool { - self.cc.borrow()[&target].clone() + self.cc[&target].clone() } /// Returns the internal `cc::Tool` for the C++ compiler. fn cxx_tool(&self, target: TargetSelection) -> Tool { - self.cxx.borrow()[&target].clone() + self.cxx[&target].clone() } /// Returns C flags that `cc-rs` thinks should be enabled for the @@ -1163,8 +1158,8 @@ impl Build { return Vec::new(); } let base = match c { - CLang::C => self.cc.borrow()[&target].clone(), - CLang::Cxx => self.cxx.borrow()[&target].clone(), + CLang::C => self.cc[&target].clone(), + CLang::Cxx => self.cxx[&target].clone(), }; // Filter out -O and /O (the optimization flags) that we picked up @@ -1217,7 +1212,7 @@ impl Build { if self.config.dry_run() { return None; } - self.ar.borrow().get(&target).cloned() + self.ar.get(&target).cloned() } /// Returns the path to the `ranlib` utility for the target specified. @@ -1225,7 +1220,7 @@ impl Build { if self.config.dry_run() { return None; } - self.ranlib.borrow().get(&target).cloned() + self.ranlib.get(&target).cloned() } /// Returns the path to the C++ compiler for the target specified. @@ -1233,7 +1228,7 @@ impl Build { if self.config.dry_run() { return Ok(PathBuf::new()); } - match self.cxx.borrow().get(&target) { + match self.cxx.get(&target) { Some(p) => Ok(p.path().into()), None => Err(format!("target `{target}` is not configured as a host, only as a target")), } @@ -1250,7 +1245,7 @@ impl Build { } else if target.contains("vxworks") { // need to use CXX compiler as linker to resolve the exception functions // that are only existed in CXX libraries - Some(self.cxx.borrow()[&target].path().into()) + Some(self.cxx[&target].path().into()) } else if !self.config.is_host_target(target) && helpers::use_host_linker(target) && !target.is_msvc() diff --git a/src/bootstrap/src/utils/build_stamp/tests.rs b/src/bootstrap/src/utils/build_stamp/tests.rs index 2d7d1f712465..f150266159a2 100644 --- a/src/bootstrap/src/utils/build_stamp/tests.rs +++ b/src/bootstrap/src/utils/build_stamp/tests.rs @@ -1,32 +1,28 @@ use std::path::PathBuf; -use crate::{BuildStamp, Config, Flags}; +use tempfile::TempDir; -fn temp_dir() -> PathBuf { - let config = - Config::parse(Flags::parse(&["check".to_owned(), "--config=/does/not/exist".to_owned()])); - config.tempdir() -} +use crate::{BuildStamp, Config, Flags}; #[test] #[should_panic(expected = "prefix can not start or end with '.'")] fn test_with_invalid_prefix() { - let dir = temp_dir(); - BuildStamp::new(&dir).with_prefix(".invalid"); + let dir = TempDir::new().unwrap(); + BuildStamp::new(dir.path()).with_prefix(".invalid"); } #[test] #[should_panic(expected = "prefix can not start or end with '.'")] fn test_with_invalid_prefix2() { - let dir = temp_dir(); - BuildStamp::new(&dir).with_prefix("invalid."); + let dir = TempDir::new().unwrap(); + BuildStamp::new(dir.path()).with_prefix("invalid."); } #[test] fn test_is_up_to_date() { - let dir = temp_dir(); + let dir = TempDir::new().unwrap(); - let mut build_stamp = BuildStamp::new(&dir).add_stamp("v1.0.0"); + let mut build_stamp = BuildStamp::new(dir.path()).add_stamp("v1.0.0"); build_stamp.write().unwrap(); assert!( @@ -45,9 +41,9 @@ fn test_is_up_to_date() { #[test] fn test_with_prefix() { - let dir = temp_dir(); + let dir = TempDir::new().unwrap(); - let stamp = BuildStamp::new(&dir).add_stamp("v1.0.0"); + let stamp = BuildStamp::new(dir.path()).add_stamp("v1.0.0"); assert_eq!(stamp.path.file_name().unwrap(), ".stamp"); let stamp = stamp.with_prefix("test"); diff --git a/src/bootstrap/src/utils/cache.rs b/src/bootstrap/src/utils/cache.rs index 46eeffad88c3..0c7374709584 100644 --- a/src/bootstrap/src/utils/cache.rs +++ b/src/bootstrap/src/utils/cache.rs @@ -17,6 +17,7 @@ use std::borrow::Borrow; use std::cell::RefCell; use std::cmp::Ordering; use std::collections::HashMap; +use std::fmt::Debug; use std::hash::{Hash, Hasher}; use std::marker::PhantomData; use std::ops::Deref; @@ -208,25 +209,30 @@ pub static INTERNER: LazyLock = LazyLock::new(Interner::default); /// any type in its output. It is a write-once cache; values are never evicted, /// which means that references to the value can safely be returned from the /// `get()` method. -#[derive(Debug)] -pub struct Cache( - RefCell< +#[derive(Debug, Default)] +pub struct Cache { + cache: RefCell< HashMap< TypeId, Box, // actually a HashMap> >, >, -); + #[cfg(test)] + /// Contains steps in the same order in which they were executed + /// Useful for tests + /// Tuples (step, step output) + executed_steps: RefCell, Box)>>, +} impl Cache { /// Creates a new empty cache. pub fn new() -> Cache { - Cache(RefCell::new(HashMap::new())) + Cache::default() } /// Stores the result of a computation step in the cache. pub fn put(&self, step: S, value: S::Output) { - let mut cache = self.0.borrow_mut(); + let mut cache = self.cache.borrow_mut(); let type_id = TypeId::of::(); let stepcache = cache .entry(type_id) @@ -234,12 +240,20 @@ impl Cache { .downcast_mut::>() .expect("invalid type mapped"); assert!(!stepcache.contains_key(&step), "processing {step:?} a second time"); + + #[cfg(test)] + { + let step: Box = Box::new(step.clone()); + let output: Box = Box::new(value.clone()); + self.executed_steps.borrow_mut().push((step, output)); + } + stepcache.insert(step, value); } /// Retrieves a cached result for the given step, if available. pub fn get(&self, step: &S) -> Option { - let mut cache = self.0.borrow_mut(); + let mut cache = self.cache.borrow_mut(); let type_id = TypeId::of::(); let stepcache = cache .entry(type_id) @@ -252,8 +266,8 @@ impl Cache { #[cfg(test)] impl Cache { - pub fn all(&mut self) -> Vec<(S, S::Output)> { - let cache = self.0.get_mut(); + pub fn all(&mut self) -> Vec<(S, S::Output)> { + let cache = self.cache.get_mut(); let type_id = TypeId::of::(); let mut v = cache .remove(&type_id) @@ -265,7 +279,12 @@ impl Cache { } pub fn contains(&self) -> bool { - self.0.borrow().contains_key(&TypeId::of::()) + self.cache.borrow().contains_key(&TypeId::of::()) + } + + #[cfg(test)] + pub fn into_executed_steps(mut self) -> Vec<(Box, Box)> { + mem::take(&mut self.executed_steps.borrow_mut()) } } diff --git a/src/bootstrap/src/utils/cc_detect.rs b/src/bootstrap/src/utils/cc_detect.rs index 851bb38074ef..dcafeb80f90c 100644 --- a/src/bootstrap/src/utils/cc_detect.rs +++ b/src/bootstrap/src/utils/cc_detect.rs @@ -61,8 +61,8 @@ fn new_cc_build(build: &Build, target: TargetSelection) -> cc::Build { /// /// This function determines which targets need a C compiler (and, if needed, a C++ compiler) /// by combining the primary build target, host targets, and any additional targets. For -/// each target, it calls [`find_target`] to configure the necessary compiler tools. -pub fn find(build: &Build) { +/// each target, it calls [`fill_target_compiler`] to configure the necessary compiler tools. +pub fn fill_compilers(build: &mut Build) { let targets: HashSet<_> = match build.config.cmd { // We don't need to check cross targets for these commands. crate::Subcommand::Clean { .. } @@ -87,7 +87,7 @@ pub fn find(build: &Build) { }; for target in targets.into_iter() { - find_target(build, target); + fill_target_compiler(build, target); } } @@ -96,7 +96,7 @@ pub fn find(build: &Build) { /// This function uses both user-specified configuration (from `bootstrap.toml`) and auto-detection /// logic to determine the correct C/C++ compilers for the target. It also determines the appropriate /// archiver (`ar`) and sets up additional compilation flags (both handled and unhandled). -pub fn find_target(build: &Build, target: TargetSelection) { +pub fn fill_target_compiler(build: &mut Build, target: TargetSelection) { let mut cfg = new_cc_build(build, target); let config = build.config.target_config.get(&target); if let Some(cc) = config @@ -113,7 +113,7 @@ pub fn find_target(build: &Build, target: TargetSelection) { cfg.try_get_archiver().map(|c| PathBuf::from(c.get_program())).ok() }; - build.cc.borrow_mut().insert(target, compiler.clone()); + build.cc.insert(target, compiler.clone()); let mut cflags = build.cc_handled_clags(target, CLang::C); cflags.extend(build.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::C)); @@ -135,7 +135,7 @@ pub fn find_target(build: &Build, target: TargetSelection) { // for VxWorks, record CXX compiler which will be used in lib.rs:linker() if cxx_configured || target.contains("vxworks") { let compiler = cfg.get_compiler(); - build.cxx.borrow_mut().insert(target, compiler); + build.cxx.insert(target, compiler); } build.verbose(|| println!("CC_{} = {:?}", target.triple, build.cc(target))); @@ -148,11 +148,11 @@ pub fn find_target(build: &Build, target: TargetSelection) { } if let Some(ar) = ar { build.verbose(|| println!("AR_{} = {ar:?}", target.triple)); - build.ar.borrow_mut().insert(target, ar); + build.ar.insert(target, ar); } if let Some(ranlib) = config.and_then(|c| c.ranlib.clone()) { - build.ranlib.borrow_mut().insert(target, ranlib); + build.ranlib.insert(target, ranlib); } } @@ -221,7 +221,10 @@ fn default_compiler( } t if t.contains("-wasi") => { - let root = PathBuf::from(std::env::var_os("WASI_SDK_PATH")?); + let root = build + .wasi_sdk_path + .as_ref() + .expect("WASI_SDK_PATH mut be configured for a -wasi target"); let compiler = match compiler { Language::C => format!("{t}-clang"), Language::CPlusPlus => format!("{t}-clang++"), diff --git a/src/bootstrap/src/utils/cc_detect/tests.rs b/src/bootstrap/src/utils/cc_detect/tests.rs index 1f50738959fb..bed03c18aaad 100644 --- a/src/bootstrap/src/utils/cc_detect/tests.rs +++ b/src/bootstrap/src/utils/cc_detect/tests.rs @@ -77,11 +77,11 @@ fn test_new_cc_build() { #[test] fn test_default_compiler_wasi() { - let build = Build::new(Config { ..Config::parse(Flags::parse(&["build".to_owned()])) }); + let mut build = Build::new(Config { ..Config::parse(Flags::parse(&["build".to_owned()])) }); let target = TargetSelection::from_user("wasm32-wasi"); let wasi_sdk = PathBuf::from("/wasi-sdk"); - // SAFETY: bootstrap tests run on a single thread - unsafe { env::set_var("WASI_SDK_PATH", &wasi_sdk) }; + build.wasi_sdk_path = Some(wasi_sdk.clone()); + let mut cfg = cc::Build::new(); if let Some(result) = default_compiler(&mut cfg, Language::C, target.clone(), &build) { let expected = { @@ -94,10 +94,6 @@ fn test_default_compiler_wasi() { "default_compiler should return a compiler path for wasi target when WASI_SDK_PATH is set" ); } - // SAFETY: bootstrap tests run on a single thread - unsafe { - env::remove_var("WASI_SDK_PATH"); - } } #[test] @@ -119,18 +115,14 @@ fn test_find_target_with_config() { target_config.ar = Some(PathBuf::from("dummy-ar")); target_config.ranlib = Some(PathBuf::from("dummy-ranlib")); build.config.target_config.insert(target.clone(), target_config); - find_target(&build, target.clone()); - let binding = build.cc.borrow(); - let cc_tool = binding.get(&target).unwrap(); + fill_target_compiler(&mut build, target.clone()); + let cc_tool = build.cc.get(&target).unwrap(); assert_eq!(cc_tool.path(), &PathBuf::from("dummy-cc")); - let binding = build.cxx.borrow(); - let cxx_tool = binding.get(&target).unwrap(); + let cxx_tool = build.cxx.get(&target).unwrap(); assert_eq!(cxx_tool.path(), &PathBuf::from("dummy-cxx")); - let binding = build.ar.borrow(); - let ar = binding.get(&target).unwrap(); + let ar = build.ar.get(&target).unwrap(); assert_eq!(ar, &PathBuf::from("dummy-ar")); - let binding = build.ranlib.borrow(); - let ranlib = binding.get(&target).unwrap(); + let ranlib = build.ranlib.get(&target).unwrap(); assert_eq!(ranlib, &PathBuf::from("dummy-ranlib")); } @@ -139,12 +131,12 @@ fn test_find_target_without_config() { let mut build = Build::new(Config { ..Config::parse(Flags::parse(&["build".to_owned()])) }); let target = TargetSelection::from_user("x86_64-unknown-linux-gnu"); build.config.target_config.clear(); - find_target(&build, target.clone()); - assert!(build.cc.borrow().contains_key(&target)); + fill_target_compiler(&mut build, target.clone()); + assert!(build.cc.contains_key(&target)); if !target.triple.contains("vxworks") { - assert!(build.cxx.borrow().contains_key(&target)); + assert!(build.cxx.contains_key(&target)); } - assert!(build.ar.borrow().contains_key(&target)); + assert!(build.ar.contains_key(&target)); } #[test] @@ -154,8 +146,8 @@ fn test_find() { let target2 = TargetSelection::from_user("x86_64-unknown-openbsd"); build.targets.push(target1.clone()); build.hosts.push(target2.clone()); - find(&build); + fill_compilers(&mut build); for t in build.hosts.iter().chain(build.targets.iter()).chain(iter::once(&build.host_target)) { - assert!(build.cc.borrow().contains_key(t), "CC not set for target {}", t.triple); + assert!(build.cc.contains_key(t), "CC not set for target {}", t.triple); } } diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs index 3e04e0468446..f4be22f1e649 100644 --- a/src/bootstrap/src/utils/helpers.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -98,7 +98,7 @@ pub fn is_dylib(path: &Path) -> bool { /// Return the path to the containing submodule if available. pub fn submodule_path_of(builder: &Builder<'_>, path: &str) -> Option { - let submodule_paths = build_helper::util::parse_gitmodules(&builder.src); + let submodule_paths = builder.submodule_paths(); submodule_paths.iter().find_map(|submodule_path| { if path.starts_with(submodule_path) { Some(submodule_path.to_string()) } else { None } }) @@ -270,24 +270,6 @@ pub fn is_valid_test_suite_arg<'a, P: AsRef>( } } -// FIXME: get rid of this function -pub fn check_run(cmd: &mut BootstrapCommand, print_cmd_on_fail: bool) -> bool { - let status = match cmd.as_command_mut().status() { - Ok(status) => status, - Err(e) => { - println!("failed to execute command: {cmd:?}\nERROR: {e}"); - return false; - } - }; - if !status.success() && print_cmd_on_fail { - println!( - "\n\ncommand did not execute successfully: {cmd:?}\n\ - expected success, got: {status}\n\n" - ); - } - status.success() -} - pub fn make(host: &str) -> PathBuf { if host.contains("dragonfly") || host.contains("freebsd") diff --git a/src/bootstrap/src/utils/shared_helpers.rs b/src/bootstrap/src/utils/shared_helpers.rs index 561af34a4478..9c6b4a7615d8 100644 --- a/src/bootstrap/src/utils/shared_helpers.rs +++ b/src/bootstrap/src/utils/shared_helpers.rs @@ -6,6 +6,9 @@ #![allow(dead_code)] +#[cfg(test)] +mod tests; + use std::env; use std::ffi::OsString; use std::fs::OpenOptions; diff --git a/src/bootstrap/src/utils/tests/shared_helpers_tests.rs b/src/bootstrap/src/utils/shared_helpers/tests.rs similarity index 73% rename from src/bootstrap/src/utils/tests/shared_helpers_tests.rs rename to src/bootstrap/src/utils/shared_helpers/tests.rs index 6c47e7f24387..559e9f70abd2 100644 --- a/src/bootstrap/src/utils/tests/shared_helpers_tests.rs +++ b/src/bootstrap/src/utils/shared_helpers/tests.rs @@ -1,10 +1,3 @@ -//! The `shared_helpers` module can't have its own tests submodule, because -//! that would cause problems for the shim binaries that include it via -//! `#[path]`, so instead those unit tests live here. -//! -//! To prevent tidy from complaining about this file not being named `tests.rs`, -//! it lives inside a submodule directory named `tests`. - use crate::utils::shared_helpers::parse_value_from_args; #[test] diff --git a/src/bootstrap/src/utils/tests/mod.rs b/src/bootstrap/src/utils/tests/mod.rs index 73d55db994cc..73c500f6e369 100644 --- a/src/bootstrap/src/utils/tests/mod.rs +++ b/src/bootstrap/src/utils/tests/mod.rs @@ -1,2 +1,3 @@ +//! This module contains shared utilities for bootstrap tests. + pub mod git; -mod shared_helpers_tests; diff --git a/src/build_helper/src/util.rs b/src/build_helper/src/util.rs index 72c05c4c48ab..80dd6813d136 100644 --- a/src/build_helper/src/util.rs +++ b/src/build_helper/src/util.rs @@ -2,7 +2,6 @@ use std::fs::File; use std::io::{BufRead, BufReader}; use std::path::Path; use std::process::Command; -use std::sync::OnceLock; /// Invokes `build_helper::util::detail_exit` with `cfg!(test)` /// @@ -51,25 +50,20 @@ pub fn try_run(cmd: &mut Command, print_cmd_on_fail: bool) -> Result<(), ()> { } /// Returns the submodule paths from the `.gitmodules` file in the given directory. -pub fn parse_gitmodules(target_dir: &Path) -> &[String] { - static SUBMODULES_PATHS: OnceLock> = OnceLock::new(); +pub fn parse_gitmodules(target_dir: &Path) -> Vec { let gitmodules = target_dir.join(".gitmodules"); assert!(gitmodules.exists(), "'{}' file is missing.", gitmodules.display()); - let init_submodules_paths = || { - let file = File::open(gitmodules).unwrap(); + let file = File::open(gitmodules).unwrap(); - let mut submodules_paths = vec![]; - for line in BufReader::new(file).lines().map_while(Result::ok) { - let line = line.trim(); - if line.starts_with("path") { - let actual_path = line.split(' ').last().expect("Couldn't get value of path"); - submodules_paths.push(actual_path.to_owned()); - } + let mut submodules_paths = vec![]; + for line in BufReader::new(file).lines().map_while(Result::ok) { + let line = line.trim(); + if line.starts_with("path") { + let actual_path = line.split(' ').last().expect("Couldn't get value of path"); + submodules_paths.push(actual_path.to_owned()); } + } - submodules_paths - }; - - SUBMODULES_PATHS.get_or_init(|| init_submodules_paths()) + submodules_paths } diff --git a/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile b/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile index 241199d3bafb..58e66fd637a2 100644 --- a/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile +++ b/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile @@ -22,10 +22,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -RUN mkdir -p /config -RUN echo "[rust]" > /config/nopt-std-config.toml -RUN echo "optimize = false" >> /config/nopt-std-config.toml - ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu --disable-optimize-tests ARG SCRIPT_ARG COPY scripts/stage_2_test_set1.sh /scripts/ diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile index 1b57ae7c8da0..854c36ee01c1 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile @@ -22,12 +22,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -RUN mkdir -p /config -RUN echo "[rust]" > /config/nopt-std-config.toml -RUN echo "optimize = false" >> /config/nopt-std-config.toml - ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu \ --disable-optimize-tests \ --set rust.test-compare-mode -ENV SCRIPT python3 ../x.py test --stage 1 --config /config/nopt-std-config.toml library/std \ +ENV SCRIPT python3 ../x.py test --stage 1 --set rust.optimize=false library/std \ && python3 ../x.py --stage 2 test diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index d6d9e0fb7736..217cf764afbb 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -300,7 +300,7 @@ auto: env: IMAGE: i686-gnu-nopt DOCKER_SCRIPT: >- - python3 ../x.py test --stage 1 --config /config/nopt-std-config.toml library/std && + python3 ../x.py test --stage 1 --set rust.optimize=false library/std && /scripts/stage_2_test_set2.sh <<: *job-linux-4c diff --git a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md index b67f49c3a380..1e74c47221c7 100644 --- a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md +++ b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md @@ -207,120 +207,3 @@ conditionally compile code instead. This is notably different to the way native platforms such as x86\_64 work, and this is due to the fact that WebAssembly binaries must only contain code the engine understands. Native binaries work so long as the CPU doesn't execute unknown code dynamically at runtime. - -## Broken `extern "C"` ABI - -This target has what is considered a broken `extern "C"` ABI implementation at -this time. Notably the same signature in Rust and C will compile to different -WebAssembly functions and be incompatible. This is considered a bug and it will -be fixed in a future version of Rust. - -For example this Rust code: - -```rust,ignore (does-not-link) -#[repr(C)] -struct MyPair { - a: u32, - b: u32, -} - -extern "C" { - fn take_my_pair(pair: MyPair) -> u32; -} - -#[no_mangle] -pub unsafe extern "C" fn call_c() -> u32 { - take_my_pair(MyPair { a: 1, b: 2 }) -} -``` - -compiles to a WebAssembly module that looks like: - -```wasm -(module - (import "env" "take_my_pair" (func $take_my_pair (param i32 i32) (result i32))) - (func $call_c - i32.const 1 - i32.const 2 - call $take_my_pair - ) -) -``` - -The function when defined in C, however, looks like - -```c -struct my_pair { - unsigned a; - unsigned b; -}; - -unsigned take_my_pair(struct my_pair pair) { - return pair.a + pair.b; -} -``` - -```wasm -(module - (import "env" "__linear_memory" (memory 0)) - (func $take_my_pair (param i32) (result i32) - local.get 0 - i32.load offset=4 - local.get 0 - i32.load - i32.add - ) -) -``` - -Notice how Rust thinks `take_my_pair` takes two `i32` parameters but C thinks it -only takes one. - -The correct definition of the `extern "C"` ABI for WebAssembly is located in the -[WebAssembly/tool-conventions](https://github.com/WebAssembly/tool-conventions/blob/main/BasicCABI.md) -repository. The `wasm32-unknown-unknown` target (and only this target, not other -WebAssembly targets Rust support) does not correctly follow this document. - -Example issues in the Rust repository about this bug are: - -* [#115666](https://github.com/rust-lang/rust/issues/115666) -* [#129486](https://github.com/rust-lang/rust/issues/129486) - -This current state of the `wasm32-unknown-unknown` backend is due to an -unfortunate accident which got relied on. The `wasm-bindgen` project prior to -0.2.89 was incompatible with the "correct" definition of `extern "C"` and it was -seen as not worth the tradeoff of breaking `wasm-bindgen` historically to fix -this issue in the compiler. - -Thanks to the heroic efforts of many involved in this, however, `wasm-bindgen` -0.2.89 and later are compatible with the correct definition of `extern "C"` and -the nightly compiler currently supports a `-Zwasm-c-abi` implemented in -[#117919](https://github.com/rust-lang/rust/pull/117919). This nightly-only flag -can be used to indicate whether the spec-defined version of `extern "C"` should -be used instead of the "legacy" version of -whatever-the-Rust-target-originally-implemented. For example using the above -code you can see (lightly edited for clarity): - -```shell -$ rustc +nightly -Zwasm-c-abi=spec foo.rs --target wasm32-unknown-unknown --crate-type lib --emit obj -O -$ wasm-tools print foo.o -(module - (import "env" "take_my_pair" (func $take_my_pair (param i32) (result i32))) - (func $call_c (result i32) - ;; ... - ) - ;; ... -) -``` - -which shows that the C and Rust definitions of the same function now agree like -they should. - -The `-Zwasm-c-abi` compiler flag is tracked in -[#122532](https://github.com/rust-lang/rust/issues/122532) and a lint was -implemented in [#117918](https://github.com/rust-lang/rust/issues/117918) to -help warn users about the transition if they're using `wasm-bindgen` 0.2.88 or -prior. The current plan is to, in the future, switch `-Zwasm-c-api=spec` to -being the default. Some time after that the `-Zwasm-c-abi` flag and the -"legacy" implementation will all be removed. During this process users on a -sufficiently updated version of `wasm-bindgen` should not experience breakage. diff --git a/src/llvm-project b/src/llvm-project index c1118fdbb302..ed6566573eb2 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit c1118fdbb3024157df7f4cfe765f2b0b4339e8a2 +Subproject commit ed6566573eb21b00a3f87815e14ff766fd56ef42 diff --git a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs index 8e8c55cf3832..010f09d4c1d3 100644 --- a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs +++ b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs @@ -185,7 +185,7 @@ pub(super) fn check<'tcx>( Node::Expr(parent) if is_borrow_expr(cx, parent) && !is_in_allowed_macro(cx, parent) => { MaybeParenOrBlock::Block }, - Node::Expr(parent) if cast_expr.precedence() < parent.precedence() => MaybeParenOrBlock::Paren, + Node::Expr(parent) if cx.precedence(cast_expr) < cx.precedence(parent) => MaybeParenOrBlock::Paren, _ => MaybeParenOrBlock::Nothing, }; diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index cde9528cd878..7463d7b5c3bd 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -972,7 +972,7 @@ fn report<'tcx>( "&" }; - let expr_str = if !expr_is_macro_call && is_ufcs && expr.precedence() < ExprPrecedence::Prefix { + let expr_str = if !expr_is_macro_call && is_ufcs && cx.precedence(expr) < ExprPrecedence::Prefix { Cow::Owned(format!("({expr_str})")) } else { expr_str @@ -1015,10 +1015,10 @@ fn report<'tcx>( Node::Expr(e) => match e.kind { ExprKind::Call(callee, _) if callee.hir_id != data.first_expr.hir_id => false, ExprKind::Call(..) => { - expr.precedence() < ExprPrecedence::Unambiguous + cx.precedence(expr) < ExprPrecedence::Unambiguous || matches!(expr.kind, ExprKind::Field(..)) }, - _ => expr.precedence() < e.precedence(), + _ => cx.precedence(expr) < cx.precedence(e), }, _ => false, }; @@ -1066,7 +1066,7 @@ fn report<'tcx>( Mutability::Not => "&", Mutability::Mut => "&mut ", }; - (prefix, expr.precedence() < ExprPrecedence::Prefix) + (prefix, cx.precedence(expr) < ExprPrecedence::Prefix) }, None if !ty.is_ref() && data.adjusted_ty.is_ref() => ("&", false), _ => ("", false), @@ -1172,7 +1172,7 @@ impl<'tcx> Dereferencing<'tcx> { }, Some(parent) if !parent.span.from_expansion() => { // Double reference might be needed at this point. - if parent.precedence() == ExprPrecedence::Unambiguous { + if cx.precedence(parent) == ExprPrecedence::Unambiguous { // Parentheses would be needed here, don't lint. *outer_pat = None; } else { diff --git a/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs b/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs index 12719c4f94bf..d66771a8b5be 100644 --- a/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/single_element_loop.rs @@ -84,7 +84,7 @@ pub(super) fn check<'tcx>( if !prefix.is_empty() && ( // Precedence of internal expression is less than or equal to precedence of `&expr`. - arg_expression.precedence() <= ExprPrecedence::Prefix || is_range_literal(arg_expression) + cx.precedence(arg_expression) <= ExprPrecedence::Prefix || is_range_literal(arg_expression) ) { arg_snip = format!("({arg_snip})").into(); diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs b/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs index d0905733ab50..dbae71bbb1b0 100644 --- a/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs +++ b/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs @@ -117,7 +117,7 @@ where // it's being passed by value. let scrutinee = peel_hir_expr_refs(scrutinee).0; let (scrutinee_str, _) = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app); - let scrutinee_str = if scrutinee.span.eq_ctxt(expr.span) && scrutinee.precedence() < ExprPrecedence::Unambiguous { + let scrutinee_str = if scrutinee.span.eq_ctxt(expr.span) && cx.precedence(scrutinee) < ExprPrecedence::Unambiguous { format!("({scrutinee_str})") } else { scrutinee_str.into() diff --git a/src/tools/clippy/clippy_lints/src/neg_multiply.rs b/src/tools/clippy/clippy_lints/src/neg_multiply.rs index 74c8142787eb..442280f99982 100644 --- a/src/tools/clippy/clippy_lints/src/neg_multiply.rs +++ b/src/tools/clippy/clippy_lints/src/neg_multiply.rs @@ -64,7 +64,7 @@ fn check_mul(cx: &LateContext<'_>, span: Span, lit: &Expr<'_>, exp: &Expr<'_>) { { let mut applicability = Applicability::MachineApplicable; let (snip, from_macro) = snippet_with_context(cx, exp.span, span.ctxt(), "..", &mut applicability); - let suggestion = if !from_macro && exp.precedence() < ExprPrecedence::Prefix && !has_enclosing_paren(&snip) { + let suggestion = if !from_macro && cx.precedence(exp) < ExprPrecedence::Prefix && !has_enclosing_paren(&snip) { format!("-({snip})") } else { format!("-{snip}") diff --git a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs index 1117dea703c2..324a05cdcc0c 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs @@ -86,7 +86,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing { let (indexed_ty, indexed_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(indexed)); let parent_expr = get_parent_expr(cx, expr); let needs_parens_for_prefix = - parent_expr.is_some_and(|parent| parent.precedence() > ExprPrecedence::Prefix); + parent_expr.is_some_and(|parent| cx.precedence(parent) > ExprPrecedence::Prefix); if expr_ty == indexed_ty { if expr_ref_count > indexed_ref_count { diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs index 0d5cf45a5e65..18897fbb5b8f 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs @@ -44,7 +44,7 @@ pub(super) fn check<'tcx>( }; if let Node::Expr(parent) = cx.tcx.parent_hir_node(e.hir_id) - && parent.precedence() > ExprPrecedence::Cast + && cx.precedence(parent) > ExprPrecedence::Cast { sugg = format!("({sugg})"); } diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 68f7d14f57f0..e96c81d5b1d1 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -16,7 +16,7 @@ #![feature(unqualified_local_imports)] #![feature(derive_coerce_pointee)] #![feature(arbitrary_self_types)] -#![feature(file_lock)] +#![cfg_attr(bootstrap, feature(file_lock))] // Configure clippy and other lints #![allow( clippy::collapsible_else_if, diff --git a/src/tools/miri/tests/pass/shims/fs.rs b/src/tools/miri/tests/pass/shims/fs.rs index 2f30827c9336..9d5725773e64 100644 --- a/src/tools/miri/tests/pass/shims/fs.rs +++ b/src/tools/miri/tests/pass/shims/fs.rs @@ -2,7 +2,6 @@ #![feature(io_error_more)] #![feature(io_error_uncategorized)] -#![feature(file_lock)] use std::collections::BTreeMap; use std::ffi::OsString; diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs index 543ac0619dd3..385c98ef8778 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs @@ -486,7 +486,7 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_legacy_const_generics, Normal, template!(List: "N"), ErrorFollowing, INTERNAL_UNSTABLE ), - // Do not const-check this function's body. It will always get replaced during CTFE. + // Do not const-check this function's body. It will always get replaced during CTFE via `hook_special_const_fn`. rustc_attr!( rustc_do_not_const_check, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE ), diff --git a/tests/assembly/asm/loongarch-type.rs b/tests/assembly/asm/loongarch-type.rs index 86d9e03bc931..c782be19f1d2 100644 --- a/tests/assembly/asm/loongarch-type.rs +++ b/tests/assembly/asm/loongarch-type.rs @@ -4,7 +4,7 @@ //@ compile-flags: -Zmerge-functions=disabled //@ needs-llvm-components: loongarch -#![feature(no_core)] +#![feature(no_core, f16)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register, non_camel_case_types)] @@ -69,6 +69,12 @@ check!(reg_i8, i8, reg, "move"); // CHECK: #NO_APP check!(reg_i16, i16, reg, "move"); +// CHECK-LABEL: reg_f16: +// CHECK: #APP +// CHECK: move ${{[a-z0-9]+}}, ${{[a-z0-9]+}} +// CHECK: #NO_APP +check!(reg_f16, f16, reg, "move"); + // CHECK-LABEL: reg_i32: // CHECK: #APP // CHECK: move ${{[a-z0-9]+}}, ${{[a-z0-9]+}} @@ -99,6 +105,12 @@ check!(reg_f64, f64, reg, "move"); // CHECK: #NO_APP check!(reg_ptr, ptr, reg, "move"); +// CHECK-LABEL: freg_f16: +// CHECK: #APP +// CHECK: fmov.s $f{{[a-z0-9]+}}, $f{{[a-z0-9]+}} +// CHECK: #NO_APP +check!(freg_f16, f16, freg, "fmov.s"); + // CHECK-LABEL: freg_f32: // CHECK: #APP // CHECK: fmov.s $f{{[a-z0-9]+}}, $f{{[a-z0-9]+}} @@ -123,6 +135,12 @@ check_reg!(r4_i8, i8, "$r4", "move"); // CHECK: #NO_APP check_reg!(r4_i16, i16, "$r4", "move"); +// CHECK-LABEL: r4_f16: +// CHECK: #APP +// CHECK: move $a0, $a0 +// CHECK: #NO_APP +check_reg!(r4_f16, f16, "$r4", "move"); + // CHECK-LABEL: r4_i32: // CHECK: #APP // CHECK: move $a0, $a0 @@ -153,6 +171,12 @@ check_reg!(r4_f64, f64, "$r4", "move"); // CHECK: #NO_APP check_reg!(r4_ptr, ptr, "$r4", "move"); +// CHECK-LABEL: f0_f16: +// CHECK: #APP +// CHECK: fmov.s $f{{[a-z0-9]+}}, $f{{[a-z0-9]+}} +// CHECK: #NO_APP +check_reg!(f0_f16, f16, "$f0", "fmov.s"); + // CHECK-LABEL: f0_f32: // CHECK: #APP // CHECK: fmov.s $f{{[a-z0-9]+}}, $f{{[a-z0-9]+}} diff --git a/tests/assembly/naked-functions/wasm32.rs b/tests/assembly/naked-functions/wasm32.rs index 71e4d80764a3..984152f2b453 100644 --- a/tests/assembly/naked-functions/wasm32.rs +++ b/tests/assembly/naked-functions/wasm32.rs @@ -1,10 +1,10 @@ -// FIXME: add wasm32-unknown when the wasm32-unknown-unknown ABI is fixed -// see https://github.com/rust-lang/rust/issues/115666 -//@ revisions: wasm64-unknown wasm32-wasip1 +//@ revisions: wasm32-unknown wasm64-unknown wasm32-wasip1 //@ add-core-stubs //@ assembly-output: emit-asm +//@ [wasm32-unknown] compile-flags: --target wasm32-unknown-unknown //@ [wasm64-unknown] compile-flags: --target wasm64-unknown-unknown //@ [wasm32-wasip1] compile-flags: --target wasm32-wasip1 +//@ [wasm32-unknown] needs-llvm-components: webassembly //@ [wasm64-unknown] needs-llvm-components: webassembly //@ [wasm32-wasip1] needs-llvm-components: webassembly @@ -97,6 +97,7 @@ extern "C" fn fn_i64_i64(num: i64) -> i64 { } // CHECK-LABEL: fn_i128_i128: +// wasm32-unknown: .functype fn_i128_i128 (i32, i64, i64) -> () // wasm32-wasip1: .functype fn_i128_i128 (i32, i64, i64) -> () // wasm64-unknown: .functype fn_i128_i128 (i64, i64, i64) -> () #[allow(improper_ctypes_definitions)] @@ -114,6 +115,7 @@ extern "C" fn fn_i128_i128(num: i128) -> i128 { } // CHECK-LABEL: fn_f128_f128: +// wasm32-unknown: .functype fn_f128_f128 (i32, i64, i64) -> () // wasm32-wasip1: .functype fn_f128_f128 (i32, i64, i64) -> () // wasm64-unknown: .functype fn_f128_f128 (i64, i64, i64) -> () #[no_mangle] @@ -136,6 +138,7 @@ struct Compound { } // CHECK-LABEL: fn_compound_compound: +// wasm32-unknown: .functype fn_compound_compound (i32, i32) -> () // wasm32-wasip1: .functype fn_compound_compound (i32, i32) -> () // wasm64-unknown: .functype fn_compound_compound (i64, i64) -> () #[no_mangle] diff --git a/tests/assembly/pic-relocation-model.rs b/tests/assembly/pic-relocation-model.rs index d35cd968389a..15a8723f756e 100644 --- a/tests/assembly/pic-relocation-model.rs +++ b/tests/assembly/pic-relocation-model.rs @@ -19,7 +19,7 @@ pub fn call_other_fn() -> u8 { } // CHECK-LABEL: other_fn: -// CHECK: callq *foreign_fn@GOTPCREL(%rip) +// CHECK: {{(jmpq|callq)}} *foreign_fn@GOTPCREL(%rip) #[no_mangle] #[inline(never)] pub fn other_fn() -> u8 { diff --git a/tests/assembly/pie-relocation-model.rs b/tests/assembly/pie-relocation-model.rs index 5c74b34eb313..cbe0001041ef 100644 --- a/tests/assembly/pie-relocation-model.rs +++ b/tests/assembly/pie-relocation-model.rs @@ -22,7 +22,7 @@ pub fn call_other_fn() -> u8 { // CHECK-LABEL: other_fn: // External functions are still called through GOT, since we don't know if the symbol // is defined in the binary or in the shared library. -// CHECK: callq *foreign_fn@GOTPCREL(%rip) +// CHECK: {{(jmpq|callq)}} *foreign_fn@GOTPCREL(%rip) #[no_mangle] #[inline(never)] pub fn other_fn() -> u8 { diff --git a/tests/assembly/riscv-float-struct-abi.rs b/tests/assembly/riscv-float-struct-abi.rs new file mode 100644 index 000000000000..5d9ac9d70b83 --- /dev/null +++ b/tests/assembly/riscv-float-struct-abi.rs @@ -0,0 +1,177 @@ +//@ add-core-stubs +//@ assembly-output: emit-asm +//@ compile-flags: -Copt-level=3 --target riscv64gc-unknown-linux-gnu +//@ needs-llvm-components: riscv + +#![feature(no_core, lang_items)] +#![no_std] +#![no_core] +#![crate_type = "lib"] + +extern crate minicore; +use minicore::*; + +#[repr(C, align(64))] +struct Aligned(f64); + +#[repr(C)] +struct Padded(u8, Aligned); + +#[repr(C, packed)] +struct Packed(u8, f32); + +impl Copy for Aligned {} +impl Copy for Padded {} +impl Copy for Packed {} + +extern "C" { + fn take_padded(x: Padded); + fn get_padded() -> Padded; + fn take_packed(x: Packed); + fn get_packed() -> Packed; +} + +// CHECK-LABEL: pass_padded +#[unsafe(no_mangle)] +extern "C" fn pass_padded(out: &mut Padded, x: Padded) { + // CHECK: sb a1, 0(a0) + // CHECK-NEXT: fsd fa0, 64(a0) + // CHECK-NEXT: ret + *out = x; +} + +// CHECK-LABEL: ret_padded +#[unsafe(no_mangle)] +extern "C" fn ret_padded(x: &Padded) -> Padded { + // CHECK: fld fa0, 64(a0) + // CHECK-NEXT: lbu a0, 0(a0) + // CHECK-NEXT: ret + *x +} + +#[unsafe(no_mangle)] +extern "C" fn call_padded(x: &Padded) { + // CHECK: fld fa0, 64(a0) + // CHECK-NEXT: lbu a0, 0(a0) + // CHECK-NEXT: tail take_padded + unsafe { + take_padded(*x); + } +} + +#[unsafe(no_mangle)] +extern "C" fn receive_padded(out: &mut Padded) { + // CHECK: addi sp, sp, -16 + // CHECK-NEXT: .cfi_def_cfa_offset 16 + // CHECK-NEXT: sd ra, [[#%d,RA_SPILL:]](sp) + // CHECK-NEXT: sd [[TEMP:.*]], [[#%d,TEMP_SPILL:]](sp) + // CHECK-NEXT: .cfi_offset ra, [[#%d,RA_SPILL - 16]] + // CHECK-NEXT: .cfi_offset [[TEMP]], [[#%d,TEMP_SPILL - 16]] + // CHECK-NEXT: mv [[TEMP]], a0 + // CHECK-NEXT: call get_padded + // CHECK-NEXT: sb a0, 0([[TEMP]]) + // CHECK-NEXT: fsd fa0, 64([[TEMP]]) + // CHECK-NEXT: ld ra, [[#%d,RA_SPILL]](sp) + // CHECK-NEXT: ld [[TEMP]], [[#%d,TEMP_SPILL]](sp) + // CHECK: addi sp, sp, 16 + // CHECK: ret + unsafe { + *out = get_padded(); + } +} + +// CHECK-LABEL: pass_packed +#[unsafe(no_mangle)] +extern "C" fn pass_packed(out: &mut Packed, x: Packed) { + // CHECK: addi sp, sp, -16 + // CHECK-NEXT: .cfi_def_cfa_offset 16 + // CHECK-NEXT: sb a1, 0(a0) + // CHECK-NEXT: fsw fa0, 8(sp) + // CHECK-NEXT: lw [[VALUE:.*]], 8(sp) + // CHECK-DAG: srli [[BYTE4:.*]], [[VALUE]], 24 + // CHECK-DAG: srli [[BYTE3:.*]], [[VALUE]], 16 + // CHECK-DAG: srli [[BYTE2:.*]], [[VALUE]], 8 + // CHECK-DAG: sb [[VALUE]], 1(a0) + // CHECK-DAG: sb [[BYTE2]], 2(a0) + // CHECK-DAG: sb [[BYTE3]], 3(a0) + // CHECK-DAG: sb [[BYTE4]], 4(a0) + // CHECK-NEXT: addi sp, sp, 16 + // CHECK: ret + *out = x; +} + +// CHECK-LABEL: ret_packed +#[unsafe(no_mangle)] +extern "C" fn ret_packed(x: &Packed) -> Packed { + // CHECK: addi sp, sp, -16 + // CHECK-NEXT: .cfi_def_cfa_offset 16 + // CHECK-NEXT: lbu [[BYTE2:.*]], 2(a0) + // CHECK-NEXT: lbu [[BYTE1:.*]], 1(a0) + // CHECK-NEXT: lbu [[BYTE3:.*]], 3(a0) + // CHECK-NEXT: lbu [[BYTE4:.*]], 4(a0) + // CHECK-NEXT: slli [[SHIFTED2:.*]], [[BYTE2]], 8 + // CHECK-NEXT: or [[BYTE12:.*]], [[SHIFTED2]], [[BYTE1]] + // CHECK-NEXT: slli [[SHIFTED3:.*]], [[BYTE3]], 16 + // CHECK-NEXT: slli [[SHIFTED4:.*]], [[BYTE4]], 24 + // CHECK-NEXT: or [[BYTE34:.*]], [[SHIFTED3]], [[SHIFTED4]] + // CHECK-NEXT: or [[VALUE:.*]], [[BYTE12]], [[BYTE34]] + // CHECK-NEXT: sw [[VALUE]], 8(sp) + // CHECK-NEXT: flw fa0, 8(sp) + // CHECK-NEXT: lbu a0, 0(a0) + // CHECK-NEXT: addi sp, sp, 16 + // CHECK: ret + *x +} + +#[unsafe(no_mangle)] +extern "C" fn call_packed(x: &Packed) { + // CHECK: addi sp, sp, -16 + // CHECK-NEXT: .cfi_def_cfa_offset 16 + // CHECK-NEXT: lbu [[BYTE2:.*]], 2(a0) + // CHECK-NEXT: lbu [[BYTE1:.*]], 1(a0) + // CHECK-NEXT: lbu [[BYTE3:.*]], 3(a0) + // CHECK-NEXT: lbu [[BYTE4:.*]], 4(a0) + // CHECK-NEXT: slli [[SHIFTED2:.*]], [[BYTE2]], 8 + // CHECK-NEXT: or [[BYTE12:.*]], [[SHIFTED2]], [[BYTE1]] + // CHECK-NEXT: slli [[SHIFTED3:.*]], [[BYTE3]], 16 + // CHECK-NEXT: slli [[SHIFTED4:.*]], [[BYTE4]], 24 + // CHECK-NEXT: or [[BYTE34:.*]], [[SHIFTED3]], [[SHIFTED4]] + // CHECK-NEXT: or [[VALUE:.*]], [[BYTE12]], [[BYTE34]] + // CHECK-NEXT: sw [[VALUE]], 8(sp) + // CHECK-NEXT: flw fa0, 8(sp) + // CHECK-NEXT: lbu a0, 0(a0) + // CHECK-NEXT: addi sp, sp, 16 + // CHECK: tail take_packed + unsafe { + take_packed(*x); + } +} + +#[unsafe(no_mangle)] +extern "C" fn receive_packed(out: &mut Packed) { + // CHECK: addi sp, sp, -32 + // CHECK-NEXT: .cfi_def_cfa_offset 32 + // CHECK-NEXT: sd ra, [[#%d,RA_SPILL:]](sp) + // CHECK-NEXT: sd [[TEMP:.*]], [[#%d,TEMP_SPILL:]](sp) + // CHECK-NEXT: .cfi_offset ra, [[#%d,RA_SPILL - 32]] + // CHECK-NEXT: .cfi_offset [[TEMP]], [[#%d,TEMP_SPILL - 32]] + // CHECK-NEXT: mv [[TEMP]], a0 + // CHECK-NEXT: call get_packed + // CHECK-NEXT: sb a0, 0([[TEMP]]) + // CHECK-NEXT: fsw fa0, [[FLOAT_SPILL:.*]](sp) + // CHECK-NEXT: lw [[VALUE:.*]], [[FLOAT_SPILL]](sp) + // CHECK-DAG: srli [[BYTE4:.*]], [[VALUE]], 24 + // CHECK-DAG: srli [[BYTE3:.*]], [[VALUE]], 16 + // CHECK-DAG: srli [[BYTE2:.*]], [[VALUE]], 8 + // CHECK-DAG: sb [[VALUE]], 1([[TEMP]]) + // CHECK-DAG: sb [[BYTE2]], 2([[TEMP]]) + // CHECK-DAG: sb [[BYTE3]], 3([[TEMP]]) + // CHECK-DAG: sb [[BYTE4]], 4([[TEMP]]) + // CHECK-NEXT: ld ra, [[#%d,RA_SPILL]](sp) + // CHECK-NEXT: ld [[TEMP]], [[#%d,TEMP_SPILL]](sp) + // CHECK: addi sp, sp, 32 + // CHECK: ret + unsafe { + *out = get_packed(); + } +} diff --git a/tests/codegen/pie-relocation-model.rs b/tests/codegen/pie-relocation-model.rs index b10af6934522..cb8de91ccd7b 100644 --- a/tests/codegen/pie-relocation-model.rs +++ b/tests/codegen/pie-relocation-model.rs @@ -13,7 +13,7 @@ pub fn call_foreign_fn() -> u8 { // External functions are still marked as non-dso_local, since we don't know if the symbol // is defined in the binary or in the shared library. -// CHECK: declare zeroext i8 @foreign_fn() +// CHECK: declare i8 @foreign_fn() extern "C" { fn foreign_fn() -> u8; } diff --git a/tests/codegen/riscv-abi/cast-local-large-enough.rs b/tests/codegen/riscv-abi/cast-local-large-enough.rs new file mode 100644 index 000000000000..9d21d73b4597 --- /dev/null +++ b/tests/codegen/riscv-abi/cast-local-large-enough.rs @@ -0,0 +1,44 @@ +//@ add-core-stubs +//@ compile-flags: -Copt-level=0 -Cdebuginfo=0 --target riscv64gc-unknown-linux-gnu +//@ needs-llvm-components: riscv + +#![feature(no_core, lang_items)] +#![no_std] +#![no_core] +#![crate_type = "lib"] + +extern crate minicore; +use minicore::*; + +#[repr(C, align(64))] +struct Aligned(f64); + +#[repr(C, align(64))] +struct AlignedPair(f32, f64); + +impl Copy for Aligned {} +impl Copy for AlignedPair {} + +// CHECK-LABEL: define double @read_aligned +#[unsafe(no_mangle)] +pub extern "C" fn read_aligned(x: &Aligned) -> Aligned { + // CHECK: %[[TEMP:.*]] = alloca [64 x i8], align 64 + // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 64 %[[TEMP]], ptr align 64 %[[PTR:.*]], i64 64, i1 false) + // CHECK-NEXT: %[[RES:.*]] = load double, ptr %[[TEMP]], align 64 + // CHECK-NEXT: ret double %[[RES]] + *x +} + +// CHECK-LABEL: define { float, double } @read_aligned_pair +#[unsafe(no_mangle)] +pub extern "C" fn read_aligned_pair(x: &AlignedPair) -> AlignedPair { + // CHECK: %[[TEMP:.*]] = alloca [64 x i8], align 64 + // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 64 %[[TEMP]], ptr align 64 %[[PTR:.*]], i64 64, i1 false) + // CHECK-NEXT: %[[FIRST:.*]] = load float, ptr %[[TEMP]], align 64 + // CHECK-NEXT: %[[SECOND_PTR:.*]] = getelementptr inbounds i8, ptr %[[TEMP]], i64 8 + // CHECK-NEXT: %[[SECOND:.*]] = load double, ptr %[[SECOND_PTR]], align 8 + // CHECK-NEXT: %[[RES1:.*]] = insertvalue { float, double } poison, float %[[FIRST]], 0 + // CHECK-NEXT: %[[RES2:.*]] = insertvalue { float, double } %[[RES1]], double %[[SECOND]], 1 + // CHECK-NEXT: ret { float, double } %[[RES2]] + *x +} diff --git a/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir b/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir new file mode 100644 index 000000000000..347e4119cd0e --- /dev/null +++ b/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-abort.mir @@ -0,0 +1,100 @@ +// MIR for `a::{closure#0}` 0 coroutine_drop_async + +fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) -> Poll<()> { + debug _task_context => _19; + debug x => ((*(_1.0: &mut {async fn body of a()})).0: T); + let mut _0: std::task::Poll<()>; + let _3: T; + let mut _4: impl std::future::Future; + let mut _5: &mut T; + let mut _6: std::pin::Pin<&mut T>; + let mut _7: &mut T; + let mut _8: *mut T; + let mut _9: (); + let mut _10: std::task::Poll<()>; + let mut _11: &mut std::task::Context<'_>; + let mut _12: &mut impl std::future::Future; + let mut _13: std::pin::Pin<&mut impl std::future::Future>; + let mut _14: isize; + let mut _15: &mut std::task::Context<'_>; + let mut _16: &mut impl std::future::Future; + let mut _17: std::pin::Pin<&mut impl std::future::Future>; + let mut _18: isize; + let mut _19: &mut std::task::Context<'_>; + let mut _20: u32; + scope 1 { + debug x => (((*(_1.0: &mut {async fn body of a()})) as variant#4).0: T); + } + + bb0: { + _20 = discriminant((*(_1.0: &mut {async fn body of a()}))); + switchInt(move _20) -> [0: bb9, 3: bb12, 4: bb13, otherwise: bb14]; + } + + bb1: { + nop; + nop; + goto -> bb2; + } + + bb2: { + _0 = Poll::<()>::Ready(const ()); + return; + } + + bb3: { + _0 = Poll::<()>::Pending; + discriminant((*(_1.0: &mut {async fn body of a()}))) = 4; + return; + } + + bb4: { + StorageLive(_17); + _16 = &mut (((*(_1.0: &mut {async fn body of a()})) as variant#4).1: impl std::future::Future); + _17 = Pin::<&mut impl Future>::new_unchecked(move _16) -> [return: bb7, unwind unreachable]; + } + + bb5: { + unreachable; + } + + bb6: { + StorageDead(_17); + _18 = discriminant(_10); + switchInt(move _18) -> [0: bb1, 1: bb3, otherwise: bb5]; + } + + bb7: { + _10 = as Future>::poll(move _17, move _15) -> [return: bb6, unwind unreachable]; + } + + bb8: { + _0 = Poll::<()>::Ready(const ()); + return; + } + + bb9: { + goto -> bb11; + } + + bb10: { + goto -> bb8; + } + + bb11: { + drop(((*(_1.0: &mut {async fn body of a()})).0: T)) -> [return: bb10, unwind unreachable]; + } + + bb12: { + goto -> bb4; + } + + bb13: { + goto -> bb4; + } + + bb14: { + _0 = Poll::<()>::Ready(const ()); + return; + } +} diff --git a/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir b/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir new file mode 100644 index 000000000000..b1cf5373f919 --- /dev/null +++ b/tests/mir-opt/async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.panic-unwind.mir @@ -0,0 +1,123 @@ +// MIR for `a::{closure#0}` 0 coroutine_drop_async + +fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) -> Poll<()> { + debug _task_context => _19; + debug x => ((*(_1.0: &mut {async fn body of a()})).0: T); + let mut _0: std::task::Poll<()>; + let _3: T; + let mut _4: impl std::future::Future; + let mut _5: &mut T; + let mut _6: std::pin::Pin<&mut T>; + let mut _7: &mut T; + let mut _8: *mut T; + let mut _9: (); + let mut _10: std::task::Poll<()>; + let mut _11: &mut std::task::Context<'_>; + let mut _12: &mut impl std::future::Future; + let mut _13: std::pin::Pin<&mut impl std::future::Future>; + let mut _14: isize; + let mut _15: &mut std::task::Context<'_>; + let mut _16: &mut impl std::future::Future; + let mut _17: std::pin::Pin<&mut impl std::future::Future>; + let mut _18: isize; + let mut _19: &mut std::task::Context<'_>; + let mut _20: u32; + scope 1 { + debug x => (((*(_1.0: &mut {async fn body of a()})) as variant#4).0: T); + } + + bb0: { + _20 = discriminant((*(_1.0: &mut {async fn body of a()}))); + switchInt(move _20) -> [0: bb12, 2: bb18, 3: bb16, 4: bb17, otherwise: bb19]; + } + + bb1: { + nop; + nop; + goto -> bb2; + } + + bb2: { + _0 = Poll::<()>::Ready(const ()); + return; + } + + bb3 (cleanup): { + nop; + nop; + goto -> bb5; + } + + bb4 (cleanup): { + goto -> bb15; + } + + bb5 (cleanup): { + goto -> bb4; + } + + bb6: { + _0 = Poll::<()>::Pending; + discriminant((*(_1.0: &mut {async fn body of a()}))) = 4; + return; + } + + bb7: { + StorageLive(_17); + _16 = &mut (((*(_1.0: &mut {async fn body of a()})) as variant#4).1: impl std::future::Future); + _17 = Pin::<&mut impl Future>::new_unchecked(move _16) -> [return: bb10, unwind: bb15]; + } + + bb8: { + unreachable; + } + + bb9: { + StorageDead(_17); + _18 = discriminant(_10); + switchInt(move _18) -> [0: bb1, 1: bb6, otherwise: bb8]; + } + + bb10: { + _10 = as Future>::poll(move _17, move _15) -> [return: bb9, unwind: bb3]; + } + + bb11: { + _0 = Poll::<()>::Ready(const ()); + return; + } + + bb12: { + goto -> bb14; + } + + bb13: { + goto -> bb11; + } + + bb14: { + drop(((*(_1.0: &mut {async fn body of a()})).0: T)) -> [return: bb13, unwind: bb4]; + } + + bb15 (cleanup): { + discriminant((*(_1.0: &mut {async fn body of a()}))) = 2; + resume; + } + + bb16: { + goto -> bb7; + } + + bb17: { + goto -> bb7; + } + + bb18: { + assert(const false, "`async fn` resumed after panicking") -> [success: bb18, unwind continue]; + } + + bb19: { + _0 = Poll::<()>::Ready(const ()); + return; + } +} diff --git a/tests/mir-opt/async_drop_live_dead.rs b/tests/mir-opt/async_drop_live_dead.rs new file mode 100644 index 000000000000..348866bbb8c7 --- /dev/null +++ b/tests/mir-opt/async_drop_live_dead.rs @@ -0,0 +1,11 @@ +//@ edition:2024 +// skip-filecheck +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY + +#![feature(async_drop)] +#![allow(incomplete_features)] + +// EMIT_MIR async_drop_live_dead.a-{closure#0}.coroutine_drop_async.0.mir +async fn a(x: T) {} + +fn main() {} diff --git a/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs b/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs index ba887b3d791d..8824a498306e 100644 --- a/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs +++ b/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs @@ -1,3 +1,4 @@ +//@ needs-target-std // ignore-tidy-linelength // Check that the `CURRENT_RUSTC_VERSION` placeholder is correctly replaced by the current diff --git a/tests/run-make/allow-warnings-cmdline-stability/rmake.rs b/tests/run-make/allow-warnings-cmdline-stability/rmake.rs index 22a31266176b..66ca3eb3383b 100644 --- a/tests/run-make/allow-warnings-cmdline-stability/rmake.rs +++ b/tests/run-make/allow-warnings-cmdline-stability/rmake.rs @@ -1,3 +1,4 @@ +//@ needs-target-std // Test that `-Awarnings` suppresses warnings for unstable APIs. use run_make_support::rustc; diff --git a/tests/run-make/artifact-incr-cache-no-obj/rmake.rs b/tests/run-make/artifact-incr-cache-no-obj/rmake.rs index d5bc46dff470..8395b38f6125 100644 --- a/tests/run-make/artifact-incr-cache-no-obj/rmake.rs +++ b/tests/run-make/artifact-incr-cache-no-obj/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // emitting an object file is not necessary if user didn't ask for one // // This test is similar to run-make/artifact-incr-cache but it doesn't diff --git a/tests/run-make/artifact-incr-cache/rmake.rs b/tests/run-make/artifact-incr-cache/rmake.rs index b4b63313cfc4..670c851e1e00 100644 --- a/tests/run-make/artifact-incr-cache/rmake.rs +++ b/tests/run-make/artifact-incr-cache/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // rustc should be able to emit required files (asm, llvm-*, etc) during incremental // compilation on the first pass by running the code gen as well as on subsequent runs - // extracting them from the cache diff --git a/tests/run-make/bin-emit-no-symbols/rmake.rs b/tests/run-make/bin-emit-no-symbols/rmake.rs index 5586e53c0508..2faeb20025bb 100644 --- a/tests/run-make/bin-emit-no-symbols/rmake.rs +++ b/tests/run-make/bin-emit-no-symbols/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // When setting the crate type as a "bin" (in app.rs), // this could cause a bug where some symbols would not be // emitted in the object files. This has been fixed, and diff --git a/tests/run-make/box-struct-no-segfault/rmake.rs b/tests/run-make/box-struct-no-segfault/rmake.rs index 1bbefd03541a..06dcf61e9ccd 100644 --- a/tests/run-make/box-struct-no-segfault/rmake.rs +++ b/tests/run-make/box-struct-no-segfault/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // The crate "foo" tied to this test executes a very specific function, // which involves boxing an instance of the struct Foo. However, // this once caused a segmentation fault in cargo release builds due to an LLVM diff --git a/tests/run-make/checksum-freshness/rmake.rs b/tests/run-make/checksum-freshness/rmake.rs index 071db6b145b5..60e4f81269b1 100644 --- a/tests/run-make/checksum-freshness/rmake.rs +++ b/tests/run-make/checksum-freshness/rmake.rs @@ -1,3 +1,4 @@ +//@ needs-target-std use run_make_support::{rfs, rustc}; fn main() { diff --git a/tests/run-make/compiler-lookup-paths-2/rmake.rs b/tests/run-make/compiler-lookup-paths-2/rmake.rs index 99efb157b537..5401787b9bf9 100644 --- a/tests/run-make/compiler-lookup-paths-2/rmake.rs +++ b/tests/run-make/compiler-lookup-paths-2/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // This test checks that extern crate declarations in Cargo without a corresponding declaration // in the manifest of a dependency are NOT allowed. The last rustc call does it anyways, which // should result in a compilation failure. diff --git a/tests/run-make/compiler-lookup-paths/rmake.rs b/tests/run-make/compiler-lookup-paths/rmake.rs index 3ffa6e0592f0..0e00f9b34001 100644 --- a/tests/run-make/compiler-lookup-paths/rmake.rs +++ b/tests/run-make/compiler-lookup-paths/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // Since #19941, rustc can accept specifications on its library search paths. // This test runs Rust programs with varied library dependencies, expecting them // to succeed or fail depending on the situation. diff --git a/tests/run-make/const-trait-stable-toolchain/rmake.rs b/tests/run-make/const-trait-stable-toolchain/rmake.rs index 241de11ed59c..09a7c27a1064 100644 --- a/tests/run-make/const-trait-stable-toolchain/rmake.rs +++ b/tests/run-make/const-trait-stable-toolchain/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // Test output of const super trait errors in both stable and nightly. // We don't want to provide suggestions on stable that only make sense in nightly. diff --git a/tests/run-make/crate-circular-deps-link/rmake.rs b/tests/run-make/crate-circular-deps-link/rmake.rs index 7cc28ac93e14..6771fdec7e8a 100644 --- a/tests/run-make/crate-circular-deps-link/rmake.rs +++ b/tests/run-make/crate-circular-deps-link/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // Test that previously triggered a linker failure with root cause // similar to one found in the issue #69368. // diff --git a/tests/run-make/cross-lang-lto-upstream-rlibs/rmake.rs b/tests/run-make/cross-lang-lto-upstream-rlibs/rmake.rs index f0b8fa75bee3..7fb0f6903974 100644 --- a/tests/run-make/cross-lang-lto-upstream-rlibs/rmake.rs +++ b/tests/run-make/cross-lang-lto-upstream-rlibs/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // When using the flag -C linker-plugin-lto, static libraries could lose their upstream object // files during compilation. This bug was fixed in #53031, and this test compiles a staticlib // dependent on upstream, checking that the upstream object file still exists after no LTO and diff --git a/tests/run-make/cross-lang-lto/rmake.rs b/tests/run-make/cross-lang-lto/rmake.rs index 50d37460d8db..8773070b1a9e 100644 --- a/tests/run-make/cross-lang-lto/rmake.rs +++ b/tests/run-make/cross-lang-lto/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // This test checks that the object files we generate are actually // LLVM bitcode files (as used by linker LTO plugins) when compiling with // -Clinker-plugin-lto. diff --git a/tests/run-make/debugger-visualizer-dep-info/rmake.rs b/tests/run-make/debugger-visualizer-dep-info/rmake.rs index f5cf39157ac6..95a095e49d84 100644 --- a/tests/run-make/debugger-visualizer-dep-info/rmake.rs +++ b/tests/run-make/debugger-visualizer-dep-info/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // This test checks that files referenced via #[debugger_visualizer] are // included in `--emit dep-info` output. // See https://github.com/rust-lang/rust/pull/111641 diff --git a/tests/run-make/dep-info/rmake.rs b/tests/run-make/dep-info/rmake.rs index 508569b7671c..8cef6e87f7cf 100644 --- a/tests/run-make/dep-info/rmake.rs +++ b/tests/run-make/dep-info/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // This is a simple smoke test for rustc's `--emit dep-info` feature. It prints out // information about dependencies in a Makefile-compatible format, as a `.d` file. // Note that this test does not check that the `.d` file is Makefile-compatible. diff --git a/tests/run-make/diagnostics-traits-from-duplicate-crates/rmake.rs b/tests/run-make/diagnostics-traits-from-duplicate-crates/rmake.rs index 32c4cf338964..5bc0a0c9519f 100644 --- a/tests/run-make/diagnostics-traits-from-duplicate-crates/rmake.rs +++ b/tests/run-make/diagnostics-traits-from-duplicate-crates/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // Non-regression test for issue #132920 where multiple versions of the same crate are present in // the dependency graph, and an unexpected error in a dependent crate caused an ICE in the // unsatisfied bounds diagnostics for traits present in multiple crate versions. diff --git a/tests/run-make/doctests-merge/rmake.rs b/tests/run-make/doctests-merge/rmake.rs index a88b050c50fa..8236997d72d7 100644 --- a/tests/run-make/doctests-merge/rmake.rs +++ b/tests/run-make/doctests-merge/rmake.rs @@ -1,3 +1,4 @@ +//@ needs-target-std use std::path::Path; use run_make_support::{cwd, diff, rustc, rustdoc}; diff --git a/tests/run-make/doctests-runtool/rmake.rs b/tests/run-make/doctests-runtool/rmake.rs index 817001c514b5..aaba41749102 100644 --- a/tests/run-make/doctests-runtool/rmake.rs +++ b/tests/run-make/doctests-runtool/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // Tests behavior of rustdoc `--test-runtool`. use std::path::PathBuf; diff --git a/tests/run-make/dump-mono-stats/rmake.rs b/tests/run-make/dump-mono-stats/rmake.rs index f4142e0a31c3..8ebc5758d9d7 100644 --- a/tests/run-make/dump-mono-stats/rmake.rs +++ b/tests/run-make/dump-mono-stats/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // A flag named dump-mono-stats was added to the compiler in 2022, which // collects stats on instantiation of items and their associated costs. // This test checks that the output stat file exists, and that it contains diff --git a/tests/run-make/duplicate-output-flavors/rmake.rs b/tests/run-make/duplicate-output-flavors/rmake.rs index 09545228807b..f07339aceb92 100644 --- a/tests/run-make/duplicate-output-flavors/rmake.rs +++ b/tests/run-make/duplicate-output-flavors/rmake.rs @@ -1,3 +1,4 @@ +//@ needs-target-std use run_make_support::rustc; fn main() { diff --git a/tests/run-make/embed-metadata/rmake.rs b/tests/run-make/embed-metadata/rmake.rs index acefb1864844..a41716d15429 100644 --- a/tests/run-make/embed-metadata/rmake.rs +++ b/tests/run-make/embed-metadata/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // Tests the -Zembed-metadata compiler flag. // Tracking issue: https://github.com/rust-lang/rust/issues/139165 diff --git a/tests/run-make/embed-source-dwarf/rmake.rs b/tests/run-make/embed-source-dwarf/rmake.rs index 550c8b9b3c90..99fad359054b 100644 --- a/tests/run-make/embed-source-dwarf/rmake.rs +++ b/tests/run-make/embed-source-dwarf/rmake.rs @@ -1,3 +1,4 @@ +//@ needs-target-std //@ ignore-windows //@ ignore-apple diff --git a/tests/run-make/emit-named-files/rmake.rs b/tests/run-make/emit-named-files/rmake.rs index 1570e1adc256..b482fb3268b9 100644 --- a/tests/run-make/emit-named-files/rmake.rs +++ b/tests/run-make/emit-named-files/rmake.rs @@ -1,3 +1,4 @@ +//@ needs-target-std use std::path::Path; use run_make_support::{rfs, rustc}; diff --git a/tests/run-make/emit-path-unhashed/rmake.rs b/tests/run-make/emit-path-unhashed/rmake.rs index a97153e37dd9..5d5256621cea 100644 --- a/tests/run-make/emit-path-unhashed/rmake.rs +++ b/tests/run-make/emit-path-unhashed/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // Specifying how rustc outputs a file can be done in different ways, such as // the output flag or the KIND=NAME syntax. However, some of these methods used // to result in different hashes on output files even though they yielded the diff --git a/tests/run-make/emit-stack-sizes/rmake.rs b/tests/run-make/emit-stack-sizes/rmake.rs index 53cc9ee5943f..886e875cfae8 100644 --- a/tests/run-make/emit-stack-sizes/rmake.rs +++ b/tests/run-make/emit-stack-sizes/rmake.rs @@ -6,6 +6,7 @@ // this diagnostics information should be located. // See https://github.com/rust-lang/rust/pull/51946 +//@ needs-target-std //@ ignore-windows //@ ignore-apple // Reason: this feature only works when the output object format is ELF. diff --git a/tests/run-make/emit-to-stdout/rmake.rs b/tests/run-make/emit-to-stdout/rmake.rs index a9a3796731b4..19c15b72fe47 100644 --- a/tests/run-make/emit-to-stdout/rmake.rs +++ b/tests/run-make/emit-to-stdout/rmake.rs @@ -1,3 +1,4 @@ +//@ needs-target-std //! If `-o -` or `--emit KIND=-` is provided, output should be written to stdout //! instead. Binary output (`obj`, `llvm-bc`, `link` and `metadata`) //! being written this way will result in an error if stdout is a tty. diff --git a/tests/run-make/env-dep-info/rmake.rs b/tests/run-make/env-dep-info/rmake.rs index 5b51a5476f49..97006a632057 100644 --- a/tests/run-make/env-dep-info/rmake.rs +++ b/tests/run-make/env-dep-info/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // Inside dep-info emit files, #71858 made it so all accessed environment // variables are usefully printed. This test checks that this feature works // as intended by checking if the environment variables used in compilation diff --git a/tests/run-make/error-found-staticlib-instead-crate/rmake.rs b/tests/run-make/error-found-staticlib-instead-crate/rmake.rs index 8c707092b7e4..15f09c83e200 100644 --- a/tests/run-make/error-found-staticlib-instead-crate/rmake.rs +++ b/tests/run-make/error-found-staticlib-instead-crate/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // When rustc is looking for a crate but is given a staticlib instead, // the error message should be helpful and indicate precisely the cause // of the compilation failure. diff --git a/tests/run-make/exit-code/rmake.rs b/tests/run-make/exit-code/rmake.rs index d3dcc04428cb..5fdf920b55a6 100644 --- a/tests/run-make/exit-code/rmake.rs +++ b/tests/run-make/exit-code/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // Test that we exit with the correct exit code for successful / unsuccessful / ICE compilations use run_make_support::{rustc, rustdoc}; diff --git a/tests/run-make/export/disambiguator/rmake.rs b/tests/run-make/export/disambiguator/rmake.rs index 743db1933fb4..f855e42d08ee 100644 --- a/tests/run-make/export/disambiguator/rmake.rs +++ b/tests/run-make/export/disambiguator/rmake.rs @@ -1,12 +1,7 @@ +//@ needs-target-std use run_make_support::rustc; fn main() { - rustc() - .env("RUSTC_FORCE_RUSTC_VERSION", "1") - .input("libr.rs") - .run(); - rustc() - .env("RUSTC_FORCE_RUSTC_VERSION", "2") - .input("app.rs") - .run(); + rustc().env("RUSTC_FORCE_RUSTC_VERSION", "1").input("libr.rs").run(); + rustc().env("RUSTC_FORCE_RUSTC_VERSION", "2").input("app.rs").run(); } diff --git a/tests/run-make/export/extern-opt/rmake.rs b/tests/run-make/export/extern-opt/rmake.rs index 821e2eb21491..a2f9ba28c2f5 100644 --- a/tests/run-make/export/extern-opt/rmake.rs +++ b/tests/run-make/export/extern-opt/rmake.rs @@ -1,10 +1,8 @@ -use run_make_support::{rustc, dynamic_lib_name}; +//@ needs-target-std +use run_make_support::{dynamic_lib_name, rustc}; fn main() { - rustc() - .env("RUSTC_FORCE_RUSTC_VERSION", "1") - .input("libr.rs") - .run(); + rustc().env("RUSTC_FORCE_RUSTC_VERSION", "1").input("libr.rs").run(); rustc() .env("RUSTC_FORCE_RUSTC_VERSION", "2") diff --git a/tests/run-make/export/simple/rmake.rs b/tests/run-make/export/simple/rmake.rs index 743db1933fb4..f855e42d08ee 100644 --- a/tests/run-make/export/simple/rmake.rs +++ b/tests/run-make/export/simple/rmake.rs @@ -1,12 +1,7 @@ +//@ needs-target-std use run_make_support::rustc; fn main() { - rustc() - .env("RUSTC_FORCE_RUSTC_VERSION", "1") - .input("libr.rs") - .run(); - rustc() - .env("RUSTC_FORCE_RUSTC_VERSION", "2") - .input("app.rs") - .run(); + rustc().env("RUSTC_FORCE_RUSTC_VERSION", "1").input("libr.rs").run(); + rustc().env("RUSTC_FORCE_RUSTC_VERSION", "2").input("app.rs").run(); } diff --git a/tests/run-make/extern-diff-internal-name/rmake.rs b/tests/run-make/extern-diff-internal-name/rmake.rs index 1a7f34d65bc2..1bae8decb052 100644 --- a/tests/run-make/extern-diff-internal-name/rmake.rs +++ b/tests/run-make/extern-diff-internal-name/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // In the following scenario: // 1. The crate foo, is referenced multiple times // 2. --extern foo=./path/to/libbar.rlib is specified to rustc diff --git a/tests/run-make/extern-flag-fun/rmake.rs b/tests/run-make/extern-flag-fun/rmake.rs index c1825f6bbb88..181a76b7cfa0 100644 --- a/tests/run-make/extern-flag-fun/rmake.rs +++ b/tests/run-make/extern-flag-fun/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // The --extern flag can override the default crate search of // the compiler and directly fetch a given path. There are a few rules // to follow: for example, there can't be more than one rlib, the crates must diff --git a/tests/run-make/extern-flag-rename-transitive/rmake.rs b/tests/run-make/extern-flag-rename-transitive/rmake.rs index 0090d487f03d..c5bff7bbb696 100644 --- a/tests/run-make/extern-flag-rename-transitive/rmake.rs +++ b/tests/run-make/extern-flag-rename-transitive/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // In this test, baz.rs is looking for an extern crate "a" which // does not exist, and can only run through the --extern rustc flag // defining that the "a" crate is in fact just "foo". This test diff --git a/tests/run-make/extern-multiple-copies/rmake.rs b/tests/run-make/extern-multiple-copies/rmake.rs index 8b67e6d9facf..d9d769d178c3 100644 --- a/tests/run-make/extern-multiple-copies/rmake.rs +++ b/tests/run-make/extern-multiple-copies/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // In this test, the rust library foo1 exists in two different locations, but only one // is required by the --extern flag. This test checks that the copy is ignored (as --extern // demands fetching only the original instance of foo1) and that no error is emitted, resulting diff --git a/tests/run-make/extern-multiple-copies2/rmake.rs b/tests/run-make/extern-multiple-copies2/rmake.rs index 59913bfa42bb..4188d5bdc182 100644 --- a/tests/run-make/extern-multiple-copies2/rmake.rs +++ b/tests/run-make/extern-multiple-copies2/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // Almost identical to `extern-multiple-copies`, but with a variation in the --extern calls // and the addition of #[macro_use] in the rust code files, which used to break --extern // until #33625. diff --git a/tests/run-make/ice-static-mir/rmake.rs b/tests/run-make/ice-static-mir/rmake.rs index 2d4ffa379b62..b6a04bf877e7 100644 --- a/tests/run-make/ice-static-mir/rmake.rs +++ b/tests/run-make/ice-static-mir/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // Trying to access mid-level internal representation (MIR) in statics // used to cause an internal compiler error (ICE), now handled as a proper // error since #100211. This test checks that the correct error is printed diff --git a/tests/run-make/include-all-symbols-linking/rmake.rs b/tests/run-make/include-all-symbols-linking/rmake.rs index bab510fb5be3..4f85ee179f5f 100644 --- a/tests/run-make/include-all-symbols-linking/rmake.rs +++ b/tests/run-make/include-all-symbols-linking/rmake.rs @@ -7,6 +7,7 @@ // See https://github.com/rust-lang/rust/pull/95604 // See https://github.com/rust-lang/rust/issues/47384 +//@ needs-target-std //@ ignore-wasm differences in object file formats causes errors in the llvm_objdump step. //@ ignore-windows differences in object file formats causes errors in the llvm_objdump step. diff --git a/tests/run-make/include-bytes-deps/rmake.rs b/tests/run-make/include-bytes-deps/rmake.rs index ea371ddae567..2938f334243f 100644 --- a/tests/run-make/include-bytes-deps/rmake.rs +++ b/tests/run-make/include-bytes-deps/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // include_bytes! and include_str! in `main.rs` // should register the included file as of #24423, // and this test checks that this is still the case. diff --git a/tests/run-make/incremental-debugger-visualizer/rmake.rs b/tests/run-make/incremental-debugger-visualizer/rmake.rs index 07c920cc04a6..3a4fc1d17929 100644 --- a/tests/run-make/incremental-debugger-visualizer/rmake.rs +++ b/tests/run-make/incremental-debugger-visualizer/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // This test ensures that changes to files referenced via #[debugger_visualizer] // (in this case, foo.py and foo.natvis) are picked up when compiling incrementally. // See https://github.com/rust-lang/rust/pull/111641 diff --git a/tests/run-make/inline-always-many-cgu/rmake.rs b/tests/run-make/inline-always-many-cgu/rmake.rs index 678b949bc700..18068578dd04 100644 --- a/tests/run-make/inline-always-many-cgu/rmake.rs +++ b/tests/run-make/inline-always-many-cgu/rmake.rs @@ -1,3 +1,4 @@ +//@ needs-target-std use std::ffi::OsStr; use run_make_support::regex::Regex; diff --git a/tests/run-make/invalid-so/rmake.rs b/tests/run-make/invalid-so/rmake.rs index 754c53a49b92..ee886b5ee3a6 100644 --- a/tests/run-make/invalid-so/rmake.rs +++ b/tests/run-make/invalid-so/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // When a fake library was given to the compiler, it would // result in an obscure and unhelpful error message. This test // creates a false "foo" dylib, and checks that the standard error diff --git a/tests/run-make/invalid-staticlib/rmake.rs b/tests/run-make/invalid-staticlib/rmake.rs index ba9e07dd07b8..4844bff329ac 100644 --- a/tests/run-make/invalid-staticlib/rmake.rs +++ b/tests/run-make/invalid-staticlib/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // If the static library provided is not valid (in this test, // created as an empty file), // rustc should print a normal error message and not throw diff --git a/tests/run-make/invalid-symlink-search-path/rmake.rs b/tests/run-make/invalid-symlink-search-path/rmake.rs index 7b7e7c794421..4eb6e6f77069 100644 --- a/tests/run-make/invalid-symlink-search-path/rmake.rs +++ b/tests/run-make/invalid-symlink-search-path/rmake.rs @@ -5,6 +5,7 @@ // // See https://github.com/rust-lang/rust/issues/26006 +//@ needs-target-std //@ needs-symlink //Reason: symlink requires elevated permission in Windows diff --git a/tests/run-make/invalid-tmpdir-env-var/rmake.rs b/tests/run-make/invalid-tmpdir-env-var/rmake.rs index db44debb319e..c5b9dca33a94 100644 --- a/tests/run-make/invalid-tmpdir-env-var/rmake.rs +++ b/tests/run-make/invalid-tmpdir-env-var/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // When the TMP (on Windows) or TMPDIR (on Unix) variable is set to an invalid // or non-existing directory, this used to cause an internal compiler error (ICE). After the // addition of proper error handling in #28430, this test checks that the expected message is diff --git a/tests/run-make/issue-107495-archive-permissions/rmake.rs b/tests/run-make/issue-107495-archive-permissions/rmake.rs index 87d4faaa77a2..80474ba32c2e 100644 --- a/tests/run-make/issue-107495-archive-permissions/rmake.rs +++ b/tests/run-make/issue-107495-archive-permissions/rmake.rs @@ -1,3 +1,4 @@ +//@ needs-target-std #[cfg(unix)] use std::os::unix::fs::PermissionsExt; use std::path::Path; diff --git a/tests/run-make/issue-125484-used-dependencies/rmake.rs b/tests/run-make/issue-125484-used-dependencies/rmake.rs index bc0a18de66e7..afcea34783f9 100644 --- a/tests/run-make/issue-125484-used-dependencies/rmake.rs +++ b/tests/run-make/issue-125484-used-dependencies/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // Non-regression test for issues #125474, #125484, #125646, with the repro taken from #125484. Some // queries use "used dependencies" while others use "speculatively loaded dependencies", and an // indexing ICE appeared in some cases when these were unexpectedly used in the same context. diff --git a/tests/run-make/json-error-no-offset/rmake.rs b/tests/run-make/json-error-no-offset/rmake.rs index 629d9c4c16e4..3f45778ca04a 100644 --- a/tests/run-make/json-error-no-offset/rmake.rs +++ b/tests/run-make/json-error-no-offset/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // The byte positions in json format error logging used to have a small, difficult // to predict offset. This was changed to be the top of the file every time in #42973, // and this test checks that the measurements appearing in the standard error are correct. diff --git a/tests/run-make/lib-trait-for-trait-no-ice/rmake.rs b/tests/run-make/lib-trait-for-trait-no-ice/rmake.rs index 0c5e12055e81..af42911502e0 100644 --- a/tests/run-make/lib-trait-for-trait-no-ice/rmake.rs +++ b/tests/run-make/lib-trait-for-trait-no-ice/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // Inside a library, implementing a trait for another trait // with a lifetime used to cause an internal compiler error (ICE). // This test checks that this bug does not make a resurgence - diff --git a/tests/run-make/link-arg/rmake.rs b/tests/run-make/link-arg/rmake.rs index c0bf8d972af7..bfceaae0dba6 100644 --- a/tests/run-make/link-arg/rmake.rs +++ b/tests/run-make/link-arg/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // In 2016, the rustc flag "-C link-arg" was introduced - it can be repeatedly used // to add single arguments to the linker. This test passes 2 arguments to the linker using it, // then checks that the compiler's output contains the arguments passed to it. diff --git a/tests/run-make/link-args-order/rmake.rs b/tests/run-make/link-args-order/rmake.rs index fe0d02926eff..a4591ea3949e 100644 --- a/tests/run-make/link-args-order/rmake.rs +++ b/tests/run-make/link-args-order/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // Passing linker arguments to the compiler used to be lost or reordered in a messy way // as they were passed further to the linker. This was fixed in #70665, and this test // checks that linker arguments remain intact and in the order they were originally passed in. diff --git a/tests/run-make/link-dedup/rmake.rs b/tests/run-make/link-dedup/rmake.rs index f38603dee8cb..0148817f9878 100644 --- a/tests/run-make/link-dedup/rmake.rs +++ b/tests/run-make/link-dedup/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // When native libraries are passed to the linker, there used to be an annoyance // where multiple instances of the same library in a row would cause duplication in // outputs. This has been fixed, and this test checks that it stays fixed. diff --git a/tests/run-make/linker-warning/rmake.rs b/tests/run-make/linker-warning/rmake.rs index bc21739fefc6..eb1bbbff8ef0 100644 --- a/tests/run-make/linker-warning/rmake.rs +++ b/tests/run-make/linker-warning/rmake.rs @@ -1,3 +1,4 @@ +//@ needs-target-std use run_make_support::{Rustc, diff, regex, rustc}; fn run_rustc() -> Rustc { diff --git a/tests/run-make/llvm-outputs/rmake.rs b/tests/run-make/llvm-outputs/rmake.rs index 2ce31b260a16..dabae38c141c 100644 --- a/tests/run-make/llvm-outputs/rmake.rs +++ b/tests/run-make/llvm-outputs/rmake.rs @@ -1,3 +1,4 @@ +//@ needs-target-std // test that directories get created when emitting llvm bitcode and IR use std::path::PathBuf; diff --git a/tests/run-make/lto-avoid-object-duplication/rmake.rs b/tests/run-make/lto-avoid-object-duplication/rmake.rs index b0e7494cb513..394aed2b881f 100644 --- a/tests/run-make/lto-avoid-object-duplication/rmake.rs +++ b/tests/run-make/lto-avoid-object-duplication/rmake.rs @@ -8,6 +8,7 @@ // This test makes sure that functions defined in the upstream crates do not // appear twice in the final staticlib when listing all the symbols from it. +//@ needs-target-std //@ ignore-windows // Reason: `llvm-objdump`'s output looks different on windows than on other platforms. // Only checking on Unix platforms should suffice. diff --git a/tests/run-make/manual-crate-name/rmake.rs b/tests/run-make/manual-crate-name/rmake.rs index 9f480ec6b6af..ead3b669e2da 100644 --- a/tests/run-make/manual-crate-name/rmake.rs +++ b/tests/run-make/manual-crate-name/rmake.rs @@ -1,3 +1,4 @@ +//@ needs-target-std use run_make_support::{path, rustc}; fn main() { diff --git a/tests/run-make/many-crates-but-no-match/rmake.rs b/tests/run-make/many-crates-but-no-match/rmake.rs index 938ffce6a036..449b6e2908d0 100644 --- a/tests/run-make/many-crates-but-no-match/rmake.rs +++ b/tests/run-make/many-crates-but-no-match/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // An extended version of the ui/changing-crates.rs test, this test puts // multiple mismatching crates into the search path of crateC (A2 and A3) // and checks that the standard error contains helpful messages to indicate diff --git a/tests/run-make/metadata-dep-info/rmake.rs b/tests/run-make/metadata-dep-info/rmake.rs index f4bb3ea63fb1..82fa4c014e17 100644 --- a/tests/run-make/metadata-dep-info/rmake.rs +++ b/tests/run-make/metadata-dep-info/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // Emitting dep-info alongside metadata would present subtle discrepancies // in the output file, such as the filename transforming underscores_ into hyphens-. // After the fix in #114750, this test checks that the emitted files are identical diff --git a/tests/run-make/metadata-only-crate-no-ice/rmake.rs b/tests/run-make/metadata-only-crate-no-ice/rmake.rs index e6f852fca413..2e771d879333 100644 --- a/tests/run-make/metadata-only-crate-no-ice/rmake.rs +++ b/tests/run-make/metadata-only-crate-no-ice/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // In a dependency hierarchy, metadata-only crates could cause an Internal // Compiler Error (ICE) due to a compiler bug - not correctly fetching sources for // metadata-only crates. This test is a minimal reproduction of a program that triggered diff --git a/tests/run-make/missing-crate-dependency/rmake.rs b/tests/run-make/missing-crate-dependency/rmake.rs index dae77032f7d4..7abdd11c5098 100644 --- a/tests/run-make/missing-crate-dependency/rmake.rs +++ b/tests/run-make/missing-crate-dependency/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // A simple smoke test to check that rustc fails compilation // and outputs a helpful message when a dependency is missing // in a dependency chain. diff --git a/tests/run-make/multiple-emits/rmake.rs b/tests/run-make/multiple-emits/rmake.rs index 8a5eb1d9d856..d8a008660c06 100644 --- a/tests/run-make/multiple-emits/rmake.rs +++ b/tests/run-make/multiple-emits/rmake.rs @@ -1,3 +1,4 @@ +//@ needs-target-std use run_make_support::{path, rustc}; fn main() { diff --git a/tests/run-make/native-lib-alt-naming/rmake.rs b/tests/run-make/native-lib-alt-naming/rmake.rs index d1ea0fc86876..a1dc002533f5 100644 --- a/tests/run-make/native-lib-alt-naming/rmake.rs +++ b/tests/run-make/native-lib-alt-naming/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // On MSVC the alternative naming format for static libraries (`libfoo.a`) is accepted in addition // to the default format (`foo.lib`). diff --git a/tests/run-make/native-link-modifier-verbatim-linker/rmake.rs b/tests/run-make/native-link-modifier-verbatim-linker/rmake.rs index 6868cb368ccc..e06be13d9b95 100644 --- a/tests/run-make/native-link-modifier-verbatim-linker/rmake.rs +++ b/tests/run-make/native-link-modifier-verbatim-linker/rmake.rs @@ -3,6 +3,7 @@ // This test is the same as native-link-modifier-rustc, but without rlibs. // See https://github.com/rust-lang/rust/issues/99425 +//@ needs-target-std //@ ignore-apple // Reason: linking fails due to the unusual ".ext" staticlib name. diff --git a/tests/run-make/native-link-modifier-verbatim-rustc/rmake.rs b/tests/run-make/native-link-modifier-verbatim-rustc/rmake.rs index 703b8a80ef3e..d885df9e79eb 100644 --- a/tests/run-make/native-link-modifier-verbatim-rustc/rmake.rs +++ b/tests/run-make/native-link-modifier-verbatim-rustc/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // `verbatim` is a native link modifier that forces rustc to only accept libraries with // a specified name. This test checks that this modifier works as intended. // This test is the same as native-link-modifier-linker, but with rlibs. diff --git a/tests/run-make/no-builtins-attribute/rmake.rs b/tests/run-make/no-builtins-attribute/rmake.rs index 7182c65a2c59..038958f19ed9 100644 --- a/tests/run-make/no-builtins-attribute/rmake.rs +++ b/tests/run-make/no-builtins-attribute/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // `no_builtins` is an attribute related to LLVM's optimizations. In order to ensure that it has an // effect on link-time optimizations (LTO), it should be added to function declarations in a crate. // This test uses the `llvm-filecheck` tool to determine that this attribute is successfully diff --git a/tests/run-make/no-builtins-lto/rmake.rs b/tests/run-make/no-builtins-lto/rmake.rs index 56fdfde42f04..a1d9dc43e713 100644 --- a/tests/run-make/no-builtins-lto/rmake.rs +++ b/tests/run-make/no-builtins-lto/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // The rlib produced by a no_builtins crate should be explicitly linked // during compilation, and as a result be present in the linker arguments. // See the comments inside this file for more details. diff --git a/tests/run-make/non-unicode-env/rmake.rs b/tests/run-make/non-unicode-env/rmake.rs index d708192908c1..b7a3c51db5bf 100644 --- a/tests/run-make/non-unicode-env/rmake.rs +++ b/tests/run-make/non-unicode-env/rmake.rs @@ -1,3 +1,4 @@ +//@ needs-target-std use run_make_support::{rfs, rustc}; fn main() { diff --git a/tests/run-make/non-unicode-in-incremental-dir/rmake.rs b/tests/run-make/non-unicode-in-incremental-dir/rmake.rs index 42bd4b1b7999..5c437a3fe00c 100644 --- a/tests/run-make/non-unicode-in-incremental-dir/rmake.rs +++ b/tests/run-make/non-unicode-in-incremental-dir/rmake.rs @@ -1,3 +1,4 @@ +//@ needs-target-std use run_make_support::{rfs, rustc}; fn main() { diff --git a/tests/run-make/notify-all-emit-artifacts/rmake.rs b/tests/run-make/notify-all-emit-artifacts/rmake.rs index 321eda489410..5896cffefcce 100644 --- a/tests/run-make/notify-all-emit-artifacts/rmake.rs +++ b/tests/run-make/notify-all-emit-artifacts/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // rust should produce artifact notifications about files it was asked to --emit. // // It should work in incremental mode both on the first pass where files are generated as well diff --git a/tests/run-make/optimization-remarks-dir/rmake.rs b/tests/run-make/optimization-remarks-dir/rmake.rs index afcb8c3e3ebd..df656302d789 100644 --- a/tests/run-make/optimization-remarks-dir/rmake.rs +++ b/tests/run-make/optimization-remarks-dir/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // In this test, the function `bar` has #[inline(never)] and the function `foo` // does not. This test outputs LLVM optimization remarks twice - first for all // functions (including `bar`, and the `inline` mention), and then for only `foo` diff --git a/tests/run-make/overwrite-input/rmake.rs b/tests/run-make/overwrite-input/rmake.rs index b87a7c7e0a85..bdf7860caa8a 100644 --- a/tests/run-make/overwrite-input/rmake.rs +++ b/tests/run-make/overwrite-input/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // An attempt to set the output `-o` into a directory or a file we cannot write into should indeed // be an error; but not an ICE (Internal Compiler Error). This test attempts both and checks // that the standard error matches what is expected. diff --git a/tests/run-make/parallel-rustc-no-overwrite/rmake.rs b/tests/run-make/parallel-rustc-no-overwrite/rmake.rs index aa38eb664cf5..f7531ab4bf69 100644 --- a/tests/run-make/parallel-rustc-no-overwrite/rmake.rs +++ b/tests/run-make/parallel-rustc-no-overwrite/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // When two instances of rustc are invoked in parallel, they // can conflict on their temporary files and overwrite each others', // leading to unsuccessful compilation. The -Z temps-dir flag adds diff --git a/tests/run-make/pass-linker-flags-from-dep/rmake.rs b/tests/run-make/pass-linker-flags-from-dep/rmake.rs index 4b8e0486e142..1cd55468737d 100644 --- a/tests/run-make/pass-linker-flags-from-dep/rmake.rs +++ b/tests/run-make/pass-linker-flags-from-dep/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // A similar test to pass-linker-flags, testing that the `-l link-arg` flag // respects the order relative to other `-l` flags, but this time, the flags // are passed on the compilation of a dependency. This test checks that the diff --git a/tests/run-make/pass-linker-flags/rmake.rs b/tests/run-make/pass-linker-flags/rmake.rs index de69567a6e60..a44da7b32ff8 100644 --- a/tests/run-make/pass-linker-flags/rmake.rs +++ b/tests/run-make/pass-linker-flags/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // This test checks the proper function of `-l link-arg=NAME`, which, unlike // -C link-arg, is supposed to guarantee that the order relative to other -l // options will be respected. In this test, compilation fails (because none of the diff --git a/tests/run-make/pgo-gen-no-imp-symbols/rmake.rs b/tests/run-make/pgo-gen-no-imp-symbols/rmake.rs index 85ade7885ce7..db25eab104a8 100644 --- a/tests/run-make/pgo-gen-no-imp-symbols/rmake.rs +++ b/tests/run-make/pgo-gen-no-imp-symbols/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // LLVM's profiling instrumentation adds a few symbols that are used by the profiler runtime. // Since these show up as globals in the LLVM IR, the compiler generates dllimport-related // __imp_ stubs for them. This can lead to linker errors because the instrumentation diff --git a/tests/run-make/pretty-print-with-dep-file/rmake.rs b/tests/run-make/pretty-print-with-dep-file/rmake.rs index 24ae6bc24560..e473854a12ea 100644 --- a/tests/run-make/pretty-print-with-dep-file/rmake.rs +++ b/tests/run-make/pretty-print-with-dep-file/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // Passing --emit=dep-info to the Rust compiler should create a .d file... // but it failed to do so in Rust 1.69.0 when combined with -Z unpretty=expanded // due to a bug. This test checks that -Z unpretty=expanded does not prevent the diff --git a/tests/run-make/proc-macro-three-crates/rmake.rs b/tests/run-make/proc-macro-three-crates/rmake.rs index d3735540fdd4..e5a3385acbc5 100644 --- a/tests/run-make/proc-macro-three-crates/rmake.rs +++ b/tests/run-make/proc-macro-three-crates/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // A compiler bug caused the following issue: // If a crate A depends on crate B, and crate B // depends on crate C, and crate C contains a procedural diff --git a/tests/run-make/remap-path-prefix-dwarf/rmake.rs b/tests/run-make/remap-path-prefix-dwarf/rmake.rs index 3d6ca014fc2a..3b88fca0bb7f 100644 --- a/tests/run-make/remap-path-prefix-dwarf/rmake.rs +++ b/tests/run-make/remap-path-prefix-dwarf/rmake.rs @@ -4,6 +4,7 @@ // It tests several cases, each of them has a detailed description attached to it. // See https://github.com/rust-lang/rust/pull/96867 +//@ needs-target-std //@ ignore-windows // Reason: the remap path prefix is not printed in the dwarf dump. diff --git a/tests/run-make/remap-path-prefix/rmake.rs b/tests/run-make/remap-path-prefix/rmake.rs index b4f7f4769b5b..b75ca9e796ac 100644 --- a/tests/run-make/remap-path-prefix/rmake.rs +++ b/tests/run-make/remap-path-prefix/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // Generating metadata alongside remap-path-prefix would fail to actually remap the path // in the metadata. After this was fixed in #85344, this test checks that "auxiliary" is being // successfully remapped to "/the/aux" in the rmeta files. diff --git a/tests/run-make/repr128-dwarf/rmake.rs b/tests/run-make/repr128-dwarf/rmake.rs index 8227c51516fa..1372d2bcc465 100644 --- a/tests/run-make/repr128-dwarf/rmake.rs +++ b/tests/run-make/repr128-dwarf/rmake.rs @@ -1,3 +1,4 @@ +//@ needs-target-std //@ ignore-windows // This test should be replaced with one in tests/debuginfo once GDB or LLDB support 128-bit enums. diff --git a/tests/run-make/reproducible-build-2/rmake.rs b/tests/run-make/reproducible-build-2/rmake.rs index 8b5825cad302..0e1781dbfbe4 100644 --- a/tests/run-make/reproducible-build-2/rmake.rs +++ b/tests/run-make/reproducible-build-2/rmake.rs @@ -6,6 +6,7 @@ // Outputs should be identical. // See https://github.com/rust-lang/rust/issues/34902 +//@ needs-target-std //@ ignore-windows // Reasons: // 1. The object files are reproducible, but their paths are not, which causes diff --git a/tests/run-make/resolve-rename/rmake.rs b/tests/run-make/resolve-rename/rmake.rs index 21ec7f852747..8afdaadbfde1 100644 --- a/tests/run-make/resolve-rename/rmake.rs +++ b/tests/run-make/resolve-rename/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // If a library is compiled with -C extra-filename, the rust compiler // will take this into account when searching for libraries. However, // if that library is then renamed, the rust compiler should fall back diff --git a/tests/run-make/rlib-format-packed-bundled-libs-2/rmake.rs b/tests/run-make/rlib-format-packed-bundled-libs-2/rmake.rs index 5a1460963b64..70d1ead85b5d 100644 --- a/tests/run-make/rlib-format-packed-bundled-libs-2/rmake.rs +++ b/tests/run-make/rlib-format-packed-bundled-libs-2/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // `-Z packed_bundled_libs` is an unstable rustc flag that makes the compiler // only require a native library and no supplementary object files to compile. // This test simply checks that this flag can be passed alongside verbatim syntax diff --git a/tests/run-make/rustc-macro-dep-files/rmake.rs b/tests/run-make/rustc-macro-dep-files/rmake.rs index bc02a04c9b8f..eb4771fea7a6 100644 --- a/tests/run-make/rustc-macro-dep-files/rmake.rs +++ b/tests/run-make/rustc-macro-dep-files/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // --emit dep-info used to print all macro-generated code it could // find as if it was part of a nonexistent file named "proc-macro source", // which is not a valid path. After this was fixed in #36776, this test checks diff --git a/tests/run-make/rustdoc-scrape-examples-invalid-expr/rmake.rs b/tests/run-make/rustdoc-scrape-examples-invalid-expr/rmake.rs index e9c54fa39223..8996ff184c90 100644 --- a/tests/run-make/rustdoc-scrape-examples-invalid-expr/rmake.rs +++ b/tests/run-make/rustdoc-scrape-examples-invalid-expr/rmake.rs @@ -1,3 +1,4 @@ +//@ needs-target-std #[path = "../rustdoc-scrape-examples-remap/scrape.rs"] mod scrape; diff --git a/tests/run-make/rustdoc-scrape-examples-multiple/rmake.rs b/tests/run-make/rustdoc-scrape-examples-multiple/rmake.rs index e9c54fa39223..8996ff184c90 100644 --- a/tests/run-make/rustdoc-scrape-examples-multiple/rmake.rs +++ b/tests/run-make/rustdoc-scrape-examples-multiple/rmake.rs @@ -1,3 +1,4 @@ +//@ needs-target-std #[path = "../rustdoc-scrape-examples-remap/scrape.rs"] mod scrape; diff --git a/tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs b/tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs index e9c54fa39223..8996ff184c90 100644 --- a/tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs +++ b/tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs @@ -1,3 +1,4 @@ +//@ needs-target-std #[path = "../rustdoc-scrape-examples-remap/scrape.rs"] mod scrape; diff --git a/tests/run-make/rustdoc-scrape-examples-remap/rmake.rs b/tests/run-make/rustdoc-scrape-examples-remap/rmake.rs index 4e3b895aef0c..ead3920c7613 100644 --- a/tests/run-make/rustdoc-scrape-examples-remap/rmake.rs +++ b/tests/run-make/rustdoc-scrape-examples-remap/rmake.rs @@ -1,3 +1,4 @@ +//@ needs-target-std mod scrape; fn main() { diff --git a/tests/run-make/rustdoc-scrape-examples-test/rmake.rs b/tests/run-make/rustdoc-scrape-examples-test/rmake.rs index f96ba113ff73..0868507c4ae5 100644 --- a/tests/run-make/rustdoc-scrape-examples-test/rmake.rs +++ b/tests/run-make/rustdoc-scrape-examples-test/rmake.rs @@ -1,3 +1,4 @@ +//@ needs-target-std #[path = "../rustdoc-scrape-examples-remap/scrape.rs"] mod scrape; diff --git a/tests/run-make/rustdoc-scrape-examples-whitespace/rmake.rs b/tests/run-make/rustdoc-scrape-examples-whitespace/rmake.rs index e9c54fa39223..8996ff184c90 100644 --- a/tests/run-make/rustdoc-scrape-examples-whitespace/rmake.rs +++ b/tests/run-make/rustdoc-scrape-examples-whitespace/rmake.rs @@ -1,3 +1,4 @@ +//@ needs-target-std #[path = "../rustdoc-scrape-examples-remap/scrape.rs"] mod scrape; diff --git a/tests/run-make/rustdoc-with-short-out-dir-option/rmake.rs b/tests/run-make/rustdoc-with-short-out-dir-option/rmake.rs index 4a8896cc975b..49df3bedc849 100644 --- a/tests/run-make/rustdoc-with-short-out-dir-option/rmake.rs +++ b/tests/run-make/rustdoc-with-short-out-dir-option/rmake.rs @@ -1,3 +1,4 @@ +//@ needs-target-std use run_make_support::{htmldocck, rustdoc}; fn main() { diff --git a/tests/run-make/share-generics-dylib/rmake.rs b/tests/run-make/share-generics-dylib/rmake.rs index e0e647fe1995..2d52cd43db75 100644 --- a/tests/run-make/share-generics-dylib/rmake.rs +++ b/tests/run-make/share-generics-dylib/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // This test makes sure all generic instances get re-exported from Rust dylibs for use by // `-Zshare-generics`. There are two rlibs (`instance_provider_a` and `instance_provider_b`) // which both provide an instance of `Cell::set`. There is `instance_user_dylib` which is diff --git a/tests/run-make/short-ice/rmake.rs b/tests/run-make/short-ice/rmake.rs index 81403931c783..8377954f4672 100644 --- a/tests/run-make/short-ice/rmake.rs +++ b/tests/run-make/short-ice/rmake.rs @@ -4,6 +4,7 @@ // was shortened down to an appropriate length. // See https://github.com/rust-lang/rust/issues/107910 +//@ needs-target-std //@ ignore-windows // Reason: the assert_eq! on line 32 fails, as error output on Windows is different. diff --git a/tests/run-make/stable-symbol-names/rmake.rs b/tests/run-make/stable-symbol-names/rmake.rs index 402f411c7f5e..dacee1a9a3ee 100644 --- a/tests/run-make/stable-symbol-names/rmake.rs +++ b/tests/run-make/stable-symbol-names/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // A typo in rustc caused generic symbol names to be non-deterministic - // that is, it was possible to compile the same file twice with no changes // and get outputs with different symbol names. diff --git a/tests/run-make/staticlib-blank-lib/rmake.rs b/tests/run-make/staticlib-blank-lib/rmake.rs index 11a85d102aad..1ab527b61689 100644 --- a/tests/run-make/staticlib-blank-lib/rmake.rs +++ b/tests/run-make/staticlib-blank-lib/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // In this test, the static library foo is made blank, which used to cause // a compilation error. As the compiler now returns Ok upon encountering a blank // staticlib as of #12379, this test checks that compilation is successful despite diff --git a/tests/run-make/staticlib-broken-bitcode/rmake.rs b/tests/run-make/staticlib-broken-bitcode/rmake.rs index 17d17c1f0f5e..ab406d321761 100644 --- a/tests/run-make/staticlib-broken-bitcode/rmake.rs +++ b/tests/run-make/staticlib-broken-bitcode/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // Regression test for https://github.com/rust-lang/rust/issues/128955#issuecomment-2657811196 // which checks that rustc can read an archive containing LLVM bitcode with a // newer version from the one rustc links against. diff --git a/tests/run-make/staticlib-thin-archive/rmake.rs b/tests/run-make/staticlib-thin-archive/rmake.rs index 955c50da2011..1fb56ac05381 100644 --- a/tests/run-make/staticlib-thin-archive/rmake.rs +++ b/tests/run-make/staticlib-thin-archive/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // Regression test for https://github.com/rust-lang/rust/issues/107407 which // checks that rustc can read thin archive. Before the object crate added thin // archive support rustc would add emit object files to the staticlib and after diff --git a/tests/run-make/stdin-rustc/rmake.rs b/tests/run-make/stdin-rustc/rmake.rs index 2d634dd455eb..318d569a7605 100644 --- a/tests/run-make/stdin-rustc/rmake.rs +++ b/tests/run-make/stdin-rustc/rmake.rs @@ -1,3 +1,4 @@ +//@ needs-target-std //! This test checks rustc `-` (stdin) support use std::path::PathBuf; diff --git a/tests/run-make/symbol-visibility/rmake.rs b/tests/run-make/symbol-visibility/rmake.rs index ec936bc3b07f..0175158d08b8 100644 --- a/tests/run-make/symbol-visibility/rmake.rs +++ b/tests/run-make/symbol-visibility/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // Dynamic libraries on Rust used to export a very high amount of symbols, // going as far as filling the output with mangled names and generic function // names. After the rework of #38117, this test checks that no mangled Rust symbols diff --git a/tests/run-make/symbols-include-type-name/rmake.rs b/tests/run-make/symbols-include-type-name/rmake.rs index 746c7486bf0c..3b46050e6620 100644 --- a/tests/run-make/symbols-include-type-name/rmake.rs +++ b/tests/run-make/symbols-include-type-name/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // Method names used to be obfuscated when exported into symbols, // leaving only an obscure ``. After the fix in #30328, // this test checks that method names are successfully saved in the symbol list. diff --git a/tests/run-make/track-path-dep-info/rmake.rs b/tests/run-make/track-path-dep-info/rmake.rs index 9b21644c41bc..4b98a1b48d5f 100644 --- a/tests/run-make/track-path-dep-info/rmake.rs +++ b/tests/run-make/track-path-dep-info/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // This test checks the functionality of `tracked_path::path`, a procedural macro // feature that adds a dependency to another file inside the procmacro. In this case, // the text file is added through this method, and the test checks that the compilation diff --git a/tests/run-make/type-mismatch-same-crate-name/rmake.rs b/tests/run-make/type-mismatch-same-crate-name/rmake.rs index ecf80d88d51c..b095027071f1 100644 --- a/tests/run-make/type-mismatch-same-crate-name/rmake.rs +++ b/tests/run-make/type-mismatch-same-crate-name/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // When a compilation failure deals with seemingly identical types, some helpful // errors should be printed. // The main use case of this error is when there are two crates diff --git a/tests/run-make/unknown-mod-stdin/rmake.rs b/tests/run-make/unknown-mod-stdin/rmake.rs index 6be3119c0fd1..101711b0d2c7 100644 --- a/tests/run-make/unknown-mod-stdin/rmake.rs +++ b/tests/run-make/unknown-mod-stdin/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // Rustc displays a compilation error when it finds a `mod` (module) // statement referencing a file that does not exist. However, a bug from 2019 // caused invalid `mod` statements to silently insert empty inline modules diff --git a/tests/run-make/unstable-feature-usage-metrics-incremental/rmake.rs b/tests/run-make/unstable-feature-usage-metrics-incremental/rmake.rs index 7e070d80c793..a7215ca9d50b 100644 --- a/tests/run-make/unstable-feature-usage-metrics-incremental/rmake.rs +++ b/tests/run-make/unstable-feature-usage-metrics-incremental/rmake.rs @@ -10,6 +10,7 @@ //! - forked from dump-ice-to-disk test, which has flakeyness issues on i686-mingw, I'm assuming //! those will be present in this test as well on the same platform +//@ needs-target-std //@ ignore-windows //FIXME(#128911): still flakey on i686-mingw. diff --git a/tests/run-make/unstable-feature-usage-metrics/rmake.rs b/tests/run-make/unstable-feature-usage-metrics/rmake.rs index 2183e28e89ab..dbe078bf468a 100644 --- a/tests/run-make/unstable-feature-usage-metrics/rmake.rs +++ b/tests/run-make/unstable-feature-usage-metrics/rmake.rs @@ -10,6 +10,7 @@ //! - forked from dump-ice-to-disk test, which has flakeyness issues on i686-mingw, I'm assuming //! those will be present in this test as well on the same platform +//@ needs-target-std //@ ignore-windows //FIXME(#128911): still flakey on i686-mingw. diff --git a/tests/run-make/use-suggestions-rust-2018/rmake.rs b/tests/run-make/use-suggestions-rust-2018/rmake.rs index 52c694da75e9..4d2163e7cc4b 100644 --- a/tests/run-make/use-suggestions-rust-2018/rmake.rs +++ b/tests/run-make/use-suggestions-rust-2018/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // The compilation error caused by calling on an unimported crate // should have a suggestion to write, say, crate::bar::Foo instead // of just bar::Foo. However, this suggestion used to only appear for diff --git a/tests/run-make/used/rmake.rs b/tests/run-make/used/rmake.rs index 39f36b2eea8f..daed69c1b385 100644 --- a/tests/run-make/used/rmake.rs +++ b/tests/run-make/used/rmake.rs @@ -1,3 +1,5 @@ +//@ needs-target-std +// // This test ensures that the compiler is keeping static variables, even if not referenced // by another part of the program, in the output object file. // diff --git a/tests/ui-fulldeps/auxiliary/parser.rs b/tests/ui-fulldeps/auxiliary/parser.rs index be51bd29008a..8a3705124601 100644 --- a/tests/ui-fulldeps/auxiliary/parser.rs +++ b/tests/ui-fulldeps/auxiliary/parser.rs @@ -7,15 +7,17 @@ extern crate rustc_parse; extern crate rustc_session; extern crate rustc_span; -use rustc_ast::ast::{DUMMY_NODE_ID, Expr}; -use rustc_ast::mut_visit::MutVisitor; +use rustc_ast::ast::{AttrKind, Attribute, DUMMY_NODE_ID, Expr}; +use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::node_id::NodeId; use rustc_ast::ptr::P; -use rustc_ast::token; +use rustc_ast::token::{self, Token}; +use rustc_ast::tokenstream::{AttrTokenStream, AttrTokenTree, LazyAttrTokenStream}; use rustc_errors::Diag; use rustc_parse::parser::Recovery; use rustc_session::parse::ParseSess; -use rustc_span::{DUMMY_SP, FileName, Span}; +use rustc_span::{AttrId, DUMMY_SP, FileName, Span}; +use std::sync::Arc; pub fn parse_expr(psess: &ParseSess, source_code: &str) -> Option> { let parser = rustc_parse::unwrap_or_emit_fatal(rustc_parse::new_parser_from_source_str( @@ -46,4 +48,36 @@ impl MutVisitor for Normalize { fn visit_span(&mut self, span: &mut Span) { *span = DUMMY_SP; } + + fn visit_attribute(&mut self, attr: &mut Attribute) { + attr.id = AttrId::from_u32(0); + if let AttrKind::Normal(normal_attr) = &mut attr.kind { + if let Some(tokens) = &mut normal_attr.tokens { + let mut stream = tokens.to_attr_token_stream(); + normalize_attr_token_stream(&mut stream); + *tokens = LazyAttrTokenStream::new_direct(stream); + } + } + mut_visit::walk_attribute(self, attr); + } +} + +fn normalize_attr_token_stream(stream: &mut AttrTokenStream) { + Arc::make_mut(&mut stream.0) + .iter_mut() + .for_each(normalize_attr_token_tree); +} + +fn normalize_attr_token_tree(token: &mut AttrTokenTree) { + match token { + AttrTokenTree::Token(token, _spacing) => { + Normalize.visit_span(&mut token.span); + } + AttrTokenTree::Delimited(dspan, _spacing, _delim, stream) => { + normalize_attr_token_stream(stream); + Normalize.visit_span(&mut dspan.open); + Normalize.visit_span(&mut dspan.close); + } + AttrTokenTree::AttrsTarget(_) => unimplemented!("AttrTokenTree::AttrsTarget"), + } } diff --git a/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs b/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs index 656cfca1ed1d..8449479287f0 100644 --- a/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs +++ b/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs @@ -33,17 +33,10 @@ impl CodegenBackend for TheBackend { "" } - fn codegen_crate<'a, 'tcx>( - &self, - tcx: TyCtxt<'tcx>, - metadata: EncodedMetadata, - _need_metadata_module: bool, - ) -> Box { + fn codegen_crate(&self, tcx: TyCtxt<'_>) -> Box { Box::new(CodegenResults { modules: vec![], allocator_module: None, - metadata_module: None, - metadata, crate_info: CrateInfo::new(tcx, "fake_target_cpu".to_string()), }) } @@ -60,7 +53,13 @@ impl CodegenBackend for TheBackend { (*codegen_results, FxIndexMap::default()) } - fn link(&self, sess: &Session, codegen_results: CodegenResults, outputs: &OutputFilenames) { + fn link( + &self, + sess: &Session, + codegen_results: CodegenResults, + _metadata: EncodedMetadata, + outputs: &OutputFilenames, + ) { use std::io::Write; use rustc_session::config::{CrateType, OutFileName}; diff --git a/tests/ui-fulldeps/pprust-parenthesis-insertion.rs b/tests/ui-fulldeps/pprust-parenthesis-insertion.rs index 36916e978562..08bed40abe86 100644 --- a/tests/ui-fulldeps/pprust-parenthesis-insertion.rs +++ b/tests/ui-fulldeps/pprust-parenthesis-insertion.rs @@ -88,6 +88,11 @@ static EXPRS: &[&str] = &[ // expressions. "match 2 { _ => 1 - 1 }", "match 2 { _ => ({ 1 }) - 1 }", + // Expressions with an outer attr have lower precedence than expressions + // with an inner attr. + "#[attr] loop {}.field", + "(#[attr] loop {}).field", + "loop { #![attr] }.field", // Grammar restriction: break value starting with a labeled loop is not // allowed, except if the break is also labeled. "break 'outer 'inner: loop {} + 2", diff --git a/tests/ui-fulldeps/stable-mir/check_variant.rs b/tests/ui-fulldeps/stable-mir/check_variant.rs new file mode 100644 index 000000000000..b0de3369830b --- /dev/null +++ b/tests/ui-fulldeps/stable-mir/check_variant.rs @@ -0,0 +1,183 @@ +//@ run-pass +//! Test that users are able to use stable mir APIs to retrieve +//! discriminant value and type for AdtDef and Coroutine variants + +//@ ignore-stage1 +//@ ignore-cross-compile +//@ ignore-remote +//@ edition: 2024 + +#![feature(rustc_private)] +#![feature(assert_matches)] + +extern crate rustc_middle; +#[macro_use] +extern crate rustc_smir; +extern crate rustc_driver; +extern crate rustc_interface; +extern crate stable_mir; + +use std::io::Write; +use std::ops::ControlFlow; + +use stable_mir::CrateItem; +use stable_mir::crate_def::CrateDef; +use stable_mir::mir::{AggregateKind, Rvalue, Statement, StatementKind}; +use stable_mir::ty::{IntTy, RigidTy, Ty}; + +const CRATE_NAME: &str = "crate_variant_ty"; + +/// Test if we can retrieve discriminant info for different types. +fn test_def_tys() -> ControlFlow<()> { + check_adt_mono(); + check_adt_poly(); + check_adt_poly2(); + + ControlFlow::Continue(()) +} + +fn check_adt_mono() { + let mono = get_fn("mono").expect_body(); + + check_statement_is_aggregate_assign( + &mono.blocks[0].statements[0], + 0, + RigidTy::Int(IntTy::Isize), + ); + check_statement_is_aggregate_assign( + &mono.blocks[1].statements[0], + 1, + RigidTy::Int(IntTy::Isize), + ); + check_statement_is_aggregate_assign( + &mono.blocks[2].statements[0], + 2, + RigidTy::Int(IntTy::Isize), + ); +} + +fn check_adt_poly() { + let poly = get_fn("poly").expect_body(); + + check_statement_is_aggregate_assign( + &poly.blocks[0].statements[0], + 0, + RigidTy::Int(IntTy::Isize), + ); + check_statement_is_aggregate_assign( + &poly.blocks[1].statements[0], + 1, + RigidTy::Int(IntTy::Isize), + ); + check_statement_is_aggregate_assign( + &poly.blocks[2].statements[0], + 2, + RigidTy::Int(IntTy::Isize), + ); +} + +fn check_adt_poly2() { + let poly = get_fn("poly2").expect_body(); + + check_statement_is_aggregate_assign( + &poly.blocks[0].statements[0], + 0, + RigidTy::Int(IntTy::Isize), + ); + check_statement_is_aggregate_assign( + &poly.blocks[1].statements[0], + 1, + RigidTy::Int(IntTy::Isize), + ); + check_statement_is_aggregate_assign( + &poly.blocks[2].statements[0], + 2, + RigidTy::Int(IntTy::Isize), + ); +} + +fn get_fn(name: &str) -> CrateItem { + stable_mir::all_local_items().into_iter().find(|it| it.name().eq(name)).unwrap() +} + +fn check_statement_is_aggregate_assign( + statement: &Statement, + expected_discr_val: u128, + expected_discr_ty: RigidTy, +) { + if let Statement { kind: StatementKind::Assign(_, rvalue), .. } = statement + && let Rvalue::Aggregate(aggregate, _) = rvalue + && let AggregateKind::Adt(adt_def, variant_idx, ..) = aggregate + { + let discr = adt_def.discriminant_for_variant(*variant_idx); + + assert_eq!(discr.val, expected_discr_val); + assert_eq!(discr.ty, Ty::from_rigid_kind(expected_discr_ty)); + } else { + unreachable!("Unexpected statement"); + } +} + +/// This test will generate and analyze a dummy crate using the stable mir. +/// For that, it will first write the dummy crate into a file. +/// Then it will create a `StableMir` using custom arguments and then +/// it will run the compiler. +fn main() { + let path = "defs_ty_input.rs"; + generate_input(&path).unwrap(); + let args = &[ + "rustc".to_string(), + "-Cpanic=abort".to_string(), + "--crate-name".to_string(), + CRATE_NAME.to_string(), + path.to_string(), + ]; + run!(args, test_def_tys).unwrap(); +} + +fn generate_input(path: &str) -> std::io::Result<()> { + let mut file = std::fs::File::create(path)?; + write!( + file, + r#" + use std::hint::black_box; + + enum Mono {{ + A, + B(i32), + C {{ a: i32, b: u32 }}, + }} + + enum Poly {{ + A, + B(T), + C {{ t: T }}, + }} + + pub fn main() {{ + mono(); + poly(); + poly2::(1); + }} + + fn mono() {{ + black_box(Mono::A); + black_box(Mono::B(6)); + black_box(Mono::C {{a: 1, b: 10 }}); + }} + + fn poly() {{ + black_box(Poly::::A); + black_box(Poly::B(1i32)); + black_box(Poly::C {{ t: 1i32 }}); + }} + + fn poly2(t: T) {{ + black_box(Poly::::A); + black_box(Poly::B(t)); + black_box(Poly::C {{ t: t }}); + }} + "# + )?; + Ok(()) +} diff --git a/tests/ui/abi/numbers-arithmetic/float-struct.rs b/tests/ui/abi/numbers-arithmetic/float-struct.rs new file mode 100644 index 000000000000..a958dc272722 --- /dev/null +++ b/tests/ui/abi/numbers-arithmetic/float-struct.rs @@ -0,0 +1,44 @@ +//@ run-pass + +use std::fmt::Debug; +use std::hint::black_box; + +#[repr(C)] +#[derive(Copy, Clone, PartialEq, Debug, Default)] +struct Regular(f32, f64); + +#[repr(C, packed)] +#[derive(Copy, Clone, PartialEq, Debug, Default)] +struct Packed(f32, f64); + +#[repr(C, align(64))] +#[derive(Copy, Clone, PartialEq, Debug, Default)] +struct AlignedF32(f32); + +#[repr(C)] +#[derive(Copy, Clone, PartialEq, Debug, Default)] +struct Aligned(f64, AlignedF32); + +#[inline(never)] +extern "C" fn read(x: &T) -> T { + *black_box(x) +} + +#[inline(never)] +extern "C" fn write(x: T, dest: &mut T) { + *dest = black_box(x) +} + +#[track_caller] +fn check(x: T) { + assert_eq!(read(&x), x); + let mut out = T::default(); + write(x, &mut out); + assert_eq!(out, x); +} + +fn main() { + check(Regular(1.0, 2.0)); + check(Packed(3.0, 4.0)); + check(Aligned(5.0, AlignedF32(6.0))); +} diff --git a/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.apple.stderr b/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.apple.stderr new file mode 100644 index 000000000000..02015d2a2e51 --- /dev/null +++ b/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.apple.stderr @@ -0,0 +1,536 @@ +error: fn_abi_of(i8) = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: i8, + layout: Layout { + size: Size(1 bytes), + align: AbiAlign { + abi: Align(1 bytes), + }, + backend_repr: Scalar( + Initialized { + value: Int( + I8, + true, + ), + valid_range: 0..=255, + }, + ), + fields: Primitive, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(1 bytes), + randomization_seed: 71776123356184577, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: Sext, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: i8, + layout: Layout { + size: Size(1 bytes), + align: AbiAlign { + abi: Align(1 bytes), + }, + backend_repr: Scalar( + Initialized { + value: Int( + I8, + true, + ), + valid_range: 0..=255, + }, + ), + fields: Primitive, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(1 bytes), + randomization_seed: 71776123356184577, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: Sext, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + c_variadic: false, + fixed_count: 1, + conv: X86( + SysV64, + ), + can_unwind: false, + } + --> $DIR/x86-64-sysv64-arg-ext.rs:13:1 + | +LL | pub extern "sysv64" fn i8(x: i8) -> i8 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: fn_abi_of(u8) = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: u8, + layout: Layout { + size: Size(1 bytes), + align: AbiAlign { + abi: Align(1 bytes), + }, + backend_repr: Scalar( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=255, + }, + ), + fields: Primitive, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(1 bytes), + randomization_seed: 71776127651151873, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: Zext, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: u8, + layout: Layout { + size: Size(1 bytes), + align: AbiAlign { + abi: Align(1 bytes), + }, + backend_repr: Scalar( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=255, + }, + ), + fields: Primitive, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(1 bytes), + randomization_seed: 71776127651151873, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: Zext, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + c_variadic: false, + fixed_count: 1, + conv: X86( + SysV64, + ), + can_unwind: false, + } + --> $DIR/x86-64-sysv64-arg-ext.rs:19:1 + | +LL | pub extern "sysv64" fn u8(x: u8) -> u8 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: fn_abi_of(i16) = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: i16, + layout: Layout { + size: Size(2 bytes), + align: AbiAlign { + abi: Align(2 bytes), + }, + backend_repr: Scalar( + Initialized { + value: Int( + I16, + true, + ), + valid_range: 0..=65535, + }, + ), + fields: Primitive, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(2 bytes), + randomization_seed: 18446462603027808258, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: Sext, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: i16, + layout: Layout { + size: Size(2 bytes), + align: AbiAlign { + abi: Align(2 bytes), + }, + backend_repr: Scalar( + Initialized { + value: Int( + I16, + true, + ), + valid_range: 0..=65535, + }, + ), + fields: Primitive, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(2 bytes), + randomization_seed: 18446462603027808258, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: Sext, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + c_variadic: false, + fixed_count: 1, + conv: X86( + SysV64, + ), + can_unwind: false, + } + --> $DIR/x86-64-sysv64-arg-ext.rs:25:1 + | +LL | pub extern "sysv64" fn i16(x: i16) -> i16 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: fn_abi_of(u16) = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: u16, + layout: Layout { + size: Size(2 bytes), + align: AbiAlign { + abi: Align(2 bytes), + }, + backend_repr: Scalar( + Initialized { + value: Int( + I16, + false, + ), + valid_range: 0..=65535, + }, + ), + fields: Primitive, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(2 bytes), + randomization_seed: 18446462607322775554, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: Zext, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: u16, + layout: Layout { + size: Size(2 bytes), + align: AbiAlign { + abi: Align(2 bytes), + }, + backend_repr: Scalar( + Initialized { + value: Int( + I16, + false, + ), + valid_range: 0..=65535, + }, + ), + fields: Primitive, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(2 bytes), + randomization_seed: 18446462607322775554, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: Zext, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + c_variadic: false, + fixed_count: 1, + conv: X86( + SysV64, + ), + can_unwind: false, + } + --> $DIR/x86-64-sysv64-arg-ext.rs:31:1 + | +LL | pub extern "sysv64" fn u16(x: u16) -> u16 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: fn_abi_of(i32) = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: i32, + layout: Layout { + size: Size(4 bytes), + align: AbiAlign { + abi: Align(4 bytes), + }, + backend_repr: Scalar( + Initialized { + value: Int( + I32, + true, + ), + valid_range: 0..=4294967295, + }, + ), + fields: Primitive, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(4 bytes), + randomization_seed: 18446462603027873795, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: None, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: i32, + layout: Layout { + size: Size(4 bytes), + align: AbiAlign { + abi: Align(4 bytes), + }, + backend_repr: Scalar( + Initialized { + value: Int( + I32, + true, + ), + valid_range: 0..=4294967295, + }, + ), + fields: Primitive, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(4 bytes), + randomization_seed: 18446462603027873795, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: None, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + c_variadic: false, + fixed_count: 1, + conv: X86( + SysV64, + ), + can_unwind: false, + } + --> $DIR/x86-64-sysv64-arg-ext.rs:37:1 + | +LL | pub extern "sysv64" fn i32(x: i32) -> i32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: fn_abi_of(u32) = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: u32, + layout: Layout { + size: Size(4 bytes), + align: AbiAlign { + abi: Align(4 bytes), + }, + backend_repr: Scalar( + Initialized { + value: Int( + I32, + false, + ), + valid_range: 0..=4294967295, + }, + ), + fields: Primitive, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(4 bytes), + randomization_seed: 18446462607322841091, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: None, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: u32, + layout: Layout { + size: Size(4 bytes), + align: AbiAlign { + abi: Align(4 bytes), + }, + backend_repr: Scalar( + Initialized { + value: Int( + I32, + false, + ), + valid_range: 0..=4294967295, + }, + ), + fields: Primitive, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(4 bytes), + randomization_seed: 18446462607322841091, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: None, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + c_variadic: false, + fixed_count: 1, + conv: X86( + SysV64, + ), + can_unwind: false, + } + --> $DIR/x86-64-sysv64-arg-ext.rs:43:1 + | +LL | pub extern "sysv64" fn u32(x: u32) -> u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.other.stderr b/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.other.stderr new file mode 100644 index 000000000000..9bb2ab45d984 --- /dev/null +++ b/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.other.stderr @@ -0,0 +1,536 @@ +error: fn_abi_of(i8) = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: i8, + layout: Layout { + size: Size(1 bytes), + align: AbiAlign { + abi: Align(1 bytes), + }, + backend_repr: Scalar( + Initialized { + value: Int( + I8, + true, + ), + valid_range: 0..=255, + }, + ), + fields: Primitive, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(1 bytes), + randomization_seed: 71776123356184577, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: Sext, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: i8, + layout: Layout { + size: Size(1 bytes), + align: AbiAlign { + abi: Align(1 bytes), + }, + backend_repr: Scalar( + Initialized { + value: Int( + I8, + true, + ), + valid_range: 0..=255, + }, + ), + fields: Primitive, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(1 bytes), + randomization_seed: 71776123356184577, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: None, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + c_variadic: false, + fixed_count: 1, + conv: X86( + SysV64, + ), + can_unwind: false, + } + --> $DIR/x86-64-sysv64-arg-ext.rs:13:1 + | +LL | pub extern "sysv64" fn i8(x: i8) -> i8 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: fn_abi_of(u8) = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: u8, + layout: Layout { + size: Size(1 bytes), + align: AbiAlign { + abi: Align(1 bytes), + }, + backend_repr: Scalar( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=255, + }, + ), + fields: Primitive, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(1 bytes), + randomization_seed: 71776127651151873, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: Zext, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: u8, + layout: Layout { + size: Size(1 bytes), + align: AbiAlign { + abi: Align(1 bytes), + }, + backend_repr: Scalar( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=255, + }, + ), + fields: Primitive, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(1 bytes), + randomization_seed: 71776127651151873, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: None, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + c_variadic: false, + fixed_count: 1, + conv: X86( + SysV64, + ), + can_unwind: false, + } + --> $DIR/x86-64-sysv64-arg-ext.rs:19:1 + | +LL | pub extern "sysv64" fn u8(x: u8) -> u8 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: fn_abi_of(i16) = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: i16, + layout: Layout { + size: Size(2 bytes), + align: AbiAlign { + abi: Align(2 bytes), + }, + backend_repr: Scalar( + Initialized { + value: Int( + I16, + true, + ), + valid_range: 0..=65535, + }, + ), + fields: Primitive, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(2 bytes), + randomization_seed: 18446462603027808258, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: Sext, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: i16, + layout: Layout { + size: Size(2 bytes), + align: AbiAlign { + abi: Align(2 bytes), + }, + backend_repr: Scalar( + Initialized { + value: Int( + I16, + true, + ), + valid_range: 0..=65535, + }, + ), + fields: Primitive, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(2 bytes), + randomization_seed: 18446462603027808258, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: None, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + c_variadic: false, + fixed_count: 1, + conv: X86( + SysV64, + ), + can_unwind: false, + } + --> $DIR/x86-64-sysv64-arg-ext.rs:25:1 + | +LL | pub extern "sysv64" fn i16(x: i16) -> i16 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: fn_abi_of(u16) = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: u16, + layout: Layout { + size: Size(2 bytes), + align: AbiAlign { + abi: Align(2 bytes), + }, + backend_repr: Scalar( + Initialized { + value: Int( + I16, + false, + ), + valid_range: 0..=65535, + }, + ), + fields: Primitive, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(2 bytes), + randomization_seed: 18446462607322775554, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: Zext, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: u16, + layout: Layout { + size: Size(2 bytes), + align: AbiAlign { + abi: Align(2 bytes), + }, + backend_repr: Scalar( + Initialized { + value: Int( + I16, + false, + ), + valid_range: 0..=65535, + }, + ), + fields: Primitive, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(2 bytes), + randomization_seed: 18446462607322775554, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: None, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + c_variadic: false, + fixed_count: 1, + conv: X86( + SysV64, + ), + can_unwind: false, + } + --> $DIR/x86-64-sysv64-arg-ext.rs:31:1 + | +LL | pub extern "sysv64" fn u16(x: u16) -> u16 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: fn_abi_of(i32) = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: i32, + layout: Layout { + size: Size(4 bytes), + align: AbiAlign { + abi: Align(4 bytes), + }, + backend_repr: Scalar( + Initialized { + value: Int( + I32, + true, + ), + valid_range: 0..=4294967295, + }, + ), + fields: Primitive, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(4 bytes), + randomization_seed: 18446462603027873795, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: None, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: i32, + layout: Layout { + size: Size(4 bytes), + align: AbiAlign { + abi: Align(4 bytes), + }, + backend_repr: Scalar( + Initialized { + value: Int( + I32, + true, + ), + valid_range: 0..=4294967295, + }, + ), + fields: Primitive, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(4 bytes), + randomization_seed: 18446462603027873795, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: None, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + c_variadic: false, + fixed_count: 1, + conv: X86( + SysV64, + ), + can_unwind: false, + } + --> $DIR/x86-64-sysv64-arg-ext.rs:37:1 + | +LL | pub extern "sysv64" fn i32(x: i32) -> i32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: fn_abi_of(u32) = FnAbi { + args: [ + ArgAbi { + layout: TyAndLayout { + ty: u32, + layout: Layout { + size: Size(4 bytes), + align: AbiAlign { + abi: Align(4 bytes), + }, + backend_repr: Scalar( + Initialized { + value: Int( + I32, + false, + ), + valid_range: 0..=4294967295, + }, + ), + fields: Primitive, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(4 bytes), + randomization_seed: 18446462607322841091, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: None, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + ], + ret: ArgAbi { + layout: TyAndLayout { + ty: u32, + layout: Layout { + size: Size(4 bytes), + align: AbiAlign { + abi: Align(4 bytes), + }, + backend_repr: Scalar( + Initialized { + value: Int( + I32, + false, + ), + valid_range: 0..=4294967295, + }, + ), + fields: Primitive, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(4 bytes), + randomization_seed: 18446462607322841091, + }, + }, + mode: Direct( + ArgAttributes { + regular: NoUndef, + arg_ext: None, + pointee_size: Size(0 bytes), + pointee_align: None, + }, + ), + }, + c_variadic: false, + fixed_count: 1, + conv: X86( + SysV64, + ), + can_unwind: false, + } + --> $DIR/x86-64-sysv64-arg-ext.rs:43:1 + | +LL | pub extern "sysv64" fn u32(x: u32) -> u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.rs b/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.rs new file mode 100644 index 000000000000..29a3061cfd0c --- /dev/null +++ b/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.rs @@ -0,0 +1,46 @@ +//@ only-x86_64 +//@ revisions: apple other +//@[apple] only-apple +//@[other] ignore-apple + +// Apple targets extend up to 32 bits for both arguments and returns, other targets only extend +// arguments. + +#![crate_type = "lib"] +#![feature(rustc_attrs)] + +#[rustc_abi(debug)] +pub extern "sysv64" fn i8(x: i8) -> i8 { + //~^ ERROR fn_abi_of(i8) + x +} + +#[rustc_abi(debug)] +pub extern "sysv64" fn u8(x: u8) -> u8 { + //~^ ERROR fn_abi_of(u8) + x +} + +#[rustc_abi(debug)] +pub extern "sysv64" fn i16(x: i16) -> i16 { + //~^ ERROR fn_abi_of(i16) + x +} + +#[rustc_abi(debug)] +pub extern "sysv64" fn u16(x: u16) -> u16 { + //~^ ERROR fn_abi_of(u16) + x +} + +#[rustc_abi(debug)] +pub extern "sysv64" fn i32(x: i32) -> i32 { + //~^ ERROR fn_abi_of(i32) + x +} + +#[rustc_abi(debug)] +pub extern "sysv64" fn u32(x: u32) -> u32 { + //~^ ERROR fn_abi_of(u32) + x +} diff --git a/tests/ui/async-await/async-drop/async-drop-initial.rs b/tests/ui/async-await/async-drop/async-drop-initial.rs index 263b70699f5e..cd33c143fba0 100644 --- a/tests/ui/async-await/async-drop/async-drop-initial.rs +++ b/tests/ui/async-await/async-drop/async-drop-initial.rs @@ -62,7 +62,7 @@ fn main() { test_async_drop(&j, 16).await; test_async_drop( AsyncStruct { b: AsyncInt(8), a: AsyncInt(7), i: 6 }, - if cfg!(panic = "unwind") { 168 } else { 136 }, + 136, ).await; test_async_drop(ManuallyDrop::new(AsyncInt(9)), 16).await; diff --git a/tests/ui/async-await/async-drop/async-without-sync.rs b/tests/ui/async-await/async-drop/async-without-sync.rs new file mode 100644 index 000000000000..8a748636cc78 --- /dev/null +++ b/tests/ui/async-await/async-drop/async-without-sync.rs @@ -0,0 +1,19 @@ +//@ edition: 2024 +#![feature(async_drop)] +#![allow(incomplete_features)] +#![crate_type = "lib"] + +use std::future::AsyncDrop; +use std::pin::Pin; + +async fn foo() { + let _st = St; +} + +struct St; + +impl AsyncDrop for St { //~ ERROR: `AsyncDrop` impl without `Drop` impl + async fn drop(self: Pin<&mut Self>) { + println!("123"); + } +} diff --git a/tests/ui/async-await/async-drop/async-without-sync.stderr b/tests/ui/async-await/async-drop/async-without-sync.stderr new file mode 100644 index 000000000000..0eaca322dc03 --- /dev/null +++ b/tests/ui/async-await/async-drop/async-without-sync.stderr @@ -0,0 +1,10 @@ +error: `AsyncDrop` impl without `Drop` impl + --> $DIR/async-without-sync.rs:15:1 + | +LL | impl AsyncDrop for St { + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: type implementing `AsyncDrop` trait must also implement `Drop` trait to be used in sync context and unwinds + +error: aborting due to 1 previous error + diff --git a/tests/crashes/140429.rs b/tests/ui/async-await/async-drop/live-dead-storage.rs similarity index 62% rename from tests/crashes/140429.rs rename to tests/ui/async-await/async-drop/live-dead-storage.rs index 041eaf86c5c3..e6f25d351c3e 100644 --- a/tests/crashes/140429.rs +++ b/tests/ui/async-await/async-drop/live-dead-storage.rs @@ -1,6 +1,9 @@ -//@ known-bug: #140429 +// ex-ice: #140429 //@ compile-flags: -Zlint-mir --crate-type lib //@ edition:2024 +//@ check-pass #![feature(async_drop)] +#![allow(incomplete_features)] + async fn a(x: T) {} diff --git a/tests/crashes/140531.rs b/tests/ui/async-await/async-drop/live-dead-storage2.rs similarity index 50% rename from tests/crashes/140531.rs rename to tests/ui/async-await/async-drop/live-dead-storage2.rs index f664481d4402..18df870785e3 100644 --- a/tests/crashes/140531.rs +++ b/tests/ui/async-await/async-drop/live-dead-storage2.rs @@ -1,7 +1,11 @@ -//@ known-bug: #140531 -//@compile-flags: -Zlint-mir --crate-type lib +// ex-ice: #140531 +//@ compile-flags: -Zlint-mir --crate-type lib //@ edition:2024 +//@ check-pass + #![feature(async_drop)] +#![allow(incomplete_features)] + async fn call_once(f: impl AsyncFnOnce()) { let fut = Box::pin(f()); } diff --git a/tests/ui/async-await/async-drop/live-dead-storage3.rs b/tests/ui/async-await/async-drop/live-dead-storage3.rs new file mode 100644 index 000000000000..d9fba5759f73 --- /dev/null +++ b/tests/ui/async-await/async-drop/live-dead-storage3.rs @@ -0,0 +1,56 @@ +// ex-ice: #141761 +//@ compile-flags: -Zlint-mir --crate-type lib +//@ edition:2024 +//@ check-pass + +#![feature(async_drop)] +#![allow(incomplete_features)] + +type BoxFuture = std::pin::Pin>>; +fn main() {} +async fn f() { + run("").await +} +struct InMemoryStorage; +struct User<'dep> { + dep: &'dep str, +} +impl<'a> StorageRequest for SaveUser<'a> { + fn execute(&self) -> BoxFuture> { + todo!() + } +} +trait Storage { + type Error; +} +impl Storage for InMemoryStorage { + type Error = String; +} +trait StorageRequestReturnType { + type Output; +} +trait StorageRequest: StorageRequestReturnType { + fn execute(&self) -> BoxFuture::Output, S::Error>>; +} +struct SaveUser<'a> { + name: &'a str, +} +impl<'a> StorageRequestReturnType for SaveUser<'a> { + type Output = (); +} +impl<'dep> User<'dep> { + async fn save(self) + where + S: Storage, + for<'a> SaveUser<'a>: StorageRequest, + { + SaveUser { name: "" }.execute().await; + } +} +async fn run(dep: &str) +where + S: Storage, + for<'a> SaveUser<'a>: StorageRequest, +{ + User { dep }.save().await +} diff --git a/tests/ui/async-await/async-drop/live-dead-storage4.rs b/tests/ui/async-await/async-drop/live-dead-storage4.rs new file mode 100644 index 000000000000..d927cb96674f --- /dev/null +++ b/tests/ui/async-await/async-drop/live-dead-storage4.rs @@ -0,0 +1,56 @@ +// ex-ice: #141409 +//@ compile-flags: -Zmir-enable-passes=+Inline -Zvalidate-mir -Zlint-mir --crate-type lib +//@ edition:2024 +//@ check-pass + +#![feature(async_drop)] +#![allow(incomplete_features)] +#![allow(non_snake_case)] + +use std::mem::ManuallyDrop; +use std::{ + future::{async_drop_in_place, Future}, + pin::{pin, Pin}, + sync::{mpsc, Arc}, + task::{Context, Poll, Wake, Waker}, +}; +fn main() { + block_on(bar(0)) +} +async fn baz(ident_base: usize) {} +async fn bar(ident_base: usize) { + baz(1).await +} +fn block_on(fut_unpin: F) -> F::Output +where + F: Future, +{ + let fut_pin = pin!(ManuallyDrop::new(fut_unpin)); + let mut fut = unsafe { Pin::map_unchecked_mut(fut_pin, |x| &mut **x) }; + let (waker, rx) = simple_waker(); + let mut context = Context::from_waker(&waker); + let rv = loop { + match fut.as_mut().poll(&mut context) { + Poll::Ready(out) => break out, + PollPending => (), + } + }; + let drop_fut_unpin = unsafe { async_drop_in_place(fut.get_unchecked_mut()) }; + let drop_fut = pin!(drop_fut_unpin); + loop { + match drop_fut.poll(&mut context) { + Poll => break, + } + } + rv +} +fn simple_waker() -> (Waker, mpsc::Receiver<()>) { + struct SimpleWaker { + tx: mpsc::Sender<()>, + } + impl Wake for SimpleWaker { + fn wake(self: Arc) {} + } + let (tx, rx) = mpsc::channel(); + (Waker::from(Arc::new(SimpleWaker { tx })), rx) +} diff --git a/tests/ui/borrowck/span-semicolon-issue-139049.fixed b/tests/ui/borrowck/span-semicolon-issue-139049.fixed new file mode 100644 index 000000000000..0b263b222963 --- /dev/null +++ b/tests/ui/borrowck/span-semicolon-issue-139049.fixed @@ -0,0 +1,52 @@ +// Make sure the generated suggestion suggest editing the user +// code instead of the std macro implementation + +//@ run-rustfix + +#![allow(dead_code)] + +use std::fmt::{self, Display}; + +struct Mutex; + +impl Mutex { + fn lock(&self) -> MutexGuard<'_> { + MutexGuard(self) + } +} + +struct MutexGuard<'a>(&'a Mutex); + +impl<'a> Drop for MutexGuard<'a> { + fn drop(&mut self) {} +} + +struct Out; + +impl Out { + fn write_fmt(&self, _args: fmt::Arguments) {} +} + +impl<'a> Display for MutexGuard<'a> { + fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result { + Ok(()) + } +} + +fn main() { + let _write = { + let mutex = Mutex; + write!(Out, "{}", mutex.lock()); + //~^ ERROR `mutex` does not live long enough + //~| SUGGESTION ; + }; + + let _write = { + use std::io::Write as _; + + let mutex = Mutex; + let x = write!(std::io::stdout(), "{}", mutex.lock()); x + //~^ ERROR `mutex` does not live long enough + //~| SUGGESTION let x + }; +} diff --git a/tests/ui/borrowck/span-semicolon-issue-139049.rs b/tests/ui/borrowck/span-semicolon-issue-139049.rs new file mode 100644 index 000000000000..a92742ac94b2 --- /dev/null +++ b/tests/ui/borrowck/span-semicolon-issue-139049.rs @@ -0,0 +1,52 @@ +// Make sure the generated suggestion suggest editing the user +// code instead of the std macro implementation + +//@ run-rustfix + +#![allow(dead_code)] + +use std::fmt::{self, Display}; + +struct Mutex; + +impl Mutex { + fn lock(&self) -> MutexGuard<'_> { + MutexGuard(self) + } +} + +struct MutexGuard<'a>(&'a Mutex); + +impl<'a> Drop for MutexGuard<'a> { + fn drop(&mut self) {} +} + +struct Out; + +impl Out { + fn write_fmt(&self, _args: fmt::Arguments) {} +} + +impl<'a> Display for MutexGuard<'a> { + fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result { + Ok(()) + } +} + +fn main() { + let _write = { + let mutex = Mutex; + write!(Out, "{}", mutex.lock()) + //~^ ERROR `mutex` does not live long enough + //~| SUGGESTION ; + }; + + let _write = { + use std::io::Write as _; + + let mutex = Mutex; + write!(std::io::stdout(), "{}", mutex.lock()) + //~^ ERROR `mutex` does not live long enough + //~| SUGGESTION let x + }; +} diff --git a/tests/ui/borrowck/span-semicolon-issue-139049.stderr b/tests/ui/borrowck/span-semicolon-issue-139049.stderr new file mode 100644 index 000000000000..123bdf4bc67e --- /dev/null +++ b/tests/ui/borrowck/span-semicolon-issue-139049.stderr @@ -0,0 +1,47 @@ +error[E0597]: `mutex` does not live long enough + --> $DIR/span-semicolon-issue-139049.rs:39:27 + | +LL | let mutex = Mutex; + | ----- binding `mutex` declared here +LL | write!(Out, "{}", mutex.lock()) + | ^^^^^------- + | | + | borrowed value does not live long enough + | a temporary with access to the borrow is created here ... +... +LL | }; + | -- ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `MutexGuard` + | | + | `mutex` dropped here while still borrowed + | +help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped + | +LL | write!(Out, "{}", mutex.lock()); + | + + +error[E0597]: `mutex` does not live long enough + --> $DIR/span-semicolon-issue-139049.rs:48:41 + | +LL | let mutex = Mutex; + | ----- binding `mutex` declared here +LL | write!(std::io::stdout(), "{}", mutex.lock()) + | ^^^^^------- + | | + | borrowed value does not live long enough + | a temporary with access to the borrow is created here ... +... +LL | }; + | -- ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `MutexGuard` + | | + | `mutex` dropped here while still borrowed + | + = note: the temporary is part of an expression at the end of a block; + consider forcing this temporary to be dropped sooner, before the block's local variables are dropped +help: for example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block + | +LL | let x = write!(std::io::stdout(), "{}", mutex.lock()); x + | +++++++ +++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/editions/never-type-fallback-breaking.e2021.stderr b/tests/ui/editions/never-type-fallback-breaking.e2021.stderr index 4ca179188276..6b84a64fffe2 100644 --- a/tests/ui/editions/never-type-fallback-breaking.e2021.stderr +++ b/tests/ui/editions/never-type-fallback-breaking.e2021.stderr @@ -96,3 +96,108 @@ LL | takes_apit2(mk::<()>()?); warning: 5 warnings emitted +Future incompatibility report: Future breakage diagnostic: +warning: this function depends on never type fallback being `()` + --> $DIR/never-type-fallback-breaking.rs:18:1 + | +LL | fn m() { + | ^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the types explicitly +note: in edition 2024, the requirement `!: Default` will fail + --> $DIR/never-type-fallback-breaking.rs:22:17 + | +LL | true => Default::default(), + | ^^^^^^^^^^^^^^^^^^ + = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default +help: use `()` annotations to avoid fallback changes + | +LL | let x: () = match true { + | ++++ + +Future breakage diagnostic: +warning: this function depends on never type fallback being `()` + --> $DIR/never-type-fallback-breaking.rs:30:1 + | +LL | fn q() -> Option<()> { + | ^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the types explicitly +note: in edition 2024, the requirement `!: Default` will fail + --> $DIR/never-type-fallback-breaking.rs:37:5 + | +LL | deserialize()?; + | ^^^^^^^^^^^^^ + = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default +help: use `()` annotations to avoid fallback changes + | +LL | deserialize::<()>()?; + | ++++++ + +Future breakage diagnostic: +warning: this function depends on never type fallback being `()` + --> $DIR/never-type-fallback-breaking.rs:47:1 + | +LL | fn meow() -> Result<(), ()> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the types explicitly +note: in edition 2024, the requirement `(): From` will fail + --> $DIR/never-type-fallback-breaking.rs:50:5 + | +LL | help(1)?; + | ^^^^^^^ + = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default +help: use `()` annotations to avoid fallback changes + | +LL | help::<(), _>(1)?; + | +++++++++ + +Future breakage diagnostic: +warning: this function depends on never type fallback being `()` + --> $DIR/never-type-fallback-breaking.rs:59:1 + | +LL | pub fn fallback_return() -> Result<(), ()> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the types explicitly +note: in edition 2024, the requirement `!: Default` will fail + --> $DIR/never-type-fallback-breaking.rs:62:19 + | +LL | takes_apit(|| Default::default())?; + | ^^^^^^^^^^^^^^^^^^ + = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default +help: use `()` annotations to avoid fallback changes + | +LL | takes_apit::<()>(|| Default::default())?; + | ++++++ + +Future breakage diagnostic: +warning: this function depends on never type fallback being `()` + --> $DIR/never-type-fallback-breaking.rs:73:1 + | +LL | fn fully_apit() -> Result<(), ()> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the types explicitly +note: in edition 2024, the requirement `!: Default` will fail + --> $DIR/never-type-fallback-breaking.rs:76:17 + | +LL | takes_apit2(mk()?); + | ^^^^^ + = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default +help: use `()` annotations to avoid fallback changes + | +LL | takes_apit2(mk::<()>()?); + | ++++++ + diff --git a/tests/ui/label/label_misspelled.stderr b/tests/ui/label/label_misspelled.stderr index 3f4020e7be0a..9f9d32dce6b5 100644 --- a/tests/ui/label/label_misspelled.stderr +++ b/tests/ui/label/label_misspelled.stderr @@ -78,6 +78,14 @@ LL | break for_loop; | not found in this scope | help: use the similarly named label: `'for_loop` +warning: denote infinite loops with `loop { ... }` + --> $DIR/label_misspelled.rs:4:5 + | +LL | 'while_loop: while true { + | ^^^^^^^^^^^^^^^^^^^^^^^ help: use `loop` + | + = note: `#[warn(while_true)]` on by default + warning: unused label --> $DIR/label_misspelled.rs:4:5 | @@ -90,14 +98,6 @@ note: the lint level is defined here LL | #![warn(unused_labels)] | ^^^^^^^^^^^^^ -warning: denote infinite loops with `loop { ... }` - --> $DIR/label_misspelled.rs:4:5 - | -LL | 'while_loop: while true { - | ^^^^^^^^^^^^^^^^^^^^^^^ help: use `loop` - | - = note: `#[warn(while_true)]` on by default - warning: unused label --> $DIR/label_misspelled.rs:9:5 | @@ -122,18 +122,18 @@ warning: denote infinite loops with `loop { ... }` LL | 'while_loop: while true { | ^^^^^^^^^^^^^^^^^^^^^^^ help: use `loop` -warning: unused label - --> $DIR/label_misspelled.rs:47:5 - | -LL | 'while_loop: while true { - | ^^^^^^^^^^^ - warning: denote infinite loops with `loop { ... }` --> $DIR/label_misspelled.rs:47:5 | LL | 'while_loop: while true { | ^^^^^^^^^^^^^^^^^^^^^^^ help: use `loop` +warning: unused label + --> $DIR/label_misspelled.rs:47:5 + | +LL | 'while_loop: while true { + | ^^^^^^^^^^^ + warning: unused label --> $DIR/label_misspelled.rs:52:5 | diff --git a/tests/ui/lint/wasm_c_abi_transition.rs b/tests/ui/lint/wasm_c_abi_transition.rs deleted file mode 100644 index 411772ae890b..000000000000 --- a/tests/ui/lint/wasm_c_abi_transition.rs +++ /dev/null @@ -1,57 +0,0 @@ -//@ compile-flags: --target wasm32-unknown-unknown -//@ needs-llvm-components: webassembly -//@ add-core-stubs -//@ build-fail - -#![feature(no_core, repr_simd)] -#![no_core] -#![crate_type = "lib"] -#![deny(wasm_c_abi)] - -extern crate minicore; -use minicore::*; - -pub extern "C" fn my_fun_trivial(_x: i32, _y: f32) {} - -#[repr(C)] -pub struct MyType(i32, i32); -pub extern "C" fn my_fun(_x: MyType) {} //~ERROR: wasm ABI transition -//~^WARN: previously accepted - -// This one is ABI-safe as it only wraps a single field, -// and the return type can be anything. -#[repr(C)] -pub struct MySafeType(i32); -pub extern "C" fn my_fun_safe(_x: MySafeType) -> MyType { loop {} } - -// This one not ABI-safe due to the alignment. -#[repr(C, align(16))] -pub struct MyAlignedType(i32); -pub extern "C" fn my_fun_aligned(_x: MyAlignedType) {} //~ERROR: wasm ABI transition -//~^WARN: previously accepted - -// Check call-site warning -extern "C" { - fn other_fun(x: MyType); -} - -pub fn call_other_fun(x: MyType) { - unsafe { other_fun(x) } //~ERROR: wasm ABI transition - //~^WARN: previously accepted -} - -// Zero-sized types are safe in both ABIs -#[repr(C)] -pub struct MyZstType; -#[allow(improper_ctypes_definitions)] -pub extern "C" fn zst_safe(_x: (), _y: MyZstType) {} - -// The old and new wasm ABI treats simd types like `v128` the same way, so no -// wasm_c_abi warning should be emitted. -#[repr(simd)] -#[allow(non_camel_case_types)] -pub struct v128([i32; 4]); -#[target_feature(enable = "simd128")] -pub extern "C" fn my_safe_simd(x: v128) -> v128 { x } -//~^ WARN `extern` fn uses type `v128`, which is not FFI-safe -//~| WARN `extern` fn uses type `v128`, which is not FFI-safe diff --git a/tests/ui/lint/wasm_c_abi_transition.stderr b/tests/ui/lint/wasm_c_abi_transition.stderr deleted file mode 100644 index b4526bf8d687..000000000000 --- a/tests/ui/lint/wasm_c_abi_transition.stderr +++ /dev/null @@ -1,114 +0,0 @@ -warning: `extern` fn uses type `v128`, which is not FFI-safe - --> $DIR/wasm_c_abi_transition.rs:55:35 - | -LL | pub extern "C" fn my_safe_simd(x: v128) -> v128 { x } - | ^^^^ not FFI-safe - | - = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct - = note: this struct has unspecified layout -note: the type is defined here - --> $DIR/wasm_c_abi_transition.rs:53:1 - | -LL | pub struct v128([i32; 4]); - | ^^^^^^^^^^^^^^^ - = note: `#[warn(improper_ctypes_definitions)]` on by default - -warning: `extern` fn uses type `v128`, which is not FFI-safe - --> $DIR/wasm_c_abi_transition.rs:55:44 - | -LL | pub extern "C" fn my_safe_simd(x: v128) -> v128 { x } - | ^^^^ not FFI-safe - | - = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct - = note: this struct has unspecified layout -note: the type is defined here - --> $DIR/wasm_c_abi_transition.rs:53:1 - | -LL | pub struct v128([i32; 4]); - | ^^^^^^^^^^^^^^^ - -error: this function definition involves an argument of type `MyType` which is affected by the wasm ABI transition - --> $DIR/wasm_c_abi_transition.rs:18:1 - | -LL | pub extern "C" fn my_fun(_x: MyType) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #138762 - = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target -note: the lint level is defined here - --> $DIR/wasm_c_abi_transition.rs:9:9 - | -LL | #![deny(wasm_c_abi)] - | ^^^^^^^^^^ - -error: this function definition involves an argument of type `MyAlignedType` which is affected by the wasm ABI transition - --> $DIR/wasm_c_abi_transition.rs:30:1 - | -LL | pub extern "C" fn my_fun_aligned(_x: MyAlignedType) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #138762 - = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target - -error: this function call involves an argument of type `MyType` which is affected by the wasm ABI transition - --> $DIR/wasm_c_abi_transition.rs:39:14 - | -LL | unsafe { other_fun(x) } - | ^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #138762 - = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target - -error: aborting due to 3 previous errors; 2 warnings emitted - -Future incompatibility report: Future breakage diagnostic: -error: this function definition involves an argument of type `MyType` which is affected by the wasm ABI transition - --> $DIR/wasm_c_abi_transition.rs:18:1 - | -LL | pub extern "C" fn my_fun(_x: MyType) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #138762 - = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target -note: the lint level is defined here - --> $DIR/wasm_c_abi_transition.rs:9:9 - | -LL | #![deny(wasm_c_abi)] - | ^^^^^^^^^^ - -Future breakage diagnostic: -error: this function definition involves an argument of type `MyAlignedType` which is affected by the wasm ABI transition - --> $DIR/wasm_c_abi_transition.rs:30:1 - | -LL | pub extern "C" fn my_fun_aligned(_x: MyAlignedType) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #138762 - = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target -note: the lint level is defined here - --> $DIR/wasm_c_abi_transition.rs:9:9 - | -LL | #![deny(wasm_c_abi)] - | ^^^^^^^^^^ - -Future breakage diagnostic: -error: this function call involves an argument of type `MyType` which is affected by the wasm ABI transition - --> $DIR/wasm_c_abi_transition.rs:39:14 - | -LL | unsafe { other_fun(x) } - | ^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #138762 - = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target -note: the lint level is defined here - --> $DIR/wasm_c_abi_transition.rs:9:9 - | -LL | #![deny(wasm_c_abi)] - | ^^^^^^^^^^ - diff --git a/tests/ui/macros/format-args-temporaries-in-write.stderr b/tests/ui/macros/format-args-temporaries-in-write.stderr index e05246cfbe38..e58a43383f6e 100644 --- a/tests/ui/macros/format-args-temporaries-in-write.stderr +++ b/tests/ui/macros/format-args-temporaries-in-write.stderr @@ -14,6 +14,10 @@ LL | }; | | | `mutex` dropped here while still borrowed | +help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped + | +LL | write!(Out, "{}", mutex.lock()); /* no semicolon */ + | + error[E0597]: `mutex` does not live long enough --> $DIR/format-args-temporaries-in-write.rs:47:29 @@ -31,6 +35,10 @@ LL | }; | | | `mutex` dropped here while still borrowed | +help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped + | +LL | writeln!(Out, "{}", mutex.lock()); /* no semicolon */ + | + error: aborting due to 2 previous errors diff --git a/tests/ui/never_type/defaulted-never-note.nofallback.stderr b/tests/ui/never_type/defaulted-never-note.nofallback.stderr index 2abff61fa542..6de323ad12c2 100644 --- a/tests/ui/never_type/defaulted-never-note.nofallback.stderr +++ b/tests/ui/never_type/defaulted-never-note.nofallback.stderr @@ -20,3 +20,24 @@ LL | let _x: () = return; warning: 1 warning emitted +Future incompatibility report: Future breakage diagnostic: +warning: this function depends on never type fallback being `()` + --> $DIR/defaulted-never-note.rs:28:1 + | +LL | fn smeg() { + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the types explicitly +note: in edition 2024, the requirement `!: ImplementedForUnitButNotNever` will fail + --> $DIR/defaulted-never-note.rs:32:9 + | +LL | foo(_x); + | ^^ + = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default +help: use `()` annotations to avoid fallback changes + | +LL | let _x: () = return; + | ++++ + diff --git a/tests/ui/never_type/dependency-on-fallback-to-unit.stderr b/tests/ui/never_type/dependency-on-fallback-to-unit.stderr index bf37cc7b4b47..be8075662e0c 100644 --- a/tests/ui/never_type/dependency-on-fallback-to-unit.stderr +++ b/tests/ui/never_type/dependency-on-fallback-to-unit.stderr @@ -40,3 +40,46 @@ LL | deserialize::<()>()?; warning: 2 warnings emitted +Future incompatibility report: Future breakage diagnostic: +warning: this function depends on never type fallback being `()` + --> $DIR/dependency-on-fallback-to-unit.rs:8:1 + | +LL | fn def() { + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the types explicitly +note: in edition 2024, the requirement `!: Default` will fail + --> $DIR/dependency-on-fallback-to-unit.rs:12:19 + | +LL | false => <_>::default(), + | ^ + = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default +help: use `()` annotations to avoid fallback changes + | +LL - false => <_>::default(), +LL + false => <()>::default(), + | + +Future breakage diagnostic: +warning: this function depends on never type fallback being `()` + --> $DIR/dependency-on-fallback-to-unit.rs:19:1 + | +LL | fn question_mark() -> Result<(), ()> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the types explicitly +note: in edition 2024, the requirement `!: Default` will fail + --> $DIR/dependency-on-fallback-to-unit.rs:22:5 + | +LL | deserialize()?; + | ^^^^^^^^^^^^^ + = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default +help: use `()` annotations to avoid fallback changes + | +LL | deserialize::<()>()?; + | ++++++ + diff --git a/tests/ui/never_type/diverging-fallback-control-flow.nofallback.stderr b/tests/ui/never_type/diverging-fallback-control-flow.nofallback.stderr index 4b8a5d5e934a..44ebdb435104 100644 --- a/tests/ui/never_type/diverging-fallback-control-flow.nofallback.stderr +++ b/tests/ui/never_type/diverging-fallback-control-flow.nofallback.stderr @@ -39,3 +39,45 @@ LL | let x: (); warning: 2 warnings emitted +Future incompatibility report: Future breakage diagnostic: +warning: this function depends on never type fallback being `()` + --> $DIR/diverging-fallback-control-flow.rs:30:1 + | +LL | fn assignment() { + | ^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the types explicitly +note: in edition 2024, the requirement `!: UnitDefault` will fail + --> $DIR/diverging-fallback-control-flow.rs:36:13 + | +LL | x = UnitDefault::default(); + | ^^^^^^^^^^^^^^^^^^^^^^ + = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default +help: use `()` annotations to avoid fallback changes + | +LL | let x: (); + | ++++ + +Future breakage diagnostic: +warning: this function depends on never type fallback being `()` + --> $DIR/diverging-fallback-control-flow.rs:42:1 + | +LL | fn assignment_rev() { + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the types explicitly +note: in edition 2024, the requirement `!: UnitDefault` will fail + --> $DIR/diverging-fallback-control-flow.rs:50:13 + | +LL | x = UnitDefault::default(); + | ^^^^^^^^^^^^^^^^^^^^^^ + = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default +help: use `()` annotations to avoid fallback changes + | +LL | let x: (); + | ++++ + diff --git a/tests/ui/never_type/diverging-fallback-no-leak.nofallback.stderr b/tests/ui/never_type/diverging-fallback-no-leak.nofallback.stderr index 94af02a3698d..4a8dea42a4d6 100644 --- a/tests/ui/never_type/diverging-fallback-no-leak.nofallback.stderr +++ b/tests/ui/never_type/diverging-fallback-no-leak.nofallback.stderr @@ -20,3 +20,24 @@ LL | unconstrained_arg::<()>(return); warning: 1 warning emitted +Future incompatibility report: Future breakage diagnostic: +warning: this function depends on never type fallback being `()` + --> $DIR/diverging-fallback-no-leak.rs:14:1 + | +LL | fn main() { + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the types explicitly +note: in edition 2024, the requirement `!: Test` will fail + --> $DIR/diverging-fallback-no-leak.rs:20:23 + | +LL | unconstrained_arg(return); + | ^^^^^^ + = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default +help: use `()` annotations to avoid fallback changes + | +LL | unconstrained_arg::<()>(return); + | ++++++ + diff --git a/tests/ui/never_type/diverging-fallback-unconstrained-return.nofallback.stderr b/tests/ui/never_type/diverging-fallback-unconstrained-return.nofallback.stderr index 22349d398570..803af39fd86f 100644 --- a/tests/ui/never_type/diverging-fallback-unconstrained-return.nofallback.stderr +++ b/tests/ui/never_type/diverging-fallback-unconstrained-return.nofallback.stderr @@ -20,3 +20,24 @@ LL | let _: () = if true { unconstrained_return() } else { panic!() }; warning: 1 warning emitted +Future incompatibility report: Future breakage diagnostic: +warning: this function depends on never type fallback being `()` + --> $DIR/diverging-fallback-unconstrained-return.rs:28:1 + | +LL | fn main() { + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the types explicitly +note: in edition 2024, the requirement `!: UnitReturn` will fail + --> $DIR/diverging-fallback-unconstrained-return.rs:39:23 + | +LL | let _ = if true { unconstrained_return() } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^ + = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default +help: use `()` annotations to avoid fallback changes + | +LL | let _: () = if true { unconstrained_return() } else { panic!() }; + | ++++ + diff --git a/tests/ui/never_type/dont-suggest-turbofish-from-expansion.stderr b/tests/ui/never_type/dont-suggest-turbofish-from-expansion.stderr index 3fe642a8401a..365e8869897c 100644 --- a/tests/ui/never_type/dont-suggest-turbofish-from-expansion.stderr +++ b/tests/ui/never_type/dont-suggest-turbofish-from-expansion.stderr @@ -24,3 +24,28 @@ LL | let created: () = create_ok_default()?; error: aborting due to 1 previous error +Future incompatibility report: Future breakage diagnostic: +error: this function depends on never type fallback being `()` + --> $DIR/dont-suggest-turbofish-from-expansion.rs:10:1 + | +LL | fn main() -> Result<(), ()> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the types explicitly +note: in edition 2024, the requirement `!: Default` will fail + --> $DIR/dont-suggest-turbofish-from-expansion.rs:14:23 + | +LL | let created = create_ok_default()?; + | ^^^^^^^^^^^^^^^^^^^ +note: the lint level is defined here + --> $DIR/dont-suggest-turbofish-from-expansion.rs:1:9 + | +LL | #![deny(dependency_on_unit_never_type_fallback)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: use `()` annotations to avoid fallback changes + | +LL | let created: () = create_ok_default()?; + | ++++ + diff --git a/tests/ui/never_type/fallback-closure-ret.nofallback.stderr b/tests/ui/never_type/fallback-closure-ret.nofallback.stderr index d7463be6acce..cf19363a7d8b 100644 --- a/tests/ui/never_type/fallback-closure-ret.nofallback.stderr +++ b/tests/ui/never_type/fallback-closure-ret.nofallback.stderr @@ -20,3 +20,24 @@ LL | foo::<()>(|| panic!()); warning: 1 warning emitted +Future incompatibility report: Future breakage diagnostic: +warning: this function depends on never type fallback being `()` + --> $DIR/fallback-closure-ret.rs:21:1 + | +LL | fn main() { + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the types explicitly +note: in edition 2024, the requirement `!: Bar` will fail + --> $DIR/fallback-closure-ret.rs:24:5 + | +LL | foo(|| panic!()); + | ^^^^^^^^^^^^^^^^ + = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default +help: use `()` annotations to avoid fallback changes + | +LL | foo::<()>(|| panic!()); + | ++++++ + diff --git a/tests/ui/never_type/impl_trait_fallback.stderr b/tests/ui/never_type/impl_trait_fallback.stderr index 72788a648885..7250db127cd6 100644 --- a/tests/ui/never_type/impl_trait_fallback.stderr +++ b/tests/ui/never_type/impl_trait_fallback.stderr @@ -16,3 +16,20 @@ LL | fn should_ret_unit() -> impl T { warning: 1 warning emitted +Future incompatibility report: Future breakage diagnostic: +warning: this function depends on never type fallback being `()` + --> $DIR/impl_trait_fallback.rs:8:1 + | +LL | fn should_ret_unit() -> impl T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the types explicitly +note: in edition 2024, the requirement `!: T` will fail + --> $DIR/impl_trait_fallback.rs:8:25 + | +LL | fn should_ret_unit() -> impl T { + | ^^^^^^ + = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default + diff --git a/tests/ui/never_type/lint-breaking-2024-assign-underscore.stderr b/tests/ui/never_type/lint-breaking-2024-assign-underscore.stderr index 86786c3bfe00..945db40782ec 100644 --- a/tests/ui/never_type/lint-breaking-2024-assign-underscore.stderr +++ b/tests/ui/never_type/lint-breaking-2024-assign-underscore.stderr @@ -24,3 +24,28 @@ LL | _ = foo::<()>()?; error: aborting due to 1 previous error +Future incompatibility report: Future breakage diagnostic: +error: this function depends on never type fallback being `()` + --> $DIR/lint-breaking-2024-assign-underscore.rs:10:1 + | +LL | fn test() -> Result<(), ()> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the types explicitly +note: in edition 2024, the requirement `!: Default` will fail + --> $DIR/lint-breaking-2024-assign-underscore.rs:13:9 + | +LL | _ = foo()?; + | ^^^^^ +note: the lint level is defined here + --> $DIR/lint-breaking-2024-assign-underscore.rs:4:9 + | +LL | #![deny(dependency_on_unit_never_type_fallback)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: use `()` annotations to avoid fallback changes + | +LL | _ = foo::<()>()?; + | ++++++ + diff --git a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2015.stderr b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2015.stderr index 49b966f32ced..c90efd277845 100644 --- a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2015.stderr +++ b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2015.stderr @@ -133,3 +133,155 @@ LL | msg_send!(); warning: 10 warnings emitted +Future incompatibility report: Future breakage diagnostic: +warning: never type fallback affects this call to an `unsafe` function + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:12:18 + | +LL | unsafe { mem::zeroed() } + | ^^^^^^^^^^^^^ + | + = warning: this changes meaning in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the type explicitly + = note: `#[warn(never_type_fallback_flowing_into_unsafe)]` on by default +help: use `()` annotations to avoid fallback changes + | +LL | unsafe { mem::zeroed::<()>() } + | ++++++ + +Future breakage diagnostic: +warning: never type fallback affects this call to an `unsafe` function + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:29:13 + | +LL | core::mem::transmute(Zst) + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this changes meaning in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the type explicitly + = note: `#[warn(never_type_fallback_flowing_into_unsafe)]` on by default +help: use `()` annotations to avoid fallback changes + | +LL | core::mem::transmute::<_, ()>(Zst) + | +++++++++ + +Future breakage diagnostic: +warning: never type fallback affects this union access + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:46:18 + | +LL | unsafe { Union { a: () }.b } + | ^^^^^^^^^^^^^^^^^ + | + = warning: this changes meaning in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the type explicitly + = note: `#[warn(never_type_fallback_flowing_into_unsafe)]` on by default + +Future breakage diagnostic: +warning: never type fallback affects this raw pointer dereference + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:57:18 + | +LL | unsafe { *ptr::from_ref(&()).cast() } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this changes meaning in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the type explicitly + = note: `#[warn(never_type_fallback_flowing_into_unsafe)]` on by default +help: use `()` annotations to avoid fallback changes + | +LL | unsafe { *ptr::from_ref(&()).cast::<()>() } + | ++++++ + +Future breakage diagnostic: +warning: never type fallback affects this call to an `unsafe` function + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:78:18 + | +LL | unsafe { internally_create(x) } + | ^^^^^^^^^^^^^^^^^^^^ + | + = warning: this changes meaning in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the type explicitly + = note: `#[warn(never_type_fallback_flowing_into_unsafe)]` on by default +help: use `()` annotations to avoid fallback changes + | +LL | unsafe { internally_create::<()>(x) } + | ++++++ + +Future breakage diagnostic: +warning: never type fallback affects this call to an `unsafe` function + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:96:18 + | +LL | unsafe { zeroed() } + | ^^^^^^^^ + | + = warning: this changes meaning in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the type explicitly + = note: `#[warn(never_type_fallback_flowing_into_unsafe)]` on by default +help: use `()` annotations to avoid fallback changes + | +LL | let zeroed = mem::zeroed::<()>; + | ++++++ + +Future breakage diagnostic: +warning: never type fallback affects this `unsafe` function + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:91:22 + | +LL | let zeroed = mem::zeroed; + | ^^^^^^^^^^^ + | + = warning: this changes meaning in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the type explicitly + = note: `#[warn(never_type_fallback_flowing_into_unsafe)]` on by default +help: use `()` annotations to avoid fallback changes + | +LL | let zeroed = mem::zeroed::<()>; + | ++++++ + +Future breakage diagnostic: +warning: never type fallback affects this `unsafe` function + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:114:17 + | +LL | let f = internally_create; + | ^^^^^^^^^^^^^^^^^ + | + = warning: this changes meaning in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the type explicitly + = note: `#[warn(never_type_fallback_flowing_into_unsafe)]` on by default +help: use `()` annotations to avoid fallback changes + | +LL | let f = internally_create::<()>; + | ++++++ + +Future breakage diagnostic: +warning: never type fallback affects this call to an `unsafe` method + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:139:13 + | +LL | S(marker::PhantomData).create_out_of_thin_air() + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this changes meaning in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the type explicitly + = note: `#[warn(never_type_fallback_flowing_into_unsafe)]` on by default + +Future breakage diagnostic: +warning: never type fallback affects this call to an `unsafe` function + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:157:19 + | +LL | match send_message::<_ /* ?0 */>() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | msg_send!(); + | ----------- in this macro invocation + | + = warning: this changes meaning in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the type explicitly + = note: `#[warn(never_type_fallback_flowing_into_unsafe)]` on by default + = note: this warning originates in the macro `msg_send` (in Nightly builds, run with -Z macro-backtrace for more info) + diff --git a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2024.stderr b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2024.stderr index 4d3692a7b043..858d7381eeda 100644 --- a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2024.stderr +++ b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2024.stderr @@ -142,3 +142,155 @@ LL | unsafe { mem::zeroed() } error: aborting due to 10 previous errors; 1 warning emitted +Future incompatibility report: Future breakage diagnostic: +error: never type fallback affects this call to an `unsafe` function + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:12:18 + | +LL | unsafe { mem::zeroed() } + | ^^^^^^^^^^^^^ + | + = warning: this changes meaning in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the type explicitly + = note: `#[deny(never_type_fallback_flowing_into_unsafe)]` on by default +help: use `()` annotations to avoid fallback changes + | +LL | unsafe { mem::zeroed::<()>() } + | ++++++ + +Future breakage diagnostic: +error: never type fallback affects this call to an `unsafe` function + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:29:13 + | +LL | core::mem::transmute(Zst) + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this changes meaning in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the type explicitly + = note: `#[deny(never_type_fallback_flowing_into_unsafe)]` on by default +help: use `()` annotations to avoid fallback changes + | +LL | core::mem::transmute::<_, ()>(Zst) + | +++++++++ + +Future breakage diagnostic: +error: never type fallback affects this union access + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:46:18 + | +LL | unsafe { Union { a: () }.b } + | ^^^^^^^^^^^^^^^^^ + | + = warning: this changes meaning in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the type explicitly + = note: `#[deny(never_type_fallback_flowing_into_unsafe)]` on by default + +Future breakage diagnostic: +error: never type fallback affects this raw pointer dereference + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:57:18 + | +LL | unsafe { *ptr::from_ref(&()).cast() } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this changes meaning in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the type explicitly + = note: `#[deny(never_type_fallback_flowing_into_unsafe)]` on by default +help: use `()` annotations to avoid fallback changes + | +LL | unsafe { *ptr::from_ref(&()).cast::<()>() } + | ++++++ + +Future breakage diagnostic: +error: never type fallback affects this call to an `unsafe` function + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:78:18 + | +LL | unsafe { internally_create(x) } + | ^^^^^^^^^^^^^^^^^^^^ + | + = warning: this changes meaning in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the type explicitly + = note: `#[deny(never_type_fallback_flowing_into_unsafe)]` on by default +help: use `()` annotations to avoid fallback changes + | +LL | unsafe { internally_create::<()>(x) } + | ++++++ + +Future breakage diagnostic: +error: never type fallback affects this call to an `unsafe` function + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:96:18 + | +LL | unsafe { zeroed() } + | ^^^^^^^^ + | + = warning: this changes meaning in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the type explicitly + = note: `#[deny(never_type_fallback_flowing_into_unsafe)]` on by default +help: use `()` annotations to avoid fallback changes + | +LL | let zeroed = mem::zeroed::<()>; + | ++++++ + +Future breakage diagnostic: +error: never type fallback affects this `unsafe` function + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:91:22 + | +LL | let zeroed = mem::zeroed; + | ^^^^^^^^^^^ + | + = warning: this changes meaning in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the type explicitly + = note: `#[deny(never_type_fallback_flowing_into_unsafe)]` on by default +help: use `()` annotations to avoid fallback changes + | +LL | let zeroed = mem::zeroed::<()>; + | ++++++ + +Future breakage diagnostic: +error: never type fallback affects this `unsafe` function + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:114:17 + | +LL | let f = internally_create; + | ^^^^^^^^^^^^^^^^^ + | + = warning: this changes meaning in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the type explicitly + = note: `#[deny(never_type_fallback_flowing_into_unsafe)]` on by default +help: use `()` annotations to avoid fallback changes + | +LL | let f = internally_create::<()>; + | ++++++ + +Future breakage diagnostic: +error: never type fallback affects this call to an `unsafe` method + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:139:13 + | +LL | S(marker::PhantomData).create_out_of_thin_air() + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this changes meaning in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the type explicitly + = note: `#[deny(never_type_fallback_flowing_into_unsafe)]` on by default + +Future breakage diagnostic: +error: never type fallback affects this call to an `unsafe` function + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:157:19 + | +LL | match send_message::<_ /* ?0 */>() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | msg_send!(); + | ----------- in this macro invocation + | + = warning: this changes meaning in Rust 2024 and in a future release in all editions! + = note: for more information, see + = help: specify the type explicitly + = note: `#[deny(never_type_fallback_flowing_into_unsafe)]` on by default + = note: this error originates in the macro `msg_send` (in Nightly builds, run with -Z macro-backtrace for more info) + diff --git a/tests/ui/parser/doc-comment-after-missing-comma-issue-142311.rs b/tests/ui/parser/doc-comment-after-missing-comma-issue-142311.rs new file mode 100644 index 000000000000..7ac6fa127f4d --- /dev/null +++ b/tests/ui/parser/doc-comment-after-missing-comma-issue-142311.rs @@ -0,0 +1,34 @@ +//! Check that if the parser suggests converting `///` to a regular comment +//! when it appears after a missing comma in an list (e.g. `enum` variants). +//! +//! Related issue +//! - https://github.com/rust-lang/rust/issues/142311 + +enum Foo { + /// Like the noise a sheep makes + Bar + /// Like where people drink + //~^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found doc comment `/// Like where people drink` + Baa///xxxxxx + //~^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found doc comment `///xxxxxx` + Baz///xxxxxx + //~^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found doc comment `///xxxxxx` +} + +fn foo() { + let a = [ + 1///xxxxxx + //~^ ERROR expected one of `,`, `.`, `;`, `?`, `]`, or an operator, found doc comment `///xxxxxx` + 2 + ]; +} + +fn bar() { + let a = [ + 1, + 2///xxxxxx + //~^ ERROR expected one of `,`, `.`, `?`, `]`, or an operator, found doc comment `///xxxxxx` + ]; +} + +fn main() {} diff --git a/tests/ui/parser/doc-comment-after-missing-comma-issue-142311.stderr b/tests/ui/parser/doc-comment-after-missing-comma-issue-142311.stderr new file mode 100644 index 000000000000..d95cecfc560b --- /dev/null +++ b/tests/ui/parser/doc-comment-after-missing-comma-issue-142311.stderr @@ -0,0 +1,43 @@ +error: expected one of `(`, `,`, `=`, `{`, or `}`, found doc comment `/// Like where people drink` + --> $DIR/doc-comment-after-missing-comma-issue-142311.rs:10:5 + | +LL | Bar + | - + | | + | expected one of `(`, `,`, `=`, `{`, or `}` + | help: missing `,` +LL | /// Like where people drink + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ unexpected token + +error: expected one of `(`, `,`, `=`, `{`, or `}`, found doc comment `///xxxxxx` + --> $DIR/doc-comment-after-missing-comma-issue-142311.rs:12:8 + | +LL | Baa///xxxxxx + | -^^^^^^^^ + | | + | expected one of `(`, `,`, `=`, `{`, or `}` + | help: missing `,` + +error: expected one of `(`, `,`, `=`, `{`, or `}`, found doc comment `///xxxxxx` + --> $DIR/doc-comment-after-missing-comma-issue-142311.rs:14:8 + | +LL | Baz///xxxxxx + | ^^^^^^^^^ expected one of `(`, `,`, `=`, `{`, or `}` + | + = help: doc comments must come before what they document, if a comment was intended use `//` + = help: enum variants can be `Variant`, `Variant = `, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }` + +error: expected one of `,`, `.`, `;`, `?`, `]`, or an operator, found doc comment `///xxxxxx` + --> $DIR/doc-comment-after-missing-comma-issue-142311.rs:20:10 + | +LL | 1///xxxxxx + | ^^^^^^^^^ expected one of `,`, `.`, `;`, `?`, `]`, or an operator + +error: expected one of `,`, `.`, `?`, `]`, or an operator, found doc comment `///xxxxxx` + --> $DIR/doc-comment-after-missing-comma-issue-142311.rs:29:10 + | +LL | 2///xxxxxx + | ^^^^^^^^^ expected one of `,`, `.`, `?`, `]`, or an operator + +error: aborting due to 5 previous errors +