Skip to content

Commit 847c8ba

Browse files
committed
Remove IdFunctor trait.
It's defined in `rustc_data_structures` but is only used in `rustc_type_ir`. The code is shorter and easier to read if we remove this layer of abstraction and just do the things directly where they are needed.
1 parent 4175c9b commit 847c8ba

File tree

4 files changed

+48
-125
lines changed

4 files changed

+48
-125
lines changed

compiler/rustc_data_structures/src/functor.rs

-116
This file was deleted.

compiler/rustc_data_structures/src/lib.rs

-3
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,12 @@
1818
#![feature(min_specialization)]
1919
#![feature(never_type)]
2020
#![feature(type_alias_impl_trait)]
21-
#![feature(new_uninit)]
2221
#![feature(lazy_cell)]
2322
#![feature(rustc_attrs)]
2423
#![feature(negative_impls)]
2524
#![feature(test)]
2625
#![feature(thread_id_value)]
2726
#![feature(allocator_api)]
28-
#![feature(get_mut_unchecked)]
2927
#![feature(lint_reasons)]
3028
#![feature(unwrap_infallible)]
3129
#![feature(strict_provenance)]
@@ -61,7 +59,6 @@ pub mod binary_search_util;
6159
pub mod captures;
6260
pub mod flat_map_in_place;
6361
pub mod flock;
64-
pub mod functor;
6562
pub mod fx;
6663
pub mod graph;
6764
pub mod intern;

compiler/rustc_type_ir/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#![feature(associated_type_defaults)]
22
#![feature(fmt_helpers_for_derive)]
3+
#![feature(get_mut_unchecked)]
34
#![feature(min_specialization)]
45
#![feature(never_type)]
6+
#![feature(new_uninit)]
57
#![feature(rustc_attrs)]
68
#![feature(unwrap_infallible)]
79
#![deny(rustc::untranslatable_diagnostic)]

compiler/rustc_type_ir/src/structural_impls.rs

+46-6
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55
use crate::fold::{FallibleTypeFolder, TypeFoldable};
66
use crate::visit::{TypeVisitable, TypeVisitor};
77
use crate::{ConstKind, FloatTy, InferTy, IntTy, Interner, UintTy, UniverseIndex};
8-
use rustc_data_structures::functor::IdFunctor;
98
use rustc_data_structures::sync::Lrc;
109
use rustc_index::{Idx, IndexVec};
1110

1211
use core::fmt;
1312
use std::marker::PhantomData;
13+
use std::mem;
1414
use std::ops::ControlFlow;
1515

1616
///////////////////////////////////////////////////////////////////////////
@@ -108,8 +108,39 @@ impl<I: Interner, T: TypeVisitable<I>, E: TypeVisitable<I>> TypeVisitable<I> for
108108
}
109109

110110
impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Lrc<T> {
111-
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
112-
self.try_map_id(|value| value.try_fold_with(folder))
111+
fn try_fold_with<F: FallibleTypeFolder<I>>(mut self, folder: &mut F) -> Result<Self, F::Error> {
112+
// We merely want to replace the contained `T`, if at all possible,
113+
// so that we don't needlessly allocate a new `Lrc` or indeed clone
114+
// the contained type.
115+
unsafe {
116+
// First step is to ensure that we have a unique reference to
117+
// the contained type, which `Lrc::make_mut` will accomplish (by
118+
// allocating a new `Lrc` and cloning the `T` only if required).
119+
// This is done *before* casting to `Lrc<ManuallyDrop<T>>` so that
120+
// panicking during `make_mut` does not leak the `T`.
121+
Lrc::make_mut(&mut self);
122+
123+
// Casting to `Lrc<ManuallyDrop<T>>` is safe because `ManuallyDrop`
124+
// is `repr(transparent)`.
125+
let ptr = Lrc::into_raw(self).cast::<mem::ManuallyDrop<T>>();
126+
let mut unique = Lrc::from_raw(ptr);
127+
128+
// Call to `Lrc::make_mut` above guarantees that `unique` is the
129+
// sole reference to the contained value, so we can avoid doing
130+
// a checked `get_mut` here.
131+
let slot = Lrc::get_mut_unchecked(&mut unique);
132+
133+
// Semantically move the contained type out from `unique`, fold
134+
// it, then move the folded value back into `unique`. Should
135+
// folding fail, `ManuallyDrop` ensures that the "moved-out"
136+
// value is not re-dropped.
137+
let owned = mem::ManuallyDrop::take(slot);
138+
let folded = owned.try_fold_with(folder)?;
139+
*slot = mem::ManuallyDrop::new(folded);
140+
141+
// Cast back to `Lrc<T>`.
142+
Ok(Lrc::from_raw(Lrc::into_raw(unique).cast()))
143+
}
113144
}
114145
}
115146

@@ -121,7 +152,16 @@ impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Lrc<T> {
121152

122153
impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Box<T> {
123154
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
124-
self.try_map_id(|value| value.try_fold_with(folder))
155+
let raw = Box::into_raw(self);
156+
Ok(unsafe {
157+
// SAFETY: The raw pointer points to a valid value of type `T`.
158+
let value = raw.read();
159+
// SAFETY: Converts `Box<T>` to `Box<MaybeUninit<T>>` which is the
160+
// inverse of `Box::assume_init()` and should be safe.
161+
let raw: Box<mem::MaybeUninit<T>> = Box::from_raw(raw.cast());
162+
// SAFETY: Write the mapped value back into the `Box`.
163+
Box::write(raw, value.try_fold_with(folder)?)
164+
})
125165
}
126166
}
127167

@@ -133,7 +173,7 @@ impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Box<T> {
133173

134174
impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Vec<T> {
135175
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
136-
self.try_map_id(|t| t.try_fold_with(folder))
176+
self.into_iter().map(|t| t.try_fold_with(folder)).collect()
137177
}
138178
}
139179

@@ -161,7 +201,7 @@ impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Box<[T]> {
161201

162202
impl<I: Interner, T: TypeFoldable<I>, Ix: Idx> TypeFoldable<I> for IndexVec<Ix, T> {
163203
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
164-
self.try_map_id(|x| x.try_fold_with(folder))
204+
self.raw.try_fold_with(folder).map(IndexVec::from_raw)
165205
}
166206
}
167207

0 commit comments

Comments
 (0)