From c555aabc5b7df5ccb88c15b7b94f73f5b40d116c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 12 Oct 2020 10:08:25 +0200 Subject: [PATCH 01/21] clarify rules for ZST Boxes --- library/alloc/src/boxed.rs | 9 +++++++++ library/core/src/ptr/mod.rs | 7 +++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 5c8c2c5a5a868..c543ee2d0c581 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -62,6 +62,11 @@ //! T` obtained from [`Box::::into_raw`] may be deallocated using the //! [`Global`] allocator with [`Layout::for_value(&*value)`]. //! +//! For zero-sized values, the `Box` pointer still has to be [valid] for reads and writes and +//! sufficiently aligned. In particular, casting any aligned non-zero integer to a raw pointer +//! produces a valid pointer, but a pointer pointing into previously allocated memory that since got +//! freed is not valid. +//! //! So long as `T: Sized`, a `Box` is guaranteed to be represented //! as a single pointer and is also ABI-compatible with C pointers //! (i.e. the C type `T*`). This means that if you have extern "C" @@ -125,6 +130,7 @@ //! [`Global`]: crate::alloc::Global //! [`Layout`]: crate::alloc::Layout //! [`Layout::for_value(&*value)`]: crate::alloc::Layout::for_value +//! [valid]: ptr#safety #![stable(feature = "rust1", since = "1.0.0")] @@ -385,7 +391,10 @@ impl Box { /// memory problems. For example, a double-free may occur if the /// function is called twice on the same raw pointer. /// + /// The safety conditions are described in the [memory layout] section. + /// /// # Examples + /// /// Recreate a `Box` which was previously converted to a raw pointer /// using [`Box::into_raw`]: /// ``` diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 92c4f2ccfe8a0..453621d9eadff 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -16,12 +16,15 @@ //! provided at this point are very minimal: //! //! * A [null] pointer is *never* valid, not even for accesses of [size zero][zst]. -//! * All pointers (except for the null pointer) are valid for all operations of -//! [size zero][zst]. //! * For a pointer to be valid, it is necessary, but not always sufficient, that the pointer //! be *dereferenceable*: the memory range of the given size starting at the pointer must all be //! within the bounds of a single allocated object. Note that in Rust, //! every (stack-allocated) variable is considered a separate allocated object. +//! * Even for operations of [size zero][zst], the pointer must not be "dangling" in the sense of +//! pointing to deallocated memory. However, casting any non-zero integer to a pointer is valid +//! for zero-sized accesses. This corresponds to writing your own allocator; allocating zero-sized +//! objects is not very hard. In contrast, when you use the standard allocator, after memory got +//! deallocated, even zero-sized accesses to that memory are invalid. //! * All accesses performed by functions in this module are *non-atomic* in the sense //! of [atomic operations] used to synchronize between threads. This means it is //! undefined behavior to perform two concurrent accesses to the same location from different From 0f572a9810e2c54b7067641583a5527acff6cae5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 13 Oct 2020 09:30:09 +0200 Subject: [PATCH 02/21] explicitly talk about integer literals --- library/alloc/src/boxed.rs | 6 +++--- library/core/src/ptr/mod.rs | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index c543ee2d0c581..7fd91aba321c5 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -63,9 +63,9 @@ //! [`Global`] allocator with [`Layout::for_value(&*value)`]. //! //! For zero-sized values, the `Box` pointer still has to be [valid] for reads and writes and -//! sufficiently aligned. In particular, casting any aligned non-zero integer to a raw pointer -//! produces a valid pointer, but a pointer pointing into previously allocated memory that since got -//! freed is not valid. +//! sufficiently aligned. In particular, casting any aligned non-zero integer literal to a raw +//! pointer produces a valid pointer, but a pointer pointing into previously allocated memory that +//! since got freed is not valid. //! //! So long as `T: Sized`, a `Box` is guaranteed to be represented //! as a single pointer and is also ABI-compatible with C pointers diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 453621d9eadff..243346a429a99 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -21,10 +21,10 @@ //! within the bounds of a single allocated object. Note that in Rust, //! every (stack-allocated) variable is considered a separate allocated object. //! * Even for operations of [size zero][zst], the pointer must not be "dangling" in the sense of -//! pointing to deallocated memory. However, casting any non-zero integer to a pointer is valid -//! for zero-sized accesses. This corresponds to writing your own allocator; allocating zero-sized -//! objects is not very hard. In contrast, when you use the standard allocator, after memory got -//! deallocated, even zero-sized accesses to that memory are invalid. +//! pointing to deallocated memory. However, casting any non-zero integer literal to a pointer is +//! valid for zero-sized accesses. This corresponds to writing your own allocator; allocating +//! zero-sized objects is not very hard. In contrast, when you use the standard allocator, after +//! memory got deallocated, even zero-sized accesses to that memory are invalid. //! * All accesses performed by functions in this module are *non-atomic* in the sense //! of [atomic operations] used to synchronize between threads. This means it is //! undefined behavior to perform two concurrent accesses to the same location from different From 071d8b14dab01f636aa4c8ec707a59a00bfa356d Mon Sep 17 00:00:00 2001 From: Hannah McLaughlin Date: Sun, 15 Nov 2020 20:45:52 +0000 Subject: [PATCH 03/21] Fix rustdoc: Referencing methods on extern_types does not resolve #78777: handle DefKind::ForeignTy variant --- src/librustdoc/passes/collect_intra_doc_links.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 895414b1d7e4c..fd09ba04b3db9 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -492,7 +492,14 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { Res::PrimTy(prim) => Some( self.resolve_primitive_associated_item(prim, ns, module_id, item_name, item_str), ), - Res::Def(DefKind::Struct | DefKind::Union | DefKind::Enum | DefKind::TyAlias, did) => { + Res::Def( + DefKind::Struct + | DefKind::Union + | DefKind::Enum + | DefKind::TyAlias + | DefKind::ForeignTy, + did, + ) => { debug!("looking for associated item named {} for item {:?}", item_name, did); // Checks if item_name belongs to `impl SomeItem` let assoc_item = cx From d38dbcb19f6ef1c5ffcf7869767674ef3d6d045f Mon Sep 17 00:00:00 2001 From: Hannah McLaughlin Date: Sun, 15 Nov 2020 21:14:00 +0000 Subject: [PATCH 04/21] Improve error message when we try to get_type on something that does not have a type --- compiler/rustc_metadata/src/rmeta/decoder.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index a1df1a63fc58d..19340dd51de14 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -947,7 +947,12 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } fn get_type(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { - self.root.tables.ty.get(self, id).unwrap().decode((self, tcx)) + self.root + .tables + .ty + .get(self, id) + .unwrap_or_else(|| panic!("Not a type: {:?}", id)) + .decode((self, tcx)) } fn get_stability(&self, id: DefIndex) -> Option { From 32cd4bc790ae8a4b0d7105e2a70de90616a5a621 Mon Sep 17 00:00:00 2001 From: Hannah McLaughlin Date: Wed, 18 Nov 2020 22:14:58 +0000 Subject: [PATCH 05/21] Add test --- src/test/rustdoc/intra-link-extern-type.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/test/rustdoc/intra-link-extern-type.rs diff --git a/src/test/rustdoc/intra-link-extern-type.rs b/src/test/rustdoc/intra-link-extern-type.rs new file mode 100644 index 0000000000000..418e0d91ea7ef --- /dev/null +++ b/src/test/rustdoc/intra-link-extern-type.rs @@ -0,0 +1,18 @@ +#![feature(extern_types)] + +extern { + pub type ExternType; +} + +impl ExternType { + pub fn f(&self) { + + } +} + +// @has 'intra_link_extern_type/foreigntype.ExternType.html' +// @has 'intra_link_extern_type/fn.links_to_extern_type.html' \ +// 'href="../intra_link_extern_type/foreigntype.ExternType.html#method.f"' +/// See also [ExternType::f] +pub fn links_to_extern_type() { +} From a7677f77146bd69b26b5fb5eaa8f88ac080ff347 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 20 Nov 2020 10:25:59 +0100 Subject: [PATCH 06/21] reference NonNull::dangling --- library/alloc/src/boxed.rs | 10 ++++++---- library/core/src/ptr/mod.rs | 11 ++++++----- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 7fd91aba321c5..9676572e45d3a 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -62,10 +62,12 @@ //! T` obtained from [`Box::::into_raw`] may be deallocated using the //! [`Global`] allocator with [`Layout::for_value(&*value)`]. //! -//! For zero-sized values, the `Box` pointer still has to be [valid] for reads and writes and -//! sufficiently aligned. In particular, casting any aligned non-zero integer literal to a raw -//! pointer produces a valid pointer, but a pointer pointing into previously allocated memory that -//! since got freed is not valid. +//! For zero-sized values, the `Box` pointer still has to be [valid] for reads +//! and writes and sufficiently aligned. In particular, casting any aligned +//! non-zero integer literal to a raw pointer produces a valid pointer, but a +//! pointer pointing into previously allocated memory that since got freed is +//! not valid. The recommended way to build a Box to a ZST if `Box::new` cannot +//! be used is to use [`ptr::NonNull::dangling`]. //! //! So long as `T: Sized`, a `Box` is guaranteed to be represented //! as a single pointer and is also ABI-compatible with C pointers diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 243346a429a99..6544dd4fd7a5e 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -20,11 +20,12 @@ //! be *dereferenceable*: the memory range of the given size starting at the pointer must all be //! within the bounds of a single allocated object. Note that in Rust, //! every (stack-allocated) variable is considered a separate allocated object. -//! * Even for operations of [size zero][zst], the pointer must not be "dangling" in the sense of -//! pointing to deallocated memory. However, casting any non-zero integer literal to a pointer is -//! valid for zero-sized accesses. This corresponds to writing your own allocator; allocating -//! zero-sized objects is not very hard. In contrast, when you use the standard allocator, after -//! memory got deallocated, even zero-sized accesses to that memory are invalid. +//! * Even for operations of [size zero][zst], the pointer must not be pointing to deallocated +//! memory, i.e., deallocation makes pointers invalid even for zero-sized operations. However, +//! casting any non-zero integer *literal* to a pointer is valid for zero-sized accesses, even if +//! some memory happens to exist at that address and gets deallocated. This corresponds to writing +//! your own allocator: allocating zero-sized objects is not very hard. The canonical way to +//! obtain a pointer that is valid for zero-sized accesses is [`NonNull::dangling`]. //! * All accesses performed by functions in this module are *non-atomic* in the sense //! of [atomic operations] used to synchronize between threads. This means it is //! undefined behavior to perform two concurrent accesses to the same location from different From 459c83f98026551bb0d3d86ede21e6d7424d375e Mon Sep 17 00:00:00 2001 From: Ngo Iok Ui Date: Fri, 20 Nov 2020 21:49:49 +0800 Subject: [PATCH 07/21] Exhaustively match in variant count instrinsic --- .../rustc_mir/src/interpret/intrinsics.rs | 17 ++++++++------- src/test/ui/consts/issue-79137-monomorphic.rs | 19 +++++++++++++++++ src/test/ui/consts/issue-79137-toogeneric.rs | 21 +++++++++++++++++++ .../ui/consts/issue-79137-toogeneric.stderr | 14 +++++++++++++ 4 files changed, 64 insertions(+), 7 deletions(-) create mode 100644 src/test/ui/consts/issue-79137-monomorphic.rs create mode 100644 src/test/ui/consts/issue-79137-toogeneric.rs create mode 100644 src/test/ui/consts/issue-79137-toogeneric.stderr diff --git a/compiler/rustc_mir/src/interpret/intrinsics.rs b/compiler/rustc_mir/src/interpret/intrinsics.rs index d3b6d706337ed..d4857e00d3aa5 100644 --- a/compiler/rustc_mir/src/interpret/intrinsics.rs +++ b/compiler/rustc_mir/src/interpret/intrinsics.rs @@ -75,13 +75,16 @@ crate fn eval_nullary_intrinsic<'tcx>( ensure_monomorphic_enough(tcx, tp_ty)?; ConstValue::from_u64(tcx.type_id_hash(tp_ty)) } - sym::variant_count => { - if let ty::Adt(ref adt, _) = tp_ty.kind() { - ConstValue::from_machine_usize(adt.variants.len() as u64, &tcx) - } else { - ConstValue::from_machine_usize(0u64, &tcx) - } - } + sym::variant_count => match tp_ty.kind() { + ty::Adt(ref adt, _) => ConstValue::from_machine_usize(adt.variants.len() as u64, &tcx), + ty::Projection(_) + | ty::Opaque(_, _) + | ty::Param(_) + | ty::Bound(_, _) + | ty::Placeholder(_) + | ty::Infer(_) => throw_inval!(TooGeneric), + _ => ConstValue::from_machine_usize(0u64, &tcx), + }, other => bug!("`{}` is not a zero arg intrinsic", other), }) } diff --git a/src/test/ui/consts/issue-79137-monomorphic.rs b/src/test/ui/consts/issue-79137-monomorphic.rs new file mode 100644 index 0000000000000..58e0c387ffb9c --- /dev/null +++ b/src/test/ui/consts/issue-79137-monomorphic.rs @@ -0,0 +1,19 @@ +// check-pass + +// Verify that variant count intrinsic can still evaluate for types like `Option`. + +#![feature(variant_count)] + +pub struct GetVariantCount(T); + +impl GetVariantCount { + pub const VALUE: usize = std::mem::variant_count::(); +} + +const fn check_variant_count() -> bool { + matches!(GetVariantCount::>::VALUE, GetVariantCount::>::VALUE) +} + +fn main() { + assert!(check_variant_count::<()>()); +} diff --git a/src/test/ui/consts/issue-79137-toogeneric.rs b/src/test/ui/consts/issue-79137-toogeneric.rs new file mode 100644 index 0000000000000..b2c62099de562 --- /dev/null +++ b/src/test/ui/consts/issue-79137-toogeneric.rs @@ -0,0 +1,21 @@ +// The instrinsic call for variant count should exhaustively match on `tp_ty` and forbid +// `ty::Projection`, `ty::Opaque`, `ty::Param`, `ty::Bound`, `ty::Placeholder` and `ty::Infer` +// variant. This test checks that it will fail if it's too generic. + +#![feature(variant_count)] + +pub struct GetVariantCount(T); + +impl GetVariantCount { + pub const VALUE: usize = std::mem::variant_count::(); +} + +const fn check_variant_count() -> bool { + matches!(GetVariantCount::::VALUE, GetVariantCount::::VALUE) + //~^ ERROR constant pattern depends on a generic parameter + //~| ERROR constant pattern depends on a generic parameter +} + +fn main() { + assert!(check_variant_count::>()); +} diff --git a/src/test/ui/consts/issue-79137-toogeneric.stderr b/src/test/ui/consts/issue-79137-toogeneric.stderr new file mode 100644 index 0000000000000..945bfa452c70c --- /dev/null +++ b/src/test/ui/consts/issue-79137-toogeneric.stderr @@ -0,0 +1,14 @@ +error: constant pattern depends on a generic parameter + --> $DIR/issue-79137-toogeneric.rs:14:43 + | +LL | matches!(GetVariantCount::::VALUE, GetVariantCount::::VALUE) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: constant pattern depends on a generic parameter + --> $DIR/issue-79137-toogeneric.rs:14:43 + | +LL | matches!(GetVariantCount::::VALUE, GetVariantCount::::VALUE) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + From 5ed2d4233472a37b1754804257930d29b5cd7b4b Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 20 Nov 2020 19:34:44 +0200 Subject: [PATCH 08/21] Direct RUSTC_LOG (tracing/log) output to stderr instead of stdout. --- compiler/rustc_driver/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index c544761255534..e49e456792b0d 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -1286,6 +1286,7 @@ pub fn init_env_logger(env: &str) { } let filter = tracing_subscriber::EnvFilter::from_env(env); let layer = tracing_tree::HierarchicalLayer::default() + .with_writer(io::stderr) .with_indent_lines(true) .with_ansi(true) .with_targets(true) From fac8b4e21a5621bb333d98a9ba15adc44e0284fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sat, 21 Nov 2020 00:00:00 +0000 Subject: [PATCH 09/21] Support building clone shims for arrays with generic size --- compiler/rustc_mir/src/shim.rs | 19 +++++++++++++------ .../array-clone-with-generic-size.rs | 13 +++++++++++++ 2 files changed, 26 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/mir/mir-inlining/array-clone-with-generic-size.rs diff --git a/compiler/rustc_mir/src/shim.rs b/compiler/rustc_mir/src/shim.rs index 3a1fa0018c104..aa5835686a291 100644 --- a/compiler/rustc_mir/src/shim.rs +++ b/compiler/rustc_mir/src/shim.rs @@ -308,10 +308,7 @@ fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) - match self_ty.kind() { _ if is_copy => builder.copy_shim(), - ty::Array(ty, len) => { - let len = len.eval_usize(tcx, param_env); - builder.array_shim(dest, src, ty, len) - } + ty::Array(ty, len) => builder.array_shim(dest, src, ty, len), ty::Closure(_, substs) => { builder.tuple_like_shim(dest, src, substs.as_closure().upvar_tys()) } @@ -485,7 +482,13 @@ impl CloneShimBuilder<'tcx> { } } - fn array_shim(&mut self, dest: Place<'tcx>, src: Place<'tcx>, ty: Ty<'tcx>, len: u64) { + fn array_shim( + &mut self, + dest: Place<'tcx>, + src: Place<'tcx>, + ty: Ty<'tcx>, + len: &'tcx ty::Const<'tcx>, + ) { let tcx = self.tcx; let span = self.span; @@ -503,7 +506,11 @@ impl CloneShimBuilder<'tcx> { ))), self.make_statement(StatementKind::Assign(box ( end, - Rvalue::Use(Operand::Constant(self.make_usize(len))), + Rvalue::Use(Operand::Constant(box Constant { + span: self.span, + user_ty: None, + literal: len, + })), ))), ]; self.block(inits, TerminatorKind::Goto { target: BasicBlock::new(1) }, false); diff --git a/src/test/ui/mir/mir-inlining/array-clone-with-generic-size.rs b/src/test/ui/mir/mir-inlining/array-clone-with-generic-size.rs new file mode 100644 index 0000000000000..8a96303e6b904 --- /dev/null +++ b/src/test/ui/mir/mir-inlining/array-clone-with-generic-size.rs @@ -0,0 +1,13 @@ +// Checks that we can build a clone shim for array with generic size. +// Regression test for issue #79269. +// +// build-pass +// compile-flags: -Zmir-opt-level=2 -Zvalidate-mir +#![feature(min_const_generics)] + +#[derive(Clone)] +struct Array([T; N]); + +fn main() { + let _ = Array([0u32, 1u32, 2u32]).clone(); +} From ef34e067817448d8ffbb9ac70e97699bf8b7566e Mon Sep 17 00:00:00 2001 From: Ngo Iok Ui Date: Sat, 21 Nov 2020 13:45:59 +0800 Subject: [PATCH 10/21] List all variants of TyKind --- .../rustc_mir/src/interpret/intrinsics.rs | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_mir/src/interpret/intrinsics.rs b/compiler/rustc_mir/src/interpret/intrinsics.rs index d4857e00d3aa5..f666a89ca56de 100644 --- a/compiler/rustc_mir/src/interpret/intrinsics.rs +++ b/compiler/rustc_mir/src/interpret/intrinsics.rs @@ -83,7 +83,26 @@ crate fn eval_nullary_intrinsic<'tcx>( | ty::Bound(_, _) | ty::Placeholder(_) | ty::Infer(_) => throw_inval!(TooGeneric), - _ => ConstValue::from_machine_usize(0u64, &tcx), + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Foreign(_) + | ty::Str + | ty::Array(_, _) + | ty::Slice(_) + | ty::RawPtr(_) + | ty::Ref(_, _, _) + | ty::FnDef(_, _) + | ty::FnPtr(_) + | ty::Dynamic(_, _) + | ty::Closure(_, _) + | ty::Generator(_, _, _) + | ty::GeneratorWitness(_) + | ty::Never + | ty::Tuple(_) + | ty::Error(_) => ConstValue::from_machine_usize(0u64, &tcx), }, other => bug!("`{}` is not a zero arg intrinsic", other), }) From bc43380297c38f8cc888ce3e92fe20de9afbe50e Mon Sep 17 00:00:00 2001 From: Ngo Iok Ui Date: Sat, 21 Nov 2020 13:47:09 +0800 Subject: [PATCH 11/21] Fix comments of toogeneris test --- src/test/ui/consts/issue-79137-toogeneric.rs | 4 +--- src/test/ui/consts/issue-79137-toogeneric.stderr | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/test/ui/consts/issue-79137-toogeneric.rs b/src/test/ui/consts/issue-79137-toogeneric.rs index b2c62099de562..456035458cfc5 100644 --- a/src/test/ui/consts/issue-79137-toogeneric.rs +++ b/src/test/ui/consts/issue-79137-toogeneric.rs @@ -1,6 +1,4 @@ -// The instrinsic call for variant count should exhaustively match on `tp_ty` and forbid -// `ty::Projection`, `ty::Opaque`, `ty::Param`, `ty::Bound`, `ty::Placeholder` and `ty::Infer` -// variant. This test checks that it will fail if it's too generic. +// Test that `variant_count` only gets evaluated once the type is concrete enough. #![feature(variant_count)] diff --git a/src/test/ui/consts/issue-79137-toogeneric.stderr b/src/test/ui/consts/issue-79137-toogeneric.stderr index 945bfa452c70c..579e6aa09bdbd 100644 --- a/src/test/ui/consts/issue-79137-toogeneric.stderr +++ b/src/test/ui/consts/issue-79137-toogeneric.stderr @@ -1,11 +1,11 @@ error: constant pattern depends on a generic parameter - --> $DIR/issue-79137-toogeneric.rs:14:43 + --> $DIR/issue-79137-toogeneric.rs:12:43 | LL | matches!(GetVariantCount::::VALUE, GetVariantCount::::VALUE) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: constant pattern depends on a generic parameter - --> $DIR/issue-79137-toogeneric.rs:14:43 + --> $DIR/issue-79137-toogeneric.rs:12:43 | LL | matches!(GetVariantCount::::VALUE, GetVariantCount::::VALUE) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ From db8b86b2df5646b00278720187a460a0027b107f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Sat, 21 Nov 2020 09:06:45 +0100 Subject: [PATCH 12/21] Fix typos --- compiler/rustc_query_system/src/query/job.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index c1d3210b61768..5fed500390b68 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -33,11 +33,11 @@ pub struct QueryInfo { pub(crate) type QueryMap = FxHashMap, QueryJobInfo>; -/// A value uniquely identifiying an active query job within a shard in the query cache. +/// A value uniquely identifying an active query job within a shard in the query cache. #[derive(Copy, Clone, Eq, PartialEq, Hash)] pub struct QueryShardJobId(pub NonZeroU32); -/// A value uniquely identifiying an active query job. +/// A value uniquely identifying an active query job. #[derive(Copy, Clone, Eq, PartialEq, Hash)] pub struct QueryJobId { /// Which job within a shard is this @@ -536,7 +536,7 @@ fn remove_cycle( }; // We unwrap `waiter` here since there must always be one - // edge which is resumeable / waited using a query latch + // edge which is resumable / waited using a query latch let (waitee_query, waiter_idx) = waiter.unwrap(); // Extract the waiter we want to resume From 0459aca41a31213f18471aeafe246cd20cc846e9 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Fri, 20 Nov 2020 23:50:13 -0500 Subject: [PATCH 13/21] Get rid of some doctree items They can be derived directly from the `hir::Item`, there's no special logic. - TypeDef - OpaqueTy - Constant - Static - TraitAlias - Enum - Union - Struct --- src/librustdoc/clean/mod.rs | 181 ++++++++++++------------------------ src/librustdoc/doctree.rs | 80 +--------------- src/librustdoc/visit_ast.rs | 91 ++---------------- 3 files changed, 71 insertions(+), 281 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 9d84089eb405c..5bc30357f62a5 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -231,21 +231,14 @@ impl Clean for doctree::Module<'_> { let mut items: Vec = vec![]; items.extend(self.extern_crates.iter().flat_map(|x| x.clean(cx))); items.extend(self.imports.iter().flat_map(|x| x.clean(cx))); - items.extend(self.structs.iter().map(|x| x.clean(cx))); - items.extend(self.unions.iter().map(|x| x.clean(cx))); - items.extend(self.enums.iter().map(|x| x.clean(cx))); items.extend(self.fns.iter().map(|x| x.clean(cx))); items.extend(self.foreigns.iter().map(|x| x.clean(cx))); items.extend(self.mods.iter().map(|x| x.clean(cx))); - items.extend(self.typedefs.iter().map(|x| x.clean(cx))); - items.extend(self.opaque_tys.iter().map(|x| x.clean(cx))); - items.extend(self.statics.iter().map(|x| x.clean(cx))); - items.extend(self.constants.iter().map(|x| x.clean(cx))); + items.extend(self.items.iter().map(|x| x.clean(cx))); items.extend(self.traits.iter().map(|x| x.clean(cx))); items.extend(self.impls.iter().flat_map(|x| x.clean(cx))); items.extend(self.macros.iter().map(|x| x.clean(cx))); items.extend(self.proc_macros.iter().map(|x| x.clean(cx))); - items.extend(self.trait_aliases.iter().map(|x| x.clean(cx))); // determine if we should display the inner contents or // the outer `mod` item for the source code. @@ -1020,20 +1013,6 @@ impl Clean for doctree::Trait<'_> { } } -impl Clean for doctree::TraitAlias<'_> { - fn clean(&self, cx: &DocContext<'_>) -> Item { - Item::from_hir_id_and_parts( - self.id, - Some(self.name), - TraitAliasItem(TraitAlias { - generics: self.generics.clean(cx), - bounds: self.bounds.clean(cx), - }), - cx, - ) - } -} - impl Clean for hir::IsAuto { fn clean(&self, _: &DocContext<'_>) -> bool { match *self { @@ -1777,38 +1756,6 @@ impl Clean for ty::Visibility { } } -impl Clean for doctree::Struct<'_> { - fn clean(&self, cx: &DocContext<'_>) -> Item { - Item::from_hir_id_and_parts( - self.id, - Some(self.name), - StructItem(Struct { - struct_type: self.struct_type, - generics: self.generics.clean(cx), - fields: self.fields.clean(cx), - fields_stripped: false, - }), - cx, - ) - } -} - -impl Clean for doctree::Union<'_> { - fn clean(&self, cx: &DocContext<'_>) -> Item { - Item::from_hir_id_and_parts( - self.id, - Some(self.name), - UnionItem(Union { - struct_type: self.struct_type, - generics: self.generics.clean(cx), - fields: self.fields.clean(cx), - fields_stripped: false, - }), - cx, - ) - } -} - impl Clean for rustc_hir::VariantData<'_> { fn clean(&self, cx: &DocContext<'_>) -> VariantStruct { VariantStruct { @@ -1819,21 +1766,6 @@ impl Clean for rustc_hir::VariantData<'_> { } } -impl Clean for doctree::Enum<'_> { - fn clean(&self, cx: &DocContext<'_>) -> Item { - Item::from_hir_id_and_parts( - self.id, - Some(self.name), - EnumItem(Enum { - variants: self.variants.iter().map(|v| v.clean(cx)).collect(), - generics: self.generics.clean(cx), - variants_stripped: false, - }), - cx, - ) - } -} - impl Clean for doctree::Variant<'_> { fn clean(&self, cx: &DocContext<'_>) -> Item { let what_rustc_thinks = Item::from_hir_id_and_parts( @@ -1981,33 +1913,6 @@ impl Clean for Symbol { } } -impl Clean for doctree::Typedef<'_> { - fn clean(&self, cx: &DocContext<'_>) -> Item { - let type_ = self.ty.clean(cx); - let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did)); - Item::from_hir_id_and_parts( - self.id, - Some(self.name), - TypedefItem(Typedef { type_, generics: self.gen.clean(cx), item_type }, false), - cx, - ) - } -} - -impl Clean for doctree::OpaqueTy<'_> { - fn clean(&self, cx: &DocContext<'_>) -> Item { - Item::from_hir_id_and_parts( - self.id, - Some(self.name), - OpaqueTyItem(OpaqueTy { - bounds: self.opaque_ty.bounds.clean(cx), - generics: self.opaque_ty.generics.clean(cx), - }), - cx, - ) - } -} - impl Clean for hir::BareFnTy<'_> { fn clean(&self, cx: &DocContext<'_>) -> BareFunctionDecl { let (generic_params, decl) = enter_impl_trait(cx, || { @@ -2017,37 +1922,71 @@ impl Clean for hir::BareFnTy<'_> { } } -impl Clean for doctree::Static<'_> { +impl Clean for hir::Item<'_> { fn clean(&self, cx: &DocContext<'_>) -> Item { - debug!("cleaning static {}: {:?}", self.name.clean(cx), self); - Item::from_hir_id_and_parts( - self.id, - Some(self.name), - StaticItem(Static { - type_: self.type_.clean(cx), - mutability: self.mutability, - expr: print_const_expr(cx, self.expr), + use hir::ItemKind; + + let def_id = cx.tcx.hir().local_def_id(self.hir_id).to_def_id(); + let name = cx.tcx.hir().name(self.hir_id); + let kind = match self.kind { + ItemKind::Static(ty, mutability, body_id) => StaticItem(Static { + type_: ty.clean(cx), + mutability, + expr: print_const_expr(cx, body_id), }), - cx, - ) + ItemKind::Const(ty, body_id) => ConstantItem(Constant { + type_: ty.clean(cx), + expr: print_const_expr(cx, body_id), + value: print_evaluated_const(cx, def_id), + is_literal: is_literal_expr(cx, body_id.hir_id), + }), + ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy { + bounds: ty.bounds.clean(cx), + generics: ty.generics.clean(cx), + }), + ItemKind::TyAlias(ty, ref generics) => { + let rustdoc_ty = ty.clean(cx); + let item_type = rustdoc_ty.def_id().and_then(|did| inline::build_ty(cx, did)); + TypedefItem( + Typedef { type_: rustdoc_ty, generics: generics.clean(cx), item_type }, + false, + ) + } + ItemKind::Enum(ref def, ref generics) => EnumItem(Enum { + variants: def.variants.iter().map(|v| v.clean(cx)).collect(), + generics: generics.clean(cx), + variants_stripped: false, + }), + ItemKind::TraitAlias(ref generics, bounds) => TraitAliasItem(TraitAlias { + generics: generics.clean(cx), + bounds: bounds.clean(cx), + }), + ItemKind::Union(ref variant_data, ref generics) => UnionItem(Union { + struct_type: doctree::struct_type_from_def(&variant_data), + generics: generics.clean(cx), + fields: variant_data.fields().clean(cx), + fields_stripped: false, + }), + ItemKind::Struct(ref variant_data, ref generics) => StructItem(Struct { + struct_type: doctree::struct_type_from_def(&variant_data), + generics: generics.clean(cx), + fields: variant_data.fields().clean(cx), + fields_stripped: false, + }), + _ => unreachable!("not yet converted"), + }; + + Item::from_def_id_and_parts(def_id, Some(name), kind, cx) } } -impl Clean for doctree::Constant<'_> { +impl Clean for hir::Variant<'_> { fn clean(&self, cx: &DocContext<'_>) -> Item { - let def_id = cx.tcx.hir().local_def_id(self.id).to_def_id(); - - Item::from_def_id_and_parts( - def_id, - Some(self.name), - ConstantItem(Constant { - type_: self.type_.clean(cx), - expr: print_const_expr(cx, self.expr), - value: print_evaluated_const(cx, def_id), - is_literal: is_literal_expr(cx, self.expr.hir_id), - }), - cx, - ) + let kind = VariantItem(Variant { kind: self.data.clean(cx) }); + let what_rustc_thinks = + Item::from_hir_id_and_parts(self.id, Some(self.ident.name), kind, cx); + // don't show `pub` for variants, which are always public + Item { visibility: Inherited, ..what_rustc_thinks } } } diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index bd9262191356f..69baffcc6131b 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -17,22 +17,15 @@ crate struct Module<'hir> { crate where_inner: Span, crate extern_crates: Vec>, crate imports: Vec>, - crate structs: Vec>, - crate unions: Vec>, - crate enums: Vec>, crate fns: Vec>, crate mods: Vec>, crate id: hir::HirId, - crate typedefs: Vec>, - crate opaque_tys: Vec>, - crate statics: Vec>, - crate constants: Vec>, + crate items: Vec<&'hir hir::Item<'hir>>, crate traits: Vec>, crate impls: Vec>, crate foreigns: Vec>, crate macros: Vec, crate proc_macros: Vec, - crate trait_aliases: Vec>, crate is_crate: bool, } @@ -46,21 +39,14 @@ impl Module<'hir> { attrs, extern_crates: Vec::new(), imports: Vec::new(), - structs: Vec::new(), - unions: Vec::new(), - enums: Vec::new(), fns: Vec::new(), mods: Vec::new(), - typedefs: Vec::new(), - opaque_tys: Vec::new(), - statics: Vec::new(), - constants: Vec::new(), + items: Vec::new(), traits: Vec::new(), impls: Vec::new(), foreigns: Vec::new(), macros: Vec::new(), proc_macros: Vec::new(), - trait_aliases: Vec::new(), is_crate: false, } } @@ -76,29 +62,6 @@ crate enum StructType { Unit, } -crate struct Struct<'hir> { - crate id: hir::HirId, - crate struct_type: StructType, - crate name: Symbol, - crate generics: &'hir hir::Generics<'hir>, - crate fields: &'hir [hir::StructField<'hir>], -} - -crate struct Union<'hir> { - crate id: hir::HirId, - crate struct_type: StructType, - crate name: Symbol, - crate generics: &'hir hir::Generics<'hir>, - crate fields: &'hir [hir::StructField<'hir>], -} - -crate struct Enum<'hir> { - crate variants: Vec>, - crate generics: &'hir hir::Generics<'hir>, - crate id: hir::HirId, - crate name: Symbol, -} - crate struct Variant<'hir> { crate name: Symbol, crate id: hir::HirId, @@ -114,38 +77,6 @@ crate struct Function<'hir> { crate body: hir::BodyId, } -crate struct Typedef<'hir> { - crate ty: &'hir hir::Ty<'hir>, - crate gen: &'hir hir::Generics<'hir>, - crate name: Symbol, - crate id: hir::HirId, -} - -crate struct OpaqueTy<'hir> { - crate opaque_ty: &'hir hir::OpaqueTy<'hir>, - crate name: Symbol, - crate id: hir::HirId, -} - -#[derive(Debug)] -crate struct Static<'hir> { - crate type_: &'hir hir::Ty<'hir>, - crate mutability: hir::Mutability, - crate expr: hir::BodyId, - crate name: Symbol, - crate attrs: &'hir [ast::Attribute], - crate vis: &'hir hir::Visibility<'hir>, - crate id: hir::HirId, - crate span: Span, -} - -crate struct Constant<'hir> { - crate type_: &'hir hir::Ty<'hir>, - crate expr: hir::BodyId, - crate name: Symbol, - crate id: hir::HirId, -} - crate struct Trait<'hir> { crate is_auto: hir::IsAuto, crate unsafety: hir::Unsafety, @@ -157,13 +88,6 @@ crate struct Trait<'hir> { crate id: hir::HirId, } -crate struct TraitAlias<'hir> { - crate name: Symbol, - crate generics: &'hir hir::Generics<'hir>, - crate bounds: &'hir [hir::GenericBound<'hir>], - crate id: hir::HirId, -} - #[derive(Debug)] crate struct Impl<'hir> { crate unsafety: hir::Unsafety, diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 76fae11291805..fc42ef79dcc9e 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -82,50 +82,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { module } - fn visit_variant_data( - &mut self, - item: &'tcx hir::Item<'_>, - name: Symbol, - sd: &'tcx hir::VariantData<'_>, - generics: &'tcx hir::Generics<'_>, - ) -> Struct<'tcx> { - debug!("visiting struct"); - let struct_type = struct_type_from_def(&*sd); - Struct { id: item.hir_id, struct_type, name, generics, fields: sd.fields() } - } - - fn visit_union_data( - &mut self, - item: &'tcx hir::Item<'_>, - name: Symbol, - sd: &'tcx hir::VariantData<'_>, - generics: &'tcx hir::Generics<'_>, - ) -> Union<'tcx> { - debug!("visiting union"); - let struct_type = struct_type_from_def(&*sd); - Union { id: item.hir_id, struct_type, name, generics, fields: sd.fields() } - } - - fn visit_enum_def( - &mut self, - it: &'tcx hir::Item<'_>, - name: Symbol, - def: &'tcx hir::EnumDef<'_>, - generics: &'tcx hir::Generics<'_>, - ) -> Enum<'tcx> { - debug!("visiting enum"); - Enum { - name, - variants: def - .variants - .iter() - .map(|v| Variant { name: v.ident.name, id: v.id, def: &v.data }) - .collect(), - generics, - id: it.hir_id, - } - } - fn visit_fn( &mut self, om: &mut Module<'tcx>, @@ -414,45 +370,21 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { Some(ident.name), )); } - hir::ItemKind::Enum(ref ed, ref gen) => { - om.enums.push(self.visit_enum_def(item, ident.name, ed, gen)) - } - hir::ItemKind::Struct(ref sd, ref gen) => { - om.structs.push(self.visit_variant_data(item, ident.name, sd, gen)) - } - hir::ItemKind::Union(ref sd, ref gen) => { - om.unions.push(self.visit_union_data(item, ident.name, sd, gen)) - } + hir::ItemKind::Enum(..) => om.items.push(item), + hir::ItemKind::Struct(..) => om.items.push(item), + hir::ItemKind::Union(..) => om.items.push(item), hir::ItemKind::Fn(ref sig, ref gen, body) => { self.visit_fn(om, item, ident.name, &sig.decl, sig.header, gen, body) } - hir::ItemKind::TyAlias(ty, ref gen) => { - let t = Typedef { ty, gen, name: ident.name, id: item.hir_id }; - om.typedefs.push(t); - } - hir::ItemKind::OpaqueTy(ref opaque_ty) => { - let t = OpaqueTy { opaque_ty, name: ident.name, id: item.hir_id }; - om.opaque_tys.push(t); - } - hir::ItemKind::Static(type_, mutability, expr) => { - let s = Static { - type_, - mutability, - expr, - id: item.hir_id, - name: ident.name, - attrs: &item.attrs, - span: item.span, - vis: &item.vis, - }; - om.statics.push(s); - } - hir::ItemKind::Const(type_, expr) => { + hir::ItemKind::TyAlias(..) + | hir::ItemKind::OpaqueTy(..) + | hir::ItemKind::Static(..) + | hir::ItemKind::TraitAlias(..) => om.items.push(item), + hir::ItemKind::Const(..) => { // Underscore constants do not correspond to a nameable item and // so are never useful in documentation. if ident.name != kw::Underscore { - let s = Constant { type_, expr, id: item.hir_id, name: ident.name }; - om.constants.push(s); + om.items.push(item); } } hir::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref item_ids) => { @@ -469,11 +401,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { }; om.traits.push(t); } - hir::ItemKind::TraitAlias(ref generics, ref bounds) => { - let t = TraitAlias { name: ident.name, generics, bounds, id: item.hir_id }; - om.trait_aliases.push(t); - } - hir::ItemKind::Impl { unsafety, polarity, From 8c94f8be992719a6e6652018e39a653366b4227f Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sat, 21 Nov 2020 10:16:07 -0500 Subject: [PATCH 14/21] Add more tests for renamed items --- src/test/rustdoc/redirect-rename.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/test/rustdoc/redirect-rename.rs b/src/test/rustdoc/redirect-rename.rs index 7de56080e52b9..504c0687c8dc2 100644 --- a/src/test/rustdoc/redirect-rename.rs +++ b/src/test/rustdoc/redirect-rename.rs @@ -4,6 +4,10 @@ mod hidden { // @has foo/hidden/struct.Foo.html // @has - '//p/a' '../../foo/struct.FooBar.html' pub struct Foo {} + pub union U { a: usize } + pub enum Empty {} + pub const C: usize = 1; + pub static S: usize = 1; // @has foo/hidden/bar/index.html // @has - '//p/a' '../../foo/baz/index.html' @@ -16,6 +20,14 @@ mod hidden { // @has foo/struct.FooBar.html pub use hidden::Foo as FooBar; +// @has foo/union.FooU.html +pub use hidden::U as FooU; +// @has foo/enum.FooEmpty.html +pub use hidden::Empty as FooEmpty; +// @has foo/constant.FooC.html +pub use hidden::C as FooC; +// @has foo/static.FooS.html +pub use hidden::S as FooS; // @has foo/baz/index.html // @has foo/baz/struct.Thing.html From 788840612e9da529158ada25d2160ca07d5a8dc9 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sat, 21 Nov 2020 10:10:03 -0500 Subject: [PATCH 15/21] Fix wrong names when inlining --- src/librustdoc/clean/mod.rs | 12 ++++++++---- src/librustdoc/doctree.rs | 5 +++-- src/librustdoc/visit_ast.rs | 12 ++++++------ 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 5bc30357f62a5..d58a88957df22 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1922,13 +1922,17 @@ impl Clean for hir::BareFnTy<'_> { } } -impl Clean for hir::Item<'_> { +impl Clean for (&hir::Item<'_>, Option) { fn clean(&self, cx: &DocContext<'_>) -> Item { use hir::ItemKind; - let def_id = cx.tcx.hir().local_def_id(self.hir_id).to_def_id(); - let name = cx.tcx.hir().name(self.hir_id); - let kind = match self.kind { + let (item, renamed) = self; + let def_id = cx.tcx.hir().local_def_id(item.hir_id).to_def_id(); + let name = match renamed { + Some(ident) => ident.name, + None => cx.tcx.hir().name(item.hir_id), + }; + let kind = match item.kind { ItemKind::Static(ty, mutability, body_id) => StaticItem(Static { type_: ty.clean(cx), mutability, diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index 69baffcc6131b..d56328cc2aa08 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -4,7 +4,7 @@ crate use self::StructType::*; use rustc_ast as ast; use rustc_span::hygiene::MacroKind; -use rustc_span::{self, Span, Symbol}; +use rustc_span::{self, symbol::Ident, Span, Symbol}; use rustc_hir as hir; use rustc_hir::def_id::CrateNum; @@ -20,7 +20,8 @@ crate struct Module<'hir> { crate fns: Vec>, crate mods: Vec>, crate id: hir::HirId, - crate items: Vec<&'hir hir::Item<'hir>>, + // (item, renamed) + crate items: Vec<(&'hir hir::Item<'hir>, Option)>, crate traits: Vec>, crate impls: Vec>, crate foreigns: Vec>, diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index fc42ef79dcc9e..c55e5f7690c14 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -370,21 +370,21 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { Some(ident.name), )); } - hir::ItemKind::Enum(..) => om.items.push(item), - hir::ItemKind::Struct(..) => om.items.push(item), - hir::ItemKind::Union(..) => om.items.push(item), hir::ItemKind::Fn(ref sig, ref gen, body) => { self.visit_fn(om, item, ident.name, &sig.decl, sig.header, gen, body) } - hir::ItemKind::TyAlias(..) + hir::ItemKind::Enum(..) + | hir::ItemKind::Struct(..) + | hir::ItemKind::Union(..) + | hir::ItemKind::TyAlias(..) | hir::ItemKind::OpaqueTy(..) | hir::ItemKind::Static(..) - | hir::ItemKind::TraitAlias(..) => om.items.push(item), + | hir::ItemKind::TraitAlias(..) => om.items.push((item, renamed)), hir::ItemKind::Const(..) => { // Underscore constants do not correspond to a nameable item and // so are never useful in documentation. if ident.name != kw::Underscore { - om.items.push(item); + om.items.push((item, renamed)); } } hir::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref item_ids) => { From e280ae862c735a0bc74b7f4f479459eefb9f9b65 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sat, 21 Nov 2020 11:08:58 -0500 Subject: [PATCH 16/21] x.py test --bless --- .../rustdoc-ui/doc-without-codeblock.stderr | 12 +- .../rustdoc-ui/intra-links-ambiguity.stderr | 38 +++--- .../rustdoc-ui/intra-links-warning.stderr | 108 +++++++++--------- .../lint-missing-doc-code-example.stderr | 28 ++--- 4 files changed, 93 insertions(+), 93 deletions(-) diff --git a/src/test/rustdoc-ui/doc-without-codeblock.stderr b/src/test/rustdoc-ui/doc-without-codeblock.stderr index f2b2328322a7b..3372304f44a3d 100644 --- a/src/test/rustdoc-ui/doc-without-codeblock.stderr +++ b/src/test/rustdoc-ui/doc-without-codeblock.stderr @@ -16,12 +16,6 @@ note: the lint level is defined here LL | #![deny(missing_doc_code_examples)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: missing code example in this documentation - --> $DIR/doc-without-codeblock.rs:3:1 - | -LL | /// Some docs. - | ^^^^^^^^^^^^^^ - error: missing code example in this documentation --> $DIR/doc-without-codeblock.rs:7:1 | @@ -34,5 +28,11 @@ error: missing code example in this documentation LL | /// Or maybe not because she saved herself! | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: missing code example in this documentation + --> $DIR/doc-without-codeblock.rs:3:1 + | +LL | /// Some docs. + | ^^^^^^^^^^^^^^ + error: aborting due to 4 previous errors diff --git a/src/test/rustdoc-ui/intra-links-ambiguity.stderr b/src/test/rustdoc-ui/intra-links-ambiguity.stderr index 21b92a9673755..936055da01cf7 100644 --- a/src/test/rustdoc-ui/intra-links-ambiguity.stderr +++ b/src/test/rustdoc-ui/intra-links-ambiguity.stderr @@ -1,14 +1,29 @@ -error: `ambiguous` is both a struct and a function - --> $DIR/intra-links-ambiguity.rs:27:6 +error: `true` is both a module and a builtin type + --> $DIR/intra-links-ambiguity.rs:38:6 | -LL | /// [`ambiguous`] is ambiguous. - | ^^^^^^^^^^^ ambiguous link +LL | /// [true] + | ^^^^ ambiguous link | note: the lint level is defined here --> $DIR/intra-links-ambiguity.rs:1:9 | LL | #![deny(broken_intra_doc_links)] | ^^^^^^^^^^^^^^^^^^^^^^ +help: to link to the module, prefix with `mod@` + | +LL | /// [mod@true] + | ^^^^^^^^ +help: to link to the builtin type, prefix with `prim@` + | +LL | /// [prim@true] + | ^^^^^^^^^ + +error: `ambiguous` is both a struct and a function + --> $DIR/intra-links-ambiguity.rs:27:6 + | +LL | /// [`ambiguous`] is ambiguous. + | ^^^^^^^^^^^ ambiguous link + | help: to link to the struct, prefix with `struct@` | LL | /// [`struct@ambiguous`] is ambiguous. @@ -82,20 +97,5 @@ help: to link to the function, add parentheses LL | /// Ambiguous non-implied shortcut link [`foo::bar()`]. | ^^^^^^^^^^^^ -error: `true` is both a module and a builtin type - --> $DIR/intra-links-ambiguity.rs:38:6 - | -LL | /// [true] - | ^^^^ ambiguous link - | -help: to link to the module, prefix with `mod@` - | -LL | /// [mod@true] - | ^^^^^^^^ -help: to link to the builtin type, prefix with `prim@` - | -LL | /// [prim@true] - | ^^^^^^^^^ - error: aborting due to 6 previous errors diff --git a/src/test/rustdoc-ui/intra-links-warning.stderr b/src/test/rustdoc-ui/intra-links-warning.stderr index 4cdb8bbdde782..bf437a7cf4674 100644 --- a/src/test/rustdoc-ui/intra-links-warning.stderr +++ b/src/test/rustdoc-ui/intra-links-warning.stderr @@ -36,6 +36,60 @@ warning: unresolved link to `Qux::Z` LL | //! , [Uniooon::X] and [Qux::Z]. | ^^^^^^ no item named `Qux` in scope +warning: unresolved link to `BarA` + --> $DIR/intra-links-warning.rs:21:10 + | +LL | /// bar [BarA] bar + | ^^^^ no item named `BarA` in scope + | + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` + +warning: unresolved link to `BarB` + --> $DIR/intra-links-warning.rs:27:9 + | +LL | * bar [BarB] bar + | ^^^^ no item named `BarB` in scope + | + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` + +warning: unresolved link to `BarC` + --> $DIR/intra-links-warning.rs:34:6 + | +LL | bar [BarC] bar + | ^^^^ no item named `BarC` in scope + | + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` + +warning: unresolved link to `BarD` + --> $DIR/intra-links-warning.rs:45:1 + | +LL | #[doc = "Foo\nbar [BarD] bar\nbaz"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the link appears in this line: + + bar [BarD] bar + ^^^^ + = note: no item named `BarD` in scope + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` + +warning: unresolved link to `BarF` + --> $DIR/intra-links-warning.rs:50:9 + | +LL | #[doc = $f] + | ^^^^^^^^^^^ +... +LL | f!("Foo\nbar [BarF] bar\nbaz"); + | ------------------------------- in this macro invocation + | + = note: the link appears in this line: + + bar [BarF] bar + ^^^^ + = note: no item named `BarF` in scope + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` + = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + warning: unresolved link to `Qux:Y` --> $DIR/intra-links-warning.rs:14:13 | @@ -117,59 +171,5 @@ LL | /// docs [error2] | = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` -warning: unresolved link to `BarA` - --> $DIR/intra-links-warning.rs:21:10 - | -LL | /// bar [BarA] bar - | ^^^^ no item named `BarA` in scope - | - = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` - -warning: unresolved link to `BarB` - --> $DIR/intra-links-warning.rs:27:9 - | -LL | * bar [BarB] bar - | ^^^^ no item named `BarB` in scope - | - = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` - -warning: unresolved link to `BarC` - --> $DIR/intra-links-warning.rs:34:6 - | -LL | bar [BarC] bar - | ^^^^ no item named `BarC` in scope - | - = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` - -warning: unresolved link to `BarD` - --> $DIR/intra-links-warning.rs:45:1 - | -LL | #[doc = "Foo\nbar [BarD] bar\nbaz"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the link appears in this line: - - bar [BarD] bar - ^^^^ - = note: no item named `BarD` in scope - = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` - -warning: unresolved link to `BarF` - --> $DIR/intra-links-warning.rs:50:9 - | -LL | #[doc = $f] - | ^^^^^^^^^^^ -... -LL | f!("Foo\nbar [BarF] bar\nbaz"); - | ------------------------------- in this macro invocation - | - = note: the link appears in this line: - - bar [BarF] bar - ^^^^ - = note: no item named `BarF` in scope - = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` - = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) - warning: 19 warnings emitted diff --git a/src/test/rustdoc-ui/lint-missing-doc-code-example.stderr b/src/test/rustdoc-ui/lint-missing-doc-code-example.stderr index 32756c99e7f9f..e02ed4a056c12 100644 --- a/src/test/rustdoc-ui/lint-missing-doc-code-example.stderr +++ b/src/test/rustdoc-ui/lint-missing-doc-code-example.stderr @@ -1,8 +1,9 @@ error: missing code example in this documentation - --> $DIR/lint-missing-doc-code-example.rs:49:1 + --> $DIR/lint-missing-doc-code-example.rs:19:1 | -LL | /// Doc - | ^^^^^^^ +LL | / mod module1 { +LL | | } + | |_^ | note: the lint level is defined here --> $DIR/lint-missing-doc-code-example.rs:2:9 @@ -11,29 +12,28 @@ LL | #![deny(missing_doc_code_examples)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: missing code example in this documentation - --> $DIR/lint-missing-doc-code-example.rs:63:1 + --> $DIR/lint-missing-doc-code-example.rs:37:3 | -LL | /// Doc - | ^^^^^^^ +LL | /// doc + | ^^^^^^^ error: missing code example in this documentation - --> $DIR/lint-missing-doc-code-example.rs:56:1 + --> $DIR/lint-missing-doc-code-example.rs:49:1 | LL | /// Doc | ^^^^^^^ error: missing code example in this documentation - --> $DIR/lint-missing-doc-code-example.rs:19:1 + --> $DIR/lint-missing-doc-code-example.rs:56:1 | -LL | / mod module1 { -LL | | } - | |_^ +LL | /// Doc + | ^^^^^^^ error: missing code example in this documentation - --> $DIR/lint-missing-doc-code-example.rs:37:3 + --> $DIR/lint-missing-doc-code-example.rs:63:1 | -LL | /// doc - | ^^^^^^^ +LL | /// Doc + | ^^^^^^^ error: aborting due to 5 previous errors From 967a228208a88791c66a4ee3ee72cc75fa2b7fbc Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 14 Nov 2020 12:27:57 +0100 Subject: [PATCH 17/21] Replace ZExt and SExt flags with ArgExtension enum Both flags are mutually exclusive --- compiler/rustc_codegen_llvm/src/abi.rs | 20 +++++++++++- compiler/rustc_middle/src/ty/layout.rs | 2 +- compiler/rustc_target/src/abi/call/mips64.rs | 4 +-- compiler/rustc_target/src/abi/call/mod.rs | 32 ++++++++++++++++++-- compiler/rustc_target/src/abi/call/riscv.rs | 4 +-- 5 files changed, 53 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index 7857ccb613bf8..3ca0a9ce8d983 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -36,7 +36,7 @@ impl ArgAttributeExt for ArgAttribute { where F: FnMut(llvm::Attribute), { - for_each_kind!(self, f, NoAlias, NoCapture, NonNull, ReadOnly, SExt, StructRet, ZExt, InReg) + for_each_kind!(self, f, NoAlias, NoCapture, NonNull, ReadOnly, StructRet, InReg) } } @@ -65,6 +65,15 @@ impl ArgAttributesExt for ArgAttributes { llvm::LLVMRustAddByValAttr(llfn, idx.as_uint(), ty.unwrap()); } regular.for_each_kind(|attr| attr.apply_llfn(idx, llfn)); + match self.arg_ext { + ArgExtension::None => {} + ArgExtension::Zext => { + llvm::Attribute::ZExt.apply_llfn(idx, llfn); + } + ArgExtension::Sext => { + llvm::Attribute::SExt.apply_llfn(idx, llfn); + } + } } } @@ -95,6 +104,15 @@ impl ArgAttributesExt for ArgAttributes { llvm::LLVMRustAddByValCallSiteAttr(callsite, idx.as_uint(), ty.unwrap()); } regular.for_each_kind(|attr| attr.apply_callsite(idx, callsite)); + match self.arg_ext { + ArgExtension::None => {} + ArgExtension::Zext => { + llvm::Attribute::ZExt.apply_callsite(idx, callsite); + } + ArgExtension::Sext => { + llvm::Attribute::SExt.apply_callsite(idx, callsite); + } + } } } } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 5626c864fe175..32bd9651ece99 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -2619,7 +2619,7 @@ where is_return: bool| { // Booleans are always an i1 that needs to be zero-extended. if scalar.is_bool() { - attrs.set(ArgAttribute::ZExt); + attrs.zext(); return; } diff --git a/compiler/rustc_target/src/abi/call/mips64.rs b/compiler/rustc_target/src/abi/call/mips64.rs index 917dd104d1496..739ec6112ad3b 100644 --- a/compiler/rustc_target/src/abi/call/mips64.rs +++ b/compiler/rustc_target/src/abi/call/mips64.rs @@ -1,4 +1,4 @@ -use crate::abi::call::{ArgAbi, ArgAttribute, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform}; +use crate::abi::call::{ArgAbi, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform}; use crate::abi::{self, HasDataLayout, LayoutOf, Size, TyAndLayout, TyAndLayoutMethods}; fn extend_integer_width_mips(arg: &mut ArgAbi<'_, Ty>, bits: u64) { @@ -7,7 +7,7 @@ fn extend_integer_width_mips(arg: &mut ArgAbi<'_, Ty>, bits: u64) { if let abi::Int(i, signed) = scalar.value { if !signed && i.size().bits() == 32 { if let PassMode::Direct(ref mut attrs) = arg.mode { - attrs.set(ArgAttribute::SExt); + attrs.sext(); return; } } diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 429a3375cd893..9d657250c7c79 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -57,19 +57,28 @@ mod attr_impl { const NoCapture = 1 << 2; const NonNull = 1 << 3; const ReadOnly = 1 << 4; - const SExt = 1 << 5; const StructRet = 1 << 6; - const ZExt = 1 << 7; const InReg = 1 << 8; } } } +/// Sometimes an ABI requires small integers to be extended to a full or partial register. This enum +/// defines if this extension should be zero-extension or sign-extension when necssary. When it is +/// not necesary to extend the argument, this enum is ignored. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum ArgExtension { + None, + Zext, + Sext, +} + /// A compact representation of LLVM attributes (at least those relevant for this module) /// that can be manipulated without interacting with LLVM's Attribute machinery. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub struct ArgAttributes { pub regular: ArgAttribute, + pub arg_ext: ArgExtension, /// The minimum size of the pointee, guaranteed to be valid for the duration of the whole call /// (corresponding to LLVM's dereferenceable and dereferenceable_or_null attributes). pub pointee_size: Size, @@ -80,11 +89,24 @@ impl ArgAttributes { pub fn new() -> Self { ArgAttributes { regular: ArgAttribute::default(), + arg_ext: ArgExtension::None, pointee_size: Size::ZERO, pointee_align: None, } } + pub fn zext(&mut self) -> &mut Self { + assert_ne!(self.arg_ext, ArgExtension::Sext); + self.arg_ext = ArgExtension::Zext; + self + } + + pub fn sext(&mut self) -> &mut Self { + assert_ne!(self.arg_ext, ArgExtension::Zext); + self.arg_ext = ArgExtension::Sext; + self + } + pub fn set(&mut self, attr: ArgAttribute) -> &mut Self { self.regular |= attr; self @@ -457,7 +479,11 @@ impl<'a, Ty> ArgAbi<'a, Ty> { if let abi::Int(i, signed) = scalar.value { if i.size().bits() < bits { if let PassMode::Direct(ref mut attrs) = self.mode { - attrs.set(if signed { ArgAttribute::SExt } else { ArgAttribute::ZExt }); + if signed { + attrs.sext() + } else { + attrs.zext() + }; } } } diff --git a/compiler/rustc_target/src/abi/call/riscv.rs b/compiler/rustc_target/src/abi/call/riscv.rs index 782c661c31fdb..9c4ac85ce6135 100644 --- a/compiler/rustc_target/src/abi/call/riscv.rs +++ b/compiler/rustc_target/src/abi/call/riscv.rs @@ -4,7 +4,7 @@ // Reference: Clang RISC-V ELF psABI lowering code // https://github.com/llvm/llvm-project/blob/8e780252a7284be45cf1ba224cabd884847e8e92/clang/lib/CodeGen/TargetInfo.cpp#L9311-L9773 -use crate::abi::call::{ArgAbi, ArgAttribute, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform}; +use crate::abi::call::{ArgAbi, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform}; use crate::abi::{ self, Abi, FieldsShape, HasDataLayout, LayoutOf, Size, TyAndLayout, TyAndLayoutMethods, }; @@ -308,7 +308,7 @@ fn extend_integer_width<'a, Ty>(arg: &mut ArgAbi<'a, Ty>, xlen: u64) { // 32-bit integers are always sign-extended if i.size().bits() == 32 && xlen > 32 { if let PassMode::Direct(ref mut attrs) = arg.mode { - attrs.set(ArgAttribute::SExt); + attrs.sext(); return; } } From 42b0b8080d10b412d51d414a0de0e08959a64f5f Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 14 Nov 2020 14:29:40 +0100 Subject: [PATCH 18/21] Replace ByVal attribute with on_stack field for Indirect This makes it clearer that only PassMode::Indirect allows ByVal --- compiler/rustc_codegen_llvm/src/abi.rs | 121 +++++++++++++------- compiler/rustc_codegen_ssa/src/mir/block.rs | 4 +- compiler/rustc_middle/src/ty/layout.rs | 3 +- compiler/rustc_target/src/abi/call/mod.rs | 22 ++-- compiler/rustc_target/src/abi/call/x86.rs | 9 +- 5 files changed, 102 insertions(+), 57 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index 3ca0a9ce8d983..e988fdb9d5c53 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -41,12 +41,12 @@ impl ArgAttributeExt for ArgAttribute { } pub trait ArgAttributesExt { - fn apply_llfn(&self, idx: AttributePlace, llfn: &Value, ty: Option<&Type>); - fn apply_callsite(&self, idx: AttributePlace, callsite: &Value, ty: Option<&Type>); + fn apply_attrs_to_llfn(&self, idx: AttributePlace, llfn: &Value); + fn apply_attrs_to_callsite(&self, idx: AttributePlace, callsite: &Value); } impl ArgAttributesExt for ArgAttributes { - fn apply_llfn(&self, idx: AttributePlace, llfn: &Value, ty: Option<&Type>) { + fn apply_attrs_to_llfn(&self, idx: AttributePlace, llfn: &Value) { let mut regular = self.regular; unsafe { let deref = self.pointee_size.bytes(); @@ -61,9 +61,6 @@ impl ArgAttributesExt for ArgAttributes { if let Some(align) = self.pointee_align { llvm::LLVMRustAddAlignmentAttr(llfn, idx.as_uint(), align.bytes() as u32); } - if regular.contains(ArgAttribute::ByVal) { - llvm::LLVMRustAddByValAttr(llfn, idx.as_uint(), ty.unwrap()); - } regular.for_each_kind(|attr| attr.apply_llfn(idx, llfn)); match self.arg_ext { ArgExtension::None => {} @@ -77,7 +74,7 @@ impl ArgAttributesExt for ArgAttributes { } } - fn apply_callsite(&self, idx: AttributePlace, callsite: &Value, ty: Option<&Type>) { + fn apply_attrs_to_callsite(&self, idx: AttributePlace, callsite: &Value) { let mut regular = self.regular; unsafe { let deref = self.pointee_size.bytes(); @@ -100,9 +97,6 @@ impl ArgAttributesExt for ArgAttributes { align.bytes() as u32, ); } - if regular.contains(ArgAttribute::ByVal) { - llvm::LLVMRustAddByValCallSiteAttr(callsite, idx.as_uint(), ty.unwrap()); - } regular.for_each_kind(|attr| attr.apply_callsite(idx, callsite)); match self.arg_ext { ArgExtension::None => {} @@ -285,10 +279,12 @@ impl ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> { PassMode::Pair(..) => { OperandValue::Pair(next(), next()).store(bx, dst); } - PassMode::Indirect(_, Some(_)) => { + PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ } => { OperandValue::Ref(next(), Some(next()), self.layout.align.abi).store(bx, dst); } - PassMode::Direct(_) | PassMode::Indirect(_, None) | PassMode::Cast(_) => { + PassMode::Direct(_) + | PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } + | PassMode::Cast(_) => { let next_arg = next(); self.store(bx, next_arg, dst); } @@ -333,14 +329,14 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { if let PassMode::Pair(_, _) = arg.mode { 2 } else { 1 } ).sum(); let mut llargument_tys = Vec::with_capacity( - if let PassMode::Indirect(..) = self.ret.mode { 1 } else { 0 } + args_capacity, + if let PassMode::Indirect { .. } = self.ret.mode { 1 } else { 0 } + args_capacity, ); let llreturn_ty = match self.ret.mode { PassMode::Ignore => cx.type_void(), PassMode::Direct(_) | PassMode::Pair(..) => self.ret.layout.immediate_llvm_type(cx), PassMode::Cast(cast) => cast.llvm_type(cx), - PassMode::Indirect(..) => { + PassMode::Indirect { .. } => { llargument_tys.push(cx.type_ptr_to(self.ret.memory_ty(cx))); cx.type_void() } @@ -360,7 +356,7 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(cx, 1, true)); continue; } - PassMode::Indirect(_, Some(_)) => { + PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ } => { let ptr_ty = cx.tcx.mk_mut_ptr(arg.layout.ty); let ptr_layout = cx.layout_of(ptr_ty); llargument_tys.push(ptr_layout.scalar_pair_element_llvm_type(cx, 0, true)); @@ -368,7 +364,9 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { continue; } PassMode::Cast(cast) => cast.llvm_type(cx), - PassMode::Indirect(_, None) => cx.type_ptr_to(arg.memory_ty(cx)), + PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => { + cx.type_ptr_to(arg.memory_ty(cx)) + } }; llargument_tys.push(llarg_ty); } @@ -420,35 +418,53 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { } let mut i = 0; - let mut apply = |attrs: &ArgAttributes, ty: Option<&Type>| { - attrs.apply_llfn(llvm::AttributePlace::Argument(i), llfn, ty); + let mut apply = |attrs: &ArgAttributes| { + attrs.apply_attrs_to_llfn(llvm::AttributePlace::Argument(i), llfn); i += 1; + i - 1 }; match self.ret.mode { PassMode::Direct(ref attrs) => { - attrs.apply_llfn(llvm::AttributePlace::ReturnValue, llfn, None); + attrs.apply_attrs_to_llfn(llvm::AttributePlace::ReturnValue, llfn); + } + PassMode::Indirect { ref attrs, extra_attrs: _, on_stack } => { + assert!(!on_stack); + apply(attrs); } - PassMode::Indirect(ref attrs, _) => apply(attrs, Some(self.ret.layout.llvm_type(cx))), _ => {} } for arg in &self.args { if arg.pad.is_some() { - apply(&ArgAttributes::new(), None); + apply(&ArgAttributes::new()); } match arg.mode { PassMode::Ignore => {} - PassMode::Direct(ref attrs) | PassMode::Indirect(ref attrs, None) => { - apply(attrs, Some(arg.layout.llvm_type(cx))) + PassMode::Indirect { ref attrs, extra_attrs: None, on_stack: true } => { + let i = apply(attrs); + unsafe { + llvm::LLVMRustAddByValAttr( + llfn, + llvm::AttributePlace::Argument(i).as_uint(), + arg.layout.llvm_type(cx), + ); + } + } + PassMode::Direct(ref attrs) + | PassMode::Indirect { ref attrs, extra_attrs: None, on_stack: false } => { + apply(attrs); } - PassMode::Indirect(ref attrs, Some(ref extra_attrs)) => { - apply(attrs, None); - apply(extra_attrs, None); + PassMode::Indirect { ref attrs, extra_attrs: Some(ref extra_attrs), on_stack } => { + assert!(!on_stack); + apply(attrs); + apply(extra_attrs); } PassMode::Pair(ref a, ref b) => { - apply(a, None); - apply(b, None); + apply(a); + apply(b); + } + PassMode::Cast(_) => { + apply(&ArgAttributes::new()); } - PassMode::Cast(_) => apply(&ArgAttributes::new(), None), } } } @@ -457,15 +473,19 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { // FIXME(wesleywiser, eddyb): We should apply `nounwind` and `noreturn` as appropriate to this callsite. let mut i = 0; - let mut apply = |attrs: &ArgAttributes, ty: Option<&Type>| { - attrs.apply_callsite(llvm::AttributePlace::Argument(i), callsite, ty); + let mut apply = |attrs: &ArgAttributes| { + attrs.apply_attrs_to_callsite(llvm::AttributePlace::Argument(i), callsite); i += 1; + i - 1 }; match self.ret.mode { PassMode::Direct(ref attrs) => { - attrs.apply_callsite(llvm::AttributePlace::ReturnValue, callsite, None); + attrs.apply_attrs_to_callsite(llvm::AttributePlace::ReturnValue, callsite); + } + PassMode::Indirect { ref attrs, extra_attrs: _, on_stack } => { + assert!(!on_stack); + apply(attrs); } - PassMode::Indirect(ref attrs, _) => apply(attrs, Some(self.ret.layout.llvm_type(bx))), _ => {} } if let abi::Abi::Scalar(ref scalar) = self.ret.layout.abi { @@ -483,22 +503,39 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { } for arg in &self.args { if arg.pad.is_some() { - apply(&ArgAttributes::new(), None); + apply(&ArgAttributes::new()); } match arg.mode { PassMode::Ignore => {} - PassMode::Direct(ref attrs) | PassMode::Indirect(ref attrs, None) => { - apply(attrs, Some(arg.layout.llvm_type(bx))) + PassMode::Indirect { ref attrs, extra_attrs: None, on_stack: true } => { + let i = apply(attrs); + unsafe { + llvm::LLVMRustAddByValCallSiteAttr( + callsite, + llvm::AttributePlace::Argument(i).as_uint(), + arg.layout.llvm_type(bx), + ); + } } - PassMode::Indirect(ref attrs, Some(ref extra_attrs)) => { - apply(attrs, None); - apply(extra_attrs, None); + PassMode::Direct(ref attrs) + | PassMode::Indirect { ref attrs, extra_attrs: None, on_stack: false } => { + apply(attrs); + } + PassMode::Indirect { + ref attrs, + extra_attrs: Some(ref extra_attrs), + on_stack: _, + } => { + apply(attrs); + apply(extra_attrs); } PassMode::Pair(ref a, ref b) => { - apply(a, None); - apply(b, None); + apply(a); + apply(b); + } + PassMode::Cast(_) => { + apply(&ArgAttributes::new()); } - PassMode::Cast(_) => apply(&ArgAttributes::new(), None), } } diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index ee40095883ded..fd20709f5d80f 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -255,7 +255,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { return; } let llval = match self.fn_abi.ret.mode { - PassMode::Ignore | PassMode::Indirect(..) => { + PassMode::Ignore | PassMode::Indirect { .. } => { bx.ret_void(); return; } @@ -1101,7 +1101,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Force by-ref if we have to load through a cast pointer. let (mut llval, align, by_ref) = match op.val { Immediate(_) | Pair(..) => match arg.mode { - PassMode::Indirect(..) | PassMode::Cast(_) => { + PassMode::Indirect { .. } | PassMode::Cast(_) => { let scratch = PlaceRef::alloca(bx, arg.layout); op.val.store(bx, scratch); (scratch.llval, scratch.align, true) diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 32bd9651ece99..24d2ee6ec34a7 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -2801,7 +2801,8 @@ where for arg in &mut self.args { fixup(arg, false); } - if let PassMode::Indirect(ref mut attrs, _) = self.ret.mode { + if let PassMode::Indirect { ref mut attrs, extra_attrs: _, on_stack: _ } = self.ret.mode + { attrs.set(ArgAttribute::StructRet); } return; diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 9d657250c7c79..0931e8a37714d 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -36,9 +36,12 @@ pub enum PassMode { /// a single uniform or a pair of registers. Cast(CastTarget), /// Pass the argument indirectly via a hidden pointer. - /// The second value, if any, is for the extra data (vtable or length) + /// The `extra_attrs` value, if any, is for the extra data (vtable or length) /// which indicates that it refers to an unsized rvalue. - Indirect(ArgAttributes, Option), + /// `on_stack` defines that the the value should be passed at a fixed + /// stack offset in accordance to the ABI rather than passed using a + /// pointer. This corresponds to the `byval` LLVM argument attribute. + Indirect { attrs: ArgAttributes, extra_attrs: Option, on_stack: bool }, } // Hack to disable non_upper_case_globals only for the bitflags! and not for the rest @@ -52,7 +55,6 @@ mod attr_impl { bitflags::bitflags! { #[derive(Default)] pub struct ArgAttribute: u16 { - const ByVal = 1 << 0; const NoAlias = 1 << 1; const NoCapture = 1 << 2; const NonNull = 1 << 3; @@ -460,14 +462,14 @@ impl<'a, Ty> ArgAbi<'a, Ty> { let extra_attrs = self.layout.is_unsized().then_some(ArgAttributes::new()); - self.mode = PassMode::Indirect(attrs, extra_attrs); + self.mode = PassMode::Indirect { attrs, extra_attrs, on_stack: false }; } pub fn make_indirect_byval(&mut self) { self.make_indirect(); match self.mode { - PassMode::Indirect(ref mut attrs, _) => { - attrs.set(ArgAttribute::ByVal); + PassMode::Indirect { attrs: _, extra_attrs: _, ref mut on_stack } => { + *on_stack = true; } _ => unreachable!(), } @@ -500,15 +502,15 @@ impl<'a, Ty> ArgAbi<'a, Ty> { } pub fn is_indirect(&self) -> bool { - matches!(self.mode, PassMode::Indirect(..)) + matches!(self.mode, PassMode::Indirect {..}) } pub fn is_sized_indirect(&self) -> bool { - matches!(self.mode, PassMode::Indirect(_, None)) + matches!(self.mode, PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ }) } pub fn is_unsized_indirect(&self) -> bool { - matches!(self.mode, PassMode::Indirect(_, Some(_))) + matches!(self.mode, PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ }) } pub fn is_ignore(&self) -> bool { @@ -617,7 +619,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { a => return Err(format!("unrecognized arch \"{}\" in target specification", a)), } - if let PassMode::Indirect(ref mut attrs, _) = self.ret.mode { + if let PassMode::Indirect { ref mut attrs, extra_attrs: _, on_stack: _ } = self.ret.mode { attrs.set(ArgAttribute::StructRet); } diff --git a/compiler/rustc_target/src/abi/call/x86.rs b/compiler/rustc_target/src/abi/call/x86.rs index 07bf1e94c617e..713b4100a3335 100644 --- a/compiler/rustc_target/src/abi/call/x86.rs +++ b/compiler/rustc_target/src/abi/call/x86.rs @@ -92,9 +92,14 @@ where for arg in &mut fn_abi.args { let attrs = match arg.mode { - PassMode::Ignore | PassMode::Indirect(_, None) => continue, + PassMode::Ignore + | PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => { + continue; + } PassMode::Direct(ref mut attrs) => attrs, - PassMode::Pair(..) | PassMode::Indirect(_, Some(_)) | PassMode::Cast(_) => { + PassMode::Pair(..) + | PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ } + | PassMode::Cast(_) => { unreachable!("x86 shouldn't be passing arguments by {:?}", arg.mode) } }; From 39b8b2b623087fa643daeed424bd2fa79076f463 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 14 Nov 2020 19:16:43 +0100 Subject: [PATCH 19/21] Remove StructRet arg attr It is applied exactly when the return value has an indirect pass mode. Except for InReg on x86 fastcall, arg attrs are now only used for optimization purposes and thus are fine to ignore. --- compiler/rustc_codegen_llvm/src/abi.rs | 9 ++++++--- compiler/rustc_middle/src/ty/layout.rs | 4 ---- compiler/rustc_target/src/abi/call/mod.rs | 5 ----- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index e988fdb9d5c53..bb152104d64d3 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -36,7 +36,7 @@ impl ArgAttributeExt for ArgAttribute { where F: FnMut(llvm::Attribute), { - for_each_kind!(self, f, NoAlias, NoCapture, NonNull, ReadOnly, StructRet, InReg) + for_each_kind!(self, f, NoAlias, NoCapture, NonNull, ReadOnly, InReg) } } @@ -429,7 +429,8 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { } PassMode::Indirect { ref attrs, extra_attrs: _, on_stack } => { assert!(!on_stack); - apply(attrs); + let i = apply(attrs); + llvm::Attribute::StructRet.apply_llfn(llvm::AttributePlace::Argument(i), llfn); } _ => {} } @@ -484,7 +485,9 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { } PassMode::Indirect { ref attrs, extra_attrs: _, on_stack } => { assert!(!on_stack); - apply(attrs); + let i = apply(attrs); + llvm::Attribute::StructRet + .apply_callsite(llvm::AttributePlace::Argument(i), callsite); } _ => {} } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 24d2ee6ec34a7..666160ba49763 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -2801,10 +2801,6 @@ where for arg in &mut self.args { fixup(arg, false); } - if let PassMode::Indirect { ref mut attrs, extra_attrs: _, on_stack: _ } = self.ret.mode - { - attrs.set(ArgAttribute::StructRet); - } return; } diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 0931e8a37714d..91b004c41d956 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -59,7 +59,6 @@ mod attr_impl { const NoCapture = 1 << 2; const NonNull = 1 << 3; const ReadOnly = 1 << 4; - const StructRet = 1 << 6; const InReg = 1 << 8; } } @@ -619,10 +618,6 @@ impl<'a, Ty> FnAbi<'a, Ty> { a => return Err(format!("unrecognized arch \"{}\" in target specification", a)), } - if let PassMode::Indirect { ref mut attrs, extra_attrs: _, on_stack: _ } = self.ret.mode { - attrs.set(ArgAttribute::StructRet); - } - Ok(()) } } From 6a5f537fb902864ad3b3b4a3b043bcc0ee64ec54 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sun, 15 Nov 2020 10:12:10 +0100 Subject: [PATCH 20/21] Rename prefix_chunk to prefix_chunk_size --- compiler/rustc_codegen_llvm/src/abi.rs | 2 +- compiler/rustc_target/src/abi/call/mips64.rs | 2 +- compiler/rustc_target/src/abi/call/mod.rs | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index bb152104d64d3..915dd3d9eda15 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -158,7 +158,7 @@ impl LlvmType for CastTarget { .prefix .iter() .flat_map(|option_kind| { - option_kind.map(|kind| Reg { kind, size: self.prefix_chunk }.llvm_type(cx)) + option_kind.map(|kind| Reg { kind, size: self.prefix_chunk_size }.llvm_type(cx)) }) .chain((0..rest_count).map(|_| rest_ll_unit)) .collect(); diff --git a/compiler/rustc_target/src/abi/call/mips64.rs b/compiler/rustc_target/src/abi/call/mips64.rs index 739ec6112ad3b..f91552740feb8 100644 --- a/compiler/rustc_target/src/abi/call/mips64.rs +++ b/compiler/rustc_target/src/abi/call/mips64.rs @@ -137,7 +137,7 @@ where let rest_size = size - Size::from_bytes(8) * prefix_index as u64; arg.cast_to(CastTarget { prefix, - prefix_chunk: Size::from_bytes(8), + prefix_chunk_size: Size::from_bytes(8), rest: Uniform { unit: Reg::i64(), total: rest_size }, }); } diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 91b004c41d956..83e08f637e3a2 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -203,7 +203,7 @@ impl Uniform { #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub struct CastTarget { pub prefix: [Option; 8], - pub prefix_chunk: Size, + pub prefix_chunk_size: Size, pub rest: Uniform, } @@ -215,7 +215,7 @@ impl From for CastTarget { impl From for CastTarget { fn from(uniform: Uniform) -> CastTarget { - CastTarget { prefix: [None; 8], prefix_chunk: Size::ZERO, rest: uniform } + CastTarget { prefix: [None; 8], prefix_chunk_size: Size::ZERO, rest: uniform } } } @@ -223,13 +223,13 @@ impl CastTarget { pub fn pair(a: Reg, b: Reg) -> CastTarget { CastTarget { prefix: [Some(a.kind), None, None, None, None, None, None, None], - prefix_chunk: a.size, + prefix_chunk_size: a.size, rest: Uniform::from(b), } } pub fn size(&self, cx: &C) -> Size { - (self.prefix_chunk * self.prefix.iter().filter(|x| x.is_some()).count() as u64) + (self.prefix_chunk_size * self.prefix.iter().filter(|x| x.is_some()).count() as u64) .align_to(self.rest.align(cx)) + self.rest.total } @@ -237,7 +237,7 @@ impl CastTarget { pub fn align(&self, cx: &C) -> Align { self.prefix .iter() - .filter_map(|x| x.map(|kind| Reg { kind, size: self.prefix_chunk }.align(cx))) + .filter_map(|x| x.map(|kind| Reg { kind, size: self.prefix_chunk_size }.align(cx))) .fold(cx.data_layout().aggregate_align.abi.max(self.rest.align(cx)), |acc, align| { acc.max(align) }) From 43968aa8b8c1d0073410d3af36bd83debf6fcf78 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 21 Nov 2020 19:06:35 +0100 Subject: [PATCH 21/21] Replace sext() and zext() with single ext() method --- compiler/rustc_middle/src/ty/layout.rs | 4 ++-- compiler/rustc_target/src/abi/call/mips64.rs | 4 ++-- compiler/rustc_target/src/abi/call/mod.rs | 16 +++++----------- compiler/rustc_target/src/abi/call/riscv.rs | 4 ++-- 4 files changed, 11 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 666160ba49763..fa0711193df48 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -15,7 +15,7 @@ use rustc_session::{DataTypeKind, FieldInfo, SizeKind, VariantInfo}; use rustc_span::symbol::{Ident, Symbol}; use rustc_span::DUMMY_SP; use rustc_target::abi::call::{ - ArgAbi, ArgAttribute, ArgAttributes, Conv, FnAbi, PassMode, Reg, RegKind, + ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, Conv, FnAbi, PassMode, Reg, RegKind, }; use rustc_target::abi::*; use rustc_target::spec::{abi::Abi as SpecAbi, HasTargetSpec, PanicStrategy}; @@ -2619,7 +2619,7 @@ where is_return: bool| { // Booleans are always an i1 that needs to be zero-extended. if scalar.is_bool() { - attrs.zext(); + attrs.ext(ArgExtension::Zext); return; } diff --git a/compiler/rustc_target/src/abi/call/mips64.rs b/compiler/rustc_target/src/abi/call/mips64.rs index f91552740feb8..a630c84142b4d 100644 --- a/compiler/rustc_target/src/abi/call/mips64.rs +++ b/compiler/rustc_target/src/abi/call/mips64.rs @@ -1,4 +1,4 @@ -use crate::abi::call::{ArgAbi, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform}; +use crate::abi::call::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform}; use crate::abi::{self, HasDataLayout, LayoutOf, Size, TyAndLayout, TyAndLayoutMethods}; fn extend_integer_width_mips(arg: &mut ArgAbi<'_, Ty>, bits: u64) { @@ -7,7 +7,7 @@ fn extend_integer_width_mips(arg: &mut ArgAbi<'_, Ty>, bits: u64) { if let abi::Int(i, signed) = scalar.value { if !signed && i.size().bits() == 32 { if let PassMode::Direct(ref mut attrs) = arg.mode { - attrs.sext(); + attrs.ext(ArgExtension::Sext); return; } } diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 83e08f637e3a2..5de9a8dfa7ac1 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -96,15 +96,9 @@ impl ArgAttributes { } } - pub fn zext(&mut self) -> &mut Self { - assert_ne!(self.arg_ext, ArgExtension::Sext); - self.arg_ext = ArgExtension::Zext; - self - } - - pub fn sext(&mut self) -> &mut Self { - assert_ne!(self.arg_ext, ArgExtension::Zext); - self.arg_ext = ArgExtension::Sext; + pub fn ext(&mut self, ext: ArgExtension) -> &mut Self { + assert!(self.arg_ext == ArgExtension::None || self.arg_ext == ext); + self.arg_ext = ext; self } @@ -481,9 +475,9 @@ impl<'a, Ty> ArgAbi<'a, Ty> { if i.size().bits() < bits { if let PassMode::Direct(ref mut attrs) = self.mode { if signed { - attrs.sext() + attrs.ext(ArgExtension::Sext) } else { - attrs.zext() + attrs.ext(ArgExtension::Zext) }; } } diff --git a/compiler/rustc_target/src/abi/call/riscv.rs b/compiler/rustc_target/src/abi/call/riscv.rs index 9c4ac85ce6135..1ab881dd13d1c 100644 --- a/compiler/rustc_target/src/abi/call/riscv.rs +++ b/compiler/rustc_target/src/abi/call/riscv.rs @@ -4,7 +4,7 @@ // Reference: Clang RISC-V ELF psABI lowering code // https://github.com/llvm/llvm-project/blob/8e780252a7284be45cf1ba224cabd884847e8e92/clang/lib/CodeGen/TargetInfo.cpp#L9311-L9773 -use crate::abi::call::{ArgAbi, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform}; +use crate::abi::call::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform}; use crate::abi::{ self, Abi, FieldsShape, HasDataLayout, LayoutOf, Size, TyAndLayout, TyAndLayoutMethods, }; @@ -308,7 +308,7 @@ fn extend_integer_width<'a, Ty>(arg: &mut ArgAbi<'a, Ty>, xlen: u64) { // 32-bit integers are always sign-extended if i.size().bits() == 32 && xlen > 32 { if let PassMode::Direct(ref mut attrs) = arg.mode { - attrs.sext(); + attrs.ext(ArgExtension::Sext); return; } }