Skip to content

Commit b9f1d81

Browse files
committed
Initial support for dynamically linked crates
1 parent 85c3989 commit b9f1d81

File tree

72 files changed

+1481
-79
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+1481
-79
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -4219,6 +4219,7 @@ name = "rustc_monomorphize"
42194219
version = "0.0.0"
42204220
dependencies = [
42214221
"rustc_abi",
4222+
"rustc_ast",
42224223
"rustc_attr_parsing",
42234224
"rustc_data_structures",
42244225
"rustc_errors",

compiler/rustc_ast/src/ast.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -3172,7 +3172,7 @@ impl Item {
31723172

31733173
pub fn opt_generics(&self) -> Option<&Generics> {
31743174
match &self.kind {
3175-
ItemKind::ExternCrate(_)
3175+
ItemKind::ExternCrate(_, _)
31763176
| ItemKind::Use(_)
31773177
| ItemKind::Mod(_, _)
31783178
| ItemKind::ForeignMod(_)
@@ -3374,13 +3374,19 @@ pub struct ConstItem {
33743374
pub expr: Option<P<Expr>>,
33753375
}
33763376

3377+
#[derive(PartialEq, Eq, Clone, Copy, Encodable, Decodable, Debug, HashStable_Generic)]
3378+
pub enum ExternCrateKind {
3379+
Stable,
3380+
Default,
3381+
}
3382+
33773383
// Adding a new variant? Please update `test_item` in `tests/ui/macros/stringify.rs`.
33783384
#[derive(Clone, Encodable, Decodable, Debug)]
33793385
pub enum ItemKind {
33803386
/// An `extern crate` item, with the optional *original* crate name if the crate was renamed.
33813387
///
33823388
/// E.g., `extern crate foo` or `extern crate foo_bar as foo`.
3383-
ExternCrate(Option<Symbol>),
3389+
ExternCrate(ExternCrateKind, Option<Symbol>),
33843390
/// A use declaration item (`use`).
33853391
///
33863392
/// E.g., `use foo;`, `use foo::bar;` or `use foo::bar as FooBar;`.

compiler/rustc_ast/src/mut_visit.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1196,7 +1196,7 @@ impl WalkItemKind for ItemKind {
11961196
vis: &mut impl MutVisitor,
11971197
) {
11981198
match self {
1199-
ItemKind::ExternCrate(_orig_name) => {}
1199+
ItemKind::ExternCrate(_kind, _orig_name) => {}
12001200
ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree),
12011201
ItemKind::Static(box StaticItem { ty, safety: _, mutability: _, expr }) => {
12021202
vis.visit_ty(ty);
@@ -1898,7 +1898,7 @@ impl DummyAstNode for Item {
18981898
tokens: Default::default(),
18991899
},
19001900
ident: Ident::empty(),
1901-
kind: ItemKind::ExternCrate(None),
1901+
kind: ItemKind::ExternCrate(ExternCrateKind::Default, None),
19021902
tokens: Default::default(),
19031903
}
19041904
}

compiler/rustc_ast/src/visit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ impl WalkItemKind for ItemKind {
363363
visitor: &mut V,
364364
) -> V::Result {
365365
match self {
366-
ItemKind::ExternCrate(_rename) => {}
366+
ItemKind::ExternCrate(_kind, _rename) => {}
367367
ItemKind::Use(use_tree) => try_visit!(visitor.visit_use_tree(use_tree, id, false)),
368368
ItemKind::Static(box StaticItem { ty, safety: _, mutability: _, expr }) => {
369369
try_visit!(visitor.visit_ty(ty));

compiler/rustc_ast_lowering/src/item.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
180180
i: &ItemKind,
181181
) -> hir::ItemKind<'hir> {
182182
match i {
183-
ItemKind::ExternCrate(orig_name) => hir::ItemKind::ExternCrate(*orig_name),
183+
ItemKind::ExternCrate(_, orig_name) => hir::ItemKind::ExternCrate(*orig_name),
184184
ItemKind::Use(use_tree) => {
185185
// Start with an empty prefix.
186186
let prefix = Path { segments: ThinVec::new(), span: use_tree.span, tokens: None };

compiler/rustc_ast_passes/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -273,3 +273,6 @@ ast_passes_where_clause_before_type_alias = where clauses are not allowed before
273273
.note = see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
274274
.remove_suggestion = remove this `where`
275275
.move_suggestion = move it to the end of the type declaration
276+
277+
ast_passes_wrong_mangling_scheme_for_extern_dyn =
278+
`extern dyn` annotation is only allowed with `v0` mangling scheme

compiler/rustc_ast_passes/src/ast_validation.rs

+7
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use rustc_errors::DiagCtxtHandle;
2929
use rustc_feature::Features;
3030
use rustc_parse::validate_attr;
3131
use rustc_session::Session;
32+
use rustc_session::config::SymbolManglingVersion;
3233
use rustc_session::lint::builtin::{
3334
DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, MISSING_UNSAFE_ON_EXTERN,
3435
PATTERNS_IN_FNS_WITHOUT_BODY,
@@ -1108,6 +1109,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
11081109
});
11091110
}
11101111
}
1112+
ItemKind::ExternCrate(ast::ExternCrateKind::Stable, _) => {
1113+
if self.sess.opts.get_symbol_mangling_version() != SymbolManglingVersion::V0 {
1114+
self.dcx()
1115+
.emit_err(errors::WrongManglingSchemeForExternDyn { span: item.span });
1116+
}
1117+
}
11111118
_ => {}
11121119
}
11131120

compiler/rustc_ast_passes/src/errors.rs

+7
Original file line numberDiff line numberDiff line change
@@ -824,3 +824,10 @@ pub(crate) struct DuplicatePreciseCapturing {
824824
#[label]
825825
pub bound2: Span,
826826
}
827+
828+
#[derive(Diagnostic)]
829+
#[diag(ast_passes_wrong_mangling_scheme_for_extern_dyn)]
830+
pub(crate) struct WrongManglingSchemeForExternDyn {
831+
#[primary_span]
832+
pub span: Span,
833+
}

compiler/rustc_ast_pretty/src/pprust/state.rs

+50-12
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,38 @@ pub enum AnnNode<'a> {
4949
}
5050

5151
pub trait PpAnn {
52+
fn nested(&self, state: &mut State<'_>, node: AnnNode<'_>) {
53+
print_default_nested_ann(state, node);
54+
}
5255
fn pre(&self, _state: &mut State<'_>, _node: AnnNode<'_>) {}
5356
fn post(&self, _state: &mut State<'_>, _node: AnnNode<'_>) {}
5457
}
5558

59+
pub fn print_default_nested_ann(state: &mut State<'_>, node: AnnNode<'_>) {
60+
match node {
61+
AnnNode::Block(blk) => {
62+
for (i, st) in blk.stmts.iter().enumerate() {
63+
match &st.kind {
64+
ast::StmtKind::Expr(expr) if i == blk.stmts.len() - 1 => {
65+
state.maybe_print_comment(st.span.lo());
66+
state.space_if_not_bol();
67+
state.print_expr_outer_attr_style(expr, false, FixupContext::new_stmt());
68+
state.maybe_print_trailing_comment(expr.span, Some(blk.span.hi()));
69+
}
70+
_ => state.print_stmt(st),
71+
}
72+
}
73+
}
74+
AnnNode::Crate(_)
75+
| AnnNode::Expr(_)
76+
| AnnNode::Ident(_)
77+
| AnnNode::Item(_)
78+
| AnnNode::Name(_)
79+
| AnnNode::Pat(_)
80+
| AnnNode::SubItem(_) => unimplemented!(),
81+
}
82+
}
83+
5684
struct NoAnn;
5785

5886
impl PpAnn for NoAnn {}
@@ -240,9 +268,29 @@ pub fn print_crate<'a>(
240268
edition: Edition,
241269
g: &AttrIdGenerator,
242270
) -> String {
243-
let mut s =
271+
let s =
244272
State { s: pp::Printer::new(), comments: Some(Comments::new(sm, filename, input)), ann };
273+
print_crate_with_state(s, krate, is_expanded, edition, g)
274+
}
245275

276+
pub fn print_crate_with_erased_comments<'a>(
277+
krate: &ast::Crate,
278+
ann: &'a dyn PpAnn,
279+
is_expanded: bool,
280+
edition: Edition,
281+
g: &AttrIdGenerator,
282+
) -> String {
283+
let s = State { s: pp::Printer::new(), comments: None, ann };
284+
print_crate_with_state(s, krate, is_expanded, edition, g)
285+
}
286+
287+
fn print_crate_with_state<'a>(
288+
mut s: State<'a>,
289+
krate: &ast::Crate,
290+
is_expanded: bool,
291+
edition: Edition,
292+
g: &AttrIdGenerator,
293+
) -> String {
246294
if is_expanded && !krate.attrs.iter().any(|attr| attr.has_name(sym::no_core)) {
247295
// We need to print `#![no_std]` (and its feature gate) so that
248296
// compiling pretty-printed source won't inject libstd again.
@@ -1383,17 +1431,7 @@ impl<'a> State<'a> {
13831431

13841432
let has_attrs = self.print_inner_attributes(attrs);
13851433

1386-
for (i, st) in blk.stmts.iter().enumerate() {
1387-
match &st.kind {
1388-
ast::StmtKind::Expr(expr) if i == blk.stmts.len() - 1 => {
1389-
self.maybe_print_comment(st.span.lo());
1390-
self.space_if_not_bol();
1391-
self.print_expr_outer_attr_style(expr, false, FixupContext::new_stmt());
1392-
self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi()));
1393-
}
1394-
_ => self.print_stmt(st),
1395-
}
1396-
}
1434+
self.ann.nested(self, AnnNode::Block(blk));
13971435

13981436
let empty = !has_attrs && blk.stmts.is_empty();
13991437
self.bclose_maybe_open(blk.span, empty, close_box);

compiler/rustc_ast_pretty/src/pprust/state/item.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,12 @@ impl<'a> State<'a> {
155155
self.print_outer_attributes(&item.attrs);
156156
self.ann.pre(self, AnnNode::Item(item));
157157
match &item.kind {
158-
ast::ItemKind::ExternCrate(orig_name) => {
159-
self.head(visibility_qualified(&item.vis, "extern crate"));
158+
ast::ItemKind::ExternCrate(kind, orig_name) => {
159+
let head = match kind {
160+
ast::ExternCrateKind::Default => "extern crate",
161+
ast::ExternCrateKind::Stable => "extern dyn crate",
162+
};
163+
self.head(visibility_qualified(&item.vis, head));
160164
if let &Some(orig_name) = orig_name {
161165
self.print_name(orig_name);
162166
self.space();

compiler/rustc_builtin_macros/src/proc_macro_harness.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,12 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P<ast::Item> {
278278
let span = DUMMY_SP.with_def_site_ctxt(expn_id.to_expn_id());
279279

280280
let proc_macro = Ident::new(sym::proc_macro, span);
281-
let krate = cx.item(span, proc_macro, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None));
281+
let krate = cx.item(
282+
span,
283+
proc_macro,
284+
ast::AttrVec::new(),
285+
ast::ItemKind::ExternCrate(ast::ExternCrateKind::Default, None),
286+
);
282287

283288
let bridge = Ident::new(sym::bridge, span);
284289
let client = Ident::new(sym::client, span);

compiler/rustc_builtin_macros/src/standard_library_imports.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,14 @@ pub fn inject(
5757
span,
5858
Ident::new(kw::Underscore, ident_span),
5959
thin_vec![],
60-
ast::ItemKind::ExternCrate(Some(name)),
60+
ast::ItemKind::ExternCrate(ast::ExternCrateKind::Default, Some(name)),
6161
)
6262
} else {
6363
cx.item(
6464
span,
6565
Ident::new(name, ident_span),
6666
thin_vec![cx.attr_word(sym::macro_use, span)],
67-
ast::ItemKind::ExternCrate(None),
67+
ast::ItemKind::ExternCrate(ast::ExternCrateKind::Default, None),
6868
)
6969
};
7070
krate.items.insert(0, item);

compiler/rustc_builtin_macros/src/test.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,12 @@ pub(crate) fn expand_test_or_bench(
352352
});
353353

354354
// extern crate test
355-
let test_extern = cx.item(sp, test_id, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None));
355+
let test_extern = cx.item(
356+
sp,
357+
test_id,
358+
ast::AttrVec::new(),
359+
ast::ItemKind::ExternCrate(ast::ExternCrateKind::Default, None),
360+
);
356361

357362
debug!("synthetic test item:\n{}\n", pprust::item_to_string(&test_const));
358363

compiler/rustc_builtin_macros/src/test_harness.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,12 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
318318
// extern crate test
319319
let test_extern_stmt = ecx.stmt_item(
320320
sp,
321-
ecx.item(sp, test_id, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None)),
321+
ecx.item(
322+
sp,
323+
test_id,
324+
ast::AttrVec::new(),
325+
ast::ItemKind::ExternCrate(ast::ExternCrateKind::Default, None),
326+
),
322327
);
323328

324329
// #[rustc_main]

compiler/rustc_codegen_ssa/src/back/write.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,11 @@ fn produce_final_output_artifacts(
626626
user_wants_objects = true;
627627
copy_if_one_unit(OutputType::Object, true);
628628
}
629-
OutputType::Mir | OutputType::Metadata | OutputType::Exe | OutputType::DepInfo => {}
629+
OutputType::Mir
630+
| OutputType::Metadata
631+
| OutputType::Exe
632+
| OutputType::DepInfo
633+
| OutputType::Interface => {}
630634
}
631635
}
632636

compiler/rustc_driver_impl/src/lib.rs

+8
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,14 @@ fn run_compiler(
439439
return early_exit();
440440
}
441441

442+
rustc_interface::export::write_interface(tcx);
443+
444+
if sess.opts.output_types.contains_key(&OutputType::Interface)
445+
&& sess.opts.output_types.len() == 1
446+
{
447+
return early_exit();
448+
}
449+
442450
if sess.opts.unstable_opts.no_analysis {
443451
return early_exit();
444452
}

compiler/rustc_feature/src/builtin_attrs.rs

+5
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
511511
naked_functions, experimental!(naked)
512512
),
513513

514+
gated!(
515+
export, Normal, template!(Word), WarnFollowing,
516+
EncodeCrossCrate::Yes, experimental!(export)
517+
),
518+
514519
// Testing:
515520
gated!(
516521
test_runner, CrateLevel, template!(List: "path"), ErrorFollowing,

compiler/rustc_feature/src/unstable.rs

+2
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,8 @@ declare_features! (
479479
(unstable, exhaustive_patterns, "1.13.0", Some(51085)),
480480
/// Allows explicit tail calls via `become` expression.
481481
(incomplete, explicit_tail_calls, "1.72.0", Some(112788)),
482+
/// Allows using `#[export]` which indicates that an item is exportable.
483+
(unstable, export, "CURRENT_RUSTC_VERSION", None),
482484
/// Allows defining `extern type`s.
483485
(unstable, extern_types, "1.23.0", Some(43467)),
484486
/// Allow using 128-bit (quad precision) floating point numbers.
+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
use std::fs::File;
2+
use std::io::{self, BufWriter, Write};
3+
4+
use rustc_ast_pretty::pprust::{self, AnnNode, PpAnn, State};
5+
use rustc_middle::ty::TyCtxt;
6+
use rustc_session::config::{OutFileName, OutputType};
7+
8+
struct InterfaceAnn;
9+
10+
impl PpAnn for InterfaceAnn {
11+
fn nested(&self, state: &mut State<'_>, node: AnnNode<'_>) {
12+
// Insert empty fn bodies.
13+
if let AnnNode::Block(_) = node {
14+
state.nbsp();
15+
state.word_nbsp("loop {}");
16+
return;
17+
}
18+
19+
pprust::state::print_default_nested_ann(state, node);
20+
}
21+
}
22+
23+
pub fn write_interface<'tcx>(tcx: TyCtxt<'tcx>) {
24+
let sess = tcx.sess;
25+
if !sess.opts.output_types.contains_key(&OutputType::Interface) {
26+
return;
27+
}
28+
let _timer = sess.timer("write_interface");
29+
30+
let krate = &tcx.resolver_for_lowering().borrow().1;
31+
let krate = pprust::state::print_crate_with_erased_comments(
32+
&krate,
33+
&InterfaceAnn,
34+
true,
35+
sess.edition(),
36+
&sess.psess.attr_id_generator,
37+
);
38+
let outputs = tcx.output_filenames(());
39+
let export_output = outputs.path(OutputType::Interface);
40+
match export_output {
41+
OutFileName::Stdout => {
42+
let mut file = BufWriter::new(io::stdout());
43+
let _ = write!(file, "{}", krate);
44+
}
45+
OutFileName::Real(ref path) => {
46+
let mut file = File::create_buffered(path).unwrap();
47+
let _ = write!(file, "{}", krate);
48+
}
49+
}
50+
}

compiler/rustc_interface/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
mod callbacks;
1111
pub mod errors;
12+
pub mod export;
1213
pub mod interface;
1314
pub mod passes;
1415
mod proc_macro_decls;

compiler/rustc_interface/src/passes.rs

+1
Original file line numberDiff line numberDiff line change
@@ -861,6 +861,7 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
861861
// as used, and ensures that their values are valid.
862862
tcx.ensure().limits(());
863863
tcx.ensure().stability_index(());
864+
tcx.ensure().exportable_items(LOCAL_CRATE);
864865
}
865866
);
866867
});

0 commit comments

Comments
 (0)