Skip to content

Commit ca0de63

Browse files
committed
Auto merge of #53711 - arielb1:macro-table, r=michaelwoerister
create a valid DefIdTable for proc macro crates At least the incremental compilation code, and a few other places in the compiler, require the CrateMetadata for a loaded target crate to contain a valid DefIdTable for the DefIds in the target. Previously, the CrateMetadata for a proc macro contained the crate's "host" DefIdTable, which is of course incompatible with the "target" DefIdTable, causing ICEs. This creates a DefIdTable that properly refers to the "proc macro" DefIds. Fixes #49482. r? @michaelwoerister Should we beta-nominate this?
2 parents f4e981c + 025d014 commit ca0de63

File tree

8 files changed

+195
-31
lines changed

8 files changed

+195
-31
lines changed

Diff for: src/librustc/hir/def_id.rs

+15-5
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
use ty;
12-
12+
use hir::map::definitions::FIRST_FREE_HIGH_DEF_INDEX;
1313
use rustc_data_structures::indexed_vec::Idx;
1414
use serialize;
1515
use std::fmt;
@@ -125,15 +125,25 @@ impl DefIndex {
125125
// index of the macro in the CrateMetadata::proc_macros array) to the
126126
// corresponding DefIndex.
127127
pub fn from_proc_macro_index(proc_macro_index: usize) -> DefIndex {
128-
let def_index = DefIndex::from_array_index(proc_macro_index,
129-
DefIndexAddressSpace::High);
128+
// DefIndex for proc macros start from FIRST_FREE_HIGH_DEF_INDEX,
129+
// because the first FIRST_FREE_HIGH_DEF_INDEX indexes are reserved
130+
// for internal use.
131+
let def_index = DefIndex::from_array_index(
132+
proc_macro_index.checked_add(FIRST_FREE_HIGH_DEF_INDEX)
133+
.expect("integer overflow adding `proc_macro_index`"),
134+
DefIndexAddressSpace::High);
130135
assert!(def_index != CRATE_DEF_INDEX);
131136
def_index
132137
}
133138

134139
// This function is the reverse of from_proc_macro_index() above.
135140
pub fn to_proc_macro_index(self: DefIndex) -> usize {
136-
self.as_array_index()
141+
assert_eq!(self.address_space(), DefIndexAddressSpace::High);
142+
143+
self.as_array_index().checked_sub(FIRST_FREE_HIGH_DEF_INDEX)
144+
.unwrap_or_else(|| {
145+
bug!("using local index {:?} as proc-macro index", self)
146+
})
137147
}
138148

139149
// Don't use this if you don't know about the DefIndex encoding.
@@ -150,7 +160,7 @@ impl DefIndex {
150160
impl serialize::UseSpecializedEncodable for DefIndex {}
151161
impl serialize::UseSpecializedDecodable for DefIndex {}
152162

153-
#[derive(Copy, Clone, Hash)]
163+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
154164
pub enum DefIndexAddressSpace {
155165
Low = 0,
156166
High = 1,

Diff for: src/librustc/hir/map/definitions.rs

+17
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,17 @@ impl Borrow<Fingerprint> for DefPathHash {
380380

381381
impl Definitions {
382382
/// Create new empty definition map.
383+
///
384+
/// The DefIndex returned from a new Definitions are as follows:
385+
/// 1. At DefIndexAddressSpace::Low,
386+
/// CRATE_ROOT has index 0:0, and then new indexes are allocated in
387+
/// ascending order.
388+
/// 2. At DefIndexAddressSpace::High,
389+
/// the first FIRST_FREE_HIGH_DEF_INDEX indexes are reserved for
390+
/// internal use, then 1:FIRST_FREE_HIGH_DEF_INDEX are allocated in
391+
/// ascending order.
392+
///
393+
/// FIXME: there is probably a better place to put this comment.
383394
pub fn new() -> Definitions {
384395
Definitions {
385396
table: DefPathTable {
@@ -665,6 +676,11 @@ impl DefPathData {
665676
}
666677
}
667678

679+
macro_rules! count {
680+
() => (0usize);
681+
( $x:tt $($xs:tt)* ) => (1usize + count!($($xs)*));
682+
}
683+
668684
// We define the GlobalMetaDataKind enum with this macro because we want to
669685
// make sure that we exhaustively iterate over all variants when registering
670686
// the corresponding DefIndices in the DefTable.
@@ -678,6 +694,7 @@ macro_rules! define_global_metadata_kind {
678694
}
679695

680696
const GLOBAL_MD_ADDRESS_SPACE: DefIndexAddressSpace = DefIndexAddressSpace::High;
697+
pub const FIRST_FREE_HIGH_DEF_INDEX: usize = count!($($variant)*);
681698

682699
impl GlobalMetaDataKind {
683700
fn allocate_def_indices(definitions: &mut Definitions) {

Diff for: src/librustc_metadata/creader.rs

+11-4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
1313
use cstore::{self, CStore, CrateSource, MetadataBlob};
1414
use locator::{self, CratePaths};
15+
use decoder::proc_macro_def_path_table;
1516
use schema::CrateRoot;
1617
use rustc_data_structures::sync::{Lrc, RwLock, Lock};
1718

@@ -219,8 +220,16 @@ impl<'a> CrateLoader<'a> {
219220

220221
let dependencies: Vec<CrateNum> = cnum_map.iter().cloned().collect();
221222

223+
let proc_macros = crate_root.macro_derive_registrar.map(|_| {
224+
self.load_derive_macros(&crate_root, dylib.clone().map(|p| p.0), span)
225+
});
226+
222227
let def_path_table = record_time(&self.sess.perf_stats.decode_def_path_tables_time, || {
223-
crate_root.def_path_table.decode((&metadata, self.sess))
228+
if let Some(proc_macros) = &proc_macros {
229+
proc_macro_def_path_table(&crate_root, proc_macros)
230+
} else {
231+
crate_root.def_path_table.decode((&metadata, self.sess))
232+
}
224233
});
225234

226235
let interpret_alloc_index: Vec<u32> = crate_root.interpret_alloc_index
@@ -237,9 +246,7 @@ impl<'a> CrateLoader<'a> {
237246
extern_crate: Lock::new(None),
238247
def_path_table: Lrc::new(def_path_table),
239248
trait_impls,
240-
proc_macros: crate_root.macro_derive_registrar.map(|_| {
241-
self.load_derive_macros(&crate_root, dylib.clone().map(|p| p.0), span)
242-
}),
249+
proc_macros,
243250
root: crate_root,
244251
blob: metadata,
245252
cnum_map,

Diff for: src/librustc_metadata/decoder.rs

+45-22
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@ use cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary, ForeignModule};
1414
use schema::*;
1515

1616
use rustc_data_structures::sync::{Lrc, ReadGuard};
17-
use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash,
18-
DisambiguatedDefPathData};
17+
use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash, Definitions};
1918
use rustc::hir;
2019
use rustc::middle::cstore::LinkagePreference;
2120
use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
2221
use rustc::hir::def::{self, Def, CtorKind};
23-
use rustc::hir::def_id::{CrateNum, DefId, DefIndex,
22+
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, DefIndexAddressSpace,
2423
CRATE_DEF_INDEX, LOCAL_CRATE, LocalDefId};
24+
use rustc::hir::map::definitions::DefPathTable;
2525
use rustc_data_structures::fingerprint::Fingerprint;
2626
use rustc::middle::lang_items;
2727
use rustc::mir::{self, interpret};
@@ -41,7 +41,8 @@ use syntax::attr;
4141
use syntax::ast::{self, Ident};
4242
use syntax::source_map;
4343
use syntax::symbol::InternedString;
44-
use syntax::ext::base::MacroKind;
44+
use syntax::ext::base::{MacroKind, SyntaxExtension};
45+
use syntax::ext::hygiene::Mark;
4546
use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, NO_EXPANSION};
4647

4748
pub struct DecodeContext<'a, 'tcx: 'a> {
@@ -441,6 +442,40 @@ impl<'tcx> EntryKind<'tcx> {
441442
}
442443
}
443444

445+
/// Create the "fake" DefPathTable for a given proc macro crate.
446+
///
447+
/// The DefPathTable is as follows:
448+
///
449+
/// CRATE_ROOT (DefIndex 0:0)
450+
/// |- GlobalMetaDataKind data (DefIndex 1:0 .. DefIndex 1:N)
451+
/// |- proc macro #0 (DefIndex 1:N)
452+
/// |- proc macro #1 (DefIndex 1:N+1)
453+
/// \- ...
454+
crate fn proc_macro_def_path_table(crate_root: &CrateRoot,
455+
proc_macros: &[(ast::Name, Lrc<SyntaxExtension>)])
456+
-> DefPathTable
457+
{
458+
let mut definitions = Definitions::new();
459+
460+
let name = crate_root.name.as_str();
461+
let disambiguator = crate_root.disambiguator;
462+
debug!("creating proc macro def path table for {:?}/{:?}", name, disambiguator);
463+
let crate_root = definitions.create_root_def(&name, disambiguator);
464+
for (index, (name, _)) in proc_macros.iter().enumerate() {
465+
let def_index = definitions.create_def_with_parent(
466+
crate_root,
467+
ast::DUMMY_NODE_ID,
468+
DefPathData::MacroDef(name.as_interned_str()),
469+
DefIndexAddressSpace::High,
470+
Mark::root(),
471+
DUMMY_SP);
472+
debug!("definition for {:?} is {:?}", name, def_index);
473+
assert_eq!(def_index, DefIndex::from_proc_macro_index(index));
474+
}
475+
476+
definitions.def_path_table().clone()
477+
}
478+
444479
impl<'a, 'tcx> CrateMetadata {
445480
fn is_proc_macro(&self, id: DefIndex) -> bool {
446481
self.proc_macros.is_some() && id != CRATE_DEF_INDEX
@@ -669,6 +704,10 @@ impl<'a, 'tcx> CrateMetadata {
669704
where F: FnMut(def::Export)
670705
{
671706
if let Some(ref proc_macros) = self.proc_macros {
707+
/* If we are loading as a proc macro, we want to return the view of this crate
708+
* as a proc macro crate, not as a Rust crate. See `proc_macro_def_path_table`
709+
* for the DefPathTable we are corresponding to.
710+
*/
672711
if id == CRATE_DEF_INDEX {
673712
for (id, &(name, ref ext)) in proc_macros.iter().enumerate() {
674713
let def = Def::Macro(
@@ -1066,28 +1105,12 @@ impl<'a, 'tcx> CrateMetadata {
10661105

10671106
#[inline]
10681107
pub fn def_key(&self, index: DefIndex) -> DefKey {
1069-
if !self.is_proc_macro(index) {
1070-
self.def_path_table.def_key(index)
1071-
} else {
1072-
// FIXME(#49271) - It would be better if the DefIds were consistent
1073-
// with the DefPathTable, but for proc-macro crates
1074-
// they aren't.
1075-
let name = self.proc_macros
1076-
.as_ref()
1077-
.unwrap()[index.to_proc_macro_index()].0;
1078-
DefKey {
1079-
parent: Some(CRATE_DEF_INDEX),
1080-
disambiguated_data: DisambiguatedDefPathData {
1081-
data: DefPathData::MacroDef(name.as_interned_str()),
1082-
disambiguator: 0,
1083-
}
1084-
}
1085-
}
1108+
self.def_path_table.def_key(index)
10861109
}
10871110

10881111
// Returns the path leading to the thing with this `id`.
10891112
pub fn def_path(&self, id: DefIndex) -> DefPath {
1090-
debug!("def_path(id={:?})", id);
1113+
debug!("def_path(cnum={:?}, id={:?})", self.cnum, id);
10911114
DefPath::make(self.cnum, id, |parent| self.def_path_table.def_key(parent))
10921115
}
10931116

Diff for: src/librustc_metadata/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#![feature(quote)]
2323
#![feature(rustc_diagnostic_macros)]
2424
#![feature(slice_sort_by_cached_key)]
25+
#![feature(crate_visibility_modifier)]
2526
#![feature(specialization)]
2627
#![feature(rustc_private)]
2728

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// no-prefer-dynamic
12+
13+
#![crate_type="proc-macro"]
14+
#![allow(non_snake_case)]
15+
16+
extern crate proc_macro;
17+
18+
macro_rules! proc_macro_expr_impl {
19+
($(
20+
$( #[$attr:meta] )*
21+
pub fn $func:ident($input:ident: &str) -> String;
22+
)+) => {
23+
$(
24+
$( #[$attr] )*
25+
#[proc_macro_derive($func)]
26+
pub fn $func(_input: ::proc_macro::TokenStream) -> ::proc_macro::TokenStream {
27+
panic!()
28+
}
29+
)+
30+
};
31+
}
32+
33+
proc_macro_expr_impl! {
34+
pub fn f1(input: &str) -> String;
35+
pub fn f2(input: &str) -> String;
36+
pub fn f3(input: &str) -> String;
37+
pub fn f4(input: &str) -> String;
38+
pub fn f5(input: &str) -> String;
39+
pub fn f6(input: &str) -> String;
40+
pub fn f7(input: &str) -> String;
41+
pub fn f8(input: &str) -> String;
42+
pub fn f9(input: &str) -> String;
43+
pub fn fA(input: &str) -> String;
44+
pub fn fB(input: &str) -> String;
45+
pub fn fC(input: &str) -> String;
46+
pub fn fD(input: &str) -> String;
47+
pub fn fE(input: &str) -> String;
48+
pub fn fF(input: &str) -> String;
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#[macro_use]
12+
extern crate issue_49482_macro_def;
13+
14+
pub use issue_49482_macro_def::*;
15+
16+
pub fn foo() {}

Diff for: src/test/incremental-fulldeps/issue-49482.rs

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// aux-build:issue_49482_macro_def.rs
12+
// aux-build:issue_49482_reexport.rs
13+
// ignore-stage1
14+
// revisions: rpass1
15+
16+
extern crate issue_49482_reexport;
17+
18+
pub trait KvStorage
19+
{
20+
fn get(&self);
21+
}
22+
23+
impl<K> KvStorage for Box<K>
24+
where
25+
K: KvStorage + ?Sized,
26+
{
27+
fn get(&self) {
28+
(**self).get()
29+
}
30+
}
31+
32+
impl KvStorage for u32 {
33+
fn get(&self) {}
34+
}
35+
36+
fn main() {
37+
/* force issue_49482_reexport to be loaded */
38+
issue_49482_reexport::foo();
39+
40+
Box::new(2).get();
41+
}

0 commit comments

Comments
 (0)