Skip to content

Commit 5a7773a

Browse files
authored
Auto merge of rust-lang#35100 - GuillaumeGomez:rollup, r=GuillaumeGomez
Rollup of 7 pull requests - Successful merges: rust-lang#34258, rust-lang#34894, rust-lang#35050, rust-lang#35062, rust-lang#35066, rust-lang#35072, rust-lang#35087 - Failed merges:
2 parents 1523a54 + 5f5fdf6 commit 5a7773a

File tree

8 files changed

+206
-27
lines changed

8 files changed

+206
-27
lines changed

src/doc/book/closures.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -291,9 +291,9 @@ isn’t interesting. The next part is:
291291
# some_closure(1) }
292292
```
293293

294-
Because `Fn` is a trait, we can bound our generic with it. In this case, our
295-
closure takes a `i32` as an argument and returns an `i32`, and so the generic
296-
bound we use is `Fn(i32) -> i32`.
294+
Because `Fn` is a trait, we can use it as a bound for our generic type. In
295+
this case, our closure takes a `i32` as an argument and returns an `i32`, and
296+
so the generic bound we use is `Fn(i32) -> i32`.
297297

298298
There’s one other key point here: because we’re bounding a generic with a
299299
trait, this will get monomorphized, and therefore, we’ll be doing static

src/doc/book/ffi.md

+63-10
Original file line numberDiff line numberDiff line change
@@ -575,16 +575,69 @@ against `libc` and `libm` by default.
575575

576576
# The "nullable pointer optimization"
577577

578-
Certain types are defined to not be NULL. This includes references (`&T`,
579-
`&mut T`), boxes (`Box<T>`), and function pointers (`extern "abi" fn()`).
580-
When interfacing with C, pointers that might be NULL are often used.
581-
As a special case, a generic `enum` that contains exactly two variants, one of
582-
which contains no data and the other containing a single field, is eligible
583-
for the "nullable pointer optimization". When such an enum is instantiated
584-
with one of the non-nullable types, it is represented as a single pointer,
585-
and the non-data variant is represented as the NULL pointer. So
586-
`Option<extern "C" fn(c_int) -> c_int>` is how one represents a nullable
587-
function pointer using the C ABI.
578+
Certain Rust types are defined to never be `null`. This includes references (`&T`,
579+
`&mut T`), boxes (`Box<T>`), and function pointers (`extern "abi" fn()`). When
580+
interfacing with C, pointers that might be `null` are often used, which would seem to
581+
require some messy `transmute`s and/or unsafe code to handle conversions to/from Rust types.
582+
However, the language provides a workaround.
583+
584+
As a special case, an `enum` is eligible for the "nullable pointer optimization" if it contains
585+
exactly two variants, one of which contains no data and the other contains a field of one of the
586+
non-nullable types listed above. This means no extra space is required for a discriminant; rather,
587+
the empty variant is represented by putting a `null` value into the non-nullable field. This is
588+
called an "optimization", but unlike other optimizations it is guaranteed to apply to eligible
589+
types.
590+
591+
The most common type that takes advantage of the nullable pointer optimization is `Option<T>`,
592+
where `None` corresponds to `null`. So `Option<extern "C" fn(c_int) -> c_int>` is a correct way
593+
to represent a nullable function pointer using the C ABI (corresponding to the C type
594+
`int (*)(int)`).
595+
596+
Here is a contrived example. Let's say some C library has a facility for registering a
597+
callback, which gets called in certain situations. The callback is passed a function pointer
598+
and an integer and it is supposed to run the function with the integer as a parameter. So
599+
we have function pointers flying across the FFI boundary in both directions.
600+
601+
```rust
602+
# #![feature(libc)]
603+
extern crate libc;
604+
use libc::c_int;
605+
606+
# #[cfg(hidden)]
607+
extern "C" {
608+
/// Register the callback.
609+
fn register(cb: Option<extern "C" fn(Option<extern "C" fn(c_int) -> c_int>, c_int) -> c_int>);
610+
}
611+
# unsafe fn register(_: Option<extern "C" fn(Option<extern "C" fn(c_int) -> c_int>,
612+
# c_int) -> c_int>)
613+
# {}
614+
615+
/// This fairly useless function receives a function pointer and an integer
616+
/// from C, and returns the result of calling the function with the integer.
617+
/// In case no function is provided, it squares the integer by default.
618+
extern "C" fn apply(process: Option<extern "C" fn(c_int) -> c_int>, int: c_int) -> c_int {
619+
match process {
620+
Some(f) => f(int),
621+
None => int * int
622+
}
623+
}
624+
625+
fn main() {
626+
unsafe {
627+
register(Some(apply));
628+
}
629+
}
630+
```
631+
632+
And the code on the C side looks like this:
633+
634+
```c
635+
void register(void (*f)(void (*)(int), int)) {
636+
...
637+
}
638+
```
639+
640+
No `transmute` required!
588641
589642
# Calling Rust code from C
590643

src/libcollections/fmt.rs

+7-13
Original file line numberDiff line numberDiff line change
@@ -434,37 +434,31 @@
434434
//! in this case, if one uses the format string `{<arg>:<spec>.*}`, then the `<arg>` part refers
435435
//! to the *value* to print, and the `precision` must come in the input preceding `<arg>`.
436436
//!
437-
//! For example, these:
437+
//! For example, the following calls all print the same thing `Hello x is 0.01000`:
438438
//!
439439
//! ```
440-
//! // Hello {arg 0 (x)} is {arg 1 (0.01) with precision specified inline (5)}
440+
//! // Hello {arg 0 ("x")} is {arg 1 (0.01) with precision specified inline (5)}
441441
//! println!("Hello {0} is {1:.5}", "x", 0.01);
442442
//!
443-
//! // Hello {arg 1 (x)} is {arg 2 (0.01) with precision specified in arg 0 (5)}
443+
//! // Hello {arg 1 ("x")} is {arg 2 (0.01) with precision specified in arg 0 (5)}
444444
//! println!("Hello {1} is {2:.0$}", 5, "x", 0.01);
445445
//!
446-
//! // Hello {arg 0 (x)} is {arg 2 (0.01) with precision specified in arg 1 (5)}
446+
//! // Hello {arg 0 ("x")} is {arg 2 (0.01) with precision specified in arg 1 (5)}
447447
//! println!("Hello {0} is {2:.1$}", "x", 5, 0.01);
448448
//!
449-
//! // Hello {next arg (x)} is {second of next two args (0.01) with precision
449+
//! // Hello {next arg ("x")} is {second of next two args (0.01) with precision
450450
//! // specified in first of next two args (5)}
451451
//! println!("Hello {} is {:.*}", "x", 5, 0.01);
452452
//!
453-
//! // Hello {next arg (x)} is {arg 2 (0.01) with precision
453+
//! // Hello {next arg ("x")} is {arg 2 (0.01) with precision
454454
//! // specified in its predecessor (5)}
455455
//! println!("Hello {} is {2:.*}", "x", 5, 0.01);
456456
//!
457-
//! // Hello {next arg (x)} is {arg "number" (0.01) with precision specified
457+
//! // Hello {next arg ("x")} is {arg "number" (0.01) with precision specified
458458
//! // in arg "prec" (5)}
459459
//! println!("Hello {} is {number:.prec$}", "x", prec = 5, number = 0.01);
460460
//! ```
461461
//!
462-
//! All print the same thing:
463-
//!
464-
//! ```text
465-
//! Hello x is 0.01000
466-
//! ```
467-
//!
468462
//! While these:
469463
//!
470464
//! ```

src/libcore/macros.rs

+18
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,17 @@ macro_rules! panic {
3535
/// This will invoke the `panic!` macro if the provided expression cannot be
3636
/// evaluated to `true` at runtime.
3737
///
38+
/// Assertions are always checked in both debug and release builds, and cannot
39+
/// be disabled. See `debug_assert!` for assertions that are not enabled in
40+
/// release builds by default.
41+
///
42+
/// Unsafe code relies on `assert!` to enforce run-time invariants that, if
43+
/// violated could lead to unsafety.
44+
///
45+
/// Other use-cases of `assert!` include
46+
/// [testing](https://doc.rust-lang.org/book/testing.html) and enforcing
47+
/// run-time invariants in safe code (whose violation cannot result in unsafety).
48+
///
3849
/// This macro has a second version, where a custom panic message can be provided.
3950
///
4051
/// # Examples
@@ -123,6 +134,13 @@ macro_rules! assert_eq {
123134
/// expensive to be present in a release build but may be helpful during
124135
/// development.
125136
///
137+
/// An unchecked assertion allows a program in an inconsistent state to keep
138+
/// running, which might have unexpected consequences but does not introduce
139+
/// unsafety as long as this only happens in safe code. The performance cost
140+
/// of assertions, is however, not measurable in general. Replacing `assert!`
141+
/// with `debug_assert!` is thus only encouraged after thorough profiling, and
142+
/// more importantly, only in safe code!
143+
///
126144
/// # Examples
127145
///
128146
/// ```

src/libcore/str/mod.rs

+13
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,19 @@ impl<'a> Chars<'a> {
459459
///
460460
/// This has the same lifetime as the original slice, and so the
461461
/// iterator can continue to be used while this exists.
462+
///
463+
/// # Examples
464+
///
465+
/// ```
466+
/// let mut chars = "abc".chars();
467+
///
468+
/// assert_eq!(chars.as_str(), "abc");
469+
/// chars.next();
470+
/// assert_eq!(chars.as_str(), "bc");
471+
/// chars.next();
472+
/// chars.next();
473+
/// assert_eq!(chars.as_str(), "");
474+
/// ```
462475
#[stable(feature = "iter_to_slice", since = "1.4.0")]
463476
#[inline]
464477
pub fn as_str(&self) -> &'a str {

src/libpanic_unwind/dwarf/eh.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext) -> EHAction {
108108
}
109109
}
110110
}
111-
// Ip is not present in the table. This should not hapen... but it does: issie #35011.
111+
// Ip is not present in the table. This should not happen... but it does: issue #35011.
112112
// So rather than returning EHAction::Terminate, we do this.
113113
EHAction::None
114114
} else {

src/libstd/fs.rs

+51
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,23 @@ impl Metadata {
694694
///
695695
/// This field may not be available on all platforms, and will return an
696696
/// `Err` on platforms where it is not available.
697+
///
698+
/// # Examples
699+
///
700+
/// ```
701+
/// # fn foo() -> std::io::Result<()> {
702+
/// use std::fs;
703+
///
704+
/// let metadata = try!(fs::metadata("foo.txt"));
705+
///
706+
/// if let Ok(time) = metadata.modified() {
707+
/// println!("{:?}", time);
708+
/// } else {
709+
/// println!("Not supported on this platform");
710+
/// }
711+
/// # Ok(())
712+
/// # }
713+
/// ```
697714
#[stable(feature = "fs_time", since = "1.10.0")]
698715
pub fn modified(&self) -> io::Result<SystemTime> {
699716
self.0.modified().map(FromInner::from_inner)
@@ -712,6 +729,23 @@ impl Metadata {
712729
///
713730
/// This field may not be available on all platforms, and will return an
714731
/// `Err` on platforms where it is not available.
732+
///
733+
/// # Examples
734+
///
735+
/// ```
736+
/// # fn foo() -> std::io::Result<()> {
737+
/// use std::fs;
738+
///
739+
/// let metadata = try!(fs::metadata("foo.txt"));
740+
///
741+
/// if let Ok(time) = metadata.accessed() {
742+
/// println!("{:?}", time);
743+
/// } else {
744+
/// println!("Not supported on this platform");
745+
/// }
746+
/// # Ok(())
747+
/// # }
748+
/// ```
715749
#[stable(feature = "fs_time", since = "1.10.0")]
716750
pub fn accessed(&self) -> io::Result<SystemTime> {
717751
self.0.accessed().map(FromInner::from_inner)
@@ -726,6 +760,23 @@ impl Metadata {
726760
///
727761
/// This field may not be available on all platforms, and will return an
728762
/// `Err` on platforms where it is not available.
763+
///
764+
/// # Examples
765+
///
766+
/// ```
767+
/// # fn foo() -> std::io::Result<()> {
768+
/// use std::fs;
769+
///
770+
/// let metadata = try!(fs::metadata("foo.txt"));
771+
///
772+
/// if let Ok(time) = metadata.created() {
773+
/// println!("{:?}", time);
774+
/// } else {
775+
/// println!("Not supported on this platform");
776+
/// }
777+
/// # Ok(())
778+
/// # }
779+
/// ```
729780
#[stable(feature = "fs_time", since = "1.10.0")]
730781
pub fn created(&self) -> io::Result<SystemTime> {
731782
self.0.created().map(FromInner::from_inner)

src/libstd/sys/unix/ext/fs.rs

+50
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,53 @@ use sys::platform::fs::MetadataExt as UnixMetadataExt;
2525
pub trait PermissionsExt {
2626
/// Returns the underlying raw `mode_t` bits that are the standard Unix
2727
/// permissions for this file.
28+
///
29+
/// # Examples
30+
///
31+
/// ```rust,ignore
32+
/// use std::fs::File;
33+
/// use std::os::unix::fs::PermissionsExt;
34+
///
35+
/// let f = try!(File::create("foo.txt"));
36+
/// let metadata = try!(f.metadata());
37+
/// let permissions = metadata.permissions();
38+
///
39+
/// println!("permissions: {}", permissions.mode());
40+
/// ```
2841
#[stable(feature = "fs_ext", since = "1.1.0")]
2942
fn mode(&self) -> u32;
3043

3144
/// Sets the underlying raw bits for this set of permissions.
45+
///
46+
/// # Examples
47+
///
48+
/// ```rust,ignore
49+
/// use std::fs::File;
50+
/// use std::os::unix::fs::PermissionsExt;
51+
///
52+
/// let f = try!(File::create("foo.txt"));
53+
/// let metadata = try!(f.metadata());
54+
/// let mut permissions = metadata.permissions();
55+
///
56+
/// permissions.set_mode(0o644); // Read/write for owner and read for others.
57+
/// assert_eq!(permissions.mode(), 0o644);
58+
/// ```
3259
#[stable(feature = "fs_ext", since = "1.1.0")]
3360
fn set_mode(&mut self, mode: u32);
3461

3562
/// Creates a new instance of `Permissions` from the given set of Unix
3663
/// permission bits.
64+
///
65+
/// # Examples
66+
///
67+
/// ```rust,ignore
68+
/// use std::fs::Permissions;
69+
/// use std::os::unix::fs::PermissionsExt;
70+
///
71+
/// // Read/write for owner and read for others.
72+
/// let permissions = Permissions::from_mode(0o644);
73+
/// assert_eq!(permissions.mode(), 0o644);
74+
/// ```
3775
#[stable(feature = "fs_ext", since = "1.1.0")]
3876
fn from_mode(mode: u32) -> Self;
3977
}
@@ -63,6 +101,18 @@ pub trait OpenOptionsExt {
63101
/// If no `mode` is set, the default of `0o666` will be used.
64102
/// The operating system masks out bits with the systems `umask`, to produce
65103
/// the final permissions.
104+
///
105+
/// # Examples
106+
///
107+
/// ```rust,ignore
108+
/// extern crate libc;
109+
/// use std::fs::OpenOptions;
110+
/// use std::os::unix::fs::OpenOptionsExt;
111+
///
112+
/// let mut options = OpenOptions::new();
113+
/// options.mode(0o644); // Give read/write for owner and read for others.
114+
/// let file = options.open("foo.txt");
115+
/// ```
66116
#[stable(feature = "fs_ext", since = "1.1.0")]
67117
fn mode(&mut self, mode: u32) -> &mut Self;
68118

0 commit comments

Comments
 (0)