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 8 pull requests #91033

Merged
merged 19 commits into from
Nov 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
7272b6f
Make char conversion functions unstably const
est31 Sep 25, 2021
7bc827b
Refactor single variant `Candidate` enum into a struct
tmiasko Nov 5, 2021
59edb9d
Remove `Candidate::source_info`
tmiasko Nov 5, 2021
afd9dfa
bootstap: create .cargo/config only if not present
aplanas Nov 11, 2021
ddc1d58
windows: Return the "Not Found" error when a path is empty
JohnTitor Nov 16, 2021
4ca4e09
Suggest removal of arguments for unit variant, not replacement
estebank Nov 16, 2021
5520737
Remove unnecessary lifetime argument from arena macros.
nnethercote Nov 15, 2021
f1aeebf
add const generics test
lcnr Nov 4, 2021
41d9abd
Move some tests to more reasonable directories
c410-f3r Nov 18, 2021
8ace192
bless nll
lcnr Nov 18, 2021
0a89598
Add some comments.
nnethercote Nov 15, 2021
7432588
Rollup merge of #89258 - est31:const_char_convert, r=oli-obk
JohnTitor Nov 19, 2021
81fd016
Rollup merge of #90578 - lcnr:add-test, r=Mark-Simulacrum
JohnTitor Nov 19, 2021
48947ea
Rollup merge of #90633 - tmiasko:candidate-struct, r=nagisa
JohnTitor Nov 19, 2021
b542224
Rollup merge of #90800 - aplanas:fix_cargo_config, r=Mark-Simulacrum
JohnTitor Nov 19, 2021
f62984f
Rollup merge of #90942 - JohnTitor:should-os-error-3, r=m-ou-se
JohnTitor Nov 19, 2021
022709f
Rollup merge of #90947 - c410-f3r:testsssssss, r=petrochenkov
JohnTitor Nov 19, 2021
c74ff8b
Rollup merge of #90961 - estebank:suggest-removal-of-call, r=nagisa
JohnTitor Nov 19, 2021
1576a7c
Rollup merge of #90990 - nnethercote:arenas-cleanup, r=oli-obk
JohnTitor Nov 19, 2021
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
25 changes: 17 additions & 8 deletions compiler/rustc_arena/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ impl<T> Default for TypedArena<T> {
// alloc() will trigger a grow().
ptr: Cell::new(ptr::null_mut()),
end: Cell::new(ptr::null_mut()),
chunks: RefCell::new(vec![]),
chunks: Default::default(),
_own: PhantomData,
}
}
Expand Down Expand Up @@ -325,13 +325,17 @@ unsafe impl<#[may_dangle] T> Drop for TypedArena<T> {

unsafe impl<T: Send> Send for TypedArena<T> {}

/// An arena that can hold objects of multiple different types that impl `Copy`
/// and/or satisfy `!mem::needs_drop`.
pub struct DroplessArena {
/// A pointer to the start of the free space.
start: Cell<*mut u8>,

/// A pointer to the end of free space.
///
/// The allocation proceeds from the end of the chunk towards the start.
/// The allocation proceeds downwards from the end of the chunk towards the
/// start. (This is slightly simpler and faster than allocating upwards,
/// see <https://fitzgeraldnick.com/2019/11/01/always-bump-downwards.html>.)
/// When this pointer crosses the start pointer, a new chunk is allocated.
end: Cell<*mut u8>,

Expand Down Expand Up @@ -516,10 +520,14 @@ impl DroplessArena {
}
}

// Declare an `Arena` containing one dropless arena and many typed arenas (the
// types of the typed arenas are specified by the arguments). The dropless
// arena will be used for any types that impl `Copy`, and also for any of the
// specified types that satisfy `!mem::needs_drop`.
#[rustc_macro_transparency = "semitransparent"]
pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) {
pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*]) {
#[derive(Default)]
pub struct Arena<$tcx> {
pub struct Arena<'tcx> {
pub dropless: $crate::DroplessArena,
$($name: $crate::TypedArena<$ty>,)*
}
Expand All @@ -532,6 +540,7 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) {
) -> &'a mut [Self];
}

// Any type that impls `Copy` can be arena-allocated in the `DroplessArena`.
impl<'tcx, T: Copy> ArenaAllocatable<'tcx, ()> for T {
#[inline]
fn allocate_on<'a>(self, arena: &'a Arena<'tcx>) -> &'a mut Self {
Expand All @@ -544,12 +553,11 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) {
) -> &'a mut [Self] {
arena.dropless.alloc_from_iter(iter)
}

}
$(
impl<$tcx> ArenaAllocatable<$tcx, $ty> for $ty {
impl<'tcx> ArenaAllocatable<'tcx, $ty> for $ty {
#[inline]
fn allocate_on<'a>(self, arena: &'a Arena<$tcx>) -> &'a mut Self {
fn allocate_on<'a>(self, arena: &'a Arena<'tcx>) -> &'a mut Self {
if !::std::mem::needs_drop::<Self>() {
arena.dropless.alloc(self)
} else {
Expand All @@ -559,7 +567,7 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) {

#[inline]
fn allocate_from_iter<'a>(
arena: &'a Arena<$tcx>,
arena: &'a Arena<'tcx>,
iter: impl ::std::iter::IntoIterator<Item = Self>,
) -> &'a mut [Self] {
if !::std::mem::needs_drop::<Self>() {
Expand All @@ -577,6 +585,7 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) {
value.allocate_on(self)
}

// Any type that impls `Copy` can have slices be arena-allocated in the `DroplessArena`.
#[inline]
pub fn alloc_slice<T: ::std::marker::Copy>(&self, value: &[T]) -> &mut [T] {
if value.is_empty() {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ mod item;
mod pat;
mod path;

rustc_hir::arena_types!(rustc_arena::declare_arena, 'tcx);
rustc_hir::arena_types!(rustc_arena::declare_arena);

struct LoweringContext<'a, 'hir: 'a> {
/// Used to assign IDs to HIR nodes that do not directly correspond to AST nodes.
Expand Down
183 changes: 82 additions & 101 deletions compiler/rustc_const_eval/src/transform/promote_consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,17 +93,8 @@ impl TempState {
/// returned value in a promoted MIR, unless it's a subset
/// of a larger candidate.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Candidate {
/// Borrow of a constant temporary, candidate for lifetime extension.
Ref(Location),
}

impl Candidate {
fn source_info(&self, body: &Body<'_>) -> SourceInfo {
match self {
Candidate::Ref(location) => *body.source_info(*location),
}
}
pub struct Candidate {
location: Location,
}

struct Collector<'a, 'tcx> {
Expand Down Expand Up @@ -167,7 +158,7 @@ impl<'tcx> Visitor<'tcx> for Collector<'_, 'tcx> {

match *rvalue {
Rvalue::Ref(..) => {
self.candidates.push(Candidate::Ref(location));
self.candidates.push(Candidate { location });
}
_ => {}
}
Expand Down Expand Up @@ -209,36 +200,33 @@ struct Unpromotable;

impl<'tcx> Validator<'_, 'tcx> {
fn validate_candidate(&self, candidate: Candidate) -> Result<(), Unpromotable> {
match candidate {
Candidate::Ref(loc) => {
let statement = &self.body[loc.block].statements[loc.statement_index];
match &statement.kind {
StatementKind::Assign(box (_, Rvalue::Ref(_, kind, place))) => {
// We can only promote interior borrows of promotable temps (non-temps
// don't get promoted anyway).
self.validate_local(place.local)?;

// The reference operation itself must be promotable.
// (Needs to come after `validate_local` to avoid ICEs.)
self.validate_ref(*kind, place)?;

// We do not check all the projections (they do not get promoted anyway),
// but we do stay away from promoting anything involving a dereference.
if place.projection.contains(&ProjectionElem::Deref) {
return Err(Unpromotable);
}
let loc = candidate.location;
let statement = &self.body[loc.block].statements[loc.statement_index];
match &statement.kind {
StatementKind::Assign(box (_, Rvalue::Ref(_, kind, place))) => {
// We can only promote interior borrows of promotable temps (non-temps
// don't get promoted anyway).
self.validate_local(place.local)?;

// The reference operation itself must be promotable.
// (Needs to come after `validate_local` to avoid ICEs.)
self.validate_ref(*kind, place)?;

// We cannot promote things that need dropping, since the promoted value
// would not get dropped.
if self.qualif_local::<qualifs::NeedsDrop>(place.local) {
return Err(Unpromotable);
}
// We do not check all the projections (they do not get promoted anyway),
// but we do stay away from promoting anything involving a dereference.
if place.projection.contains(&ProjectionElem::Deref) {
return Err(Unpromotable);
}

Ok(())
}
_ => bug!(),
// We cannot promote things that need dropping, since the promoted value
// would not get dropped.
if self.qualif_local::<qualifs::NeedsDrop>(place.local) {
return Err(Unpromotable);
}

Ok(())
}
_ => bug!(),
}
}

Expand Down Expand Up @@ -871,58 +859,55 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
}))
};
let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut();
match candidate {
Candidate::Ref(loc) => {
let statement = &mut blocks[loc.block].statements[loc.statement_index];
match statement.kind {
StatementKind::Assign(box (
_,
Rvalue::Ref(ref mut region, borrow_kind, ref mut place),
)) => {
// Use the underlying local for this (necessarily interior) borrow.
let ty = local_decls.local_decls()[place.local].ty;
let span = statement.source_info.span;

let ref_ty = tcx.mk_ref(
tcx.lifetimes.re_erased,
ty::TypeAndMut { ty, mutbl: borrow_kind.to_mutbl_lossy() },
);

*region = tcx.lifetimes.re_erased;

let mut projection = vec![PlaceElem::Deref];
projection.extend(place.projection);
place.projection = tcx.intern_place_elems(&projection);

// Create a temp to hold the promoted reference.
// This is because `*r` requires `r` to be a local,
// otherwise we would use the `promoted` directly.
let mut promoted_ref = LocalDecl::new(ref_ty, span);
promoted_ref.source_info = statement.source_info;
let promoted_ref = local_decls.push(promoted_ref);
assert_eq!(self.temps.push(TempState::Unpromotable), promoted_ref);

let promoted_ref_statement = Statement {
source_info: statement.source_info,
kind: StatementKind::Assign(Box::new((
Place::from(promoted_ref),
Rvalue::Use(promoted_operand(ref_ty, span)),
))),
};
self.extra_statements.push((loc, promoted_ref_statement));

Rvalue::Ref(
tcx.lifetimes.re_erased,
borrow_kind,
Place {
local: mem::replace(&mut place.local, promoted_ref),
projection: List::empty(),
},
)
}
_ => bug!(),
}
let loc = candidate.location;
let statement = &mut blocks[loc.block].statements[loc.statement_index];
match statement.kind {
StatementKind::Assign(box (
_,
Rvalue::Ref(ref mut region, borrow_kind, ref mut place),
)) => {
// Use the underlying local for this (necessarily interior) borrow.
let ty = local_decls.local_decls()[place.local].ty;
let span = statement.source_info.span;

let ref_ty = tcx.mk_ref(
tcx.lifetimes.re_erased,
ty::TypeAndMut { ty, mutbl: borrow_kind.to_mutbl_lossy() },
);

*region = tcx.lifetimes.re_erased;

let mut projection = vec![PlaceElem::Deref];
projection.extend(place.projection);
place.projection = tcx.intern_place_elems(&projection);

// Create a temp to hold the promoted reference.
// This is because `*r` requires `r` to be a local,
// otherwise we would use the `promoted` directly.
let mut promoted_ref = LocalDecl::new(ref_ty, span);
promoted_ref.source_info = statement.source_info;
let promoted_ref = local_decls.push(promoted_ref);
assert_eq!(self.temps.push(TempState::Unpromotable), promoted_ref);

let promoted_ref_statement = Statement {
source_info: statement.source_info,
kind: StatementKind::Assign(Box::new((
Place::from(promoted_ref),
Rvalue::Use(promoted_operand(ref_ty, span)),
))),
};
self.extra_statements.push((loc, promoted_ref_statement));

Rvalue::Ref(
tcx.lifetimes.re_erased,
borrow_kind,
Place {
local: mem::replace(&mut place.local, promoted_ref),
projection: List::empty(),
},
)
}
_ => bug!(),
}
};

Expand Down Expand Up @@ -964,25 +949,21 @@ pub fn promote_candidates<'tcx>(

let mut extra_statements = vec![];
for candidate in candidates.into_iter().rev() {
match candidate {
Candidate::Ref(Location { block, statement_index }) => {
if let StatementKind::Assign(box (place, _)) =
&body[block].statements[statement_index].kind
{
if let Some(local) = place.as_local() {
if temps[local] == TempState::PromotedOut {
// Already promoted.
continue;
}
}
let Location { block, statement_index } = candidate.location;
if let StatementKind::Assign(box (place, _)) = &body[block].statements[statement_index].kind
{
if let Some(local) = place.as_local() {
if temps[local] == TempState::PromotedOut {
// Already promoted.
continue;
}
}
}

// Declare return place local so that `mir::Body::new` doesn't complain.
let initial_locals = iter::once(LocalDecl::new(tcx.types.never, body.span)).collect();

let mut scope = body.source_scopes[candidate.source_info(body).scope].clone();
let mut scope = body.source_scopes[body.source_info(candidate.location).scope].clone();
scope.parent_scope = None;

let promoted = Body::new(
Expand Down
Loading