Auto merge of #131111 - matthiaskrgr:rollup-n6do187, r=matthiaskrgr

Rollup of 4 pull requests

Successful merges:

 - #130005 (Replace -Z default-hidden-visibility with -Z default-visibility)
 - #130229 (ptr::add/sub: do not claim equivalence with `offset(c as isize)`)
 - #130773 (Update Unicode escapes in `/library/core/src/char/methods.rs`)
 - #130933 (rustdoc: lists items that contain multiple paragraphs are more clear)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-10-01 19:29:26 +00:00
commit 06bb8364aa
19 changed files with 270 additions and 127 deletions

View File

@ -104,10 +104,17 @@ fn create_wrapper_function(
false, false,
); );
if tcx.sess.default_hidden_visibility() { #[cfg(feature = "master")]
#[cfg(feature = "master")] match tcx.sess.default_visibility() {
func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden)); rustc_target::spec::SymbolVisibility::Hidden => {
func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden))
}
rustc_target::spec::SymbolVisibility::Protected => {
func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Protected))
}
rustc_target::spec::SymbolVisibility::Interposable => {}
} }
if tcx.sess.must_emit_unwind_tables() { if tcx.sess.must_emit_unwind_tables() {
// TODO(antoyo): emit unwind tables. // TODO(antoyo): emit unwind tables.
} }

View File

@ -77,18 +77,20 @@ pub(crate) unsafe fn codegen(
// __rust_alloc_error_handler_should_panic // __rust_alloc_error_handler_should_panic
let name = OomStrategy::SYMBOL; let name = OomStrategy::SYMBOL;
let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_ptr().cast(), name.len(), i8); let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_ptr().cast(), name.len(), i8);
if tcx.sess.default_hidden_visibility() { llvm::LLVMRustSetVisibility(
llvm::LLVMRustSetVisibility(ll_g, llvm::Visibility::Hidden); ll_g,
} llvm::Visibility::from_generic(tcx.sess.default_visibility()),
);
let val = tcx.sess.opts.unstable_opts.oom.should_panic(); let val = tcx.sess.opts.unstable_opts.oom.should_panic();
let llval = llvm::LLVMConstInt(i8, val as u64, False); let llval = llvm::LLVMConstInt(i8, val as u64, False);
llvm::LLVMSetInitializer(ll_g, llval); llvm::LLVMSetInitializer(ll_g, llval);
let name = NO_ALLOC_SHIM_IS_UNSTABLE; let name = NO_ALLOC_SHIM_IS_UNSTABLE;
let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_ptr().cast(), name.len(), i8); let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_ptr().cast(), name.len(), i8);
if tcx.sess.default_hidden_visibility() { llvm::LLVMRustSetVisibility(
llvm::LLVMRustSetVisibility(ll_g, llvm::Visibility::Hidden); ll_g,
} llvm::Visibility::from_generic(tcx.sess.default_visibility()),
);
let llval = llvm::LLVMConstInt(i8, 0, False); let llval = llvm::LLVMConstInt(i8, 0, False);
llvm::LLVMSetInitializer(ll_g, llval); llvm::LLVMSetInitializer(ll_g, llval);
} }
@ -132,9 +134,11 @@ fn create_wrapper_function(
None None
}; };
if tcx.sess.default_hidden_visibility() { llvm::LLVMRustSetVisibility(
llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden); llfn,
} llvm::Visibility::from_generic(tcx.sess.default_visibility()),
);
if tcx.sess.must_emit_unwind_tables() { if tcx.sess.must_emit_unwind_tables() {
let uwtable = let uwtable =
attributes::uwtable_attr(llcx, tcx.sess.opts.unstable_opts.use_sync_unwind); attributes::uwtable_attr(llcx, tcx.sess.opts.unstable_opts.use_sync_unwind);

View File

@ -22,6 +22,7 @@ use tracing::debug;
use crate::abi::{FnAbi, FnAbiLlvmExt}; use crate::abi::{FnAbi, FnAbiLlvmExt};
use crate::context::CodegenCx; use crate::context::CodegenCx;
use crate::llvm::AttributePlace::Function; use crate::llvm::AttributePlace::Function;
use crate::llvm::Visibility;
use crate::type_::Type; use crate::type_::Type;
use crate::value::Value; use crate::value::Value;
use crate::{attributes, llvm}; use crate::{attributes, llvm};
@ -84,11 +85,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
fn_type: &'ll Type, fn_type: &'ll Type,
) -> &'ll Value { ) -> &'ll Value {
// Declare C ABI functions with the visibility used by C by default. // Declare C ABI functions with the visibility used by C by default.
let visibility = if self.tcx.sess.default_hidden_visibility() { let visibility = Visibility::from_generic(self.tcx.sess.default_visibility());
llvm::Visibility::Hidden
} else {
llvm::Visibility::Default
};
declare_raw_fn(self, name, llvm::CCallConv, unnamed, visibility, fn_type) declare_raw_fn(self, name, llvm::CCallConv, unnamed, visibility, fn_type)
} }
@ -107,11 +104,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
unnamed: llvm::UnnamedAddr, unnamed: llvm::UnnamedAddr,
fn_type: &'ll Type, fn_type: &'ll Type,
) -> &'ll Value { ) -> &'ll Value {
let visibility = if self.tcx.sess.default_hidden_visibility() { let visibility = Visibility::from_generic(self.tcx.sess.default_visibility());
llvm::Visibility::Hidden
} else {
llvm::Visibility::Default
};
declare_raw_fn(self, name, callconv, unnamed, visibility, fn_type) declare_raw_fn(self, name, callconv, unnamed, visibility, fn_type)
} }

View File

@ -4,6 +4,7 @@
use std::marker::PhantomData; use std::marker::PhantomData;
use libc::{c_char, c_int, c_uint, c_ulonglong, c_void, size_t}; use libc::{c_char, c_int, c_uint, c_ulonglong, c_void, size_t};
use rustc_target::spec::SymbolVisibility;
use super::RustString; use super::RustString;
use super::debuginfo::{ use super::debuginfo::{
@ -133,6 +134,16 @@ pub enum Visibility {
Protected = 2, Protected = 2,
} }
impl Visibility {
pub fn from_generic(visibility: SymbolVisibility) -> Self {
match visibility {
SymbolVisibility::Hidden => Visibility::Hidden,
SymbolVisibility::Protected => Visibility::Protected,
SymbolVisibility::Interposable => Visibility::Default,
}
}
}
/// LLVMUnnamedAddr /// LLVMUnnamedAddr
#[repr(C)] #[repr(C)]
pub enum UnnamedAddr { pub enum UnnamedAddr {

View File

@ -770,7 +770,7 @@ fn test_unstable_options_tracking_hash() {
tracked!(crate_attr, vec!["abc".to_string()]); tracked!(crate_attr, vec!["abc".to_string()]);
tracked!(cross_crate_inline_threshold, InliningThreshold::Always); tracked!(cross_crate_inline_threshold, InliningThreshold::Always);
tracked!(debug_info_for_profiling, true); tracked!(debug_info_for_profiling, true);
tracked!(default_hidden_visibility, Some(true)); tracked!(default_visibility, Some(rustc_target::spec::SymbolVisibility::Hidden));
tracked!(dep_info_omit_d_target, true); tracked!(dep_info_omit_d_target, true);
tracked!(direct_access_external_data, Some(true)); tracked!(direct_access_external_data, Some(true));
tracked!(dual_proc_macros, true); tracked!(dual_proc_macros, true);

View File

@ -15,6 +15,7 @@ use rustc_query_system::ich::StableHashingContext;
use rustc_session::config::OptLevel; use rustc_session::config::OptLevel;
use rustc_span::Span; use rustc_span::Span;
use rustc_span::symbol::Symbol; use rustc_span::symbol::Symbol;
use rustc_target::spec::SymbolVisibility;
use tracing::debug; use tracing::debug;
use crate::dep_graph::{DepNode, WorkProduct, WorkProductId}; use crate::dep_graph::{DepNode, WorkProduct, WorkProductId};
@ -305,6 +306,16 @@ pub enum Visibility {
Protected, Protected,
} }
impl From<SymbolVisibility> for Visibility {
fn from(value: SymbolVisibility) -> Self {
match value {
SymbolVisibility::Hidden => Visibility::Hidden,
SymbolVisibility::Protected => Visibility::Protected,
SymbolVisibility::Interposable => Visibility::Default,
}
}
}
impl<'tcx> CodegenUnit<'tcx> { impl<'tcx> CodegenUnit<'tcx> {
#[inline] #[inline]
pub fn new(name: Symbol) -> CodegenUnit<'tcx> { pub fn new(name: Symbol) -> CodegenUnit<'tcx> {

View File

@ -904,26 +904,22 @@ fn mono_item_visibility<'tcx>(
} }
fn default_visibility(tcx: TyCtxt<'_>, id: DefId, is_generic: bool) -> Visibility { fn default_visibility(tcx: TyCtxt<'_>, id: DefId, is_generic: bool) -> Visibility {
if !tcx.sess.default_hidden_visibility() { let export_level = if is_generic {
return Visibility::Default; // Generic functions never have export-level C.
} SymbolExportLevel::Rust
} else {
match tcx.reachable_non_generics(id.krate).get(&id) {
Some(SymbolExportInfo { level: SymbolExportLevel::C, .. }) => SymbolExportLevel::C,
_ => SymbolExportLevel::Rust,
}
};
match export_level {
// C-export level items remain at `Default` to allow C code to
// access and interpose them.
SymbolExportLevel::C => Visibility::Default,
// Generic functions never have export-level C. // For all other symbols, `default_visibility` determines which visibility to use.
if is_generic { SymbolExportLevel::Rust => tcx.sess.default_visibility().into(),
return Visibility::Hidden;
}
// Things with export level C don't get instantiated in
// downstream crates.
if !id.is_local() {
return Visibility::Hidden;
}
// C-export level items remain at `Default`, all other internal
// items become `Hidden`.
match tcx.reachable_non_generics(id.krate).get(&id) {
Some(SymbolExportInfo { level: SymbolExportLevel::C, .. }) => Visibility::Default,
_ => Visibility::Hidden,
} }
} }

View File

@ -3008,7 +3008,8 @@ pub(crate) mod dep_tracking {
use rustc_span::edition::Edition; use rustc_span::edition::Edition;
use rustc_target::spec::{ use rustc_target::spec::{
CodeModel, FramePointer, MergeFunctions, OnBrokenPipe, PanicStrategy, RelocModel, CodeModel, FramePointer, MergeFunctions, OnBrokenPipe, PanicStrategy, RelocModel,
RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TargetTriple, TlsModel, WasmCAbi, RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, SymbolVisibility, TargetTriple,
TlsModel, WasmCAbi,
}; };
use super::{ use super::{
@ -3101,6 +3102,7 @@ pub(crate) mod dep_tracking {
StackProtector, StackProtector,
SwitchWithOptPath, SwitchWithOptPath,
SymbolManglingVersion, SymbolManglingVersion,
SymbolVisibility,
RemapPathScopeComponents, RemapPathScopeComponents,
SourceFileHashAlgorithm, SourceFileHashAlgorithm,
OutFileName, OutFileName,

View File

@ -13,8 +13,8 @@ use rustc_span::edition::Edition;
use rustc_span::{RealFileName, SourceFileHashAlgorithm}; use rustc_span::{RealFileName, SourceFileHashAlgorithm};
use rustc_target::spec::{ use rustc_target::spec::{
CodeModel, FramePointer, LinkerFlavorCli, MergeFunctions, OnBrokenPipe, PanicStrategy, CodeModel, FramePointer, LinkerFlavorCli, MergeFunctions, OnBrokenPipe, PanicStrategy,
RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TargetTriple, TlsModel, RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, SymbolVisibility,
WasmCAbi, TargetTriple, TlsModel, WasmCAbi,
}; };
use crate::config::*; use crate::config::*;
@ -416,6 +416,8 @@ mod desc {
"one of: `disabled`, `trampolines`, or `aliases`"; "one of: `disabled`, `trampolines`, or `aliases`";
pub(crate) const parse_symbol_mangling_version: &str = pub(crate) const parse_symbol_mangling_version: &str =
"one of: `legacy`, `v0` (RFC 2603), or `hashed`"; "one of: `legacy`, `v0` (RFC 2603), or `hashed`";
pub(crate) const parse_opt_symbol_visibility: &str =
"one of: `hidden`, `protected`, or `interposable`";
pub(crate) const parse_src_file_hash: &str = "either `md5` or `sha1`"; pub(crate) const parse_src_file_hash: &str = "either `md5` or `sha1`";
pub(crate) const parse_relocation_model: &str = pub(crate) const parse_relocation_model: &str =
"one of supported relocation models (`rustc --print relocation-models`)"; "one of supported relocation models (`rustc --print relocation-models`)";
@ -922,6 +924,20 @@ mod parse {
true true
} }
pub(crate) fn parse_opt_symbol_visibility(
slot: &mut Option<SymbolVisibility>,
v: Option<&str>,
) -> bool {
if let Some(v) = v {
if let Ok(vis) = SymbolVisibility::from_str(v) {
*slot = Some(vis);
} else {
return false;
}
}
true
}
pub(crate) fn parse_optimization_fuel( pub(crate) fn parse_optimization_fuel(
slot: &mut Option<(String, u64)>, slot: &mut Option<(String, u64)>,
v: Option<&str>, v: Option<&str>,
@ -1688,8 +1704,8 @@ options! {
"compress debug info sections (none, zlib, zstd, default: none)"), "compress debug info sections (none, zlib, zstd, default: none)"),
deduplicate_diagnostics: bool = (true, parse_bool, [UNTRACKED], deduplicate_diagnostics: bool = (true, parse_bool, [UNTRACKED],
"deduplicate identical diagnostics (default: yes)"), "deduplicate identical diagnostics (default: yes)"),
default_hidden_visibility: Option<bool> = (None, parse_opt_bool, [TRACKED], default_visibility: Option<SymbolVisibility> = (None, parse_opt_symbol_visibility, [TRACKED],
"overrides the `default_hidden_visibility` setting of the target"), "overrides the `default_visibility` setting of the target"),
dep_info_omit_d_target: bool = (false, parse_bool, [TRACKED], dep_info_omit_d_target: bool = (false, parse_bool, [TRACKED],
"in dep-info output, omit targets for tracking dependencies of the dep-info files \ "in dep-info output, omit targets for tracking dependencies of the dep-info files \
themselves (default: no)"), themselves (default: no)"),

View File

@ -31,7 +31,8 @@ use rustc_span::{FileNameDisplayPreference, RealFileName, Span, Symbol};
use rustc_target::asm::InlineAsmArch; use rustc_target::asm::InlineAsmArch;
use rustc_target::spec::{ use rustc_target::spec::{
CodeModel, DebuginfoKind, PanicStrategy, RelocModel, RelroLevel, SanitizerSet, CodeModel, DebuginfoKind, PanicStrategy, RelocModel, RelroLevel, SanitizerSet,
SmallDataThresholdSupport, SplitDebuginfo, StackProtector, Target, TargetTriple, TlsModel, SmallDataThresholdSupport, SplitDebuginfo, StackProtector, SymbolVisibility, Target,
TargetTriple, TlsModel,
}; };
use crate::code_stats::CodeStats; use crate::code_stats::CodeStats;
@ -617,12 +618,13 @@ impl Session {
} }
} }
/// Whether the default visibility of symbols should be "hidden" rather than "default". /// Returns the default symbol visibility.
pub fn default_hidden_visibility(&self) -> bool { pub fn default_visibility(&self) -> SymbolVisibility {
self.opts self.opts
.unstable_opts .unstable_opts
.default_hidden_visibility .default_visibility
.unwrap_or(self.target.options.default_hidden_visibility) .or(self.target.options.default_visibility)
.unwrap_or(SymbolVisibility::Interposable)
} }
} }

View File

@ -830,6 +830,46 @@ impl RelroLevel {
} }
} }
#[derive(Clone, Copy, Debug, PartialEq, Hash)]
pub enum SymbolVisibility {
Hidden,
Protected,
Interposable,
}
impl SymbolVisibility {
pub fn desc(&self) -> &str {
match *self {
SymbolVisibility::Hidden => "hidden",
SymbolVisibility::Protected => "protected",
SymbolVisibility::Interposable => "interposable",
}
}
}
impl FromStr for SymbolVisibility {
type Err = ();
fn from_str(s: &str) -> Result<SymbolVisibility, ()> {
match s {
"hidden" => Ok(SymbolVisibility::Hidden),
"protected" => Ok(SymbolVisibility::Protected),
"interposable" => Ok(SymbolVisibility::Interposable),
_ => Err(()),
}
}
}
impl ToJson for SymbolVisibility {
fn to_json(&self) -> Json {
match *self {
SymbolVisibility::Hidden => "hidden".to_json(),
SymbolVisibility::Protected => "protected".to_json(),
SymbolVisibility::Interposable => "interposable".to_json(),
}
}
}
impl FromStr for RelroLevel { impl FromStr for RelroLevel {
type Err = (); type Err = ();
@ -2326,13 +2366,12 @@ pub struct TargetOptions {
/// for this target unconditionally. /// for this target unconditionally.
pub no_builtins: bool, pub no_builtins: bool,
/// The default visibility for symbols in this target should be "hidden" /// The default visibility for symbols in this target.
/// rather than "default".
/// ///
/// This value typically shouldn't be accessed directly, but through /// This value typically shouldn't be accessed directly, but through the
/// the `rustc_session::Session::default_hidden_visibility` method, which /// `rustc_session::Session::default_visibility` method, which allows `rustc` users to override
/// allows `rustc` users to override this setting using cmdline flags. /// this setting using cmdline flags.
pub default_hidden_visibility: bool, pub default_visibility: Option<SymbolVisibility>,
/// Whether a .debug_gdb_scripts section will be added to the output object file /// Whether a .debug_gdb_scripts section will be added to the output object file
pub emit_debug_gdb_scripts: bool, pub emit_debug_gdb_scripts: bool,
@ -2623,7 +2662,7 @@ impl Default for TargetOptions {
requires_lto: false, requires_lto: false,
singlethread: false, singlethread: false,
no_builtins: false, no_builtins: false,
default_hidden_visibility: false, default_visibility: None,
emit_debug_gdb_scripts: true, emit_debug_gdb_scripts: true,
requires_uwtable: false, requires_uwtable: false,
default_uwtable: false, default_uwtable: false,
@ -2963,6 +3002,18 @@ impl Target {
Some(Ok(())) Some(Ok(()))
})).unwrap_or(Ok(())) })).unwrap_or(Ok(()))
} ); } );
($key_name:ident, Option<SymbolVisibility>) => ( {
let name = (stringify!($key_name)).replace("_", "-");
obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
match s.parse::<SymbolVisibility>() {
Ok(level) => base.$key_name = Some(level),
_ => return Some(Err(format!("'{}' is not a valid value for \
symbol-visibility. Use 'hidden', 'protected, or 'interposable'.",
s))),
}
Some(Ok(()))
})).unwrap_or(Ok(()))
} );
($key_name:ident, DebuginfoKind) => ( { ($key_name:ident, DebuginfoKind) => ( {
let name = (stringify!($key_name)).replace("_", "-"); let name = (stringify!($key_name)).replace("_", "-");
obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
@ -3353,7 +3404,7 @@ impl Target {
key!(requires_lto, bool); key!(requires_lto, bool);
key!(singlethread, bool); key!(singlethread, bool);
key!(no_builtins, bool); key!(no_builtins, bool);
key!(default_hidden_visibility, bool); key!(default_visibility, Option<SymbolVisibility>)?;
key!(emit_debug_gdb_scripts, bool); key!(emit_debug_gdb_scripts, bool);
key!(requires_uwtable, bool); key!(requires_uwtable, bool);
key!(default_uwtable, bool); key!(default_uwtable, bool);
@ -3633,7 +3684,7 @@ impl ToJson for Target {
target_option_val!(requires_lto); target_option_val!(requires_lto);
target_option_val!(singlethread); target_option_val!(singlethread);
target_option_val!(no_builtins); target_option_val!(no_builtins);
target_option_val!(default_hidden_visibility); target_option_val!(default_visibility);
target_option_val!(emit_debug_gdb_scripts); target_option_val!(emit_debug_gdb_scripts);
target_option_val!(requires_uwtable); target_option_val!(requires_uwtable);
target_option_val!(default_uwtable); target_option_val!(default_uwtable);

View File

@ -69,7 +69,7 @@ impl char {
/// assert_eq!(char::from_u32(value_at_max + 1), None); /// assert_eq!(char::from_u32(value_at_max + 1), None);
/// ``` /// ```
#[stable(feature = "assoc_char_consts", since = "1.52.0")] #[stable(feature = "assoc_char_consts", since = "1.52.0")]
pub const MAX: char = '\u{10ffff}'; pub const MAX: char = '\u{10FFFF}';
/// `U+FFFD REPLACEMENT CHARACTER` (<28>) is used in Unicode to represent a /// `U+FFFD REPLACEMENT CHARACTER` (<28>) is used in Unicode to represent a
/// decoding error. /// decoding error.
@ -1841,7 +1841,6 @@ pub const fn encode_utf16_raw(mut code: u32, dst: &mut [u16]) -> &mut [u16] {
} }
(2, [a, b, ..]) => { (2, [a, b, ..]) => {
code -= 0x1_0000; code -= 0x1_0000;
*a = (code >> 10) as u16 | 0xD800; *a = (code >> 10) as u16 | 0xD800;
*b = (code & 0x3FF) as u16 | 0xDC00; *b = (code & 0x3FF) as u16 | 0xDC00;
} }

View File

@ -1425,8 +1425,7 @@ extern "rust-intrinsic" {
/// ///
/// If the computed offset is non-zero, then both the starting and resulting pointer must be /// If the computed offset is non-zero, then both the starting and resulting pointer must be
/// either in bounds or at the end of an allocated object. If either pointer is out /// either in bounds or at the end of an allocated object. If either pointer is out
/// of bounds or arithmetic overflow occurs then any further use of the returned value will /// of bounds or arithmetic overflow occurs then this operation is undefined behavior.
/// result in undefined behavior.
/// ///
/// The stabilized version of this intrinsic is [`pointer::offset`]. /// The stabilized version of this intrinsic is [`pointer::offset`].
#[must_use = "returns a new pointer rather than modifying its argument"] #[must_use = "returns a new pointer rather than modifying its argument"]

View File

@ -346,7 +346,7 @@ impl<T: ?Sized> *const T {
if self.is_null() { None } else { Some(unsafe { &*(self as *const MaybeUninit<T>) }) } if self.is_null() { None } else { Some(unsafe { &*(self as *const MaybeUninit<T>) }) }
} }
/// Adds an offset to a pointer. /// Adds a signed offset to a pointer.
/// ///
/// `count` is in units of T; e.g., a `count` of 3 represents a pointer /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
/// offset of `3 * size_of::<T>()` bytes. /// offset of `3 * size_of::<T>()` bytes.
@ -355,7 +355,8 @@ impl<T: ?Sized> *const T {
/// ///
/// If any of the following conditions are violated, the result is Undefined Behavior: /// If any of the following conditions are violated, the result is Undefined Behavior:
/// ///
/// * The computed offset, `count * size_of::<T>()` bytes, must not overflow `isize`. /// * The offset in bytes, `count * size_of::<T>()`, computed on mathematical integers (without
/// "wrapping around"), must fit in an `isize`.
/// ///
/// * If the computed offset is non-zero, then `self` must be derived from a pointer to some /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some
/// [allocated object], and the entire memory range between `self` and the result must be in /// [allocated object], and the entire memory range between `self` and the result must be in
@ -398,7 +399,7 @@ impl<T: ?Sized> *const T {
unsafe { intrinsics::offset(self, count) } unsafe { intrinsics::offset(self, count) }
} }
/// Calculates the offset from a pointer in bytes. /// Adds a signed offset in bytes to a pointer.
/// ///
/// `count` is in units of **bytes**. /// `count` is in units of **bytes**.
/// ///
@ -418,7 +419,7 @@ impl<T: ?Sized> *const T {
unsafe { self.cast::<u8>().offset(count).with_metadata_of(self) } unsafe { self.cast::<u8>().offset(count).with_metadata_of(self) }
} }
/// Calculates the offset from a pointer using wrapping arithmetic. /// Adds a signed offset to a pointer using wrapping arithmetic.
/// ///
/// `count` is in units of T; e.g., a `count` of 3 represents a pointer /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
/// offset of `3 * size_of::<T>()` bytes. /// offset of `3 * size_of::<T>()` bytes.
@ -480,7 +481,7 @@ impl<T: ?Sized> *const T {
unsafe { intrinsics::arith_offset(self, count) } unsafe { intrinsics::arith_offset(self, count) }
} }
/// Calculates the offset from a pointer in bytes using wrapping arithmetic. /// Adds a signed offset in bytes to a pointer using wrapping arithmetic.
/// ///
/// `count` is in units of **bytes**. /// `count` is in units of **bytes**.
/// ///
@ -804,7 +805,11 @@ impl<T: ?Sized> *const T {
} }
} }
/// Adds an offset to a pointer (convenience for `.offset(count as isize)`). /// Adds an unsigned offset to a pointer.
///
/// This can only move the pointer forward (or not move it). If you need to move forward or
/// backward depending on the value, then you might want [`offset`](#method.offset) instead
/// which takes a signed offset.
/// ///
/// `count` is in units of T; e.g., a `count` of 3 represents a pointer /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
/// offset of `3 * size_of::<T>()` bytes. /// offset of `3 * size_of::<T>()` bytes.
@ -813,7 +818,8 @@ impl<T: ?Sized> *const T {
/// ///
/// If any of the following conditions are violated, the result is Undefined Behavior: /// If any of the following conditions are violated, the result is Undefined Behavior:
/// ///
/// * The computed offset, `count * size_of::<T>()` bytes, must not overflow `isize`. /// * The offset in bytes, `count * size_of::<T>()`, computed on mathematical integers (without
/// "wrapping around"), must fit in an `isize`.
/// ///
/// * If the computed offset is non-zero, then `self` must be derived from a pointer to some /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some
/// [allocated object], and the entire memory range between `self` and the result must be in /// [allocated object], and the entire memory range between `self` and the result must be in
@ -856,7 +862,7 @@ impl<T: ?Sized> *const T {
unsafe { intrinsics::offset(self, count) } unsafe { intrinsics::offset(self, count) }
} }
/// Calculates the offset from a pointer in bytes (convenience for `.byte_offset(count as isize)`). /// Adds an unsigned offset in bytes to a pointer.
/// ///
/// `count` is in units of bytes. /// `count` is in units of bytes.
/// ///
@ -876,8 +882,11 @@ impl<T: ?Sized> *const T {
unsafe { self.cast::<u8>().add(count).with_metadata_of(self) } unsafe { self.cast::<u8>().add(count).with_metadata_of(self) }
} }
/// Subtracts an offset from a pointer (convenience for /// Subtracts an unsigned offset from a pointer.
/// `.offset((count as isize).wrapping_neg())`). ///
/// This can only move the pointer backward (or not move it). If you need to move forward or
/// backward depending on the value, then you might want [`offset`](#method.offset) instead
/// which takes a signed offset.
/// ///
/// `count` is in units of T; e.g., a `count` of 3 represents a pointer /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
/// offset of `3 * size_of::<T>()` bytes. /// offset of `3 * size_of::<T>()` bytes.
@ -886,7 +895,8 @@ impl<T: ?Sized> *const T {
/// ///
/// If any of the following conditions are violated, the result is Undefined Behavior: /// If any of the following conditions are violated, the result is Undefined Behavior:
/// ///
/// * The computed offset, `count * size_of::<T>()` bytes, must not overflow `isize`. /// * The offset in bytes, `count * size_of::<T>()`, computed on mathematical integers (without
/// "wrapping around"), must fit in an `isize`.
/// ///
/// * If the computed offset is non-zero, then `self` must be derived from a pointer to some /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some
/// [allocated object], and the entire memory range between `self` and the result must be in /// [allocated object], and the entire memory range between `self` and the result must be in
@ -937,8 +947,7 @@ impl<T: ?Sized> *const T {
} }
} }
/// Calculates the offset from a pointer in bytes (convenience for /// Subtracts an unsigned offset in bytes from a pointer.
/// `.byte_offset((count as isize).wrapping_neg())`).
/// ///
/// `count` is in units of bytes. /// `count` is in units of bytes.
/// ///
@ -958,8 +967,7 @@ impl<T: ?Sized> *const T {
unsafe { self.cast::<u8>().sub(count).with_metadata_of(self) } unsafe { self.cast::<u8>().sub(count).with_metadata_of(self) }
} }
/// Calculates the offset from a pointer using wrapping arithmetic. /// Adds an unsigned offset to a pointer using wrapping arithmetic.
/// (convenience for `.wrapping_offset(count as isize)`)
/// ///
/// `count` is in units of T; e.g., a `count` of 3 represents a pointer /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
/// offset of `3 * size_of::<T>()` bytes. /// offset of `3 * size_of::<T>()` bytes.
@ -1020,8 +1028,7 @@ impl<T: ?Sized> *const T {
self.wrapping_offset(count as isize) self.wrapping_offset(count as isize)
} }
/// Calculates the offset from a pointer in bytes using wrapping arithmetic. /// Adds an unsigned offset in bytes to a pointer using wrapping arithmetic.
/// (convenience for `.wrapping_byte_offset(count as isize)`)
/// ///
/// `count` is in units of bytes. /// `count` is in units of bytes.
/// ///
@ -1038,8 +1045,7 @@ impl<T: ?Sized> *const T {
self.cast::<u8>().wrapping_add(count).with_metadata_of(self) self.cast::<u8>().wrapping_add(count).with_metadata_of(self)
} }
/// Calculates the offset from a pointer using wrapping arithmetic. /// Subtracts an unsigned offset from a pointer using wrapping arithmetic.
/// (convenience for `.wrapping_offset((count as isize).wrapping_neg())`)
/// ///
/// `count` is in units of T; e.g., a `count` of 3 represents a pointer /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
/// offset of `3 * size_of::<T>()` bytes. /// offset of `3 * size_of::<T>()` bytes.
@ -1100,8 +1106,7 @@ impl<T: ?Sized> *const T {
self.wrapping_offset((count as isize).wrapping_neg()) self.wrapping_offset((count as isize).wrapping_neg())
} }
/// Calculates the offset from a pointer in bytes using wrapping arithmetic. /// Subtracts an unsigned offset in bytes from a pointer using wrapping arithmetic.
/// (convenience for `.wrapping_offset((count as isize).wrapping_neg())`)
/// ///
/// `count` is in units of bytes. /// `count` is in units of bytes.
/// ///

View File

@ -344,7 +344,7 @@ impl<T: ?Sized> *mut T {
if self.is_null() { None } else { Some(unsafe { &*(self as *const MaybeUninit<T>) }) } if self.is_null() { None } else { Some(unsafe { &*(self as *const MaybeUninit<T>) }) }
} }
/// Adds an offset to a pointer. /// Adds a signed offset to a pointer.
/// ///
/// `count` is in units of T; e.g., a `count` of 3 represents a pointer /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
/// offset of `3 * size_of::<T>()` bytes. /// offset of `3 * size_of::<T>()` bytes.
@ -353,7 +353,8 @@ impl<T: ?Sized> *mut T {
/// ///
/// If any of the following conditions are violated, the result is Undefined Behavior: /// If any of the following conditions are violated, the result is Undefined Behavior:
/// ///
/// * The computed offset, `count * size_of::<T>()` bytes, must not overflow `isize`. /// * The offset in bytes, `count * size_of::<T>()`, computed on mathematical integers (without
/// "wrapping around"), must fit in an `isize`.
/// ///
/// * If the computed offset is non-zero, then `self` must be derived from a pointer to some /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some
/// [allocated object], and the entire memory range between `self` and the result must be in /// [allocated object], and the entire memory range between `self` and the result must be in
@ -398,7 +399,7 @@ impl<T: ?Sized> *mut T {
unsafe { intrinsics::offset(self, count) } unsafe { intrinsics::offset(self, count) }
} }
/// Calculates the offset from a pointer in bytes. /// Adds a signed offset in bytes to a pointer.
/// ///
/// `count` is in units of **bytes**. /// `count` is in units of **bytes**.
/// ///
@ -418,7 +419,8 @@ impl<T: ?Sized> *mut T {
unsafe { self.cast::<u8>().offset(count).with_metadata_of(self) } unsafe { self.cast::<u8>().offset(count).with_metadata_of(self) }
} }
/// Calculates the offset from a pointer using wrapping arithmetic. /// Adds a signed offset to a pointer using wrapping arithmetic.
///
/// `count` is in units of T; e.g., a `count` of 3 represents a pointer /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
/// offset of `3 * size_of::<T>()` bytes. /// offset of `3 * size_of::<T>()` bytes.
/// ///
@ -477,7 +479,7 @@ impl<T: ?Sized> *mut T {
unsafe { intrinsics::arith_offset(self, count) as *mut T } unsafe { intrinsics::arith_offset(self, count) as *mut T }
} }
/// Calculates the offset from a pointer in bytes using wrapping arithmetic. /// Adds a signed offset in bytes to a pointer using wrapping arithmetic.
/// ///
/// `count` is in units of **bytes**. /// `count` is in units of **bytes**.
/// ///
@ -885,7 +887,11 @@ impl<T: ?Sized> *mut T {
unsafe { (self as *const T).sub_ptr(origin) } unsafe { (self as *const T).sub_ptr(origin) }
} }
/// Adds an offset to a pointer (convenience for `.offset(count as isize)`). /// Adds an unsigned offset to a pointer.
///
/// This can only move the pointer forward (or not move it). If you need to move forward or
/// backward depending on the value, then you might want [`offset`](#method.offset) instead
/// which takes a signed offset.
/// ///
/// `count` is in units of T; e.g., a `count` of 3 represents a pointer /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
/// offset of `3 * size_of::<T>()` bytes. /// offset of `3 * size_of::<T>()` bytes.
@ -894,7 +900,8 @@ impl<T: ?Sized> *mut T {
/// ///
/// If any of the following conditions are violated, the result is Undefined Behavior: /// If any of the following conditions are violated, the result is Undefined Behavior:
/// ///
/// * The computed offset, `count * size_of::<T>()` bytes, must not overflow `isize`. /// * The offset in bytes, `count * size_of::<T>()`, computed on mathematical integers (without
/// "wrapping around"), must fit in an `isize`.
/// ///
/// * If the computed offset is non-zero, then `self` must be derived from a pointer to some /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some
/// [allocated object], and the entire memory range between `self` and the result must be in /// [allocated object], and the entire memory range between `self` and the result must be in
@ -937,7 +944,7 @@ impl<T: ?Sized> *mut T {
unsafe { intrinsics::offset(self, count) } unsafe { intrinsics::offset(self, count) }
} }
/// Calculates the offset from a pointer in bytes (convenience for `.byte_offset(count as isize)`). /// Adds an unsigned offset in bytes to a pointer.
/// ///
/// `count` is in units of bytes. /// `count` is in units of bytes.
/// ///
@ -957,8 +964,11 @@ impl<T: ?Sized> *mut T {
unsafe { self.cast::<u8>().add(count).with_metadata_of(self) } unsafe { self.cast::<u8>().add(count).with_metadata_of(self) }
} }
/// Subtracts an offset from a pointer (convenience for /// Subtracts an unsigned offset from a pointer.
/// `.offset((count as isize).wrapping_neg())`). ///
/// This can only move the pointer backward (or not move it). If you need to move forward or
/// backward depending on the value, then you might want [`offset`](#method.offset) instead
/// which takes a signed offset.
/// ///
/// `count` is in units of T; e.g., a `count` of 3 represents a pointer /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
/// offset of `3 * size_of::<T>()` bytes. /// offset of `3 * size_of::<T>()` bytes.
@ -967,7 +977,8 @@ impl<T: ?Sized> *mut T {
/// ///
/// If any of the following conditions are violated, the result is Undefined Behavior: /// If any of the following conditions are violated, the result is Undefined Behavior:
/// ///
/// * The computed offset, `count * size_of::<T>()` bytes, must not overflow `isize`. /// * The offset in bytes, `count * size_of::<T>()`, computed on mathematical integers (without
/// "wrapping around"), must fit in an `isize`.
/// ///
/// * If the computed offset is non-zero, then `self` must be derived from a pointer to some /// * If the computed offset is non-zero, then `self` must be derived from a pointer to some
/// [allocated object], and the entire memory range between `self` and the result must be in /// [allocated object], and the entire memory range between `self` and the result must be in
@ -1018,8 +1029,7 @@ impl<T: ?Sized> *mut T {
} }
} }
/// Calculates the offset from a pointer in bytes (convenience for /// Subtracts an unsigned offset in bytes from a pointer.
/// `.byte_offset((count as isize).wrapping_neg())`).
/// ///
/// `count` is in units of bytes. /// `count` is in units of bytes.
/// ///
@ -1039,8 +1049,7 @@ impl<T: ?Sized> *mut T {
unsafe { self.cast::<u8>().sub(count).with_metadata_of(self) } unsafe { self.cast::<u8>().sub(count).with_metadata_of(self) }
} }
/// Calculates the offset from a pointer using wrapping arithmetic. /// Adds an unsigned offset to a pointer using wrapping arithmetic.
/// (convenience for `.wrapping_offset(count as isize)`)
/// ///
/// `count` is in units of T; e.g., a `count` of 3 represents a pointer /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
/// offset of `3 * size_of::<T>()` bytes. /// offset of `3 * size_of::<T>()` bytes.
@ -1099,8 +1108,7 @@ impl<T: ?Sized> *mut T {
self.wrapping_offset(count as isize) self.wrapping_offset(count as isize)
} }
/// Calculates the offset from a pointer in bytes using wrapping arithmetic. /// Adds an unsigned offset in bytes to a pointer using wrapping arithmetic.
/// (convenience for `.wrapping_byte_offset(count as isize)`)
/// ///
/// `count` is in units of bytes. /// `count` is in units of bytes.
/// ///
@ -1117,8 +1125,7 @@ impl<T: ?Sized> *mut T {
self.cast::<u8>().wrapping_add(count).with_metadata_of(self) self.cast::<u8>().wrapping_add(count).with_metadata_of(self)
} }
/// Calculates the offset from a pointer using wrapping arithmetic. /// Subtracts an unsigned offset from a pointer using wrapping arithmetic.
/// (convenience for `.wrapping_offset((count as isize).wrapping_neg())`)
/// ///
/// `count` is in units of T; e.g., a `count` of 3 represents a pointer /// `count` is in units of T; e.g., a `count` of 3 represents a pointer
/// offset of `3 * size_of::<T>()` bytes. /// offset of `3 * size_of::<T>()` bytes.
@ -1177,8 +1184,7 @@ impl<T: ?Sized> *mut T {
self.wrapping_offset((count as isize).wrapping_neg()) self.wrapping_offset((count as isize).wrapping_neg())
} }
/// Calculates the offset from a pointer in bytes using wrapping arithmetic. /// Subtracts an unsigned offset in bytes from a pointer using wrapping arithmetic.
/// (convenience for `.wrapping_offset((count as isize).wrapping_neg())`)
/// ///
/// `count` is in units of bytes. /// `count` is in units of bytes.
/// ///

View File

@ -1,12 +0,0 @@
# `default-hidden-visibility`
The tracking issue for this feature is: https://github.com/rust-lang/compiler-team/issues/656
------------------------
This flag can be used to override the target's
[`default_hidden_visibility`](https://doc.rust-lang.org/beta/nightly-rustc/rustc_target/spec/struct.TargetOptions.html#structfield.default_hidden_visibility)
setting.
Using `-Zdefault_hidden_visibility=yes` is roughly equivalent to Clang's
[`-fvisibility=hidden`](https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fvisibility)
cmdline flag.

View File

@ -0,0 +1,44 @@
# `default-visibility`
The tracking issue for this feature is: https://github.com/rust-lang/rust/issues/131090
------------------------
This flag can be used to override the target's
[`default_visibility`](https://doc.rust-lang.org/beta/nightly-rustc/rustc_target/spec/struct.TargetOptions.html#structfield.default_visibility)
setting.
This option only affects building of shared objects and should have no effect on executables.
Visibility an be set to one of three options:
* protected
* hidden
* interposable
## Hidden visibility
Using `-Zdefault-visibility=hidden` is roughly equivalent to Clang's
[`-fvisibility=hidden`](https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fvisibility)
cmdline flag. Hidden symbols will not be exported from the created shared object, so cannot be
referenced from other shared objects or from executables.
## Protected visibility
Using `-Zdefault-visibility=protected` will cause rust-mangled symbols to be emitted with
"protected" visibility. This signals the compiler, the linker and the runtime linker that these
symbols cannot be overridden by the executable or by other shared objects earlier in the load order.
This will allow the compiler to emit direct references to symbols, which may improve performance. It
also removes the need for these symbols to be resolved when a shared object built with this option
is loaded.
Using protected visibility when linking with GNU ld prior to 2.40 will result in linker errors when
building for Linux. Other linkers such as LLD are not affected.
## Interposable
Using `-Zdefault-visibility=interposable` will cause symbols to be emitted with "default"
visibility. On platforms that support it, this makes it so that symbols can be interposed, which
means that they can be overridden by symbols with the same name from the executable or by other
shared objects earier in the load order.

View File

@ -960,6 +960,13 @@ pre, .rustdoc.src .example-wrap, .example-wrap .src-line-numbers {
display: inline-block; display: inline-block;
} }
.docblock li {
margin-bottom: .8em;
}
.docblock li p {
margin-bottom: .1em;
}
/* "where ..." clauses with block display are also smaller */ /* "where ..." clauses with block display are also smaller */
div.where { div.where {
white-space: pre-wrap; white-space: pre-wrap;

View File

@ -1,11 +1,12 @@
// Verifies that `Session::default_hidden_visibility` is affected when using the related cmdline // Verifies that `Session::default_visibility` is affected when using the related cmdline
// flag. This is a regression test for https://github.com/rust-lang/compiler-team/issues/656. See // flag. This is a regression test for https://github.com/rust-lang/compiler-team/issues/782. See
// also https://github.com/rust-lang/rust/issues/73295 and // also https://github.com/rust-lang/rust/issues/73295 and
// https://github.com/rust-lang/rust/issues/37530. // https://github.com/rust-lang/rust/issues/37530.
//@ revisions:DEFAULT YES NO //@ revisions:DEFAULT HIDDEN PROTECTED INTERPOSABLE
//@[YES] compile-flags: -Zdefault-hidden-visibility=yes //@[HIDDEN] compile-flags: -Zdefault-visibility=hidden
//@[NO] compile-flags: -Zdefault-hidden-visibility=no //@[PROTECTED] compile-flags: -Zdefault-visibility=protected
//@[INTERPOSABLE] compile-flags: -Zdefault-visibility=interposable
// The test scenario is specifically about visibility of symbols exported out of dynamically linked // The test scenario is specifically about visibility of symbols exported out of dynamically linked
// libraries. // libraries.
@ -26,6 +27,7 @@ pub static tested_symbol: [u8; 6] = *b"foobar";
// //
//@ only-x86_64-unknown-linux-gnu //@ only-x86_64-unknown-linux-gnu
// DEFAULT: @{{.*}}default_hidden_visibility{{.*}}tested_symbol{{.*}} = constant // HIDDEN: @{{.*}}default_visibility{{.*}}tested_symbol{{.*}} = hidden constant
// YES: @{{.*}}default_hidden_visibility{{.*}}tested_symbol{{.*}} = hidden constant // PROTECTED: @{{.*}}default_visibility{{.*}}tested_symbol{{.*}} = protected constant
// NO: @{{.*}}default_hidden_visibility{{.*}}tested_symbol{{.*}} = constant // INTERPOSABLE: @{{.*}}default_visibility{{.*}}tested_symbol{{.*}} = constant
// DEFAULT: @{{.*}}default_visibility{{.*}}tested_symbol{{.*}} = constant