Skip to content

Commit d47fd9e

Browse files
committed
rustc_metadata: use specialization for {en,de}coding Ty and Substs.
1 parent 8219728 commit d47fd9e

File tree

7 files changed

+71
-168
lines changed

7 files changed

+71
-168
lines changed

src/librustc/middle/cstore.rs

Lines changed: 15 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -509,85 +509,20 @@ pub trait MacroLoader {
509509
/// Note, however, that this only works for RBML-based encoding and decoding at
510510
/// the moment.
511511
pub mod tls {
512-
use rbml::opaque::Encoder as OpaqueEncoder;
513512
use rbml::opaque::Decoder as OpaqueDecoder;
514-
use serialize;
515513
use std::cell::Cell;
516-
use std::mem;
517-
use ty::{self, Ty, TyCtxt};
514+
use ty::{Ty, TyCtxt};
518515
use ty::subst::Substs;
519516
use hir::def_id::DefId;
520517

521-
pub trait EncodingContext<'tcx> {
522-
fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx>;
523-
fn encode_ty(&self, encoder: &mut OpaqueEncoder, t: Ty<'tcx>);
524-
fn encode_substs(&self, encoder: &mut OpaqueEncoder, substs: &Substs<'tcx>);
525-
}
526-
527518
/// Marker type used for the TLS slot.
528519
/// The type context cannot be used directly because the TLS
529520
/// in libstd doesn't allow types generic over lifetimes.
530521
struct TlsPayload;
531522

532-
thread_local! {
533-
static TLS_ENCODING: Cell<Option<*const TlsPayload>> = Cell::new(None)
534-
}
535-
536-
/// Execute f after pushing the given EncodingContext onto the TLS stack.
537-
pub fn enter_encoding_context<'tcx, F, R>(ecx: &EncodingContext<'tcx>,
538-
encoder: &mut OpaqueEncoder,
539-
f: F) -> R
540-
where F: FnOnce(&EncodingContext<'tcx>, &mut OpaqueEncoder) -> R
541-
{
542-
let tls_payload = (ecx as *const _, encoder as *mut _);
543-
let tls_ptr = &tls_payload as *const _ as *const TlsPayload;
544-
TLS_ENCODING.with(|tls| {
545-
let prev = tls.get();
546-
tls.set(Some(tls_ptr));
547-
let ret = f(ecx, encoder);
548-
tls.set(prev);
549-
return ret
550-
})
551-
}
552-
553-
/// Execute f with access to the thread-local encoding context and
554-
/// rbml encoder. This function will panic if the encoder passed in and the
555-
/// context encoder are not the same.
556-
///
557-
/// Note that this method is 'practically' safe due to its checking that the
558-
/// encoder passed in is the same as the one in TLS, but it would still be
559-
/// possible to construct cases where the EncodingContext is exchanged
560-
/// while the same encoder is used, thus working with a wrong context.
561-
pub fn with_encoding_context<'tcx, E, F, R>(encoder: &mut E, f: F) -> R
562-
where F: FnOnce(&EncodingContext<'tcx>, &mut OpaqueEncoder) -> R,
563-
E: serialize::Encoder
564-
{
565-
unsafe {
566-
unsafe_with_encoding_context(|ecx, tls_encoder| {
567-
assert!(encoder as *mut _ as usize == tls_encoder as *mut _ as usize);
568-
569-
let ecx: &EncodingContext<'tcx> = mem::transmute(ecx);
570-
571-
f(ecx, tls_encoder)
572-
})
573-
}
574-
}
575-
576-
/// Execute f with access to the thread-local encoding context and
577-
/// rbml encoder.
578-
pub unsafe fn unsafe_with_encoding_context<F, R>(f: F) -> R
579-
where F: FnOnce(&EncodingContext, &mut OpaqueEncoder) -> R
580-
{
581-
TLS_ENCODING.with(|tls| {
582-
let tls = tls.get().unwrap();
583-
let tls_payload = tls as *mut (&EncodingContext, &mut OpaqueEncoder);
584-
f((*tls_payload).0, (*tls_payload).1)
585-
})
586-
}
587-
588523
pub trait DecodingContext<'tcx> {
589524
fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx>;
590-
fn decode_ty(&self, decoder: &mut OpaqueDecoder) -> ty::Ty<'tcx>;
525+
fn decode_ty(&self, decoder: &mut OpaqueDecoder) -> Ty<'tcx>;
591526
fn decode_substs(&self, decoder: &mut OpaqueDecoder) -> &'tcx Substs<'tcx>;
592527
fn translate_def_id(&self, def_id: DefId) -> DefId;
593528
}
@@ -597,56 +532,31 @@ pub mod tls {
597532
}
598533

599534
/// Execute f after pushing the given DecodingContext onto the TLS stack.
600-
pub fn enter_decoding_context<'tcx, F, R>(dcx: &DecodingContext<'tcx>,
601-
decoder: &mut OpaqueDecoder,
602-
f: F) -> R
603-
where F: FnOnce(&DecodingContext<'tcx>, &mut OpaqueDecoder) -> R
535+
pub fn enter_decoding_context<'tcx, F, R>(dcx: &DecodingContext<'tcx>, f: F) -> R
536+
where F: FnOnce(&DecodingContext<'tcx>) -> R
604537
{
605-
let tls_payload = (dcx as *const _, decoder as *mut _);
538+
let tls_payload = dcx as *const _;
606539
let tls_ptr = &tls_payload as *const _ as *const TlsPayload;
607540
TLS_DECODING.with(|tls| {
608541
let prev = tls.get();
609542
tls.set(Some(tls_ptr));
610-
let ret = f(dcx, decoder);
543+
let ret = f(dcx);
611544
tls.set(prev);
612-
return ret
545+
ret
613546
})
614547
}
615548

616-
/// Execute f with access to the thread-local decoding context and
617-
/// rbml decoder. This function will panic if the decoder passed in and the
618-
/// context decoder are not the same.
619-
///
620-
/// Note that this method is 'practically' safe due to its checking that the
621-
/// decoder passed in is the same as the one in TLS, but it would still be
622-
/// possible to construct cases where the DecodingContext is exchanged
623-
/// while the same decoder is used, thus working with a wrong context.
624-
pub fn with_decoding_context<'decoder, 'tcx, D, F, R>(d: &'decoder mut D, f: F) -> R
625-
where D: serialize::Decoder,
626-
F: FnOnce(&DecodingContext<'tcx>,
627-
&mut OpaqueDecoder) -> R,
628-
'tcx: 'decoder
549+
/// Execute f with access to the thread-local decoding context.
550+
/// FIXME(eddyb) This is horribly unsound as it allows the
551+
/// caler to pick any lifetime for 'tcx, including 'static.
552+
pub fn with_decoding_context<'tcx, F, R>(f: F) -> R
553+
where F: FnOnce(&DecodingContext<'tcx>) -> R,
629554
{
630555
unsafe {
631-
unsafe_with_decoding_context(|dcx, decoder| {
632-
assert!((d as *mut _ as usize) == (decoder as *mut _ as usize));
633-
634-
let dcx: &DecodingContext<'tcx> = mem::transmute(dcx);
635-
636-
f(dcx, decoder)
556+
TLS_DECODING.with(|tls| {
557+
let tls = tls.get().unwrap();
558+
f(*(tls as *mut &DecodingContext))
637559
})
638560
}
639561
}
640-
641-
/// Execute f with access to the thread-local decoding context and
642-
/// rbml decoder.
643-
pub unsafe fn unsafe_with_decoding_context<F, R>(f: F) -> R
644-
where F: FnOnce(&DecodingContext, &mut OpaqueDecoder) -> R
645-
{
646-
TLS_DECODING.with(|tls| {
647-
let tls = tls.get().unwrap();
648-
let tls_payload = tls as *mut (&DecodingContext, &mut OpaqueDecoder);
649-
f((*tls_payload).0, (*tls_payload).1)
650-
})
651-
}
652562
}

src/librustc/ty/mod.rs

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use util::common::MemoizationMap;
3434
use util::nodemap::NodeSet;
3535
use util::nodemap::FnvHashMap;
3636

37-
use serialize::{Encodable, Encoder, Decodable, Decoder};
37+
use serialize::{self, Encodable, Encoder, Decodable, Decoder};
3838
use std::borrow::Cow;
3939
use std::cell::Cell;
4040
use std::hash::{Hash, Hasher};
@@ -567,23 +567,8 @@ impl<'tcx> Hash for TyS<'tcx> {
567567

568568
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
569569

570-
impl<'tcx> Encodable for Ty<'tcx> {
571-
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
572-
cstore::tls::with_encoding_context(s, |ecx, rbml_w| {
573-
ecx.encode_ty(rbml_w, *self);
574-
Ok(())
575-
})
576-
}
577-
}
578-
579-
impl<'tcx> Decodable for Ty<'tcx> {
580-
fn decode<D: Decoder>(d: &mut D) -> Result<Ty<'tcx>, D::Error> {
581-
cstore::tls::with_decoding_context(d, |dcx, rbml_r| {
582-
Ok(dcx.decode_ty(rbml_r))
583-
})
584-
}
585-
}
586-
570+
impl<'tcx> serialize::UseSpecializedEncodable for Ty<'tcx> {}
571+
impl<'tcx> serialize::UseSpecializedDecodable for Ty<'tcx> {}
587572

588573
/// Upvars do not get their own node-id. Instead, we use the pair of
589574
/// the original var id (that is, the root variable that is referenced
@@ -1506,7 +1491,7 @@ impl<'tcx> Decodable for AdtDef<'tcx> {
15061491
fn decode<D: Decoder>(d: &mut D) -> Result<AdtDef<'tcx>, D::Error> {
15071492
let def_id: DefId = Decodable::decode(d)?;
15081493

1509-
cstore::tls::with_decoding_context(d, |dcx, _| {
1494+
cstore::tls::with_decoding_context(|dcx| {
15101495
let def_id = dcx.translate_def_id(def_id);
15111496
Ok(dcx.tcx().lookup_adt_def(def_id))
15121497
})

src/librustc/ty/sty.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ impl<'tcx> Encodable for ClosureSubsts<'tcx> {
275275
impl<'tcx> Decodable for ClosureSubsts<'tcx> {
276276
fn decode<D: Decoder>(d: &mut D) -> Result<ClosureSubsts<'tcx>, D::Error> {
277277
let (func_substs, upvar_tys) = Decodable::decode(d)?;
278-
cstore::tls::with_decoding_context(d, |dcx, _| {
278+
cstore::tls::with_decoding_context(|dcx| {
279279
Ok(ClosureSubsts {
280280
func_substs: func_substs,
281281
upvar_tys: dcx.tcx().mk_type_list(upvar_tys)
@@ -666,7 +666,7 @@ pub enum Region {
666666
impl<'tcx> Decodable for &'tcx Region {
667667
fn decode<D: Decoder>(d: &mut D) -> Result<&'tcx Region, D::Error> {
668668
let r = Decodable::decode(d)?;
669-
cstore::tls::with_decoding_context(d, |dcx, _| {
669+
cstore::tls::with_decoding_context(|dcx| {
670670
Ok(dcx.tcx().mk_region(r))
671671
})
672672
}

src/librustc/ty/subst.rs

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,11 @@
1010

1111
// Type substitutions.
1212

13-
use middle::cstore;
1413
use hir::def_id::DefId;
1514
use ty::{self, Ty, TyCtxt};
1615
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
1716

18-
use serialize::{Encodable, Encoder, Decodable, Decoder};
17+
use serialize;
1918
use syntax_pos::{Span, DUMMY_SP};
2019

2120
use core::nonzero::NonZero;
@@ -298,25 +297,8 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx Substs<'tcx> {
298297
}
299298
}
300299

301-
impl<'tcx> Encodable for &'tcx Substs<'tcx> {
302-
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
303-
cstore::tls::with_encoding_context(s, |ecx, rbml_w| {
304-
ecx.encode_substs(rbml_w, self);
305-
Ok(())
306-
})
307-
}
308-
}
309-
310-
impl<'tcx> Decodable for &'tcx Substs<'tcx> {
311-
fn decode<D: Decoder>(d: &mut D) -> Result<&'tcx Substs<'tcx>, D::Error> {
312-
let substs = cstore::tls::with_decoding_context(d, |dcx, rbml_r| {
313-
dcx.decode_substs(rbml_r)
314-
});
315-
316-
Ok(substs)
317-
}
318-
}
319-
300+
impl<'tcx> serialize::UseSpecializedEncodable for &'tcx Substs<'tcx> {}
301+
impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Substs<'tcx> {}
320302

321303
///////////////////////////////////////////////////////////////////////////
322304
// Public trait `Subst`

src/librustc_metadata/encoder.rs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,14 @@ use middle::dependency_format::Linkage;
2828
use rustc::dep_graph::DepNode;
2929
use rustc::traits::specialization_graph;
3030
use rustc::ty::{self, Ty, TyCtxt};
31+
use rustc::ty::subst::Substs;
3132

3233
use rustc::hir::svh::Svh;
3334
use rustc::mir::mir_map::MirMap;
3435
use rustc::session::config::{self, PanicStrategy, CrateTypeRustcMacro};
3536
use rustc::util::nodemap::{FnvHashMap, NodeSet};
3637

37-
use rustc_serialize::Encodable;
38+
use rustc_serialize::{Encodable, SpecializedEncoder, SpecializedDecoder};
3839
use std::cell::RefCell;
3940
use std::io::prelude::*;
4041
use std::io::{Cursor, SeekFrom};
@@ -78,6 +79,48 @@ impl<'a, 'tcx> DerefMut for EncodeContext<'a, 'tcx> {
7879
}
7980
}
8081

82+
impl<'a, 'tcx> SpecializedEncoder<Ty<'tcx>> for EncodeContext<'a, 'tcx> {
83+
fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> {
84+
let cx = self.ty_str_ctxt();
85+
self.emit_opaque(|opaque_encoder| {
86+
Ok(tyencode::enc_ty(opaque_encoder.cursor, &cx, ty))
87+
})
88+
}
89+
}
90+
91+
impl<'a, 'tcx> SpecializedEncoder<&'tcx Substs<'tcx>> for EncodeContext<'a, 'tcx> {
92+
fn specialized_encode(&mut self, substs: &&'tcx Substs<'tcx>) -> Result<(), Self::Error> {
93+
let cx = self.ty_str_ctxt();
94+
self.emit_opaque(|opaque_encoder| {
95+
Ok(tyencode::enc_substs(opaque_encoder.cursor, &cx, substs))
96+
})
97+
}
98+
}
99+
100+
/// FIXME(#31844) This is horribly unsound as it allows the
101+
/// caller to pick any lifetime for 'tcx, including 'static.
102+
impl<'a, 'tcx> SpecializedDecoder<Ty<'tcx>> for ::rbml::reader::Decoder<'a> {
103+
fn specialized_decode(&mut self) -> Result<Ty<'tcx>, Self::Error> {
104+
self.read_opaque(|opaque_decoder, _| {
105+
::middle::cstore::tls::with_decoding_context(|dcx| {
106+
Ok(dcx.decode_ty(opaque_decoder))
107+
})
108+
})
109+
}
110+
}
111+
112+
/// FIXME(#31844) This is horribly unsound as it allows the
113+
/// caller to pick any lifetime for 'tcx, including 'static.
114+
impl<'a, 'tcx> SpecializedDecoder<&'tcx Substs<'tcx>> for ::rbml::reader::Decoder<'a> {
115+
fn specialized_decode(&mut self) -> Result<&'tcx Substs<'tcx>, Self::Error> {
116+
self.read_opaque(|opaque_decoder, _| {
117+
::middle::cstore::tls::with_decoding_context(|dcx| {
118+
Ok(dcx.decode_substs(opaque_decoder))
119+
})
120+
})
121+
}
122+
}
123+
81124
fn encode_name(ecx: &mut EncodeContext, name: Name) {
82125
ecx.wr_tagged_str(tag_paths_data_name, &name.as_str());
83126
}

src/librustc_metadata/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#![feature(rustc_macro_lib)]
2727
#![feature(rustc_macro_internals)]
2828
#![feature(rustc_private)]
29+
#![feature(specialization)]
2930
#![feature(staged_api)]
3031
#![cfg_attr(test, feature(test))]
3132

src/librustc_metadata/tls_context.rs

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,32 +11,14 @@
1111
// This module provides implementations for the thread-local encoding and
1212
// decoding context traits in rustc::middle::cstore::tls.
1313

14-
use rbml::opaque::Encoder as OpaqueEncoder;
1514
use rbml::opaque::Decoder as OpaqueDecoder;
1615
use rustc::middle::cstore::tls;
1716
use rustc::hir::def_id::DefId;
1817
use rustc::ty::subst::Substs;
19-
use rustc::ty::{self, TyCtxt};
18+
use rustc::ty::{Ty, TyCtxt};
2019

2120
use decoder::{self, Cmd};
22-
use encoder;
2321
use tydecode::TyDecoder;
24-
use tyencode;
25-
26-
impl<'a, 'tcx: 'a> tls::EncodingContext<'tcx> for encoder::EncodeContext<'a, 'tcx> {
27-
28-
fn tcx<'s>(&'s self) -> TyCtxt<'s, 'tcx, 'tcx> {
29-
self.tcx
30-
}
31-
32-
fn encode_ty(&self, encoder: &mut OpaqueEncoder, t: ty::Ty<'tcx>) {
33-
tyencode::enc_ty(encoder.cursor, &self.ty_str_ctxt(), t);
34-
}
35-
36-
fn encode_substs(&self, encoder: &mut OpaqueEncoder, substs: &Substs<'tcx>) {
37-
tyencode::enc_substs(encoder.cursor, &self.ty_str_ctxt(), substs);
38-
}
39-
}
4022

4123
pub struct DecodingContext<'a, 'tcx: 'a> {
4224
pub crate_metadata: Cmd<'a>,
@@ -49,7 +31,7 @@ impl<'a, 'tcx: 'a> tls::DecodingContext<'tcx> for DecodingContext<'a, 'tcx> {
4931
self.tcx
5032
}
5133

52-
fn decode_ty(&self, decoder: &mut OpaqueDecoder) -> ty::Ty<'tcx> {
34+
fn decode_ty(&self, decoder: &mut OpaqueDecoder) -> Ty<'tcx> {
5335
let def_id_convert = &mut |did| {
5436
decoder::translate_def_id(self.crate_metadata, did)
5537
};

0 commit comments

Comments
 (0)