From dad587bc7dc7099e3f4c7f04f149c23b9ea7ed84 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin <twk@twki.de> Date: Sun, 13 Aug 2017 18:04:57 +0200 Subject: [PATCH 01/13] Implemented span expansion info encoding in metadata. This change adds an encoded version of hygiene related datastructures to the metadata of a crate. It is then decoded on-demand when spans and AST items from a foreign crate are accessed. Some changes might still be necessary to implement the correct behaviour, however. --- src/doc/book | 2 +- src/doc/nomicon | 2 +- src/doc/reference | 2 +- src/libcompiler_builtins | 2 +- src/liblibc | 2 +- src/librustc_metadata/creader.rs | 1 + src/librustc_metadata/cstore.rs | 4 +- src/librustc_metadata/decoder.rs | 50 ++++++- src/librustc_metadata/encoder.rs | 14 +- src/librustc_metadata/schema.rs | 3 +- src/libsyntax_pos/hygiene.rs | 124 +++++++++++++++--- src/llvm | 2 +- .../auxiliary/macro_spans_lib.rs | 25 ++++ src/test/compile-fail-fulldeps/macro-spans.rs | 18 +++ src/tools/cargo | 2 +- src/tools/rls | 2 +- src/tools/rust-installer | 2 +- 17 files changed, 226 insertions(+), 31 deletions(-) create mode 100644 src/test/compile-fail-fulldeps/auxiliary/macro_spans_lib.rs create mode 100644 src/test/compile-fail-fulldeps/macro-spans.rs diff --git a/src/doc/book b/src/doc/book index 08e79609ce885..d09c9e8144ed3 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 08e79609ce88583fa7286157dfe497486a09fabe +Subproject commit d09c9e8144ed32170b7596abb145ade8b097acaf diff --git a/src/doc/nomicon b/src/doc/nomicon index 0ee3f7265e9d0..a4322ccb289a4 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 0ee3f7265e9d09746d901cef6f1f300baff1d923 +Subproject commit a4322ccb289a43cc238d4536982f184a3eec9ba7 diff --git a/src/doc/reference b/src/doc/reference index 36adc6ae504c6..1abfbaa70313f 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 36adc6ae504c6e0343ab5d7b3871f0a2a71236da +Subproject commit 1abfbaa70313fdf527cf799ffd9b9a096a62105c diff --git a/src/libcompiler_builtins b/src/libcompiler_builtins index 0b9844764ea1f..6b9281d2b2f0e 160000 --- a/src/libcompiler_builtins +++ b/src/libcompiler_builtins @@ -1 +1 @@ -Subproject commit 0b9844764ea1f99ea11a7917a4f3ba7fd2db775c +Subproject commit 6b9281d2b2f0ebb94838814b1e8ace2de4b7035b diff --git a/src/liblibc b/src/liblibc index 44e4018e1a377..2a5b50b7f7f53 160000 --- a/src/liblibc +++ b/src/liblibc @@ -1 +1 @@ -Subproject commit 44e4018e1a37716286ec98cb5b7dd7d33ecaf940 +Subproject commit 2a5b50b7f7f539a0fd201331d6c1e0534aa332f5 diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 39bdf88925e44..91fdd3390ddd7 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -293,6 +293,7 @@ impl<'a> CrateLoader<'a> { // Initialize this with an empty set. The field is populated below // after we were able to deserialize its contents. dllimport_foreign_items: FxHashSet(), + hygiene_data_import_info: RefCell::new(None), }; let dllimports: FxHashSet<_> = cmeta diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 9e47e96aee4ef..b9af97c5d9e35 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -27,7 +27,7 @@ use owning_ref::ErasedBoxRef; use syntax::{ast, attr}; use syntax::ext::base::SyntaxExtension; use syntax::symbol::Symbol; -use syntax_pos; +use syntax_pos::{self, hygiene}; pub use rustc::middle::cstore::{NativeLibrary, NativeLibraryKind, LinkagePreference}; pub use rustc::middle::cstore::NativeLibraryKind::*; @@ -87,6 +87,8 @@ pub struct CrateMetadata { pub proc_macros: Option<Vec<(ast::Name, Rc<SyntaxExtension>)>>, // Foreign items imported from a dylib (Windows only) pub dllimport_foreign_items: FxHashSet<DefIndex>, + + pub hygiene_data_import_info: RefCell<Option<hygiene::ImportedHygieneData>>, } pub struct CStore { diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 65cf15e5a0ec7..1c7059343dc0c 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -45,7 +45,8 @@ use syntax::ast::{self, Ident}; use syntax::codemap; use syntax::symbol::{InternedString, Symbol}; use syntax::ext::base::MacroKind; -use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, NO_EXPANSION}; +use syntax_pos::{self, Span, SyntaxContext, BytePos, Pos, DUMMY_SP}; +use syntax_pos::hygiene; pub struct DecodeContext<'a, 'tcx: 'a> { opaque: opaque::Decoder<'a>, @@ -237,15 +238,42 @@ impl<'a, 'tcx> SpecializedDecoder<CrateNum> for DecodeContext<'a, 'tcx> { } } +impl<'a, 'tcx> SpecializedDecoder<hygiene::Mark> for DecodeContext<'a, 'tcx> { + fn specialized_decode(&mut self) -> Result<hygiene::Mark, Self::Error> { + let mark = u32::decode(self)?; + if self.cdata().hygiene_data_import_info.borrow().is_some() && mark != 0 { + let imported_hygiene = self.cdata().imported_hygiene_data(); + + Ok(hygiene::Mark::from_u32(mark + imported_hygiene.mark_translation_offset)) + } else { + Ok(hygiene::Mark::from_u32(mark)) + } + } +} + +impl<'a, 'tcx> SpecializedDecoder<SyntaxContext> for DecodeContext<'a, 'tcx> { + fn specialized_decode(&mut self) -> Result<SyntaxContext, Self::Error> { + let ctxt = u32::decode(self)?; + if self.cdata().hygiene_data_import_info.borrow().is_some() && ctxt != 0 { + let imported_hygiene = self.cdata().imported_hygiene_data(); + + Ok(SyntaxContext::from_u32(ctxt + imported_hygiene.ctxt_translation_offset)) + } else { + Ok(SyntaxContext::from_u32(ctxt)) + } + } +} + impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result<Span, Self::Error> { let lo = BytePos::decode(self)?; let hi = BytePos::decode(self)?; + let ctxt = SyntaxContext::decode(self)?; let sess = if let Some(sess) = self.sess { sess } else { - return Ok(Span::new(lo, hi, NO_EXPANSION)); + return Ok(Span { lo, hi, ctxt }); }; let (lo, hi) = if lo > hi { @@ -292,7 +320,7 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> { let lo = (lo - filemap.original_start_pos) + filemap.translated_filemap.start_pos; let hi = (hi - filemap.original_start_pos) + filemap.translated_filemap.start_pos; - Ok(Span::new(lo, hi, NO_EXPANSION)) + Ok(Span::new(lo, hi, ctxt)) } } @@ -1224,4 +1252,20 @@ impl<'a, 'tcx> CrateMetadata { *self.codemap_import_info.borrow_mut() = imported_filemaps; self.codemap_import_info.borrow() } + + pub fn imported_hygiene_data(&'a self) -> Ref<'a, hygiene::ImportedHygieneData> { + { + let hygiene_data = self.hygiene_data_import_info.borrow(); + if hygiene_data.is_some() { + return Ref::map(hygiene_data, |d| d.as_ref().unwrap()); + } + } + + let external_hygiene_data = self.root.hygiene_data.decode(self); + + // This shouldn't borrow twice, but there is no way to downgrade RefMut to Ref. + *self.hygiene_data_import_info.borrow_mut() = + Some(hygiene::extend_hygiene_data(external_hygiene_data)); + Ref::map(self.hygiene_data_import_info.borrow(), |d| d.as_ref().unwrap()) + } } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 6b49be3e12192..5d6c6075d5b74 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -42,7 +42,7 @@ use syntax::ast::{self, CRATE_NODE_ID}; use syntax::codemap::Spanned; use syntax::attr; use syntax::symbol::Symbol; -use syntax_pos; +use syntax_pos::{self, hygiene}; use rustc::hir::{self, PatKind}; use rustc::hir::itemlikevisit::ItemLikeVisitor; @@ -323,6 +323,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.lazy_seq_ref(adapted.iter().map(|rc| &**rc)) } + fn encode_hygiene_data(&mut self) -> Lazy<hygiene::HygieneData> { + hygiene::HygieneData::safe_with(|data| self.lazy(data)) + } + fn encode_crate_root(&mut self) -> Lazy<CrateRoot> { let mut i = self.position(); @@ -367,6 +371,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let codemap = self.encode_codemap(); let codemap_bytes = self.position() - i; + // Encode hygiene data + i = self.position(); + let hygiene_data = self.encode_hygiene_data(); + let hygiene_data_bytes = self.position() - i; + // Encode DefPathTable i = self.position(); let def_path_table = self.encode_def_path_table(); @@ -421,13 +430,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } else { None }, - crate_deps, dylib_dependency_formats, lang_items, lang_items_missing, native_libraries, codemap, + hygiene_data, def_path_table, impls, exported_symbols, @@ -456,6 +465,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { println!(" codemap bytes: {}", codemap_bytes); println!(" impl bytes: {}", impl_bytes); println!(" exp. symbols bytes: {}", exported_symbols_bytes); + println!(" hygiene data bytes: {}", hygiene_data_bytes); println!(" def-path table bytes: {}", def_path_table_bytes); println!(" item bytes: {}", item_bytes); println!(" index bytes: {}", index_bytes); diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index dad0d26d2715d..abccc50db8446 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -24,7 +24,7 @@ use rustc_back::PanicStrategy; use rustc_serialize as serialize; use syntax::{ast, attr}; use syntax::symbol::Symbol; -use syntax_pos::{self, Span}; +use syntax_pos::{self, hygiene, Span}; use std::marker::PhantomData; use std::mem; @@ -204,6 +204,7 @@ pub struct CrateRoot { pub lang_items_missing: LazySeq<lang_items::LangItem>, pub native_libraries: LazySeq<NativeLibrary>, pub codemap: LazySeq<syntax_pos::FileMap>, + pub hygiene_data: Lazy<hygiene::HygieneData>, pub def_path_table: Lazy<hir::map::definitions::DefPathTable>, pub impls: LazySeq<TraitImpls>, pub exported_symbols: LazySeq<DefIndex>, diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index 4790fa0a7edc2..72261452cbd72 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -18,16 +18,16 @@ use Span; use symbol::{Ident, Symbol}; -use serialize::{Encodable, Decodable, Encoder, Decoder}; +use serialize::{Decoder, UseSpecializedDecodable}; use std::cell::RefCell; use std::collections::HashMap; use std::fmt; /// A SyntaxContext represents a chain of macro expansions (represented by marks). -#[derive(Clone, Copy, PartialEq, Eq, Default, PartialOrd, Ord, Hash)] +#[derive(Clone, Copy, PartialEq, Eq, Default, PartialOrd, Ord, Hash, RustcEncodable)] pub struct SyntaxContext(pub(super) u32); -#[derive(Copy, Clone, Default)] +#[derive(Copy, Clone, Default, RustcEncodable, RustcDecodable)] pub struct SyntaxContextData { pub outer_mark: Mark, pub prev_ctxt: SyntaxContext, @@ -35,10 +35,10 @@ pub struct SyntaxContextData { } /// A mark is a unique id associated with a macro expansion. -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Default, RustcEncodable, RustcDecodable)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Default, RustcEncodable)] pub struct Mark(u32); -#[derive(Default)] +#[derive(Default, RustcEncodable, RustcDecodable)] struct MarkData { parent: Mark, modern: bool, @@ -66,6 +66,14 @@ impl Mark { Mark(raw) } + pub fn translate(&self, offset: u32) -> Mark { + if self.0 != 0 { + Mark(self.0 + offset) + } else { + Mark(self.0) + } + } + pub fn expn_info(self) -> Option<ExpnInfo> { HygieneData::with(|data| data.marks[self.0 as usize].expn_info.clone()) } @@ -106,7 +114,8 @@ impl Mark { } } -struct HygieneData { +#[derive(RustcEncodable, RustcDecodable)] +pub struct HygieneData { marks: Vec<MarkData>, syntax_contexts: Vec<SyntaxContextData>, markings: HashMap<(SyntaxContext, Mark), SyntaxContext>, @@ -129,13 +138,98 @@ impl HygieneData { } HYGIENE_DATA.with(|data| f(&mut *data.borrow_mut())) } + + pub fn safe_with<T, F: FnOnce(&HygieneData) -> T>(f: F) -> T { + // FIXME(twk): not sure how this would behave... + thread_local! { + static HYGIENE_DATA: RefCell<HygieneData> = RefCell::new(HygieneData::new()); + } + HYGIENE_DATA.with(|data| f(&*data.borrow())) + } } pub fn clear_markings() { HygieneData::with(|data| data.markings = HashMap::new()); } +/// Holds information about a HygieneData imported from another crate. +/// See `imported_hygiene_data()` in `rustc_metadata` for more information. +pub struct ImportedHygieneData { + /// The imported HygieneData's offset in the local HygieneData's marks vector. + pub mark_translation_offset: u32, + /// The imported HygieneData's offset in the local HygieneData's syntax contexts vector. + pub ctxt_translation_offset: u32, +} + +pub fn extend_hygiene_data(extend_with: HygieneData) -> ImportedHygieneData { + fn translate_span(span: &Span, offset: u32) -> Span { + Span { + lo: span.lo, + hi: span.hi, + ctxt: span.ctxt.translate(offset), + } + } + + HygieneData::with(move |data| { + let mark_offset = data.marks.len() as u32; + let ctxt_offset = data.syntax_contexts.len() as u32; + + // skip the default mark, it doesn't need to be translated. + for mark_data in extend_with.marks.iter().skip(1) { + data.marks.push(MarkData { + parent: mark_data.parent.translate(mark_offset), + modern: mark_data.modern, + expn_info: mark_data.expn_info.as_ref().map(|info| { + ExpnInfo { + call_site: translate_span(&info.call_site, ctxt_offset), + callee: NameAndSpan { + format: info.callee.format.clone(), + allow_internal_unstable: info.callee.allow_internal_unstable, + span: + info.callee.span.map(|span| translate_span(&span, ctxt_offset)), + }, + } + }), + }) + } + + // skip the default syntax context, it doesn't need to be translated. + for ctxt in extend_with.syntax_contexts.iter().skip(1) { + data.syntax_contexts.push(SyntaxContextData { + outer_mark: ctxt.outer_mark.translate(mark_offset), + prev_ctxt: ctxt.prev_ctxt.translate(ctxt_offset), + modern: ctxt.modern.translate(ctxt_offset), + }); + } + + // translate markings map and extend the current one + for (&(ctxt1, mark), ctxt2) in extend_with.markings.iter() { + data.markings.insert((ctxt1.translate(ctxt_offset), mark.translate(mark_offset)), + ctxt2.translate(ctxt_offset)); + } + + data.gensym_to_ctxt.extend(extend_with.gensym_to_ctxt); + + ImportedHygieneData { + mark_translation_offset: mark_offset, + ctxt_translation_offset: ctxt_offset, + } + }) +} + impl SyntaxContext { + pub fn from_u32(raw: u32) -> SyntaxContext { + SyntaxContext(raw) + } + + pub fn translate(&self, offset: u32) -> SyntaxContext { + if self.0 != 0 { + SyntaxContext(self.0 + offset) + } else { + SyntaxContext(self.0) + } + } + pub const fn empty() -> Self { SyntaxContext(0) } @@ -286,7 +380,7 @@ impl fmt::Debug for SyntaxContext { } /// Extra information for tracking spans of macro and syntax sugar expansion -#[derive(Clone, Hash, Debug)] +#[derive(Clone, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct ExpnInfo { /// The location of the actual macro invocation or syntax sugar , e.g. /// `let x = foo!();` or `if let Some(y) = x {}` @@ -302,7 +396,7 @@ pub struct ExpnInfo { pub callee: NameAndSpan } -#[derive(Clone, Hash, Debug)] +#[derive(Clone, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct NameAndSpan { /// The format with which the macro was invoked. pub format: ExpnFormat, @@ -330,7 +424,7 @@ impl NameAndSpan { } /// The source of expansion. -#[derive(Clone, Hash, Debug, PartialEq, Eq)] +#[derive(Clone, Hash, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)] pub enum ExpnFormat { /// e.g. #[derive(...)] <item> MacroAttribute(Symbol), @@ -360,15 +454,15 @@ impl CompilerDesugaringKind { } } -impl Encodable for SyntaxContext { - fn encode<E: Encoder>(&self, _: &mut E) -> Result<(), E::Error> { - Ok(()) // FIXME(jseyfried) intercrate hygiene +impl UseSpecializedDecodable for SyntaxContext { + fn default_decode<D: Decoder>(d: &mut D) -> Result<SyntaxContext, D::Error> { + d.read_u32().map(|u| SyntaxContext(u)) } } -impl Decodable for SyntaxContext { - fn decode<D: Decoder>(_: &mut D) -> Result<SyntaxContext, D::Error> { - Ok(SyntaxContext::empty()) // FIXME(jseyfried) intercrate hygiene +impl UseSpecializedDecodable for Mark { + fn default_decode<D: Decoder>(d: &mut D) -> Result<Mark, D::Error> { + d.read_u32().map(Mark::from_u32) } } diff --git a/src/llvm b/src/llvm index c7a16bd57c2a9..d9e7d2696e419 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit c7a16bd57c2a9c643a52f0cebecdaf0b6a996da1 +Subproject commit d9e7d2696e41983b6b5a0b4fac604b4e548a84d3 diff --git a/src/test/compile-fail-fulldeps/auxiliary/macro_spans_lib.rs b/src/test/compile-fail-fulldeps/auxiliary/macro_spans_lib.rs new file mode 100644 index 0000000000000..739e37feeae29 --- /dev/null +++ b/src/test/compile-fail-fulldeps/auxiliary/macro_spans_lib.rs @@ -0,0 +1,25 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +macro_rules! abc { + ($name:ident) => { + mod $name { + macro_rules! $name { + ($name2:ident) => { + struct $name { + $name2: u8, + } + } + } + + $name!(AStruct) + } + } +} diff --git a/src/test/compile-fail-fulldeps/macro-spans.rs b/src/test/compile-fail-fulldeps/macro-spans.rs new file mode 100644 index 0000000000000..a3f7a92af719e --- /dev/null +++ b/src/test/compile-fail-fulldeps/macro-spans.rs @@ -0,0 +1,18 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:macro_spans_lib.rs + +#[macro_use] +extern crate macro_spans_lib; + +abc!(Name) + +fn main() { } diff --git a/src/tools/cargo b/src/tools/cargo index e447ac7e94b7f..7704f7b1fd526 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit e447ac7e94b7f56ab13e361f9e324dafe3eb0a34 +Subproject commit 7704f7b1fd52607104cc7fdc435d636c9de1fe90 diff --git a/src/tools/rls b/src/tools/rls index 93b47d14cef57..5d4bbd9052fe2 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit 93b47d14cef5720bba7cfb4dcb8078fbf1f706c1 +Subproject commit 5d4bbd9052fe2af849a7d017b85df98ad002c20f diff --git a/src/tools/rust-installer b/src/tools/rust-installer index 0ddd53c4bc2a7..b4ff403041f17 160000 --- a/src/tools/rust-installer +++ b/src/tools/rust-installer @@ -1 +1 @@ -Subproject commit 0ddd53c4bc2a76df565a1c1fc0cc6f19f254b51e +Subproject commit b4ff403041f17957f735ad750c3241a3a428b9b7 From e6a6c64574dae52fa044934bc8594207f64d5359 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin <twk@twki.de> Date: Sun, 13 Aug 2017 18:09:35 +0200 Subject: [PATCH 02/13] Added an explanation to slightly tricky decoding logic. --- src/librustc_metadata/decoder.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 1c7059343dc0c..4353b4fe52965 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -241,6 +241,11 @@ impl<'a, 'tcx> SpecializedDecoder<CrateNum> for DecodeContext<'a, 'tcx> { impl<'a, 'tcx> SpecializedDecoder<hygiene::Mark> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result<hygiene::Mark, Self::Error> { let mark = u32::decode(self)?; + // + // We only perform translation if hygiene info is already available and if the + // mark actually needs translation. That way we avoid loops (as obtaining hygiene + // info for an external crate involves decoding marks) and avoid incorrectly translated + // default marks. if self.cdata().hygiene_data_import_info.borrow().is_some() && mark != 0 { let imported_hygiene = self.cdata().imported_hygiene_data(); @@ -254,6 +259,11 @@ impl<'a, 'tcx> SpecializedDecoder<hygiene::Mark> for DecodeContext<'a, 'tcx> { impl<'a, 'tcx> SpecializedDecoder<SyntaxContext> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result<SyntaxContext, Self::Error> { let ctxt = u32::decode(self)?; + + // We only perform translation if hygiene info is already available and if the + // syntax context actually needs translation. That way we avoid loops (as obtaining + // hygiene info for an external crate involves decoding syntax contexts) and avoid + // incorrectly translated default contexts. if self.cdata().hygiene_data_import_info.borrow().is_some() && ctxt != 0 { let imported_hygiene = self.cdata().imported_hygiene_data(); From b47a79105c911fd9ac4659bd05d38c719145edda Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin <twk@twki.de> Date: Sun, 13 Aug 2017 18:48:23 +0200 Subject: [PATCH 03/13] Fixed build after rebase --- src/libsyntax_pos/hygiene.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index 72261452cbd72..d1c101eaed5db 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -185,6 +185,7 @@ pub fn extend_hygiene_data(extend_with: HygieneData) -> ImportedHygieneData { callee: NameAndSpan { format: info.callee.format.clone(), allow_internal_unstable: info.callee.allow_internal_unstable, + allow_internal_unsafe: info.callee.allow_internal_unsafe, span: info.callee.span.map(|span| translate_span(&span, ctxt_offset)), }, From 7bb56bf742655bade24e82a883eecbb475bc86bd Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin <twk@twki.de> Date: Mon, 14 Aug 2017 12:59:04 +0200 Subject: [PATCH 04/13] Actually encode syntax context info for spans. --- src/librustc_metadata/decoder.rs | 5 ++--- src/libsyntax_pos/lib.rs | 6 +++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 4353b4fe52965..f821ccc91f9fb 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -45,8 +45,7 @@ use syntax::ast::{self, Ident}; use syntax::codemap; use syntax::symbol::{InternedString, Symbol}; use syntax::ext::base::MacroKind; -use syntax_pos::{self, Span, SyntaxContext, BytePos, Pos, DUMMY_SP}; -use syntax_pos::hygiene; +use syntax_pos::{self, hygiene, Span, SyntaxContext, BytePos, Pos, DUMMY_SP}; pub struct DecodeContext<'a, 'tcx: 'a> { opaque: opaque::Decoder<'a>, @@ -241,7 +240,7 @@ impl<'a, 'tcx> SpecializedDecoder<CrateNum> for DecodeContext<'a, 'tcx> { impl<'a, 'tcx> SpecializedDecoder<hygiene::Mark> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result<hygiene::Mark, Self::Error> { let mark = u32::decode(self)?; - // + // We only perform translation if hygiene info is already available and if the // mark actually needs translation. That way we avoid loops (as obtaining hygiene // info for an external crate involves decoding marks) and avoid incorrectly translated diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 2000db9703cf9..9f4172037892d 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -316,13 +316,17 @@ impl Default for Span { impl serialize::UseSpecializedEncodable for Span { fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_struct("Span", 2, |s| { + s.emit_struct("Span", 3, |s| { s.emit_struct_field("lo", 0, |s| { self.lo().encode(s) })?; s.emit_struct_field("hi", 1, |s| { self.hi().encode(s) + })?; + + s.emit_struct_field("ctxt", 2, |s| { + self.ctxt().encode(s) }) }) } From 214fb564e0fb917580056bdc5d6a1b55acd4cd5f Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin <twk@twki.de> Date: Mon, 14 Aug 2017 16:45:16 +0200 Subject: [PATCH 05/13] Fixed the on-demand decoding mechanism for hygiene data. --- src/librustc_metadata/creader.rs | 1 + src/librustc_metadata/cstore.rs | 1 + src/librustc_metadata/decoder.rs | 18 +++++++----------- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 91fdd3390ddd7..2cf5c92ea6721 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -294,6 +294,7 @@ impl<'a> CrateLoader<'a> { // after we were able to deserialize its contents. dllimport_foreign_items: FxHashSet(), hygiene_data_import_info: RefCell::new(None), + hygiene_data_being_decoded: Cell::new(false), }; let dllimports: FxHashSet<_> = cmeta diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index b9af97c5d9e35..38578d9c286f9 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -89,6 +89,7 @@ pub struct CrateMetadata { pub dllimport_foreign_items: FxHashSet<DefIndex>, pub hygiene_data_import_info: RefCell<Option<hygiene::ImportedHygieneData>>, + pub hygiene_data_being_decoded: Cell<bool>, } pub struct CStore { diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index f821ccc91f9fb..ef56703f68cc0 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -241,11 +241,7 @@ impl<'a, 'tcx> SpecializedDecoder<hygiene::Mark> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result<hygiene::Mark, Self::Error> { let mark = u32::decode(self)?; - // We only perform translation if hygiene info is already available and if the - // mark actually needs translation. That way we avoid loops (as obtaining hygiene - // info for an external crate involves decoding marks) and avoid incorrectly translated - // default marks. - if self.cdata().hygiene_data_import_info.borrow().is_some() && mark != 0 { + if !self.cdata().hygiene_data_being_decoded.get() && mark != 0 { let imported_hygiene = self.cdata().imported_hygiene_data(); Ok(hygiene::Mark::from_u32(mark + imported_hygiene.mark_translation_offset)) @@ -259,11 +255,7 @@ impl<'a, 'tcx> SpecializedDecoder<SyntaxContext> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result<SyntaxContext, Self::Error> { let ctxt = u32::decode(self)?; - // We only perform translation if hygiene info is already available and if the - // syntax context actually needs translation. That way we avoid loops (as obtaining - // hygiene info for an external crate involves decoding syntax contexts) and avoid - // incorrectly translated default contexts. - if self.cdata().hygiene_data_import_info.borrow().is_some() && ctxt != 0 { + if !self.cdata().hygiene_data_being_decoded.get() && ctxt != 0 { let imported_hygiene = self.cdata().imported_hygiene_data(); Ok(SyntaxContext::from_u32(ctxt + imported_hygiene.ctxt_translation_offset)) @@ -1270,11 +1262,15 @@ impl<'a, 'tcx> CrateMetadata { } } + self.hygiene_data_being_decoded.set(true); + let external_hygiene_data = self.root.hygiene_data.decode(self); // This shouldn't borrow twice, but there is no way to downgrade RefMut to Ref. *self.hygiene_data_import_info.borrow_mut() = Some(hygiene::extend_hygiene_data(external_hygiene_data)); - Ref::map(self.hygiene_data_import_info.borrow(), |d| d.as_ref().unwrap()) + self.hygiene_data_being_decoded.set(false); + + Ref::map(self.hygiene_data_import_info.borrow(), |d| d.as_ref().unwrap()); } } From 64934bab20b25ea6f58724b6c90de47c63de56cc Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin <twk@twki.de> Date: Tue, 15 Aug 2017 22:30:06 +0200 Subject: [PATCH 06/13] Fixed one possible error source when encoding hygiene metadata. Sadly, this isn't the reason the tests fail. --- src/librustc/middle/cstore.rs | 3 +++ src/librustc_metadata/cstore_impl.rs | 6 ++++++ src/librustc_metadata/decoder.rs | 2 +- src/librustc_metadata/encoder.rs | 1 + 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index a97bfa0536987..d7540aed5a024 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -253,6 +253,8 @@ pub struct ExternBodyNestedBodies { pub trait CrateStore { fn crate_data_as_rc_any(&self, krate: CrateNum) -> Rc<Any>; + fn ensure_hygiene_data_loaded(&self); + // access to the metadata loader fn metadata_loader(&self) -> &MetadataLoader; @@ -325,6 +327,7 @@ pub struct DummyCrateStore; impl CrateStore for DummyCrateStore { fn crate_data_as_rc_any(&self, krate: CrateNum) -> Rc<Any> { bug!("crate_data_as_rc_any") } + fn ensure_hygiene_data_loaded(&self) { bug!("ensure_hygiene_data_loaded") } // item info fn visibility_untracked(&self, def: DefId) -> ty::Visibility { bug!("visibility") } fn item_generics_cloned_untracked(&self, def: DefId) -> ty::Generics diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 8eacc21ab003b..3d67868f36618 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -350,6 +350,12 @@ impl CrateStore for cstore::CStore { self.get_crate_data(krate) } + fn ensure_hygiene_data_loaded(&self) { + self.iter_crate_data(|_, metadata| { + (*metadata).imported_hygiene_data(); + }); + } + fn metadata_loader(&self) -> &MetadataLoader { &*self.metadata_loader } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index ef56703f68cc0..5a80f6764d185 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -1271,6 +1271,6 @@ impl<'a, 'tcx> CrateMetadata { Some(hygiene::extend_hygiene_data(external_hygiene_data)); self.hygiene_data_being_decoded.set(false); - Ref::map(self.hygiene_data_import_info.borrow(), |d| d.as_ref().unwrap()); + Ref::map(self.hygiene_data_import_info.borrow(), |d| d.as_ref().unwrap()) } } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 5d6c6075d5b74..0010f7638e8b2 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -324,6 +324,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } fn encode_hygiene_data(&mut self) -> Lazy<hygiene::HygieneData> { + self.tcx.sess.cstore.ensure_hygiene_data_loaded(); hygiene::HygieneData::safe_with(|data| self.lazy(data)) } From 754bf65a3579750ec8227f155e97480af5d67c2c Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin <twk@twki.de> Date: Thu, 17 Aug 2017 11:26:41 +0200 Subject: [PATCH 07/13] Fixed broken functionality. However, now that it behaves as expected, the memory usage is unacceptably high. A solution would be more lazyness during encoding or a pruning scheme. --- src/libsyntax_pos/hygiene.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index d1c101eaed5db..d9d09ca467a68 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -122,6 +122,10 @@ pub struct HygieneData { gensym_to_ctxt: HashMap<Symbol, SyntaxContext>, } +thread_local! { + static HYGIENE_DATA: RefCell<HygieneData> = RefCell::new(HygieneData::new()); +} + impl HygieneData { fn new() -> Self { HygieneData { @@ -133,17 +137,10 @@ impl HygieneData { } fn with<T, F: FnOnce(&mut HygieneData) -> T>(f: F) -> T { - thread_local! { - static HYGIENE_DATA: RefCell<HygieneData> = RefCell::new(HygieneData::new()); - } HYGIENE_DATA.with(|data| f(&mut *data.borrow_mut())) } pub fn safe_with<T, F: FnOnce(&HygieneData) -> T>(f: F) -> T { - // FIXME(twk): not sure how this would behave... - thread_local! { - static HYGIENE_DATA: RefCell<HygieneData> = RefCell::new(HygieneData::new()); - } HYGIENE_DATA.with(|data| f(&*data.borrow())) } } From b653026401367917cbab0cfec87b3adfc58482ee Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin <twk@twki.de> Date: Fri, 18 Aug 2017 13:18:13 +0200 Subject: [PATCH 08/13] Implemented first steps of a new, leaner hygiene data encoding scheme. --- src/librustc_metadata/decoder.rs | 4 +- src/librustc_metadata/encoder.rs | 51 +++++-- src/librustc_metadata/schema.rs | 2 +- src/libsyntax_pos/hygiene.rs | 249 +++++++++++++++++++++++++------ 4 files changed, 243 insertions(+), 63 deletions(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 5a80f6764d185..1d7ab542cdc09 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -244,7 +244,7 @@ impl<'a, 'tcx> SpecializedDecoder<hygiene::Mark> for DecodeContext<'a, 'tcx> { if !self.cdata().hygiene_data_being_decoded.get() && mark != 0 { let imported_hygiene = self.cdata().imported_hygiene_data(); - Ok(hygiene::Mark::from_u32(mark + imported_hygiene.mark_translation_offset)) + Ok(imported_hygiene.translate_mark(hygiene::Mark::from_u32(mark))) } else { Ok(hygiene::Mark::from_u32(mark)) } @@ -258,7 +258,7 @@ impl<'a, 'tcx> SpecializedDecoder<SyntaxContext> for DecodeContext<'a, 'tcx> { if !self.cdata().hygiene_data_being_decoded.get() && ctxt != 0 { let imported_hygiene = self.cdata().imported_hygiene_data(); - Ok(SyntaxContext::from_u32(ctxt + imported_hygiene.ctxt_translation_offset)) + Ok(imported_hygiene.translate_ctxt(SyntaxContext::from_u32(ctxt))) } else { Ok(SyntaxContext::from_u32(ctxt)) } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 0010f7638e8b2..08a968c1b4c78 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -29,7 +29,7 @@ use rustc::ty::{self, Ty, TyCtxt, ReprOptions}; use rustc::session::config::{self, CrateTypeProcMacro}; use rustc::util::nodemap::{FxHashMap, NodeSet}; -use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, opaque}; +use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, UseSpecializedEncodable, opaque}; use std::hash::Hash; use std::intrinsics; @@ -61,6 +61,13 @@ pub struct EncodeContext<'a, 'tcx: 'a> { pub metadata_hashes: EncodedMetadataHashes, pub compute_ich: bool, + // We need to encode hygiene info after all spans and possibly other data structures + // that reference it have been encoded already, since we only encode those elements of it + // that are actually used to avoid excessive memory usage. Thus, we need to keep track of + // whether we already encoded the hygiene info (and thus committed to a specific set of + // information to encode) to make sure we can catch bugs introduced by further changes + // quickly. + already_encoded_hygiene_data: bool, } macro_rules! encoder_methods { @@ -136,6 +143,26 @@ impl<'a, 'tcx> SpecializedEncoder<ty::GenericPredicates<'tcx>> for EncodeContext } } +impl<'a, 'tcx> SpecializedEncoder<hygiene::SyntaxContext> for EncodeContext<'a, 'tcx> { + fn specialized_encode(&mut self, ctxt: &hygiene::SyntaxContext) -> Result<(), Self::Error> { + if self.already_encoded_hygiene_data { + bug!("trying to encode syntax context `{:?}` after encoding hygiene data!", ctxt); + } else { + ctxt.default_encode(self) + } + } +} + +impl<'a, 'tcx> SpecializedEncoder<hygiene::Mark> for EncodeContext<'a, 'tcx> { + fn specialized_encode(&mut self, mark: &hygiene::Mark) -> Result<(), Self::Error> { + if self.already_encoded_hygiene_data { + bug!("trying to encode mark `{:?}` after encoding hygiene data!", mark); + } else { + mark.default_encode(self) + } + } +} + impl<'a, 'tcx> EncodeContext<'a, 'tcx> { pub fn position(&self) -> usize { @@ -323,9 +350,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.lazy_seq_ref(adapted.iter().map(|rc| &**rc)) } - fn encode_hygiene_data(&mut self) -> Lazy<hygiene::HygieneData> { - self.tcx.sess.cstore.ensure_hygiene_data_loaded(); - hygiene::HygieneData::safe_with(|data| self.lazy(data)) + fn encode_hygiene_data(&mut self) -> Lazy<hygiene::HygieneDataMap> { + // TODO(twk): remove the `ensure_hygiene_data_loaded` method! + hygiene::HygieneData::safe_with(|data| self.lazy(&data.to_map())) } fn encode_crate_root(&mut self) -> Lazy<CrateRoot> { @@ -372,11 +399,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let codemap = self.encode_codemap(); let codemap_bytes = self.position() - i; - // Encode hygiene data - i = self.position(); - let hygiene_data = self.encode_hygiene_data(); - let hygiene_data_bytes = self.position() - i; - // Encode DefPathTable i = self.position(); let def_path_table = self.encode_def_path_table(); @@ -407,6 +429,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let index = items.write_index(&mut self.opaque.cursor); let index_bytes = self.position() - i; + // Encode hygiene data + i = self.position(); + let hygiene_data = self.encode_hygiene_data(); + let hygiene_data_bytes = self.position() - i; + self.already_encoded_hygiene_data = true; + let tcx = self.tcx; let link_meta = self.link_meta; let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateTypeProcMacro); @@ -437,11 +465,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { lang_items_missing, native_libraries, codemap, - hygiene_data, def_path_table, impls, exported_symbols, index, + hygiene_data, }); let total_bytes = self.position(); @@ -466,10 +494,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { println!(" codemap bytes: {}", codemap_bytes); println!(" impl bytes: {}", impl_bytes); println!(" exp. symbols bytes: {}", exported_symbols_bytes); - println!(" hygiene data bytes: {}", hygiene_data_bytes); println!(" def-path table bytes: {}", def_path_table_bytes); println!(" item bytes: {}", item_bytes); println!(" index bytes: {}", index_bytes); + println!(" hygiene data bytes: {}", hygiene_data_bytes); println!(" zero bytes: {}", zero_bytes); println!(" total bytes: {}", total_bytes); } @@ -1689,6 +1717,7 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, predicate_shorthands: Default::default(), metadata_hashes: EncodedMetadataHashes::new(), compute_ich, + already_encoded_hygiene_data: false, }; // Encode the rustc version string in a predictable location. diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index abccc50db8446..26e90913d0a9e 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -204,11 +204,11 @@ pub struct CrateRoot { pub lang_items_missing: LazySeq<lang_items::LangItem>, pub native_libraries: LazySeq<NativeLibrary>, pub codemap: LazySeq<syntax_pos::FileMap>, - pub hygiene_data: Lazy<hygiene::HygieneData>, pub def_path_table: Lazy<hir::map::definitions::DefPathTable>, pub impls: LazySeq<TraitImpls>, pub exported_symbols: LazySeq<DefIndex>, pub index: LazySeq<index::Index>, + pub hygiene_data: Lazy<hygiene::HygieneDataMap>, } #[derive(RustcEncodable, RustcDecodable)] diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index d9d09ca467a68..3d766279a930f 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -18,13 +18,13 @@ use Span; use symbol::{Ident, Symbol}; -use serialize::{Decoder, UseSpecializedDecodable}; +use serialize::{Decoder, Encoder, UseSpecializedDecodable, UseSpecializedEncodable}; use std::cell::RefCell; -use std::collections::HashMap; +use std::collections::{HashMap, HashSet, VecDeque}; use std::fmt; /// A SyntaxContext represents a chain of macro expansions (represented by marks). -#[derive(Clone, Copy, PartialEq, Eq, Default, PartialOrd, Ord, Hash, RustcEncodable)] +#[derive(Clone, Copy, PartialEq, Eq, Default, PartialOrd, Ord, Hash)] pub struct SyntaxContext(pub(super) u32); #[derive(Copy, Clone, Default, RustcEncodable, RustcDecodable)] @@ -35,10 +35,10 @@ pub struct SyntaxContextData { } /// A mark is a unique id associated with a macro expansion. -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Default, RustcEncodable)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Default)] pub struct Mark(u32); -#[derive(Default, RustcEncodable, RustcDecodable)] +#[derive(Clone, Default, RustcEncodable, RustcDecodable)] struct MarkData { parent: Mark, modern: bool, @@ -114,12 +114,20 @@ impl Mark { } } -#[derive(RustcEncodable, RustcDecodable)] pub struct HygieneData { marks: Vec<MarkData>, syntax_contexts: Vec<SyntaxContextData>, markings: HashMap<(SyntaxContext, Mark), SyntaxContext>, gensym_to_ctxt: HashMap<Symbol, SyntaxContext>, + used_marks: Vec<Mark>, + used_syntax_contexts: Vec<SyntaxContext>, +} + +#[derive(RustcEncodable, RustcDecodable)] +pub struct HygieneDataMap { + marks: HashMap<Mark, MarkData>, + syntax_contexts: HashMap<SyntaxContext, SyntaxContextData>, + gensym_to_ctxt: HashMap<Symbol, SyntaxContext>, } thread_local! { @@ -133,6 +141,8 @@ impl HygieneData { syntax_contexts: vec![SyntaxContextData::default()], markings: HashMap::new(), gensym_to_ctxt: HashMap::new(), + used_marks: Vec::new(), + used_syntax_contexts: Vec::new(), } } @@ -143,75 +153,202 @@ impl HygieneData { pub fn safe_with<T, F: FnOnce(&HygieneData) -> T>(f: F) -> T { HYGIENE_DATA.with(|data| f(&*data.borrow())) } + + pub fn to_map(&self) -> HygieneDataMap { + let mut marks = HashMap::new(); + let mut syntax_contexts = HashMap::new(); + + let mut mark_queue: VecDeque<_> = self.used_marks.iter().cloned().collect(); + let mut ctxt_queue: VecDeque<_> = self.used_syntax_contexts.iter().cloned().collect(); + ctxt_queue.extend(self.gensym_to_ctxt.values()); + + let gensym_to_ctxt = self.gensym_to_ctxt.clone(); + + let mut visited_marks = HashSet::new(); + let mut visited_ctxts = HashSet::new(); + + loop { + let next_mark = mark_queue.pop_front().and_then(|mark| + // skip default mark and already visited marks + if visited_marks.contains(&mark) || mark.0 == 0 { + None + } else { + visited_marks.insert(mark); + Some(mark) + }); + let next_ctxt = ctxt_queue.pop_front().and_then(|ctxt| + // skip default context and already visited contexts + if visited_ctxts.contains(&ctxt) || ctxt.0 == 0 { + None + } else { + visited_ctxts.insert(ctxt); + Some(ctxt) + }); + + if next_mark.is_none() && next_ctxt.is_none() { + break; + } + + if let Some(mark) = next_mark { + let data = &self.marks[mark.0 as usize]; + + mark_queue.push_back(data.parent); + if let Some(ref info) = data.expn_info { + ctxt_queue.push_back(info.call_site.ctxt); + + if let Some(span) = info.callee.span { + ctxt_queue.push_back(span.ctxt); + } + } + + marks.insert(mark, data.clone()); + } + + if let Some(ctxt) = next_ctxt { + let data = self.syntax_contexts[ctxt.0 as usize]; + + mark_queue.push_back(data.outer_mark); + ctxt_queue.push_back(data.prev_ctxt); + ctxt_queue.push_back(data.modern); + + syntax_contexts.insert(ctxt, data); + } + } + + HygieneDataMap { + marks, + syntax_contexts, + gensym_to_ctxt, + } + } } pub fn clear_markings() { HygieneData::with(|data| data.markings = HashMap::new()); } +fn register_mark_use(mark: Mark) { + HygieneData::with(|data| if !data.used_marks.contains(&mark) { + data.used_marks.push(mark); + }); +} + +fn register_syntax_context_use(ctxt: SyntaxContext) { + HygieneData::with(|data| if !data.used_syntax_contexts.contains(&ctxt) { + data.used_syntax_contexts.push(ctxt) + }); +} + /// Holds information about a HygieneData imported from another crate. /// See `imported_hygiene_data()` in `rustc_metadata` for more information. +#[derive(Default)] pub struct ImportedHygieneData { - /// The imported HygieneData's offset in the local HygieneData's marks vector. - pub mark_translation_offset: u32, - /// The imported HygieneData's offset in the local HygieneData's syntax contexts vector. - pub ctxt_translation_offset: u32, + /// Map an external crate's syntax contexts to the current crate's. + ctxt_map: HashMap<SyntaxContext, SyntaxContext>, + /// Map an external crate's marks to the current crate's. + mark_map: HashMap<Mark, Mark>, } -pub fn extend_hygiene_data(extend_with: HygieneData) -> ImportedHygieneData { - fn translate_span(span: &Span, offset: u32) -> Span { +impl ImportedHygieneData { + fn insert_ctxt(&mut self, external: SyntaxContext, target: SyntaxContext) { + assert!(!self.ctxt_map.contains_key(&external)); + self.ctxt_map.insert(external, target); + } + + fn insert_mark(&mut self, external: Mark, target: Mark) { + assert!(!self.mark_map.contains_key(&external)); + self.mark_map.insert(external, target); + } + + pub fn translate_ctxt(&self, external: SyntaxContext) -> SyntaxContext { + self.ctxt_map[&external] + } + + pub fn translate_mark(&self, external: Mark) -> Mark { + self.mark_map[&external] + } + + pub fn translate_span(&self, external: Span) -> Span { Span { - lo: span.lo, - hi: span.hi, - ctxt: span.ctxt.translate(offset), + lo: external.lo, + hi: external.hi, + ctxt: self.ctxt_map[&external.ctxt], + } + } + + fn translate_mark_data(&self, data: MarkData) -> MarkData { + MarkData { + parent: self.translate_mark(data.parent), + modern: data.modern, + expn_info: data.expn_info.as_ref().map(|info| { + ExpnInfo { + call_site: self.translate_span(info.call_site), + callee: NameAndSpan { + format: info.callee.format.clone(), + allow_internal_unstable: info.callee.allow_internal_unstable, + allow_internal_unsafe: info.callee.allow_internal_unsafe, + span: info.callee.span.map(|span| self.translate_span(span)), + }, + } + }), } } + fn translate_ctxt_data(&self, data: SyntaxContextData) -> SyntaxContextData { + SyntaxContextData { + outer_mark: self.translate_mark(data.outer_mark), + prev_ctxt: self.translate_ctxt(data.prev_ctxt), + modern: self.translate_ctxt(data.modern), + } + } +} + +pub fn extend_hygiene_data(extend_with: HygieneDataMap) -> ImportedHygieneData { HygieneData::with(move |data| { + let mut imported_map = ImportedHygieneData::default(); let mark_offset = data.marks.len() as u32; let ctxt_offset = data.syntax_contexts.len() as u32; - // skip the default mark, it doesn't need to be translated. - for mark_data in extend_with.marks.iter().skip(1) { - data.marks.push(MarkData { - parent: mark_data.parent.translate(mark_offset), - modern: mark_data.modern, - expn_info: mark_data.expn_info.as_ref().map(|info| { - ExpnInfo { - call_site: translate_span(&info.call_site, ctxt_offset), - callee: NameAndSpan { - format: info.callee.format.clone(), - allow_internal_unstable: info.callee.allow_internal_unstable, - allow_internal_unsafe: info.callee.allow_internal_unsafe, - span: - info.callee.span.map(|span| translate_span(&span, ctxt_offset)), - }, - } - }), + let HygieneDataMap { + mut marks, + mut syntax_contexts, + mut gensym_to_ctxt, + } = extend_with; + + let marks: Vec<_> = marks + .drain() + .enumerate() + .map(|(index_offset, (mark, data))| { + let index_offset = index_offset as u32; + imported_map.insert_mark(mark, mark.translate(mark_offset + index_offset)); + data }) - } + .collect(); + + let syntax_contexts: Vec<_> = syntax_contexts + .drain() + .enumerate() + .map(|(index_offset, (ctxt, data))| { + let index_offset = index_offset as u32; + imported_map.insert_ctxt(ctxt, ctxt.translate(ctxt_offset + index_offset)); + data + }) + .collect(); - // skip the default syntax context, it doesn't need to be translated. - for ctxt in extend_with.syntax_contexts.iter().skip(1) { - data.syntax_contexts.push(SyntaxContextData { - outer_mark: ctxt.outer_mark.translate(mark_offset), - prev_ctxt: ctxt.prev_ctxt.translate(ctxt_offset), - modern: ctxt.modern.translate(ctxt_offset), - }); + for mark in marks { + data.marks.push(imported_map.translate_mark_data(mark)); } - // translate markings map and extend the current one - for (&(ctxt1, mark), ctxt2) in extend_with.markings.iter() { - data.markings.insert((ctxt1.translate(ctxt_offset), mark.translate(mark_offset)), - ctxt2.translate(ctxt_offset)); + for ctxt in syntax_contexts { + data.syntax_contexts.push(imported_map.translate_ctxt_data(ctxt)); } - data.gensym_to_ctxt.extend(extend_with.gensym_to_ctxt); + data.gensym_to_ctxt + .extend(gensym_to_ctxt + .drain() + .map(|(symbol, ctxt)| (symbol, imported_map.translate_ctxt(ctxt)))); - ImportedHygieneData { - mark_translation_offset: mark_offset, - ctxt_translation_offset: ctxt_offset, - } + imported_map }) } @@ -458,12 +595,26 @@ impl UseSpecializedDecodable for SyntaxContext { } } +impl UseSpecializedEncodable for SyntaxContext { + fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> { + register_syntax_context_use(*self); + s.emit_u32(self.0) + } +} + impl UseSpecializedDecodable for Mark { fn default_decode<D: Decoder>(d: &mut D) -> Result<Mark, D::Error> { d.read_u32().map(Mark::from_u32) } } +impl UseSpecializedEncodable for Mark { + fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> { + register_mark_use(*self); + s.emit_u32(self.0) + } +} + impl Symbol { pub fn from_ident(ident: Ident) -> Symbol { HygieneData::with(|data| { From e3e790a9293180cab97c62b04d9ca4de604ac516 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin <twk@twki.de> Date: Sat, 19 Aug 2017 18:17:48 +0200 Subject: [PATCH 09/13] Fixed on-demand hygiene info encoding. --- src/librustc_metadata/decoder.rs | 1 + src/librustc_metadata/encoder.rs | 6 ++++-- src/libsyntax_pos/hygiene.rs | 25 ++++++++++++++----------- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 1d7ab542cdc09..2b8599a7988e5 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -1269,6 +1269,7 @@ impl<'a, 'tcx> CrateMetadata { // This shouldn't borrow twice, but there is no way to downgrade RefMut to Ref. *self.hygiene_data_import_info.borrow_mut() = Some(hygiene::extend_hygiene_data(external_hygiene_data)); + self.hygiene_data_being_decoded.set(false); Ref::map(self.hygiene_data_import_info.borrow(), |d| d.as_ref().unwrap()) diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 08a968c1b4c78..3c22ae1be8d9e 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -351,8 +351,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } fn encode_hygiene_data(&mut self) -> Lazy<hygiene::HygieneDataMap> { - // TODO(twk): remove the `ensure_hygiene_data_loaded` method! - hygiene::HygieneData::safe_with(|data| self.lazy(&data.to_map())) + // FIXME(twk): remove the `ensure_hygiene_data_loaded` method + // self.tcx.sess.cstore.ensure_hygiene_data_loaded(); + let data = hygiene::HygieneData::safe_with(|data| data.to_map()); + self.lazy(&data) } fn encode_crate_root(&mut self) -> Lazy<CrateRoot> { diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index 3d766279a930f..a9297e2847e77 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -161,13 +161,12 @@ impl HygieneData { let mut mark_queue: VecDeque<_> = self.used_marks.iter().cloned().collect(); let mut ctxt_queue: VecDeque<_> = self.used_syntax_contexts.iter().cloned().collect(); ctxt_queue.extend(self.gensym_to_ctxt.values()); - let gensym_to_ctxt = self.gensym_to_ctxt.clone(); let mut visited_marks = HashSet::new(); let mut visited_ctxts = HashSet::new(); - loop { + while !(mark_queue.is_empty() && ctxt_queue.is_empty()) { let next_mark = mark_queue.pop_front().and_then(|mark| // skip default mark and already visited marks if visited_marks.contains(&mark) || mark.0 == 0 { @@ -185,10 +184,6 @@ impl HygieneData { Some(ctxt) }); - if next_mark.is_none() && next_ctxt.is_none() { - break; - } - if let Some(mark) = next_mark { let data = &self.marks[mark.0 as usize]; @@ -261,18 +256,26 @@ impl ImportedHygieneData { } pub fn translate_ctxt(&self, external: SyntaxContext) -> SyntaxContext { - self.ctxt_map[&external] + if external.0 != 0 { + self.ctxt_map[&external] + } else { + external + } } pub fn translate_mark(&self, external: Mark) -> Mark { - self.mark_map[&external] + if external.0 != 0 { + self.mark_map[&external] + } else { + external + } } pub fn translate_span(&self, external: Span) -> Span { Span { lo: external.lo, hi: external.hi, - ctxt: self.ctxt_map[&external.ctxt], + ctxt: self.translate_ctxt(external.ctxt), } } @@ -320,7 +323,7 @@ pub fn extend_hygiene_data(extend_with: HygieneDataMap) -> ImportedHygieneData { .enumerate() .map(|(index_offset, (mark, data))| { let index_offset = index_offset as u32; - imported_map.insert_mark(mark, mark.translate(mark_offset + index_offset)); + imported_map.insert_mark(mark, Mark(mark_offset + index_offset)); data }) .collect(); @@ -330,7 +333,7 @@ pub fn extend_hygiene_data(extend_with: HygieneDataMap) -> ImportedHygieneData { .enumerate() .map(|(index_offset, (ctxt, data))| { let index_offset = index_offset as u32; - imported_map.insert_ctxt(ctxt, ctxt.translate(ctxt_offset + index_offset)); + imported_map.insert_ctxt(ctxt, SyntaxContext(ctxt_offset + index_offset)); data }) .collect(); From 3927f51def14398f94b29b996431e8242a0978a3 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin <twk@twki.de> Date: Sat, 19 Aug 2017 19:10:00 +0200 Subject: [PATCH 10/13] Added serialization instances after rebase. --- src/libsyntax_pos/hygiene.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index a9297e2847e77..eabde196f73a0 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -573,7 +573,7 @@ pub enum ExpnFormat { } /// The kind of compiler desugaring. -#[derive(Clone, Hash, Debug, PartialEq, Eq)] +#[derive(Clone, Hash, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)] pub enum CompilerDesugaringKind { BackArrow, DotFill, From 909808f9d9ea386ddd35430da23c3568de55f6ff Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin <twk@twki.de> Date: Sun, 20 Aug 2017 16:26:33 +0200 Subject: [PATCH 11/13] Removed some cruft added for macro expansion serialization. --- src/librustc/middle/cstore.rs | 3 --- src/librustc_metadata/cstore_impl.rs | 6 ------ src/librustc_metadata/encoder.rs | 2 -- 3 files changed, 11 deletions(-) diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index d7540aed5a024..a97bfa0536987 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -253,8 +253,6 @@ pub struct ExternBodyNestedBodies { pub trait CrateStore { fn crate_data_as_rc_any(&self, krate: CrateNum) -> Rc<Any>; - fn ensure_hygiene_data_loaded(&self); - // access to the metadata loader fn metadata_loader(&self) -> &MetadataLoader; @@ -327,7 +325,6 @@ pub struct DummyCrateStore; impl CrateStore for DummyCrateStore { fn crate_data_as_rc_any(&self, krate: CrateNum) -> Rc<Any> { bug!("crate_data_as_rc_any") } - fn ensure_hygiene_data_loaded(&self) { bug!("ensure_hygiene_data_loaded") } // item info fn visibility_untracked(&self, def: DefId) -> ty::Visibility { bug!("visibility") } fn item_generics_cloned_untracked(&self, def: DefId) -> ty::Generics diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 3d67868f36618..8eacc21ab003b 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -350,12 +350,6 @@ impl CrateStore for cstore::CStore { self.get_crate_data(krate) } - fn ensure_hygiene_data_loaded(&self) { - self.iter_crate_data(|_, metadata| { - (*metadata).imported_hygiene_data(); - }); - } - fn metadata_loader(&self) -> &MetadataLoader { &*self.metadata_loader } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 3c22ae1be8d9e..41cb54117dbb7 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -351,8 +351,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } fn encode_hygiene_data(&mut self) -> Lazy<hygiene::HygieneDataMap> { - // FIXME(twk): remove the `ensure_hygiene_data_loaded` method - // self.tcx.sess.cstore.ensure_hygiene_data_loaded(); let data = hygiene::HygieneData::safe_with(|data| data.to_map()); self.lazy(&data) } From 6cb141af6f7426e15d04b4dc77c9238a8e0ab9bb Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin <twk@twki.de> Date: Wed, 11 Oct 2017 20:20:34 +0200 Subject: [PATCH 12/13] Fixed submodules. Kinda. --- src/doc/book | 2 +- src/doc/nomicon | 2 +- src/doc/reference | 2 +- src/libcompiler_builtins | 2 +- src/liblibc | 2 +- src/tools/rls | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/doc/book b/src/doc/book index d09c9e8144ed3..08e79609ce885 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit d09c9e8144ed32170b7596abb145ade8b097acaf +Subproject commit 08e79609ce88583fa7286157dfe497486a09fabe diff --git a/src/doc/nomicon b/src/doc/nomicon index a4322ccb289a4..0ee3f7265e9d0 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit a4322ccb289a43cc238d4536982f184a3eec9ba7 +Subproject commit 0ee3f7265e9d09746d901cef6f1f300baff1d923 diff --git a/src/doc/reference b/src/doc/reference index 1abfbaa70313f..36adc6ae504c6 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 1abfbaa70313fdf527cf799ffd9b9a096a62105c +Subproject commit 36adc6ae504c6e0343ab5d7b3871f0a2a71236da diff --git a/src/libcompiler_builtins b/src/libcompiler_builtins index 6b9281d2b2f0e..0b9844764ea1f 160000 --- a/src/libcompiler_builtins +++ b/src/libcompiler_builtins @@ -1 +1 @@ -Subproject commit 6b9281d2b2f0ebb94838814b1e8ace2de4b7035b +Subproject commit 0b9844764ea1f99ea11a7917a4f3ba7fd2db775c diff --git a/src/liblibc b/src/liblibc index 2a5b50b7f7f53..44e4018e1a377 160000 --- a/src/liblibc +++ b/src/liblibc @@ -1 +1 @@ -Subproject commit 2a5b50b7f7f539a0fd201331d6c1e0534aa332f5 +Subproject commit 44e4018e1a37716286ec98cb5b7dd7d33ecaf940 diff --git a/src/tools/rls b/src/tools/rls index 5d4bbd9052fe2..bfe80cfa8db75 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit 5d4bbd9052fe2af849a7d017b85df98ad002c20f +Subproject commit bfe80cfa8db75500e67ca8762465d27662674637 From b79b450965d9452e7fab713f429ae6391860ad9d Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin <twk@twki.de> Date: Wed, 11 Oct 2017 22:00:24 +0200 Subject: [PATCH 13/13] (kind of) fixed build. --- src/librustc_metadata/decoder.rs | 2 +- src/libsyntax_pos/hygiene.rs | 10 +++------- src/llvm | 2 +- .../compile-fail-fulldeps/auxiliary/macro_spans_lib.rs | 5 +++-- src/test/compile-fail-fulldeps/macro-spans.rs | 2 +- src/tools/cargo | 2 +- src/tools/rls | 2 +- src/tools/rust-installer | 2 +- 8 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 2b8599a7988e5..a8176bf7a1654 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -274,7 +274,7 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> { let sess = if let Some(sess) = self.sess { sess } else { - return Ok(Span { lo, hi, ctxt }); + return Ok(Span::new(lo, hi, ctxt)); }; let (lo, hi) = if lo > hi { diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index eabde196f73a0..b8a4eaaef4977 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -189,10 +189,10 @@ impl HygieneData { mark_queue.push_back(data.parent); if let Some(ref info) = data.expn_info { - ctxt_queue.push_back(info.call_site.ctxt); + ctxt_queue.push_back(info.call_site.ctxt()); if let Some(span) = info.callee.span { - ctxt_queue.push_back(span.ctxt); + ctxt_queue.push_back(span.ctxt()); } } @@ -272,11 +272,7 @@ impl ImportedHygieneData { } pub fn translate_span(&self, external: Span) -> Span { - Span { - lo: external.lo, - hi: external.hi, - ctxt: self.translate_ctxt(external.ctxt), - } + Span::new(external.lo(), external.hi(), self.translate_ctxt(external.ctxt())) } fn translate_mark_data(&self, data: MarkData) -> MarkData { diff --git a/src/llvm b/src/llvm index d9e7d2696e419..c7a16bd57c2a9 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit d9e7d2696e41983b6b5a0b4fac604b4e548a84d3 +Subproject commit c7a16bd57c2a9c643a52f0cebecdaf0b6a996da1 diff --git a/src/test/compile-fail-fulldeps/auxiliary/macro_spans_lib.rs b/src/test/compile-fail-fulldeps/auxiliary/macro_spans_lib.rs index 739e37feeae29..eeba255923407 100644 --- a/src/test/compile-fail-fulldeps/auxiliary/macro_spans_lib.rs +++ b/src/test/compile-fail-fulldeps/auxiliary/macro_spans_lib.rs @@ -8,18 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[macro_export] macro_rules! abc { ($name:ident) => { mod $name { macro_rules! $name { ($name2:ident) => { struct $name { - $name2: u8, + $name2: $name, } } } - $name!(AStruct) + $name!(some_field); } } } diff --git a/src/test/compile-fail-fulldeps/macro-spans.rs b/src/test/compile-fail-fulldeps/macro-spans.rs index a3f7a92af719e..3a9994c7505af 100644 --- a/src/test/compile-fail-fulldeps/macro-spans.rs +++ b/src/test/compile-fail-fulldeps/macro-spans.rs @@ -13,6 +13,6 @@ #[macro_use] extern crate macro_spans_lib; -abc!(Name) +abc!(Name); //~ ERROR recursive type `Name::Name` has infinite size fn main() { } diff --git a/src/tools/cargo b/src/tools/cargo index 7704f7b1fd526..e447ac7e94b7f 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 7704f7b1fd52607104cc7fdc435d636c9de1fe90 +Subproject commit e447ac7e94b7f56ab13e361f9e324dafe3eb0a34 diff --git a/src/tools/rls b/src/tools/rls index bfe80cfa8db75..93b47d14cef57 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit bfe80cfa8db75500e67ca8762465d27662674637 +Subproject commit 93b47d14cef5720bba7cfb4dcb8078fbf1f706c1 diff --git a/src/tools/rust-installer b/src/tools/rust-installer index b4ff403041f17..0ddd53c4bc2a7 160000 --- a/src/tools/rust-installer +++ b/src/tools/rust-installer @@ -1 +1 @@ -Subproject commit b4ff403041f17957f735ad750c3241a3a428b9b7 +Subproject commit 0ddd53c4bc2a76df565a1c1fc0cc6f19f254b51e