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
This commit is contained in:
commit
f284f8b4be
18 changed files with 220 additions and 100 deletions
|
|
@ -195,14 +195,10 @@ impl<B: ?Sized + ToOwned> Clone for Cow<'_, B> {
|
|||
}
|
||||
|
||||
fn clone_from(&mut self, source: &Self) {
|
||||
if let Owned(ref mut dest) = *self {
|
||||
if let Owned(ref o) = *source {
|
||||
o.borrow().clone_into(dest);
|
||||
return;
|
||||
}
|
||||
match (self, source) {
|
||||
(&mut Owned(ref mut dest), &Owned(ref o)) => o.borrow().clone_into(dest),
|
||||
(t, s) => *t = s.clone(),
|
||||
}
|
||||
|
||||
*self = source.clone();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -449,9 +445,7 @@ impl<'a> AddAssign<&'a str> for Cow<'a, str> {
|
|||
fn add_assign(&mut self, rhs: &'a str) {
|
||||
if self.is_empty() {
|
||||
*self = Cow::Borrowed(rhs)
|
||||
} else if rhs.is_empty() {
|
||||
return;
|
||||
} else {
|
||||
} else if !rhs.is_empty() {
|
||||
if let Cow::Borrowed(lhs) = *self {
|
||||
let mut s = String::with_capacity(lhs.len() + rhs.len());
|
||||
s.push_str(lhs);
|
||||
|
|
@ -467,9 +461,7 @@ impl<'a> AddAssign<Cow<'a, str>> for Cow<'a, str> {
|
|||
fn add_assign(&mut self, rhs: Cow<'a, str>) {
|
||||
if self.is_empty() {
|
||||
*self = rhs
|
||||
} else if rhs.is_empty() {
|
||||
return;
|
||||
} else {
|
||||
} else if !rhs.is_empty() {
|
||||
if let Cow::Borrowed(lhs) = *self {
|
||||
let mut s = String::with_capacity(lhs.len() + rhs.len());
|
||||
s.push_str(lhs);
|
||||
|
|
|
|||
|
|
@ -61,7 +61,60 @@
|
|||
//! T` obtained from [`Box::<T>::into_raw`] may be deallocated using the
|
||||
//! [`Global`] allocator with [`Layout::for_value(&*value)`].
|
||||
//!
|
||||
//! So long as `T: Sized`, a `Box<T>` is guaranteed to be represented
|
||||
//! as a single pointer and is also ABI-compatible with C pointers
|
||||
//! (i.e. the C type `T*`). This means that if you have extern "C"
|
||||
//! Rust functions that will be called from C, you can define those
|
||||
//! Rust functions using `Box<T>` types, and use `T*` as corresponding
|
||||
//! type on the C side. As an example, consider this C header which
|
||||
//! declares functions that create and destroy some kind of `Foo`
|
||||
//! value:
|
||||
//!
|
||||
//! ```c
|
||||
//! /* C header */
|
||||
//!
|
||||
//! /* Returns ownership to the caller */
|
||||
//! struct Foo* foo_new(void);
|
||||
//!
|
||||
//! /* Takes ownership from the caller; no-op when invoked with NULL */
|
||||
//! void foo_delete(struct Foo*);
|
||||
//! ```
|
||||
//!
|
||||
//! These two functions might be implemented in Rust as follows. Here, the
|
||||
//! `struct Foo*` type from C is translated to `Box<Foo>`, which captures
|
||||
//! the ownership constraints. Note also that the nullable argument to
|
||||
//! `foo_delete` is represented in Rust as `Option<Box<Foo>>`, since `Box<Foo>`
|
||||
//! cannot be null.
|
||||
//!
|
||||
//! ```
|
||||
//! #[repr(C)]
|
||||
//! pub struct Foo;
|
||||
//!
|
||||
//! #[no_mangle]
|
||||
//! pub extern "C" fn foo_new() -> Box<Foo> {
|
||||
//! Box::new(Foo)
|
||||
//! }
|
||||
//!
|
||||
//! #[no_mangle]
|
||||
//! pub extern "C" fn foo_delete(_: Option<Box<Foo>>) {}
|
||||
//! ```
|
||||
//!
|
||||
//! Even though `Box<T>` has the same representation and C ABI as a C pointer,
|
||||
//! this does not mean that you can convert an arbitrary `T*` into a `Box<T>`
|
||||
//! and expect things to work. `Box<T>` values will always be fully aligned,
|
||||
//! non-null pointers. Moreover, the destructor for `Box<T>` will attempt to
|
||||
//! free the value with the global allocator. In general, the best practice
|
||||
//! is to only use `Box<T>` for pointers that originated from the global
|
||||
//! allocator.
|
||||
//!
|
||||
//! **Important.** At least at present, you should avoid using
|
||||
//! `Box<T>` types for functions that are defined in C but invoked
|
||||
//! from Rust. In those cases, you should directly mirror the C types
|
||||
//! as closely as possible. Using types like `Box<T>` where the C
|
||||
//! definition is just using `T*` can lead to undefined behavior, as
|
||||
//! described in [rust-lang/unsafe-code-guidelines#198][ucg#198].
|
||||
//!
|
||||
//! [ucg#198]: https://github.com/rust-lang/unsafe-code-guidelines/issues/198
|
||||
//! [dereferencing]: ../../std/ops/trait.Deref.html
|
||||
//! [`Box`]: struct.Box.html
|
||||
//! [`Box<T>`]: struct.Box.html
|
||||
|
|
|
|||
|
|
@ -138,4 +138,7 @@ fn check_cow_clone_from() {
|
|||
let c2: Cow<'_, str> = Cow::Owned(s);
|
||||
c1.clone_from(&c2);
|
||||
assert!(c1.into_owned().capacity() >= 25);
|
||||
let mut c3: Cow<'_, str> = Cow::Borrowed("bye");
|
||||
c3.clone_from(&c2);
|
||||
assert_eq!(c2, c3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -553,8 +553,7 @@ impl char {
|
|||
pub fn is_alphabetic(self) -> bool {
|
||||
match self {
|
||||
'a'..='z' | 'A'..='Z' => true,
|
||||
c if c > '\x7f' => derived_property::Alphabetic(c),
|
||||
_ => false,
|
||||
c => c > '\x7f' && derived_property::Alphabetic(c),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -585,8 +584,7 @@ impl char {
|
|||
pub fn is_lowercase(self) -> bool {
|
||||
match self {
|
||||
'a'..='z' => true,
|
||||
c if c > '\x7f' => derived_property::Lowercase(c),
|
||||
_ => false,
|
||||
c => c > '\x7f' && derived_property::Lowercase(c),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -617,8 +615,7 @@ impl char {
|
|||
pub fn is_uppercase(self) -> bool {
|
||||
match self {
|
||||
'A'..='Z' => true,
|
||||
c if c > '\x7f' => derived_property::Uppercase(c),
|
||||
_ => false,
|
||||
c => c > '\x7f' && derived_property::Uppercase(c),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -646,8 +643,7 @@ impl char {
|
|||
pub fn is_whitespace(self) -> bool {
|
||||
match self {
|
||||
' ' | '\x09'..='\x0d' => true,
|
||||
c if c > '\x7f' => property::White_Space(c),
|
||||
_ => false,
|
||||
c => c > '\x7f' && property::White_Space(c),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -744,8 +740,7 @@ impl char {
|
|||
pub fn is_numeric(self) -> bool {
|
||||
match self {
|
||||
'0'..='9' => true,
|
||||
c if c > '\x7f' => general_category::N(c),
|
||||
_ => false,
|
||||
c => c > '\x7f' && general_category::N(c),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -296,12 +296,7 @@ unsafe impl<'a> Searcher<'a> for CharSearcher<'a> {
|
|||
fn next_match(&mut self) -> Option<(usize, usize)> {
|
||||
loop {
|
||||
// get the haystack after the last character found
|
||||
let bytes = if let Some(slice) = self.haystack.as_bytes()
|
||||
.get(self.finger..self.finger_back) {
|
||||
slice
|
||||
} else {
|
||||
return None;
|
||||
};
|
||||
let bytes = self.haystack.as_bytes().get(self.finger..self.finger_back)?;
|
||||
// the last byte of the utf8 encoded needle
|
||||
let last_byte = unsafe { *self.utf8_encoded.get_unchecked(self.utf8_size - 1) };
|
||||
if let Some(index) = memchr::memchr(last_byte, bytes) {
|
||||
|
|
|
|||
|
|
@ -16,41 +16,29 @@ mod tests;
|
|||
|
||||
#[derive(Clone)]
|
||||
pub struct TinyList<T: PartialEq> {
|
||||
head: Option<Element<T>>
|
||||
head: Option<Element<T>>,
|
||||
}
|
||||
|
||||
impl<T: PartialEq> TinyList<T> {
|
||||
#[inline]
|
||||
pub fn new() -> TinyList<T> {
|
||||
TinyList {
|
||||
head: None
|
||||
}
|
||||
TinyList { head: None }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn new_single(data: T) -> TinyList<T> {
|
||||
TinyList {
|
||||
head: Some(Element {
|
||||
data,
|
||||
next: None,
|
||||
})
|
||||
}
|
||||
TinyList { head: Some(Element { data, next: None }) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn insert(&mut self, data: T) {
|
||||
self.head = Some(Element {
|
||||
data,
|
||||
next: self.head.take().map(Box::new)
|
||||
});
|
||||
self.head = Some(Element { data, next: self.head.take().map(Box::new) });
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn remove(&mut self, data: &T) -> bool {
|
||||
self.head = match self.head {
|
||||
Some(ref mut head) if head.data == *data => {
|
||||
head.next.take().map(|x| *x)
|
||||
}
|
||||
Some(ref mut head) if head.data == *data => head.next.take().map(|x| *x),
|
||||
Some(ref mut head) => return head.remove_next(data),
|
||||
None => return false,
|
||||
};
|
||||
|
|
@ -88,12 +76,16 @@ struct Element<T: PartialEq> {
|
|||
|
||||
impl<T: PartialEq> Element<T> {
|
||||
fn remove_next(&mut self, data: &T) -> bool {
|
||||
let new_next = match self.next {
|
||||
Some(ref mut next) if next.data == *data => next.next.take(),
|
||||
Some(ref mut next) => return next.remove_next(data),
|
||||
None => return false,
|
||||
};
|
||||
self.next = new_next;
|
||||
true
|
||||
let mut n = self;
|
||||
loop {
|
||||
match n.next {
|
||||
Some(ref mut next) if next.data == *data => {
|
||||
n.next = next.next.take();
|
||||
return true;
|
||||
}
|
||||
Some(ref mut next) => n = next,
|
||||
None => return false,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -355,7 +355,9 @@ impl UnusedParens {
|
|||
match value.kind {
|
||||
ast::ExprKind::Paren(ref inner) => {
|
||||
if !Self::is_expr_parens_necessary(inner, followed_by_block) &&
|
||||
value.attrs.is_empty() {
|
||||
value.attrs.is_empty() &&
|
||||
!value.span.from_expansion()
|
||||
{
|
||||
let expr_text = if let Ok(snippet) = cx.sess().source_map()
|
||||
.span_to_snippet(value.span) {
|
||||
snippet
|
||||
|
|
|
|||
|
|
@ -647,8 +647,6 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
|
|||
self.r.define(parent, ident, TypeNS, imported_binding);
|
||||
}
|
||||
|
||||
ItemKind::GlobalAsm(..) => {}
|
||||
|
||||
ItemKind::Mod(..) if ident.name == kw::Invalid => {} // Crate root
|
||||
|
||||
ItemKind::Mod(..) => {
|
||||
|
|
@ -667,9 +665,6 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
|
|||
self.parent_scope.module = module;
|
||||
}
|
||||
|
||||
// Handled in `rustc_metadata::{native_libs,link_args}`
|
||||
ItemKind::ForeignMod(..) => {}
|
||||
|
||||
// These items live in the value namespace.
|
||||
ItemKind::Static(..) => {
|
||||
let res = Res::Def(DefKind::Static, self.r.definitions.local_def_id(item.id));
|
||||
|
|
@ -765,12 +760,6 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
|
|||
self.insert_field_names_local(def_id, vdata);
|
||||
}
|
||||
|
||||
ItemKind::Impl(.., ref impl_items) => {
|
||||
for impl_item in impl_items {
|
||||
self.resolve_visibility(&impl_item.vis);
|
||||
}
|
||||
}
|
||||
|
||||
ItemKind::Trait(..) => {
|
||||
let def_id = self.r.definitions.local_def_id(item.id);
|
||||
|
||||
|
|
@ -785,6 +774,9 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
|
|||
self.parent_scope.module = module;
|
||||
}
|
||||
|
||||
// These items do not add names to modules.
|
||||
ItemKind::Impl(..) | ItemKind::ForeignMod(..) | ItemKind::GlobalAsm(..) => {}
|
||||
|
||||
ItemKind::MacroDef(..) | ItemKind::Mac(_) => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
|
@ -1118,7 +1110,6 @@ macro_rules! method {
|
|||
}
|
||||
|
||||
impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
|
||||
method!(visit_impl_item: ast::ImplItem, ast::ImplItemKind::Macro, walk_impl_item);
|
||||
method!(visit_expr: ast::Expr, ast::ExprKind::Mac, walk_expr);
|
||||
method!(visit_pat: ast::Pat, ast::PatKind::Mac, walk_pat);
|
||||
method!(visit_ty: ast::Ty, ast::TyKind::Mac, walk_ty);
|
||||
|
|
@ -1202,6 +1193,15 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
|
|||
visit::walk_trait_item(self, item);
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, item: &'b ast::ImplItem) {
|
||||
if let ast::ImplItemKind::Macro(..) = item.kind {
|
||||
self.visit_invoc(item.id);
|
||||
} else {
|
||||
self.resolve_visibility(&item.vis);
|
||||
visit::walk_impl_item(self, item);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_token(&mut self, t: Token) {
|
||||
if let token::Interpolated(nt) = t.kind {
|
||||
if let token::NtExpr(ref expr) = *nt {
|
||||
|
|
|
|||
|
|
@ -132,9 +132,12 @@ impl CodeStats {
|
|||
|
||||
let mut min_offset = discr_size;
|
||||
|
||||
// We want to print fields by increasing offset.
|
||||
// We want to print fields by increasing offset. We also want
|
||||
// zero-sized fields before non-zero-sized fields, otherwise
|
||||
// the loop below goes wrong; hence the `f.size` in the sort
|
||||
// key.
|
||||
let mut fields = fields.clone();
|
||||
fields.sort_by_key(|f| f.offset);
|
||||
fields.sort_by_key(|f| (f.offset, f.size));
|
||||
|
||||
for field in fields.iter() {
|
||||
let FieldInfo { ref name, offset, size, align } = *field;
|
||||
|
|
@ -146,7 +149,7 @@ impl CodeStats {
|
|||
}
|
||||
|
||||
if offset < min_offset {
|
||||
// if this happens something is very wrong
|
||||
// If this happens it's probably a union.
|
||||
println!("print-type-size {}field `.{}`: {} bytes, \
|
||||
offset: {} bytes, \
|
||||
alignment: {} bytes",
|
||||
|
|
|
|||
|
|
@ -8,8 +8,6 @@
|
|||
// Note, however, that we run on lots older linuxes, as well as cross
|
||||
// compiling from a newer linux to an older linux, so we also have a
|
||||
// fallback implementation to use as well.
|
||||
//
|
||||
// Due to rust-lang/rust#18804, make sure this is not generic!
|
||||
#[cfg(any(
|
||||
target_os = "linux",
|
||||
target_os = "fuchsia",
|
||||
|
|
|
|||
|
|
@ -17,10 +17,7 @@ macro_rules! the_worship_the_heart_lifts_above {
|
|||
|
||||
macro_rules! and_the_heavens_reject_not {
|
||||
() => {
|
||||
// ↓ But let's test that we still lint for unused parens around
|
||||
// function args inside of simple, one-deep macros.
|
||||
#[allow(dead_code)] fn the_night_for_the_morrow() -> Option<isize> { Some((2)) }
|
||||
//~^ WARN unnecessary parentheses around function argument
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +0,0 @@
|
|||
warning: unnecessary parentheses around function argument
|
||||
--> $DIR/issue-47775-nested-macro-unnecessary-parens-arg.rs:22:83
|
||||
|
|
||||
LL | #[allow(dead_code)] fn the_night_for_the_morrow() -> Option<isize> { Some((2)) }
|
||||
| ^^^ help: remove these parentheses
|
||||
...
|
||||
LL | and_the_heavens_reject_not!();
|
||||
| ------------------------------ in this macro invocation
|
||||
|
|
||||
note: lint level defined here
|
||||
--> $DIR/issue-47775-nested-macro-unnecessary-parens-arg.rs:3:9
|
||||
|
|
||||
LL | #![warn(unused_parens)]
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
|
|
@ -25,6 +25,12 @@ fn passes_unused_parens_lint() -> &'static (dyn Trait) {
|
|||
panic!()
|
||||
}
|
||||
|
||||
macro_rules! baz {
|
||||
($($foo:expr),+) => {
|
||||
($($foo),*)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo();
|
||||
bar((true)); //~ ERROR unnecessary parentheses around function argument
|
||||
|
|
@ -55,4 +61,7 @@ fn main() {
|
|||
let mut _a = (0); //~ ERROR unnecessary parentheses around assigned value
|
||||
_a = (0); //~ ERROR unnecessary parentheses around assigned value
|
||||
_a += (1); //~ ERROR unnecessary parentheses around assigned value
|
||||
|
||||
let _a = baz!(3, 4);
|
||||
let _b = baz!(3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,25 +23,25 @@ LL | fn unused_parens_around_return_type() -> (u32) {
|
|||
| ^^^^^ help: remove these parentheses
|
||||
|
||||
error: unnecessary parentheses around function argument
|
||||
--> $DIR/lint-unnecessary-parens.rs:30:9
|
||||
--> $DIR/lint-unnecessary-parens.rs:36:9
|
||||
|
|
||||
LL | bar((true));
|
||||
| ^^^^^^ help: remove these parentheses
|
||||
|
||||
error: unnecessary parentheses around `if` condition
|
||||
--> $DIR/lint-unnecessary-parens.rs:32:8
|
||||
--> $DIR/lint-unnecessary-parens.rs:38:8
|
||||
|
|
||||
LL | if (true) {}
|
||||
| ^^^^^^ help: remove these parentheses
|
||||
|
||||
error: unnecessary parentheses around `while` condition
|
||||
--> $DIR/lint-unnecessary-parens.rs:33:11
|
||||
--> $DIR/lint-unnecessary-parens.rs:39:11
|
||||
|
|
||||
LL | while (true) {}
|
||||
| ^^^^^^ help: remove these parentheses
|
||||
|
||||
warning: denote infinite loops with `loop { ... }`
|
||||
--> $DIR/lint-unnecessary-parens.rs:33:5
|
||||
--> $DIR/lint-unnecessary-parens.rs:39:5
|
||||
|
|
||||
LL | while (true) {}
|
||||
| ^^^^^^^^^^^^ help: use `loop`
|
||||
|
|
@ -49,43 +49,43 @@ LL | while (true) {}
|
|||
= note: `#[warn(while_true)]` on by default
|
||||
|
||||
error: unnecessary parentheses around `match` head expression
|
||||
--> $DIR/lint-unnecessary-parens.rs:35:11
|
||||
--> $DIR/lint-unnecessary-parens.rs:41:11
|
||||
|
|
||||
LL | match (true) {
|
||||
| ^^^^^^ help: remove these parentheses
|
||||
|
||||
error: unnecessary parentheses around `let` head expression
|
||||
--> $DIR/lint-unnecessary-parens.rs:38:16
|
||||
--> $DIR/lint-unnecessary-parens.rs:44:16
|
||||
|
|
||||
LL | if let 1 = (1) {}
|
||||
| ^^^ help: remove these parentheses
|
||||
|
||||
error: unnecessary parentheses around `let` head expression
|
||||
--> $DIR/lint-unnecessary-parens.rs:39:19
|
||||
--> $DIR/lint-unnecessary-parens.rs:45:19
|
||||
|
|
||||
LL | while let 1 = (2) {}
|
||||
| ^^^ help: remove these parentheses
|
||||
|
||||
error: unnecessary parentheses around method argument
|
||||
--> $DIR/lint-unnecessary-parens.rs:53:24
|
||||
--> $DIR/lint-unnecessary-parens.rs:59:24
|
||||
|
|
||||
LL | X { y: false }.foo((true));
|
||||
| ^^^^^^ help: remove these parentheses
|
||||
|
||||
error: unnecessary parentheses around assigned value
|
||||
--> $DIR/lint-unnecessary-parens.rs:55:18
|
||||
--> $DIR/lint-unnecessary-parens.rs:61:18
|
||||
|
|
||||
LL | let mut _a = (0);
|
||||
| ^^^ help: remove these parentheses
|
||||
|
||||
error: unnecessary parentheses around assigned value
|
||||
--> $DIR/lint-unnecessary-parens.rs:56:10
|
||||
--> $DIR/lint-unnecessary-parens.rs:62:10
|
||||
|
|
||||
LL | _a = (0);
|
||||
| ^^^ help: remove these parentheses
|
||||
|
||||
error: unnecessary parentheses around assigned value
|
||||
--> $DIR/lint-unnecessary-parens.rs:57:11
|
||||
--> $DIR/lint-unnecessary-parens.rs:63:11
|
||||
|
|
||||
LL | _a += (1);
|
||||
| ^^^ help: remove these parentheses
|
||||
|
|
|
|||
46
src/test/ui/print_type_sizes/zero-sized-fields.rs
Normal file
46
src/test/ui/print_type_sizes/zero-sized-fields.rs
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
// compile-flags: -Z print-type-sizes
|
||||
// build-pass (FIXME(62277): could be check-pass?)
|
||||
|
||||
// At one point, zero-sized fields such as those in this file were causing
|
||||
// incorrect output from `-Z print-type-sizes`.
|
||||
|
||||
#![feature(start)]
|
||||
|
||||
struct S1 {
|
||||
x: u32,
|
||||
y: u32,
|
||||
tag: (),
|
||||
}
|
||||
|
||||
struct Void();
|
||||
struct Empty {}
|
||||
|
||||
struct S5<TagW, TagZ> {
|
||||
tagw: TagW,
|
||||
w: u32,
|
||||
unit: (),
|
||||
x: u32,
|
||||
void: Void,
|
||||
y: u32,
|
||||
empty: Empty,
|
||||
z: u32,
|
||||
tagz: TagZ,
|
||||
}
|
||||
|
||||
#[start]
|
||||
fn start(_: isize, _: *const *const u8) -> isize {
|
||||
let _s1: S1 = S1 { x: 0, y: 0, tag: () };
|
||||
|
||||
let _s5: S5<(), Empty> = S5 {
|
||||
tagw: (),
|
||||
w: 1,
|
||||
unit: (),
|
||||
x: 2,
|
||||
void: Void(),
|
||||
y: 3,
|
||||
empty: Empty {},
|
||||
z: 4,
|
||||
tagz: Empty {},
|
||||
};
|
||||
0
|
||||
}
|
||||
16
src/test/ui/print_type_sizes/zero-sized-fields.stdout
Normal file
16
src/test/ui/print_type_sizes/zero-sized-fields.stdout
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
print-type-size type: `S5<(), Empty>`: 16 bytes, alignment: 4 bytes
|
||||
print-type-size field `.tagw`: 0 bytes
|
||||
print-type-size field `.unit`: 0 bytes
|
||||
print-type-size field `.void`: 0 bytes
|
||||
print-type-size field `.empty`: 0 bytes
|
||||
print-type-size field `.tagz`: 0 bytes
|
||||
print-type-size field `.w`: 4 bytes
|
||||
print-type-size field `.x`: 4 bytes
|
||||
print-type-size field `.y`: 4 bytes
|
||||
print-type-size field `.z`: 4 bytes
|
||||
print-type-size type: `S1`: 8 bytes, alignment: 4 bytes
|
||||
print-type-size field `.tag`: 0 bytes
|
||||
print-type-size field `.x`: 4 bytes
|
||||
print-type-size field `.y`: 4 bytes
|
||||
print-type-size type: `Empty`: 0 bytes, alignment: 1 bytes
|
||||
print-type-size type: `Void`: 0 bytes, alignment: 1 bytes
|
||||
25
src/test/ui/resolve/impl-items-vis-unresolved.rs
Normal file
25
src/test/ui/resolve/impl-items-vis-unresolved.rs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
// Visibilities on impl items expanded from macros are resolved (issue #64705).
|
||||
|
||||
macro_rules! perftools_inline {
|
||||
($($item:tt)*) => (
|
||||
$($item)*
|
||||
);
|
||||
}
|
||||
|
||||
mod state {
|
||||
pub struct RawFloatState;
|
||||
impl RawFloatState {
|
||||
perftools_inline! {
|
||||
pub(super) fn new() {} // OK
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RawFloatState;
|
||||
impl RawFloatState {
|
||||
perftools_inline! {
|
||||
pub(super) fn new() {} //~ ERROR failed to resolve: there are too many initial `super`s
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
9
src/test/ui/resolve/impl-items-vis-unresolved.stderr
Normal file
9
src/test/ui/resolve/impl-items-vis-unresolved.stderr
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
error[E0433]: failed to resolve: there are too many initial `super`s.
|
||||
--> $DIR/impl-items-vis-unresolved.rs:21:13
|
||||
|
|
||||
LL | pub(super) fn new() {}
|
||||
| ^^^^^ there are too many initial `super`s.
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0433`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue