diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 380dfd38723..82c3c2006eb 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -161,6 +161,7 @@ pub fn target_machine_factory( let ffunction_sections = sess.opts.debugging_opts.function_sections.unwrap_or(sess.target.function_sections); let fdata_sections = ffunction_sections; + let funique_section_names = !sess.opts.debugging_opts.no_unique_section_names; let code_model = to_llvm_code_model(sess.code_model()); @@ -205,6 +206,7 @@ pub fn target_machine_factory( use_softfp, ffunction_sections, fdata_sections, + funique_section_names, trap_unreachable, singlethread, asm_comments, diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 45fb638e3b4..d57573558da 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2187,6 +2187,7 @@ pub fn LLVMRustCreateTargetMachine( UseSoftFP: bool, FunctionSections: bool, DataSections: bool, + UniqueSectionNames: bool, TrapUnreachable: bool, Singlethread: bool, AsmComments: bool, diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index dab4d485e2d..2d3cb52f5fd 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -744,6 +744,7 @@ macro_rules! tracked { tracked!(new_llvm_pass_manager, Some(true)); tracked!(no_generate_arange_section, true); tracked!(no_link, true); + tracked!(no_unique_section_names, true); tracked!(no_profiler_runtime, true); tracked!(osx_rpath_install_name, true); tracked!(panic_abort_tests, true); diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index d6dc54c8d0a..32b866e81b1 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -462,6 +462,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( LLVMRustCodeGenOptLevel RustOptLevel, bool UseSoftFloat, bool FunctionSections, bool DataSections, + bool UniqueSectionNames, bool TrapUnreachable, bool Singlethread, bool AsmComments, @@ -491,6 +492,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( } Options.DataSections = DataSections; Options.FunctionSections = FunctionSections; + Options.UniqueSectionNames = UniqueSectionNames; Options.MCOptions.AsmVerbose = AsmComments; Options.MCOptions.PreserveAsmComments = AsmComments; Options.MCOptions.ABIName = ABIStr; diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 782055b9a77..3ff91c0553a 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1214,6 +1214,8 @@ mod parse { "compile without linking"), no_parallel_llvm: bool = (false, parse_no_flag, [UNTRACKED], "run LLVM in non-parallel mode (while keeping codegen-units and ThinLTO)"), + no_unique_section_names: bool = (false, parse_bool, [TRACKED], + "do not use unique names for text and data sections when -Z function-sections is used"), no_profiler_runtime: bool = (false, parse_no_flag, [TRACKED], "prevent automatic injection of the profiler_builtins crate"), normalize_docs: bool = (false, parse_bool, [TRACKED], diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index bc77c94809e..af3706f886e 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -247,6 +247,7 @@ fn trait_of_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option { } /// See `ParamEnv` struct definition for details. +#[instrument(level = "debug", skip(tcx))] fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { // The param_env of an impl Trait type is its defining function's param_env if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) { @@ -274,9 +275,20 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { predicates.extend(environment); } + // It's important that we include the default substs in unevaluated + // constants, since `Unevaluated` instances in predicates whose substs are None + // can lead to "duplicate" caller bounds candidates during trait selection, + // duplicate in the sense that both have their default substs, but the + // candidate that resulted from a superpredicate still uses `None` in its + // `substs_` field of `Unevaluated` to indicate that it has its default substs, + // whereas the other candidate has `substs_: Some(default_substs)`, see + // issue #89334 + predicates = tcx.expose_default_const_substs(predicates); + let unnormalized_env = ty::ParamEnv::new(tcx.intern_predicates(&predicates), traits::Reveal::UserFacing); + debug!("unnormalized_env caller bounds: {:?}", unnormalized_env.caller_bounds()); let body_id = def_id .as_local() .map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id)) diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index cd2d57699c9..776cea2ef79 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -24,7 +24,7 @@ /// ``` /// /// A basic tree traversal: -/// ```no_run +/// ``` /// use std::ops::ControlFlow; /// /// pub struct TreeNode { @@ -34,17 +34,42 @@ /// } /// /// impl TreeNode { -/// pub fn traverse_inorder(&self, mut f: impl FnMut(&T) -> ControlFlow) -> ControlFlow { +/// pub fn traverse_inorder(&self, f: &mut impl FnMut(&T) -> ControlFlow) -> ControlFlow { /// if let Some(left) = &self.left { -/// left.traverse_inorder(&mut f)?; +/// left.traverse_inorder(f)?; /// } /// f(&self.value)?; /// if let Some(right) = &self.right { -/// right.traverse_inorder(&mut f)?; +/// right.traverse_inorder(f)?; /// } /// ControlFlow::Continue(()) /// } +/// fn leaf(value: T) -> Option>> { +/// Some(Box::new(Self { value, left: None, right: None })) +/// } /// } +/// +/// let node = TreeNode { +/// value: 0, +/// left: TreeNode::leaf(1), +/// right: Some(Box::new(TreeNode { +/// value: -1, +/// left: TreeNode::leaf(5), +/// right: TreeNode::leaf(2), +/// })) +/// }; +/// let mut sum = 0; +/// +/// let res = node.traverse_inorder(&mut |val| { +/// if *val < 0 { +/// ControlFlow::Break(*val) +/// } else { +/// sum += *val; +/// ControlFlow::Continue(()) +/// } +/// }); +/// assert_eq!(res, ControlFlow::Break(-1)); +/// assert_eq!(sum, 6); /// ``` #[stable(feature = "control_flow_enum_type", since = "1.55.0")] #[derive(Debug, Clone, Copy, PartialEq)] diff --git a/src/doc/unstable-book/src/compiler-flags/no-unique-section-names.md b/src/doc/unstable-book/src/compiler-flags/no-unique-section-names.md new file mode 100644 index 00000000000..5c1c7cda701 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/no-unique-section-names.md @@ -0,0 +1,9 @@ +# `no-unique-section-names` + +------------------------ + +This flag currently applies only to ELF-based targets using the LLVM codegen backend. It prevents the generation of unique ELF section names for each separate code and data item when `-Z function-sections` is also in use, which is the default for most targets. This option can reduce the size of object files, and depending on the linker, the final ELF binary as well. + +For example, a function `func` will by default generate a code section called `.text.func`. Normally this is fine because the linker will merge all those `.text.*` sections into a single one in the binary. However, starting with [LLVM 12](https://github.com/llvm/llvm-project/commit/ee5d1a04), the backend will also generate unique section names for exception handling, so you would see a section name of `.gcc_except_table.func` in the object file and potentially in the final ELF binary, which could add significant bloat to programs that contain many functions. + +This flag instructs LLVM to use the same `.text` and `.gcc_except_table` section name for each function, and it is analogous to Clang's `-fno-unique-section-names` option. diff --git a/src/test/ui/const-generics/expose-default-substs-param-env.rs b/src/test/ui/const-generics/expose-default-substs-param-env.rs new file mode 100644 index 00000000000..e40c93116af --- /dev/null +++ b/src/test/ui/const-generics/expose-default-substs-param-env.rs @@ -0,0 +1,9 @@ +// build-pass + +#![feature(generic_const_exprs)] +#![allow(unused_braces, incomplete_features)] + +pub trait Foo {} +pub trait Bar: Foo<{ 1 }> { } + +fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-89334.rs b/src/test/ui/const-generics/issues/issue-89334.rs new file mode 100644 index 00000000000..b15b7428cdd --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-89334.rs @@ -0,0 +1,16 @@ +// build-pass + +#![feature(generic_const_exprs)] +#![allow(unused_braces, incomplete_features)] + +pub trait AnotherTrait{ + const ARRAY_SIZE: usize; +} +pub trait Shard: + AsMut<[[u8; T::ARRAY_SIZE]]> +where + [(); T::ARRAY_SIZE]: Sized +{ +} + +fn main() {} diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer index 91cbda43c2a..1f47693e028 160000 --- a/src/tools/rust-analyzer +++ b/src/tools/rust-analyzer @@ -1 +1 @@ -Subproject commit 91cbda43c2af82b9377eff70a21f59ade18cd23c +Subproject commit 1f47693e02809c97db61b51247ae4e4d46744c61