Skip to content

Commit f284f8b

Browse files
committed
Auto merge of #67246 - JohnTitor:rollup-nfa7skn, r=JohnTitor
Rollup of 8 pull requests Successful merges: - #62514 (Clarify `Box<T>` representation and its use in FFI) - #66983 (Fix `unused_parens` triggers on macro by example code) - #67215 (Fix `-Z print-type-sizes`'s handling of zero-sized fields.) - #67230 (Remove irelevant comment on `register_dtor`) - #67236 (resolve: Always resolve visibilities on impl items) - #67237 (Some small readability improvements) - #67238 (Small std::borrow::Cow improvements) - #67239 (Make TinyList::remove iterate instead of recurse) Failed merges: r? @ghost
2 parents de0abf7 + 685d4cc commit f284f8b

18 files changed

+220
-100
lines changed

src/liballoc/borrow.rs

+5-13
Original file line numberDiff line numberDiff line change
@@ -195,14 +195,10 @@ impl<B: ?Sized + ToOwned> Clone for Cow<'_, B> {
195195
}
196196

197197
fn clone_from(&mut self, source: &Self) {
198-
if let Owned(ref mut dest) = *self {
199-
if let Owned(ref o) = *source {
200-
o.borrow().clone_into(dest);
201-
return;
202-
}
198+
match (self, source) {
199+
(&mut Owned(ref mut dest), &Owned(ref o)) => o.borrow().clone_into(dest),
200+
(t, s) => *t = s.clone(),
203201
}
204-
205-
*self = source.clone();
206202
}
207203
}
208204

@@ -449,9 +445,7 @@ impl<'a> AddAssign<&'a str> for Cow<'a, str> {
449445
fn add_assign(&mut self, rhs: &'a str) {
450446
if self.is_empty() {
451447
*self = Cow::Borrowed(rhs)
452-
} else if rhs.is_empty() {
453-
return;
454-
} else {
448+
} else if !rhs.is_empty() {
455449
if let Cow::Borrowed(lhs) = *self {
456450
let mut s = String::with_capacity(lhs.len() + rhs.len());
457451
s.push_str(lhs);
@@ -467,9 +461,7 @@ impl<'a> AddAssign<Cow<'a, str>> for Cow<'a, str> {
467461
fn add_assign(&mut self, rhs: Cow<'a, str>) {
468462
if self.is_empty() {
469463
*self = rhs
470-
} else if rhs.is_empty() {
471-
return;
472-
} else {
464+
} else if !rhs.is_empty() {
473465
if let Cow::Borrowed(lhs) = *self {
474466
let mut s = String::with_capacity(lhs.len() + rhs.len());
475467
s.push_str(lhs);

src/liballoc/boxed.rs

+53
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,60 @@
6161
//! T` obtained from [`Box::<T>::into_raw`] may be deallocated using the
6262
//! [`Global`] allocator with [`Layout::for_value(&*value)`].
6363
//!
64+
//! So long as `T: Sized`, a `Box<T>` is guaranteed to be represented
65+
//! as a single pointer and is also ABI-compatible with C pointers
66+
//! (i.e. the C type `T*`). This means that if you have extern "C"
67+
//! Rust functions that will be called from C, you can define those
68+
//! Rust functions using `Box<T>` types, and use `T*` as corresponding
69+
//! type on the C side. As an example, consider this C header which
70+
//! declares functions that create and destroy some kind of `Foo`
71+
//! value:
6472
//!
73+
//! ```c
74+
//! /* C header */
75+
//!
76+
//! /* Returns ownership to the caller */
77+
//! struct Foo* foo_new(void);
78+
//!
79+
//! /* Takes ownership from the caller; no-op when invoked with NULL */
80+
//! void foo_delete(struct Foo*);
81+
//! ```
82+
//!
83+
//! These two functions might be implemented in Rust as follows. Here, the
84+
//! `struct Foo*` type from C is translated to `Box<Foo>`, which captures
85+
//! the ownership constraints. Note also that the nullable argument to
86+
//! `foo_delete` is represented in Rust as `Option<Box<Foo>>`, since `Box<Foo>`
87+
//! cannot be null.
88+
//!
89+
//! ```
90+
//! #[repr(C)]
91+
//! pub struct Foo;
92+
//!
93+
//! #[no_mangle]
94+
//! pub extern "C" fn foo_new() -> Box<Foo> {
95+
//! Box::new(Foo)
96+
//! }
97+
//!
98+
//! #[no_mangle]
99+
//! pub extern "C" fn foo_delete(_: Option<Box<Foo>>) {}
100+
//! ```
101+
//!
102+
//! Even though `Box<T>` has the same representation and C ABI as a C pointer,
103+
//! this does not mean that you can convert an arbitrary `T*` into a `Box<T>`
104+
//! and expect things to work. `Box<T>` values will always be fully aligned,
105+
//! non-null pointers. Moreover, the destructor for `Box<T>` will attempt to
106+
//! free the value with the global allocator. In general, the best practice
107+
//! is to only use `Box<T>` for pointers that originated from the global
108+
//! allocator.
109+
//!
110+
//! **Important.** At least at present, you should avoid using
111+
//! `Box<T>` types for functions that are defined in C but invoked
112+
//! from Rust. In those cases, you should directly mirror the C types
113+
//! as closely as possible. Using types like `Box<T>` where the C
114+
//! definition is just using `T*` can lead to undefined behavior, as
115+
//! described in [rust-lang/unsafe-code-guidelines#198][ucg#198].
116+
//!
117+
//! [ucg#198]: https://github.com/rust-lang/unsafe-code-guidelines/issues/198
65118
//! [dereferencing]: ../../std/ops/trait.Deref.html
66119
//! [`Box`]: struct.Box.html
67120
//! [`Box<T>`]: struct.Box.html

src/liballoc/tests/cow_str.rs

+3
Original file line numberDiff line numberDiff line change
@@ -138,4 +138,7 @@ fn check_cow_clone_from() {
138138
let c2: Cow<'_, str> = Cow::Owned(s);
139139
c1.clone_from(&c2);
140140
assert!(c1.into_owned().capacity() >= 25);
141+
let mut c3: Cow<'_, str> = Cow::Borrowed("bye");
142+
c3.clone_from(&c2);
143+
assert_eq!(c2, c3);
141144
}

src/libcore/char/methods.rs

+5-10
Original file line numberDiff line numberDiff line change
@@ -553,8 +553,7 @@ impl char {
553553
pub fn is_alphabetic(self) -> bool {
554554
match self {
555555
'a'..='z' | 'A'..='Z' => true,
556-
c if c > '\x7f' => derived_property::Alphabetic(c),
557-
_ => false,
556+
c => c > '\x7f' && derived_property::Alphabetic(c),
558557
}
559558
}
560559

@@ -585,8 +584,7 @@ impl char {
585584
pub fn is_lowercase(self) -> bool {
586585
match self {
587586
'a'..='z' => true,
588-
c if c > '\x7f' => derived_property::Lowercase(c),
589-
_ => false,
587+
c => c > '\x7f' && derived_property::Lowercase(c),
590588
}
591589
}
592590

@@ -617,8 +615,7 @@ impl char {
617615
pub fn is_uppercase(self) -> bool {
618616
match self {
619617
'A'..='Z' => true,
620-
c if c > '\x7f' => derived_property::Uppercase(c),
621-
_ => false,
618+
c => c > '\x7f' && derived_property::Uppercase(c),
622619
}
623620
}
624621

@@ -646,8 +643,7 @@ impl char {
646643
pub fn is_whitespace(self) -> bool {
647644
match self {
648645
' ' | '\x09'..='\x0d' => true,
649-
c if c > '\x7f' => property::White_Space(c),
650-
_ => false,
646+
c => c > '\x7f' && property::White_Space(c),
651647
}
652648
}
653649

@@ -744,8 +740,7 @@ impl char {
744740
pub fn is_numeric(self) -> bool {
745741
match self {
746742
'0'..='9' => true,
747-
c if c > '\x7f' => general_category::N(c),
748-
_ => false,
743+
c => c > '\x7f' && general_category::N(c),
749744
}
750745
}
751746

src/libcore/str/pattern.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -296,12 +296,7 @@ unsafe impl<'a> Searcher<'a> for CharSearcher<'a> {
296296
fn next_match(&mut self) -> Option<(usize, usize)> {
297297
loop {
298298
// get the haystack after the last character found
299-
let bytes = if let Some(slice) = self.haystack.as_bytes()
300-
.get(self.finger..self.finger_back) {
301-
slice
302-
} else {
303-
return None;
304-
};
299+
let bytes = self.haystack.as_bytes().get(self.finger..self.finger_back)?;
305300
// the last byte of the utf8 encoded needle
306301
let last_byte = unsafe { *self.utf8_encoded.get_unchecked(self.utf8_size - 1) };
307302
if let Some(index) = memchr::memchr(last_byte, bytes) {

src/librustc_data_structures/tiny_list.rs

+16-24
Original file line numberDiff line numberDiff line change
@@ -16,41 +16,29 @@ mod tests;
1616

1717
#[derive(Clone)]
1818
pub struct TinyList<T: PartialEq> {
19-
head: Option<Element<T>>
19+
head: Option<Element<T>>,
2020
}
2121

2222
impl<T: PartialEq> TinyList<T> {
2323
#[inline]
2424
pub fn new() -> TinyList<T> {
25-
TinyList {
26-
head: None
27-
}
25+
TinyList { head: None }
2826
}
2927

3028
#[inline]
3129
pub fn new_single(data: T) -> TinyList<T> {
32-
TinyList {
33-
head: Some(Element {
34-
data,
35-
next: None,
36-
})
37-
}
30+
TinyList { head: Some(Element { data, next: None }) }
3831
}
3932

4033
#[inline]
4134
pub fn insert(&mut self, data: T) {
42-
self.head = Some(Element {
43-
data,
44-
next: self.head.take().map(Box::new)
45-
});
35+
self.head = Some(Element { data, next: self.head.take().map(Box::new) });
4636
}
4737

4838
#[inline]
4939
pub fn remove(&mut self, data: &T) -> bool {
5040
self.head = match self.head {
51-
Some(ref mut head) if head.data == *data => {
52-
head.next.take().map(|x| *x)
53-
}
41+
Some(ref mut head) if head.data == *data => head.next.take().map(|x| *x),
5442
Some(ref mut head) => return head.remove_next(data),
5543
None => return false,
5644
};
@@ -88,12 +76,16 @@ struct Element<T: PartialEq> {
8876

8977
impl<T: PartialEq> Element<T> {
9078
fn remove_next(&mut self, data: &T) -> bool {
91-
let new_next = match self.next {
92-
Some(ref mut next) if next.data == *data => next.next.take(),
93-
Some(ref mut next) => return next.remove_next(data),
94-
None => return false,
95-
};
96-
self.next = new_next;
97-
true
79+
let mut n = self;
80+
loop {
81+
match n.next {
82+
Some(ref mut next) if next.data == *data => {
83+
n.next = next.next.take();
84+
return true;
85+
}
86+
Some(ref mut next) => n = next,
87+
None => return false,
88+
}
89+
}
9890
}
9991
}

src/librustc_lint/unused.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,9 @@ impl UnusedParens {
355355
match value.kind {
356356
ast::ExprKind::Paren(ref inner) => {
357357
if !Self::is_expr_parens_necessary(inner, followed_by_block) &&
358-
value.attrs.is_empty() {
358+
value.attrs.is_empty() &&
359+
!value.span.from_expansion()
360+
{
359361
let expr_text = if let Ok(snippet) = cx.sess().source_map()
360362
.span_to_snippet(value.span) {
361363
snippet

src/librustc_resolve/build_reduced_graph.rs

+12-12
Original file line numberDiff line numberDiff line change
@@ -647,8 +647,6 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
647647
self.r.define(parent, ident, TypeNS, imported_binding);
648648
}
649649

650-
ItemKind::GlobalAsm(..) => {}
651-
652650
ItemKind::Mod(..) if ident.name == kw::Invalid => {} // Crate root
653651

654652
ItemKind::Mod(..) => {
@@ -667,9 +665,6 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
667665
self.parent_scope.module = module;
668666
}
669667

670-
// Handled in `rustc_metadata::{native_libs,link_args}`
671-
ItemKind::ForeignMod(..) => {}
672-
673668
// These items live in the value namespace.
674669
ItemKind::Static(..) => {
675670
let res = Res::Def(DefKind::Static, self.r.definitions.local_def_id(item.id));
@@ -765,12 +760,6 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
765760
self.insert_field_names_local(def_id, vdata);
766761
}
767762

768-
ItemKind::Impl(.., ref impl_items) => {
769-
for impl_item in impl_items {
770-
self.resolve_visibility(&impl_item.vis);
771-
}
772-
}
773-
774763
ItemKind::Trait(..) => {
775764
let def_id = self.r.definitions.local_def_id(item.id);
776765

@@ -785,6 +774,9 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
785774
self.parent_scope.module = module;
786775
}
787776

777+
// These items do not add names to modules.
778+
ItemKind::Impl(..) | ItemKind::ForeignMod(..) | ItemKind::GlobalAsm(..) => {}
779+
788780
ItemKind::MacroDef(..) | ItemKind::Mac(_) => unreachable!(),
789781
}
790782
}
@@ -1118,7 +1110,6 @@ macro_rules! method {
11181110
}
11191111

11201112
impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
1121-
method!(visit_impl_item: ast::ImplItem, ast::ImplItemKind::Macro, walk_impl_item);
11221113
method!(visit_expr: ast::Expr, ast::ExprKind::Mac, walk_expr);
11231114
method!(visit_pat: ast::Pat, ast::PatKind::Mac, walk_pat);
11241115
method!(visit_ty: ast::Ty, ast::TyKind::Mac, walk_ty);
@@ -1202,6 +1193,15 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
12021193
visit::walk_trait_item(self, item);
12031194
}
12041195

1196+
fn visit_impl_item(&mut self, item: &'b ast::ImplItem) {
1197+
if let ast::ImplItemKind::Macro(..) = item.kind {
1198+
self.visit_invoc(item.id);
1199+
} else {
1200+
self.resolve_visibility(&item.vis);
1201+
visit::walk_impl_item(self, item);
1202+
}
1203+
}
1204+
12051205
fn visit_token(&mut self, t: Token) {
12061206
if let token::Interpolated(nt) = t.kind {
12071207
if let token::NtExpr(ref expr) = *nt {

src/librustc_session/code_stats.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,12 @@ impl CodeStats {
132132

133133
let mut min_offset = discr_size;
134134

135-
// We want to print fields by increasing offset.
135+
// We want to print fields by increasing offset. We also want
136+
// zero-sized fields before non-zero-sized fields, otherwise
137+
// the loop below goes wrong; hence the `f.size` in the sort
138+
// key.
136139
let mut fields = fields.clone();
137-
fields.sort_by_key(|f| f.offset);
140+
fields.sort_by_key(|f| (f.offset, f.size));
138141

139142
for field in fields.iter() {
140143
let FieldInfo { ref name, offset, size, align } = *field;
@@ -146,7 +149,7 @@ impl CodeStats {
146149
}
147150

148151
if offset < min_offset {
149-
// if this happens something is very wrong
152+
// If this happens it's probably a union.
150153
println!("print-type-size {}field `.{}`: {} bytes, \
151154
offset: {} bytes, \
152155
alignment: {} bytes",

src/libstd/sys/unix/fast_thread_local.rs

-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
// Note, however, that we run on lots older linuxes, as well as cross
99
// compiling from a newer linux to an older linux, so we also have a
1010
// fallback implementation to use as well.
11-
//
12-
// Due to rust-lang/rust#18804, make sure this is not generic!
1311
#[cfg(any(
1412
target_os = "linux",
1513
target_os = "fuchsia",

src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.rs

-3
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,7 @@ macro_rules! the_worship_the_heart_lifts_above {
1717

1818
macro_rules! and_the_heavens_reject_not {
1919
() => {
20-
// ↓ But let's test that we still lint for unused parens around
21-
// function args inside of simple, one-deep macros.
2220
#[allow(dead_code)] fn the_night_for_the_morrow() -> Option<isize> { Some((2)) }
23-
//~^ WARN unnecessary parentheses around function argument
2421
}
2522
}
2623

src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.stderr

-15
This file was deleted.

0 commit comments

Comments
 (0)