Skip to content

Commit

Permalink
Merge from rustc
Browse files Browse the repository at this point in the history
  • Loading branch information
oli-obk committed Jun 15, 2023
2 parents 36e0c42 + 44789b6 commit 24595f5
Show file tree
Hide file tree
Showing 860 changed files with 18,107 additions and 2,828 deletions.
17 changes: 16 additions & 1 deletion Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ dependencies = [
"rand_xorshift",
]

[[package]]
name = "allocator-api2"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4f263788a35611fba42eb41ff811c5d0360c58b97402570312a350736e2542e"

[[package]]
name = "ammonia"
version = "3.2.0"
Expand Down Expand Up @@ -1522,6 +1528,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ff8ae62cd3a9102e5637afc8452c55acf3844001bd5374e0b0bd7b6616c038"
dependencies = [
"ahash 0.8.2",
]

[[package]]
name = "hashbrown"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
dependencies = [
"allocator-api2",
"compiler_builtins",
"rustc-std-workspace-alloc",
"rustc-std-workspace-core",
Expand Down Expand Up @@ -4633,7 +4648,7 @@ dependencies = [
"core",
"dlmalloc",
"fortanix-sgx-abi",
"hashbrown 0.13.1",
"hashbrown 0.14.0",
"hermit-abi 0.3.0",
"libc",
"miniz_oxide",
Expand Down
98 changes: 54 additions & 44 deletions compiler/rustc_abi/src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,48 +57,54 @@ pub trait LayoutCalculator {
// run and bias niches to the right and then check which one is closer to one of the struct's
// edges.
if let Some(layout) = &layout {
if let Some(niche) = layout.largest_niche {
let head_space = niche.offset.bytes();
let niche_length = niche.value.size(dl).bytes();
let tail_space = layout.size.bytes() - head_space - niche_length;

// This may end up doing redundant work if the niche is already in the last field
// (e.g. a trailing bool) and there is tail padding. But it's non-trivial to get
// the unpadded size so we try anyway.
if fields.len() > 1 && head_space != 0 && tail_space > 0 {
let alt_layout = univariant(self, dl, fields, repr, kind, NicheBias::End)
.expect("alt layout should always work");
let niche = alt_layout
.largest_niche
.expect("alt layout should have a niche like the regular one");
let alt_head_space = niche.offset.bytes();
let alt_niche_len = niche.value.size(dl).bytes();
let alt_tail_space = alt_layout.size.bytes() - alt_head_space - alt_niche_len;

debug_assert_eq!(layout.size.bytes(), alt_layout.size.bytes());

let prefer_alt_layout =
alt_head_space > head_space && alt_head_space > tail_space;

debug!(
"sz: {}, default_niche_at: {}+{}, default_tail_space: {}, alt_niche_at/head_space: {}+{}, alt_tail: {}, num_fields: {}, better: {}\n\
layout: {}\n\
alt_layout: {}\n",
layout.size.bytes(),
head_space,
niche_length,
tail_space,
alt_head_space,
alt_niche_len,
alt_tail_space,
layout.fields.count(),
prefer_alt_layout,
format_field_niches(&layout, &fields, &dl),
format_field_niches(&alt_layout, &fields, &dl),
);

if prefer_alt_layout {
return Some(alt_layout);
// Don't try to calculate an end-biased layout for unsizable structs,
// otherwise we could end up with different layouts for
// Foo<Type> and Foo<dyn Trait> which would break unsizing
if !matches!(kind, StructKind::MaybeUnsized) {
if let Some(niche) = layout.largest_niche {
let head_space = niche.offset.bytes();
let niche_length = niche.value.size(dl).bytes();
let tail_space = layout.size.bytes() - head_space - niche_length;

// This may end up doing redundant work if the niche is already in the last field
// (e.g. a trailing bool) and there is tail padding. But it's non-trivial to get
// the unpadded size so we try anyway.
if fields.len() > 1 && head_space != 0 && tail_space > 0 {
let alt_layout = univariant(self, dl, fields, repr, kind, NicheBias::End)
.expect("alt layout should always work");
let niche = alt_layout
.largest_niche
.expect("alt layout should have a niche like the regular one");
let alt_head_space = niche.offset.bytes();
let alt_niche_len = niche.value.size(dl).bytes();
let alt_tail_space =
alt_layout.size.bytes() - alt_head_space - alt_niche_len;

debug_assert_eq!(layout.size.bytes(), alt_layout.size.bytes());

let prefer_alt_layout =
alt_head_space > head_space && alt_head_space > tail_space;

debug!(
"sz: {}, default_niche_at: {}+{}, default_tail_space: {}, alt_niche_at/head_space: {}+{}, alt_tail: {}, num_fields: {}, better: {}\n\
layout: {}\n\
alt_layout: {}\n",
layout.size.bytes(),
head_space,
niche_length,
tail_space,
alt_head_space,
alt_niche_len,
alt_tail_space,
layout.fields.count(),
prefer_alt_layout,
format_field_niches(&layout, &fields, &dl),
format_field_niches(&alt_layout, &fields, &dl),
);

if prefer_alt_layout {
return Some(alt_layout);
}
}
}
}
Expand Down Expand Up @@ -828,6 +834,7 @@ fn univariant(
if optimize && fields.len() > 1 {
let end = if let StructKind::MaybeUnsized = kind { fields.len() - 1 } else { fields.len() };
let optimizing = &mut inverse_memory_index.raw[..end];
let fields_excluding_tail = &fields.raw[..end];

// If `-Z randomize-layout` was enabled for the type definition we can shuffle
// the field ordering to try and catch some code making assumptions about layouts
Expand All @@ -844,8 +851,11 @@ fn univariant(
}
// Otherwise we just leave things alone and actually optimize the type's fields
} else {
let max_field_align = fields.iter().map(|f| f.align().abi.bytes()).max().unwrap_or(1);
let largest_niche_size = fields
// To allow unsizing `&Foo<Type>` -> `&Foo<dyn Trait>`, the layout of the struct must
// not depend on the layout of the tail.
let max_field_align =
fields_excluding_tail.iter().map(|f| f.align().abi.bytes()).max().unwrap_or(1);
let largest_niche_size = fields_excluding_tail
.iter()
.filter_map(|f| f.largest_niche())
.map(|n| n.available(dl))
Expand Down
20 changes: 15 additions & 5 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,12 @@ impl<'a> AstValidator<'a> {
self.err_handler().emit_err(errors::BoundInContext { span, ctx });
}

fn check_foreign_ty_genericless(&self, generics: &Generics, where_span: Span) {
fn check_foreign_ty_genericless(
&self,
generics: &Generics,
before_where_clause: &TyAliasWhereClause,
after_where_clause: &TyAliasWhereClause,
) {
let cannot_have = |span, descr, remove_descr| {
self.err_handler().emit_err(errors::ExternTypesCannotHave {
span,
Expand All @@ -378,9 +383,14 @@ impl<'a> AstValidator<'a> {
cannot_have(generics.span, "generic parameters", "generic parameters");
}

if !generics.where_clause.predicates.is_empty() {
cannot_have(where_span, "`where` clauses", "`where` clause");
}
let check_where_clause = |where_clause: &TyAliasWhereClause| {
if let TyAliasWhereClause(true, where_clause_span) = where_clause {
cannot_have(*where_clause_span, "`where` clauses", "`where` clause");
}
};

check_where_clause(before_where_clause);
check_where_clause(after_where_clause);
}

fn check_foreign_kind_bodyless(&self, ident: Ident, kind: &str, body: Option<Span>) {
Expand Down Expand Up @@ -1039,7 +1049,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
self.check_defaultness(fi.span, *defaultness);
self.check_foreign_kind_bodyless(fi.ident, "type", ty.as_ref().map(|b| b.span));
self.check_type_no_bounds(bounds, "`extern` blocks");
self.check_foreign_ty_genericless(generics, where_clauses.0.1);
self.check_foreign_ty_genericless(generics, &where_clauses.0, &where_clauses.1);
self.check_foreign_item_ascii_only(fi.ident);
}
ForeignItemKind::Static(_, _, body) => {
Expand Down
Loading

0 comments on commit 24595f5

Please sign in to comment.