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

Use min_specialization in the remaining rustc crates #72707

Merged
merged 1 commit into from
Jun 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
29 changes: 19 additions & 10 deletions src/librustc_arena/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,7 @@ macro_rules! which_arena_for_type {

#[macro_export]
macro_rules! declare_arena {
([], [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => {
([], [$($a:tt $name:ident: $ty:ty, $gen_ty:ty;)*], $tcx:lifetime) => {
#[derive(Default)]
pub struct Arena<$tcx> {
pub dropless: $crate::DroplessArena,
Expand All @@ -619,17 +619,17 @@ macro_rules! declare_arena {
}

#[marker]
pub trait ArenaAllocatable {}
pub trait ArenaAllocatable<'tcx> {}

impl<T: Copy> ArenaAllocatable for T {}
impl<'tcx, T: Copy> ArenaAllocatable<'tcx> for T {}

unsafe trait ArenaField<'tcx>: Sized {
unsafe trait ArenaField<'tcx>: Sized + ArenaAllocatable<'tcx> {
/// Returns a specific arena to allocate from.
/// If `None` is returned, the `DropArena` will be used.
fn arena<'a>(arena: &'a Arena<'tcx>) -> Option<&'a $crate::TypedArena<Self>>;
}

unsafe impl<'tcx, T> ArenaField<'tcx> for T {
unsafe impl<'tcx, T: ArenaAllocatable<'tcx>> ArenaField<'tcx> for T {
#[inline]
default fn arena<'a>(_: &'a Arena<'tcx>) -> Option<&'a $crate::TypedArena<Self>> {
panic!()
Expand All @@ -638,18 +638,27 @@ macro_rules! declare_arena {

$(
#[allow(unused_lifetimes)]
impl<$tcx> ArenaAllocatable for $ty {}
unsafe impl<$tcx> ArenaField<$tcx> for $ty {
impl<$tcx> ArenaAllocatable<$tcx> for $ty {}
unsafe impl<$tcx, '_x, '_y, '_z, '_w> ArenaField<$tcx> for $gen_ty where Self: ArenaAllocatable<$tcx> {
#[inline]
fn arena<'a>(_arena: &'a Arena<$tcx>) -> Option<&'a $crate::TypedArena<Self>> {
$crate::which_arena_for_type!($a[&_arena.$name])
// SAFETY: We only implement `ArenaAllocatable<$tcx>` for
// `$ty`, so `$ty` and Self are the same type
unsafe {
::std::mem::transmute::<
Option<&'a $crate::TypedArena<$ty>>,
Option<&'a $crate::TypedArena<Self>>,
>(
$crate::which_arena_for_type!($a[&_arena.$name])
)
}
}
}
)*

impl<'tcx> Arena<'tcx> {
#[inline]
pub fn alloc<T: ArenaAllocatable>(&self, value: T) -> &mut T {
pub fn alloc<T: ArenaAllocatable<'tcx>>(&self, value: T) -> &mut T {
if !::std::mem::needs_drop::<T>() {
return self.dropless.alloc(value);
}
Expand All @@ -667,7 +676,7 @@ macro_rules! declare_arena {
self.dropless.alloc_slice(value)
}

pub fn alloc_from_iter<'a, T: ArenaAllocatable>(
pub fn alloc_from_iter<'a, T: ArenaAllocatable<'tcx>>(
&'a self,
iter: impl ::std::iter::IntoIterator<Item = T>,
) -> &'a mut [T] {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_ast_lowering/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
#![feature(array_value_iter)]
#![feature(crate_visibility_modifier)]
#![feature(marker_trait_attr)]
#![feature(specialization)] // FIXME: min_specialization does not work
#![feature(min_specialization)]
#![feature(or_patterns)]
#![recursion_limit = "256"]

Expand Down
70 changes: 35 additions & 35 deletions src/librustc_hir/arena.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,41 +12,41 @@ macro_rules! arena_types {
($macro:path, $args:tt, $tcx:lifetime) => (
$macro!($args, [
// HIR types
[few] hir_krate: rustc_hir::Crate<$tcx>,
[] arm: rustc_hir::Arm<$tcx>,
[] asm_operand: rustc_hir::InlineAsmOperand<$tcx>,
[] asm_template: rustc_ast::ast::InlineAsmTemplatePiece,
[] attribute: rustc_ast::ast::Attribute,
[] block: rustc_hir::Block<$tcx>,
[] bare_fn_ty: rustc_hir::BareFnTy<$tcx>,
[few] global_asm: rustc_hir::GlobalAsm,
[] generic_arg: rustc_hir::GenericArg<$tcx>,
[] generic_args: rustc_hir::GenericArgs<$tcx>,
[] generic_bound: rustc_hir::GenericBound<$tcx>,
[] generic_param: rustc_hir::GenericParam<$tcx>,
[] expr: rustc_hir::Expr<$tcx>,
[] field: rustc_hir::Field<$tcx>,
[] field_pat: rustc_hir::FieldPat<$tcx>,
[] fn_decl: rustc_hir::FnDecl<$tcx>,
[] foreign_item: rustc_hir::ForeignItem<$tcx>,
[] impl_item_ref: rustc_hir::ImplItemRef<$tcx>,
[few] inline_asm: rustc_hir::InlineAsm<$tcx>,
[few] llvm_inline_asm: rustc_hir::LlvmInlineAsm<$tcx>,
[] local: rustc_hir::Local<$tcx>,
[few] macro_def: rustc_hir::MacroDef<$tcx>,
[] param: rustc_hir::Param<$tcx>,
[] pat: rustc_hir::Pat<$tcx>,
[] path: rustc_hir::Path<$tcx>,
[] path_segment: rustc_hir::PathSegment<$tcx>,
[] poly_trait_ref: rustc_hir::PolyTraitRef<$tcx>,
[] qpath: rustc_hir::QPath<$tcx>,
[] stmt: rustc_hir::Stmt<$tcx>,
[] struct_field: rustc_hir::StructField<$tcx>,
[] trait_item_ref: rustc_hir::TraitItemRef,
[] ty: rustc_hir::Ty<$tcx>,
[] type_binding: rustc_hir::TypeBinding<$tcx>,
[] variant: rustc_hir::Variant<$tcx>,
[] where_predicate: rustc_hir::WherePredicate<$tcx>,
[few] hir_krate: rustc_hir::Crate<$tcx>, rustc_hir::Crate<'_x>;
[] arm: rustc_hir::Arm<$tcx>, rustc_hir::Arm<'_x>;
[] asm_operand: rustc_hir::InlineAsmOperand<$tcx>, rustc_hir::InlineAsmOperand<'_x>;
[] asm_template: rustc_ast::ast::InlineAsmTemplatePiece, rustc_ast::ast::InlineAsmTemplatePiece;
[] attribute: rustc_ast::ast::Attribute, rustc_ast::ast::Attribute;
[] block: rustc_hir::Block<$tcx>, rustc_hir::Block<'_x>;
[] bare_fn_ty: rustc_hir::BareFnTy<$tcx>, rustc_hir::BareFnTy<'_x>;
[few] global_asm: rustc_hir::GlobalAsm, rustc_hir::GlobalAsm;
[] generic_arg: rustc_hir::GenericArg<$tcx>, rustc_hir::GenericArg<'_x>;
[] generic_args: rustc_hir::GenericArgs<$tcx>, rustc_hir::GenericArgs<'_x>;
[] generic_bound: rustc_hir::GenericBound<$tcx>, rustc_hir::GenericBound<'_x>;
[] generic_param: rustc_hir::GenericParam<$tcx>, rustc_hir::GenericParam<'_x>;
[] expr: rustc_hir::Expr<$tcx>, rustc_hir::Expr<'_x>;
[] field: rustc_hir::Field<$tcx>, rustc_hir::Field<'_x>;
[] field_pat: rustc_hir::FieldPat<$tcx>, rustc_hir::FieldPat<'_x>;
[] fn_decl: rustc_hir::FnDecl<$tcx>, rustc_hir::FnDecl<'_x>;
[] foreign_item: rustc_hir::ForeignItem<$tcx>, rustc_hir::ForeignItem<'_x>;
[] impl_item_ref: rustc_hir::ImplItemRef<$tcx>, rustc_hir::ImplItemRef<'_x>;
[few] inline_asm: rustc_hir::InlineAsm<$tcx>, rustc_hir::InlineAsm<'_x>;
[few] llvm_inline_asm: rustc_hir::LlvmInlineAsm<$tcx>, rustc_hir::LlvmInlineAsm<'_x>;
[] local: rustc_hir::Local<$tcx>, rustc_hir::Local<'_x>;
[few] macro_def: rustc_hir::MacroDef<$tcx>, rustc_hir::MacroDef<'_x>;
[] param: rustc_hir::Param<$tcx>, rustc_hir::Param<'_x>;
[] pat: rustc_hir::Pat<$tcx>, rustc_hir::Pat<'_x>;
[] path: rustc_hir::Path<$tcx>, rustc_hir::Path<'_x>;
[] path_segment: rustc_hir::PathSegment<$tcx>, rustc_hir::PathSegment<'_x>;
[] poly_trait_ref: rustc_hir::PolyTraitRef<$tcx>, rustc_hir::PolyTraitRef<'_x>;
[] qpath: rustc_hir::QPath<$tcx>, rustc_hir::QPath<'_x>;
[] stmt: rustc_hir::Stmt<$tcx>, rustc_hir::Stmt<'_x>;
[] struct_field: rustc_hir::StructField<$tcx>, rustc_hir::StructField<'_x>;
[] trait_item_ref: rustc_hir::TraitItemRef, rustc_hir::TraitItemRef;
[] ty: rustc_hir::Ty<$tcx>, rustc_hir::Ty<'_x>;
[] type_binding: rustc_hir::TypeBinding<$tcx>, rustc_hir::TypeBinding<'_x>;
[] variant: rustc_hir::Variant<$tcx>, rustc_hir::Variant<'_x>;
[] where_predicate: rustc_hir::WherePredicate<$tcx>, rustc_hir::WherePredicate<'_x>;
], $tcx);
)
}
2 changes: 1 addition & 1 deletion src/librustc_infer/infer/canonical/query_response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
) -> Fallible<CanonicalizedQueryResponse<'tcx, T>>
where
T: Debug + TypeFoldable<'tcx>,
Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable,
Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>,
{
let query_response = self.make_query_response(inference_vars, answer, fulfill_cx)?;
let canonical_result = self.canonicalize_response(&query_response);
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_macros/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {

try_load_from_on_disk_cache_stream.extend(quote! {
::rustc_middle::dep_graph::DepKind::#name => {
if <#arg as DepNodeParams<TyCtxt<'_>>>::CAN_RECONSTRUCT_QUERY_KEY {
if <#arg as DepNodeParams<TyCtxt<'_>>>::can_reconstruct_query_key() {
debug_assert!($tcx.dep_graph
.node_color($dep_node)
.map(|c| c.is_green())
Expand Down Expand Up @@ -490,7 +490,7 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
// Add a match arm to force the query given the dep node
dep_node_force_stream.extend(quote! {
::rustc_middle::dep_graph::DepKind::#name => {
if <#arg as DepNodeParams<TyCtxt<'_>>>::CAN_RECONSTRUCT_QUERY_KEY {
if <#arg as DepNodeParams<TyCtxt<'_>>>::can_reconstruct_query_key() {
if let Some(key) = <#arg as DepNodeParams<TyCtxt<'_>>>::recover($tcx, $dep_node) {
force_query::<crate::ty::query::queries::#name<'_>, _>(
$tcx,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_metadata/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#![feature(nll)]
#![feature(or_patterns)]
#![feature(proc_macro_internals)]
#![feature(specialization)] // FIXME: min_specialization ICEs
#![feature(min_specialization)]
#![feature(stmt_expr_attributes)]
#![recursion_limit = "256"]

Expand Down
17 changes: 9 additions & 8 deletions src/librustc_metadata/rmeta/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use rustc_middle::mir::{self, interpret, Body, Promoted};
use rustc_middle::ty::codec::TyDecoder;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::util::common::record_time;
use rustc_serialize::{opaque, Decodable, Decoder, SpecializedDecoder};
use rustc_serialize::{opaque, Decodable, Decoder, SpecializedDecoder, UseSpecializedDecodable};
use rustc_session::Session;
use rustc_span::source_map::{respan, Spanned};
use rustc_span::symbol::{sym, Ident, Symbol};
Expand Down Expand Up @@ -218,15 +218,15 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadataRef<'a>, TyCtxt<'tcx>) {
}
}

impl<'a, 'tcx, T: Decodable> Lazy<T> {
impl<'a, 'tcx, T: Decodable> Lazy<T, ()> {
fn decode<M: Metadata<'a, 'tcx>>(self, metadata: M) -> T {
let mut dcx = metadata.decoder(self.position.get());
dcx.lazy_state = LazyState::NodeStart(self.position);
T::decode(&mut dcx).unwrap()
}
}

impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable> Lazy<[T]> {
impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable> Lazy<[T], usize> {
fn decode<M: Metadata<'a, 'tcx>>(
self,
metadata: M,
Expand Down Expand Up @@ -321,20 +321,20 @@ impl<'a, 'tcx> TyDecoder<'tcx> for DecodeContext<'a, 'tcx> {
}
}

impl<'a, 'tcx, T> SpecializedDecoder<Lazy<T>> for DecodeContext<'a, 'tcx> {
impl<'a, 'tcx, T> SpecializedDecoder<Lazy<T, ()>> for DecodeContext<'a, 'tcx> {
fn specialized_decode(&mut self) -> Result<Lazy<T>, Self::Error> {
self.read_lazy_with_meta(())
}
}

impl<'a, 'tcx, T> SpecializedDecoder<Lazy<[T]>> for DecodeContext<'a, 'tcx> {
impl<'a, 'tcx, T> SpecializedDecoder<Lazy<[T], usize>> for DecodeContext<'a, 'tcx> {
fn specialized_decode(&mut self) -> Result<Lazy<[T]>, Self::Error> {
let len = self.read_usize()?;
if len == 0 { Ok(Lazy::empty()) } else { self.read_lazy_with_meta(len) }
}
}

impl<'a, 'tcx, I: Idx, T> SpecializedDecoder<Lazy<Table<I, T>>> for DecodeContext<'a, 'tcx>
impl<'a, 'tcx, I: Idx, T> SpecializedDecoder<Lazy<Table<I, T>, usize>> for DecodeContext<'a, 'tcx>
where
Option<T>: FixedSizeEncoding,
{
Expand Down Expand Up @@ -515,8 +515,9 @@ impl<'a, 'tcx> SpecializedDecoder<Fingerprint> for DecodeContext<'a, 'tcx> {
}
}

impl<'a, 'tcx, T: Decodable> SpecializedDecoder<mir::ClearCrossCrate<T>>
for DecodeContext<'a, 'tcx>
impl<'a, 'tcx, T> SpecializedDecoder<mir::ClearCrossCrate<T>> for DecodeContext<'a, 'tcx>
where
mir::ClearCrossCrate<T>: UseSpecializedDecodable,
{
#[inline]
fn specialized_decode(&mut self) -> Result<mir::ClearCrossCrate<T>, Self::Error> {
Expand Down
35 changes: 25 additions & 10 deletions src/librustc_metadata/rmeta/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use rustc_middle::mir::{self, interpret};
use rustc_middle::traits::specialization_graph;
use rustc_middle::ty::codec::{self as ty_codec, TyEncoder};
use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt};
use rustc_serialize::{opaque, Encodable, Encoder, SpecializedEncoder};
use rustc_serialize::{opaque, Encodable, Encoder, SpecializedEncoder, UseSpecializedEncodable};
use rustc_session::config::CrateType;
use rustc_span::source_map::Spanned;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
Expand Down Expand Up @@ -93,13 +93,13 @@ impl<'tcx> Encoder for EncodeContext<'tcx> {
}
}

impl<'tcx, T> SpecializedEncoder<Lazy<T>> for EncodeContext<'tcx> {
impl<'tcx, T> SpecializedEncoder<Lazy<T, ()>> for EncodeContext<'tcx> {
fn specialized_encode(&mut self, lazy: &Lazy<T>) -> Result<(), Self::Error> {
self.emit_lazy_distance(*lazy)
}
}

impl<'tcx, T> SpecializedEncoder<Lazy<[T]>> for EncodeContext<'tcx> {
impl<'tcx, T> SpecializedEncoder<Lazy<[T], usize>> for EncodeContext<'tcx> {
fn specialized_encode(&mut self, lazy: &Lazy<[T]>) -> Result<(), Self::Error> {
self.emit_usize(lazy.meta)?;
if lazy.meta == 0 {
Expand All @@ -109,7 +109,7 @@ impl<'tcx, T> SpecializedEncoder<Lazy<[T]>> for EncodeContext<'tcx> {
}
}

impl<'tcx, I: Idx, T> SpecializedEncoder<Lazy<Table<I, T>>> for EncodeContext<'tcx>
impl<'tcx, I: Idx, T> SpecializedEncoder<Lazy<Table<I, T>, usize>> for EncodeContext<'tcx>
where
Option<T>: FixedSizeEncoding,
{
Expand Down Expand Up @@ -228,8 +228,13 @@ impl<'tcx> SpecializedEncoder<LocalDefId> for EncodeContext<'tcx> {
}
}

impl<'tcx> SpecializedEncoder<Ty<'tcx>> for EncodeContext<'tcx> {
fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> {
impl<'a, 'b, 'tcx> SpecializedEncoder<&'a ty::TyS<'b>> for EncodeContext<'tcx>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are the two separate lifetimes 'a and 'b really necessary here? Couldn't they just be one and use Ty<'a>?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately not. Specializing impls can't repeat type/lifetime parameters.

where
&'a ty::TyS<'b>: UseSpecializedEncodable,
{
fn specialized_encode(&mut self, ty: &&'a ty::TyS<'b>) -> Result<(), Self::Error> {
debug_assert!(self.tcx.lift(ty).is_some());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a measurable perf loss to just doing lift and unwrap and skipping the transmute?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, looks like there are some serious losses here. Let's benchmark against the transmute variant and if that has no perf losses, let's merge it.

let ty = unsafe { std::mem::transmute::<&&'a ty::TyS<'b>, &&'tcx ty::TyS<'tcx>>(ty) };
ty_codec::encode_with_shorthand(self, ty, |ecx| &mut ecx.type_shorthands)
}
}
Expand All @@ -251,12 +256,19 @@ impl<'tcx> SpecializedEncoder<interpret::AllocId> for EncodeContext<'tcx> {
}
}

impl<'tcx> SpecializedEncoder<&'tcx [(ty::Predicate<'tcx>, Span)]> for EncodeContext<'tcx> {
impl<'a, 'b, 'tcx> SpecializedEncoder<&'a [(ty::Predicate<'b>, Span)]> for EncodeContext<'tcx> {
fn specialized_encode(
&mut self,
predicates: &&'tcx [(ty::Predicate<'tcx>, Span)],
predicates: &&'a [(ty::Predicate<'b>, Span)],
) -> Result<(), Self::Error> {
ty_codec::encode_spanned_predicates(self, predicates, |ecx| &mut ecx.predicate_shorthands)
debug_assert!(self.tcx.lift(*predicates).is_some());
let predicates = unsafe {
std::mem::transmute::<
&&'a [(ty::Predicate<'b>, Span)],
&&'tcx [(ty::Predicate<'tcx>, Span)],
>(predicates)
};
ty_codec::encode_spanned_predicates(self, &predicates, |ecx| &mut ecx.predicate_shorthands)
}
}

Expand All @@ -266,7 +278,10 @@ impl<'tcx> SpecializedEncoder<Fingerprint> for EncodeContext<'tcx> {
}
}

impl<'tcx, T: Encodable> SpecializedEncoder<mir::ClearCrossCrate<T>> for EncodeContext<'tcx> {
impl<'tcx, T> SpecializedEncoder<mir::ClearCrossCrate<T>> for EncodeContext<'tcx>
where
mir::ClearCrossCrate<T>: UseSpecializedEncodable,
{
fn specialized_encode(&mut self, _: &mir::ClearCrossCrate<T>) -> Result<(), Self::Error> {
Ok(())
}
Expand Down
Loading