Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 9 pull requests #72416

Closed
wants to merge 27 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
68f89fc
Make `std::char` functions and constants associated to `char`.
eduardosm May 3, 2020
0e12a9d
Try to fix doc links in new `char` methods.
eduardosm May 3, 2020
1899afa
rustc-book: Document `-Z strip=val` option
petrochenkov May 11, 2020
7d2f64b
librustc_mir: Add support for const fn offset/arith_offset
josephlr Apr 24, 2020
1711d08
core: Make pointer offset methods "const fn"
josephlr Apr 24, 2020
db56719
test/ui/consts: Add tests for const ptr offsets
josephlr May 15, 2020
0927917
miri_unleached: We now allow offset in const fn
josephlr May 18, 2020
fdc4522
Remove unused `StableHashingContext::node_to_hir_id` method
marmeladema May 19, 2020
abc2364
Implement `#[ffi_const]` and `#[ffi_pure]` function attributes
neocturne Apr 13, 2020
a7d7f0b
Add tests for `#[ffi_const]` and `#[ffi_pure]` function attributes
neocturne Apr 13, 2020
a114a23
Document `#[ffi_const]` and `#[ffi_pure]` function attributes in unst…
neocturne Apr 13, 2020
f5b4957
FIX - Char documentation for unexperienced users
May 20, 2020
2fd504c
Suggest installing VS Build Tools in more situations
ChrisDenton May 17, 2020
4b2266b
Add ClashingLocalDecl test case.
jumbatm Mar 31, 2020
85979f5
Add ClashingExternDecl lint.
jumbatm Apr 5, 2020
b389eed
Add clashing-extern-fn.rs stderr.
jumbatm Apr 5, 2020
337abf1
Update existing test cases.
jumbatm Apr 6, 2020
c7813ff
llvm: Expose tiny code model to users
petrochenkov May 20, 2020
d4d994a
Rollup merge of #70946 - jumbatm:clashing-extern-decl, r=nagisa
RalfJung May 21, 2020
7a46e28
Rollup merge of #71500 - josephlr:offset, r=oli-obk
RalfJung May 21, 2020
e89a99d
Rollup merge of #71718 - NeoRaider:ffi_const_pure, r=Amanieu
RalfJung May 21, 2020
62a85df
Rollup merge of #71854 - eduardosm:assoc-char-funcs-and-consts, r=Ama…
RalfJung May 21, 2020
6a11087
Rollup merge of #72111 - petrochenkov:docstrip, r=ehuss
RalfJung May 21, 2020
0f17a7c
Rollup merge of #72296 - ChrisDenton:msvc-link-check, r=petrochenkov
RalfJung May 21, 2020
ec4edbc
Rollup merge of #72365 - marmeladema:remove-node_to_hir_id, r=ecstati…
RalfJung May 21, 2020
1cef9bf
Rollup merge of #72371 - Elrendio:char_documentation, r=steveklabnik
RalfJung May 21, 2020
fcd93b7
Rollup merge of #72397 - petrochenkov:tiny, r=Amanieu
RalfJung May 21, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/doc/rustc/src/codegen-options/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ specification.

Supported values for this option are:

<!-- - `tiny` - Tiny code model. -->
- `tiny` - Tiny code model.
- `small` - Small code model. This is the default model for majority of supported targets.
- `kernel` - Kernel code model.
- `medium` - Medium code model.
Expand Down
17 changes: 17 additions & 0 deletions src/doc/unstable-book/src/compiler-flags/strip.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# `strip`

The tracking issue for this feature is: [#72110](https://github.com/rust-lang/rust/issues/72110).

------------------------

Option `-Z strip=val` controls stripping of debuginfo and similar auxiliary data from binaries
during linking.

Supported values for this option are:

- `none` - debuginfo and symbols (if they exist) are copied to the produced binary or separate files
depending on the target (e.g. `.pdb` files in case of MSVC).
- `debuginfo` - debuginfo sections and debuginfo symbols from the symbol table section
are stripped at link time and are not copied to the produced binary or separate files.
- `symbols` - same as `debuginfo`, but the rest of the symbol table section is stripped as well
if the linker supports it.
47 changes: 47 additions & 0 deletions src/doc/unstable-book/src/language-features/ffi-const.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# `ffi_const`

The `#[ffi_const]` attribute applies clang's `const` attribute to foreign
functions declarations.

That is, `#[ffi_const]` functions shall have no effects except for its return
value, which can only depend on the values of the function parameters, and is
not affected by changes to the observable state of the program.

Applying the `#[ffi_const]` attribute to a function that violates these
requirements is undefined behaviour.

This attribute enables Rust to perform common optimizations, like sub-expression
elimination, and it can avoid emitting some calls in repeated invocations of the
function with the same argument values regardless of other operations being
performed in between these functions calls (as opposed to `#[ffi_pure]`
functions).

## Pitfalls

A `#[ffi_const]` function can only read global memory that would not affect
its return value for the whole execution of the program (e.g. immutable global
memory). `#[ffi_const]` functions are referentially-transparent and therefore
more strict than `#[ffi_pure]` functions.

A common pitfall involves applying the `#[ffi_const]` attribute to a
function that reads memory through pointer arguments which do not necessarily
point to immutable global memory.

A `#[ffi_const]` function that returns unit has no effect on the abstract
machine's state, and a `#[ffi_const]` function cannot be `#[ffi_pure]`.

A `#[ffi_const]` function must not diverge, neither via a side effect (e.g. a
call to `abort`) nor by infinite loops.

When translating C headers to Rust FFI, it is worth verifying for which targets
the `const` attribute is enabled in those headers, and using the appropriate
`cfg` macros in the Rust side to match those definitions. While the semantics of
`const` are implemented identically by many C and C++ compilers, e.g., clang,
[GCC], [ARM C/C++ compiler], [IBM ILE C/C++], etc. they are not necessarily
implemented in this way on all of them. It is therefore also worth verifying
that the semantics of the C toolchain used to compile the binary being linked
against are compatible with those of the `#[ffi_const]`.

[ARM C/C++ compiler]: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0491c/Cacgigch.html
[GCC]: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-const-function-attribute
[IBM ILE C/C++]: https://www.ibm.com/support/knowledgecenter/fr/ssw_ibm_i_71/rzarg/fn_attrib_const.htm
51 changes: 51 additions & 0 deletions src/doc/unstable-book/src/language-features/ffi-pure.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# `ffi_pure`

The `#[ffi_pure]` attribute applies clang's `pure` attribute to foreign
functions declarations.

That is, `#[ffi_pure]` functions shall have no effects except for its return
value, which shall not change across two consecutive function calls with
the same parameters.

Applying the `#[ffi_pure]` attribute to a function that violates these
requirements is undefined behavior.

This attribute enables Rust to perform common optimizations, like sub-expression
elimination and loop optimizations. Some common examples of pure functions are
`strlen` or `memcmp`.

These optimizations are only applicable when the compiler can prove that no
program state observable by the `#[ffi_pure]` function has changed between calls
of the function, which could alter the result. See also the `#[ffi_const]`
attribute, which provides stronger guarantees regarding the allowable behavior
of a function, enabling further optimization.

## Pitfalls

A `#[ffi_pure]` function can read global memory through the function
parameters (e.g. pointers), globals, etc. `#[ffi_pure]` functions are not
referentially-transparent, and are therefore more relaxed than `#[ffi_const]`
functions.

However, accesing global memory through volatile or atomic reads can violate the
requirement that two consecutive function calls shall return the same value.

A `pure` function that returns unit has no effect on the abstract machine's
state.

A `#[ffi_pure]` function must not diverge, neither via a side effect (e.g. a
call to `abort`) nor by infinite loops.

When translating C headers to Rust FFI, it is worth verifying for which targets
the `pure` attribute is enabled in those headers, and using the appropriate
`cfg` macros in the Rust side to match those definitions. While the semantics of
`pure` are implemented identically by many C and C++ compilers, e.g., clang,
[GCC], [ARM C/C++ compiler], [IBM ILE C/C++], etc. they are not necessarily
implemented in this way on all of them. It is therefore also worth verifying
that the semantics of the C toolchain used to compile the binary being linked
against are compatible with those of the `#[ffi_pure]`.


[ARM C/C++ compiler]: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0491c/Cacigdac.html
[GCC]: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-pure-function-attribute
[IBM ILE C/C++]: https://www.ibm.com/support/knowledgecenter/fr/ssw_ibm_i_71/rzarg/fn_attrib_pure.htm
243 changes: 241 additions & 2 deletions src/libcore/char/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,243 @@ use super::*;

#[lang = "char"]
impl char {
/// The highest valid code point a `char` can have.
///
/// A `char` is a [Unicode Scalar Value], which means that it is a [Code
/// Point], but only ones within a certain range. `MAX` is the highest valid
/// code point that's a valid [Unicode Scalar Value].
///
/// [Unicode Scalar Value]: http://www.unicode.org/glossary/#unicode_scalar_value
/// [Code Point]: http://www.unicode.org/glossary/#code_point
#[unstable(feature = "assoc_char_consts", reason = "recently added", issue = "71763")]
pub const MAX: char = '\u{10ffff}';

/// `U+FFFD REPLACEMENT CHARACTER` (�) is used in Unicode to represent a
/// decoding error.
///
/// It can occur, for example, when giving ill-formed UTF-8 bytes to
/// [`String::from_utf8_lossy`](string/struct.String.html#method.from_utf8_lossy).
#[unstable(feature = "assoc_char_consts", reason = "recently added", issue = "71763")]
pub const REPLACEMENT_CHARACTER: char = '\u{FFFD}';

/// The version of [Unicode](http://www.unicode.org/) that the Unicode parts of
/// `char` and `str` methods are based on.
///
/// New versions of Unicode are released regularly and subsequently all methods
/// in the standard library depending on Unicode are updated. Therefore the
/// behavior of some `char` and `str` methods and the value of this constant
/// changes over time. This is *not* considered to be a breaking change.
///
/// The version numbering scheme is explained in
/// [Unicode 11.0 or later, Section 3.1 Versions of the Unicode Standard](https://www.unicode.org/versions/Unicode11.0.0/ch03.pdf#page=4).
#[unstable(feature = "assoc_char_consts", reason = "recently added", issue = "71763")]
pub const UNICODE_VERSION: (u8, u8, u8) = crate::unicode::UNICODE_VERSION;

/// Creates an iterator over the UTF-16 encoded code points in `iter`,
/// returning unpaired surrogates as `Err`s.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// use std::char::decode_utf16;
///
/// // 𝄞mus<invalid>ic<invalid>
/// let v = [
/// 0xD834, 0xDD1E, 0x006d, 0x0075, 0x0073, 0xDD1E, 0x0069, 0x0063, 0xD834,
/// ];
///
/// assert_eq!(
/// decode_utf16(v.iter().cloned())
/// .map(|r| r.map_err(|e| e.unpaired_surrogate()))
/// .collect::<Vec<_>>(),
/// vec![
/// Ok('𝄞'),
/// Ok('m'), Ok('u'), Ok('s'),
/// Err(0xDD1E),
/// Ok('i'), Ok('c'),
/// Err(0xD834)
/// ]
/// );
/// ```
///
/// A lossy decoder can be obtained by replacing `Err` results with the replacement character:
///
/// ```
/// use std::char::{decode_utf16, REPLACEMENT_CHARACTER};
///
/// // 𝄞mus<invalid>ic<invalid>
/// let v = [
/// 0xD834, 0xDD1E, 0x006d, 0x0075, 0x0073, 0xDD1E, 0x0069, 0x0063, 0xD834,
/// ];
///
/// assert_eq!(
/// decode_utf16(v.iter().cloned())
/// .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
/// .collect::<String>(),
/// "𝄞mus�ic�"
/// );
/// ```
#[unstable(feature = "assoc_char_funcs", reason = "recently added", issue = "71763")]
#[inline]
pub fn decode_utf16<I: IntoIterator<Item = u16>>(iter: I) -> DecodeUtf16<I::IntoIter> {
super::decode::decode_utf16(iter)
}

/// Converts a `u32` to a `char`.
///
/// Note that all `char`s are valid [`u32`]s, and can be cast to one with
/// `as`:
///
/// ```
/// let c = '💯';
/// let i = c as u32;
///
/// assert_eq!(128175, i);
/// ```
///
/// However, the reverse is not true: not all valid [`u32`]s are valid
/// `char`s. `from_u32()` will return `None` if the input is not a valid value
/// for a `char`.
///
/// [`u32`]: primitive.u32.html
///
/// For an unsafe version of this function which ignores these checks, see
/// [`from_u32_unchecked`].
///
/// [`from_u32_unchecked`]: #method.from_u32_unchecked
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// use std::char;
///
/// let c = char::from_u32(0x2764);
///
/// assert_eq!(Some('❤'), c);
/// ```
///
/// Returning `None` when the input is not a valid `char`:
///
/// ```
/// use std::char;
///
/// let c = char::from_u32(0x110000);
///
/// assert_eq!(None, c);
/// ```
#[unstable(feature = "assoc_char_funcs", reason = "recently added", issue = "71763")]
#[inline]
pub fn from_u32(i: u32) -> Option<char> {
super::convert::from_u32(i)
}

/// Converts a `u32` to a `char`, ignoring validity.
///
/// Note that all `char`s are valid [`u32`]s, and can be cast to one with
/// `as`:
///
/// ```
/// let c = '💯';
/// let i = c as u32;
///
/// assert_eq!(128175, i);
/// ```
///
/// However, the reverse is not true: not all valid [`u32`]s are valid
/// `char`s. `from_u32_unchecked()` will ignore this, and blindly cast to
/// `char`, possibly creating an invalid one.
///
/// [`u32`]: primitive.u32.html
///
/// # Safety
///
/// This function is unsafe, as it may construct invalid `char` values.
///
/// For a safe version of this function, see the [`from_u32`] function.
///
/// [`from_u32`]: #method.from_u32
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// use std::char;
///
/// let c = unsafe { char::from_u32_unchecked(0x2764) };
///
/// assert_eq!('❤', c);
/// ```
#[unstable(feature = "assoc_char_funcs", reason = "recently added", issue = "71763")]
#[inline]
pub unsafe fn from_u32_unchecked(i: u32) -> char {
super::convert::from_u32_unchecked(i)
}

/// Converts a digit in the given radix to a `char`.
///
/// A 'radix' here is sometimes also called a 'base'. A radix of two
/// indicates a binary number, a radix of ten, decimal, and a radix of
/// sixteen, hexadecimal, to give some common values. Arbitrary
/// radices are supported.
///
/// `from_digit()` will return `None` if the input is not a digit in
/// the given radix.
///
/// # Panics
///
/// Panics if given a radix larger than 36.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// use std::char;
///
/// let c = char::from_digit(4, 10);
///
/// assert_eq!(Some('4'), c);
///
/// // Decimal 11 is a single digit in base 16
/// let c = char::from_digit(11, 16);
///
/// assert_eq!(Some('b'), c);
/// ```
///
/// Returning `None` when the input is not a digit:
///
/// ```
/// use std::char;
///
/// let c = char::from_digit(20, 10);
///
/// assert_eq!(None, c);
/// ```
///
/// Passing a large radix, causing a panic:
///
/// ```
/// use std::thread;
/// use std::char;
///
/// let result = thread::spawn(|| {
/// // this panics
/// let c = char::from_digit(1, 37);
/// }).join();
///
/// assert!(result.is_err());
/// ```
#[unstable(feature = "assoc_char_funcs", reason = "recently added", issue = "71763")]
#[inline]
pub fn from_digit(num: u32, radix: u32) -> Option<char> {
super::convert::from_digit(num, radix)
}

/// Checks if a `char` is a digit in the given radix.
///
/// A 'radix' here is sometimes also called a 'base'. A radix of two
Expand Down Expand Up @@ -575,8 +812,9 @@ impl char {
/// assert!(!'A'.is_lowercase());
/// assert!(!'Δ'.is_lowercase());
///
/// // The various Chinese scripts do not have case, and so:
/// // The various Chinese scripts and punctuation do not have case, and so:
/// assert!(!'中'.is_lowercase());
/// assert!(!' '.is_lowercase());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
Expand Down Expand Up @@ -606,8 +844,9 @@ impl char {
/// assert!('A'.is_uppercase());
/// assert!('Δ'.is_uppercase());
///
/// // The various Chinese scripts do not have case, and so:
/// // The various Chinese scripts and punctuation do not have case, and so:
/// assert!(!'中'.is_uppercase());
/// assert!(!' '.is_uppercase());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
Expand Down
Loading