Skip to content

Commit a9a6a80

Browse files
committed
Initial support for dynamically linked crates
1 parent 2b3cef8 commit a9a6a80

File tree

85 files changed

+1769
-186
lines changed

Some content is hidden

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

85 files changed

+1769
-186
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3213,6 +3213,7 @@ impl Item {
32133213
pub fn opt_generics(&self) -> Option<&Generics> {
32143214
match &self.kind {
32153215
ItemKind::ExternCrate(_)
3216+
| ItemKind::ExternDynCrate(_)
32163217
| ItemKind::Use(_)
32173218
| ItemKind::Mod(_, _)
32183219
| ItemKind::ForeignMod(_)
@@ -3428,6 +3429,10 @@ pub enum ItemKind {
34283429
///
34293430
/// E.g., `extern crate foo` or `extern crate foo_bar as foo`.
34303431
ExternCrate(Option<Symbol>),
3432+
/// An extern crate with a stable interface.
3433+
///
3434+
/// E.g., `extern dyn crate foo` or `extern dyn crate foo_bar as foo`.
3435+
ExternDynCrate(Option<Symbol>),
34313436
/// A use declaration item (`use`).
34323437
///
34333438
/// E.g., `use foo;`, `use foo::bar;` or `use foo::bar as FooBar;`.
@@ -3509,13 +3514,19 @@ impl ItemKind {
35093514
Use(..) | Static(..) | Const(..) | Fn(..) | Mod(..) | GlobalAsm(..) | TyAlias(..)
35103515
| Struct(..) | Union(..) | Trait(..) | TraitAlias(..) | MacroDef(..)
35113516
| Delegation(..) | DelegationMac(..) => "a",
3512-
ExternCrate(..) | ForeignMod(..) | MacCall(..) | Enum(..) | Impl { .. } => "an",
3517+
ExternCrate(..)
3518+
| ExternDynCrate(..)
3519+
| ForeignMod(..)
3520+
| MacCall(..)
3521+
| Enum(..)
3522+
| Impl { .. } => "an",
35133523
}
35143524
}
35153525

35163526
pub fn descr(&self) -> &'static str {
35173527
match self {
35183528
ItemKind::ExternCrate(..) => "extern crate",
3529+
ItemKind::ExternDynCrate(..) => "extern dyn crate",
35193530
ItemKind::Use(..) => "`use` import",
35203531
ItemKind::Static(..) => "static item",
35213532
ItemKind::Const(..) => "constant item",

compiler/rustc_ast/src/mut_visit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1235,7 +1235,7 @@ impl WalkItemKind for ItemKind {
12351235
vis: &mut impl MutVisitor,
12361236
) {
12371237
match self {
1238-
ItemKind::ExternCrate(_orig_name) => {}
1238+
ItemKind::ExternCrate(_orig_name) | ItemKind::ExternDynCrate(_orig_name) => {}
12391239
ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree),
12401240
ItemKind::Static(box StaticItem { ty, safety: _, mutability: _, expr }) => {
12411241
vis.visit_ty(ty);

compiler/rustc_ast/src/visit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ impl WalkItemKind for ItemKind {
369369
visitor: &mut V,
370370
) -> V::Result {
371371
match self {
372-
ItemKind::ExternCrate(_rename) => {}
372+
ItemKind::ExternCrate(_rename) | ItemKind::ExternDynCrate(_rename) => {}
373373
ItemKind::Use(use_tree) => try_visit!(visitor.visit_use_tree(use_tree, id, false)),
374374
ItemKind::Static(box StaticItem { ty, safety: _, mutability: _, expr }) => {
375375
try_visit!(visitor.visit_ty(ty));

compiler/rustc_ast_lowering/src/item.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
181181
i: &ItemKind,
182182
) -> hir::ItemKind<'hir> {
183183
match i {
184-
ItemKind::ExternCrate(orig_name) => hir::ItemKind::ExternCrate(*orig_name),
184+
ItemKind::ExternCrate(orig_name) | ItemKind::ExternDynCrate(orig_name) => {
185+
hir::ItemKind::ExternCrate(*orig_name)
186+
}
185187
ItemKind::Use(use_tree) => {
186188
// Start with an empty prefix.
187189
let prefix = Path { segments: ThinVec::new(), span: use_tree.span, tokens: None };
@@ -1184,7 +1186,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
11841186
// create a fake body so that the entire rest of the compiler doesn't have to deal with
11851187
// this as a special case.
11861188
return self.lower_fn_body(decl, contract, |this| {
1187-
if attrs.iter().any(|a| a.name_or_empty() == sym::rustc_intrinsic) {
1189+
if attrs.iter().any(|a| a.name_or_empty() == sym::rustc_intrinsic)
1190+
|| this.tcx.is_interface_build()
1191+
{
11881192
let span = this.lower_span(span);
11891193
let empty_block = hir::Block {
11901194
hir_id: this.next_id(),

compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ struct AstValidator<'a> {
8282
/// Used to ban explicit safety on foreign items when the extern block is not marked as unsafe.
8383
extern_mod_safety: Option<Safety>,
8484

85+
is_interface: bool,
86+
8587
lint_buffer: &'a mut LintBuffer,
8688
}
8789

@@ -922,7 +924,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
922924

923925
let is_intrinsic =
924926
item.attrs.iter().any(|a| a.name_or_empty() == sym::rustc_intrinsic);
925-
if body.is_none() && !is_intrinsic {
927+
if body.is_none() && !is_intrinsic && !self.is_interface {
926928
self.dcx().emit_err(errors::FnWithoutBody {
927929
span: item.span,
928930
replace_span: self.ending_semi_or_hi(item.span),
@@ -1419,7 +1421,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
14191421
});
14201422
}
14211423
AssocItemKind::Fn(box Fn { body, .. }) => {
1422-
if body.is_none() {
1424+
if body.is_none() && !self.is_interface {
14231425
self.dcx().emit_err(errors::AssocFnWithoutBody {
14241426
span: item.span,
14251427
replace_span: self.ending_semi_or_hi(item.span),
@@ -1669,6 +1671,7 @@ pub fn check_crate(
16691671
sess: &Session,
16701672
features: &Features,
16711673
krate: &Crate,
1674+
is_interface: bool,
16721675
lints: &mut LintBuffer,
16731676
) -> bool {
16741677
let mut validator = AstValidator {
@@ -1680,6 +1683,7 @@ pub fn check_crate(
16801683
outer_impl_trait: None,
16811684
disallow_tilde_const: Some(TildeConstReason::Item),
16821685
extern_mod_safety: None,
1686+
is_interface,
16831687
lint_buffer: lints,
16841688
};
16851689
visit::walk_crate(&mut validator, krate);

compiler/rustc_ast_pretty/src/pprust/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ use std::borrow::Cow;
77
use rustc_ast as ast;
88
use rustc_ast::token::{Nonterminal, Token, TokenKind};
99
use rustc_ast::tokenstream::{TokenStream, TokenTree};
10-
pub use state::{AnnNode, Comments, PpAnn, PrintState, State, print_crate};
10+
pub use state::{
11+
AnnNode, Comments, PpAnn, PrintState, State, print_crate, print_crate_as_interface,
12+
};
1113

1214
pub fn nonterminal_to_string(nt: &Nonterminal) -> String {
1315
State::new().nonterminal_to_string(nt)

compiler/rustc_ast_pretty/src/pprust/state.rs

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ pub struct State<'a> {
224224
pub s: pp::Printer,
225225
comments: Option<Comments<'a>>,
226226
ann: &'a (dyn PpAnn + 'a),
227+
is_interface: bool,
227228
}
228229

229230
const INDENT_UNIT: isize = 4;
@@ -240,9 +241,37 @@ pub fn print_crate<'a>(
240241
edition: Edition,
241242
g: &AttrIdGenerator,
242243
) -> String {
243-
let mut s =
244-
State { s: pp::Printer::new(), comments: Some(Comments::new(sm, filename, input)), ann };
244+
let mut s = State {
245+
s: pp::Printer::new(),
246+
comments: Some(Comments::new(sm, filename, input)),
247+
ann,
248+
is_interface: false,
249+
};
250+
251+
print_crate_inner(&mut s, krate, is_expanded, edition, g);
252+
253+
s.ann.post(&mut s, AnnNode::Crate(krate));
254+
s.s.eof()
255+
}
256+
257+
pub fn print_crate_as_interface(
258+
krate: &ast::Crate,
259+
edition: Edition,
260+
g: &AttrIdGenerator,
261+
) -> String {
262+
let mut s = State { s: pp::Printer::new(), comments: None, ann: &NoAnn, is_interface: true };
245263

264+
print_crate_inner(&mut s, krate, false, edition, g);
265+
s.s.eof()
266+
}
267+
268+
fn print_crate_inner<'a>(
269+
s: &mut State<'a>,
270+
krate: &ast::Crate,
271+
is_expanded: bool,
272+
edition: Edition,
273+
g: &AttrIdGenerator,
274+
) {
246275
if is_expanded && !krate.attrs.iter().any(|attr| attr.has_name(sym::no_core)) {
247276
// We need to print `#![no_std]` (and its feature gate) so that
248277
// compiling pretty-printed source won't inject libstd again.
@@ -280,8 +309,6 @@ pub fn print_crate<'a>(
280309
s.print_item(item);
281310
}
282311
s.print_remaining_comments();
283-
s.ann.post(&mut s, AnnNode::Crate(krate));
284-
s.s.eof()
285312
}
286313

287314
/// Should two consecutive tokens be printed with a space between them?
@@ -1086,7 +1113,7 @@ impl<'a> PrintState<'a> for State<'a> {
10861113

10871114
impl<'a> State<'a> {
10881115
pub fn new() -> State<'a> {
1089-
State { s: pp::Printer::new(), comments: None, ann: &NoAnn }
1116+
State { s: pp::Printer::new(), comments: None, ann: &NoAnn, is_interface: false }
10901117
}
10911118

10921119
fn commasep_cmnt<T, F, G>(&mut self, b: Breaks, elts: &[T], mut op: F, mut get_span: G)

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

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use itertools::{Itertools, Position};
33
use rustc_ast as ast;
44
use rustc_ast::ModKind;
55
use rustc_ast::ptr::P;
6-
use rustc_span::Ident;
6+
use rustc_span::{Ident, Symbol};
77

88
use crate::pp::Breaks::Inconsistent;
99
use crate::pprust::state::fixup::FixupContext;
@@ -148,25 +148,42 @@ impl<'a> State<'a> {
148148
self.end(); // end outer head-block
149149
}
150150

151+
fn print_extern_crate(
152+
&mut self,
153+
vis: &ast::Visibility,
154+
head: &str,
155+
ident: Ident,
156+
orig_name: Option<Symbol>,
157+
) {
158+
self.head(visibility_qualified(vis, head));
159+
if let Some(orig_name) = orig_name {
160+
self.print_name(orig_name);
161+
self.space();
162+
self.word("as");
163+
self.space();
164+
}
165+
self.print_ident(ident);
166+
self.word(";");
167+
self.end(); // end inner head-block
168+
self.end(); // end outer head-block
169+
}
170+
151171
/// Pretty-prints an item.
152172
pub(crate) fn print_item(&mut self, item: &ast::Item) {
173+
if self.is_interface && item.span.is_dummy() {
174+
// Do not print prelude for interface files.
175+
return;
176+
}
153177
self.hardbreak_if_not_bol();
154178
self.maybe_print_comment(item.span.lo());
155179
self.print_outer_attributes(&item.attrs);
156180
self.ann.pre(self, AnnNode::Item(item));
157181
match &item.kind {
158182
ast::ItemKind::ExternCrate(orig_name) => {
159-
self.head(visibility_qualified(&item.vis, "extern crate"));
160-
if let &Some(orig_name) = orig_name {
161-
self.print_name(orig_name);
162-
self.space();
163-
self.word("as");
164-
self.space();
165-
}
166-
self.print_ident(item.ident);
167-
self.word(";");
168-
self.end(); // end inner head-block
169-
self.end(); // end outer head-block
183+
self.print_extern_crate(&item.vis, "extern crate", item.ident, *orig_name);
184+
}
185+
ast::ItemKind::ExternDynCrate(orig_name) => {
186+
self.print_extern_crate(&item.vis, "extern dyn crate", item.ident, *orig_name);
170187
}
171188
ast::ItemKind::Use(tree) => {
172189
self.print_visibility(&item.vis);
@@ -661,6 +678,12 @@ impl<'a> State<'a> {
661678
self.nbsp();
662679
self.print_contract(contract);
663680
}
681+
if self.is_interface {
682+
self.word(";");
683+
self.end(); // end inner head-block
684+
self.end(); // end outer head-block
685+
return;
686+
}
664687
if let Some(body) = body {
665688
self.nbsp();
666689
self.print_block_with_attrs(body, attrs);

compiler/rustc_codegen_gcc/src/back/lto.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,11 @@ use crate::{GccCodegenBackend, GccContext, SyncContext, to_gcc_opt_level};
4444

4545
pub fn crate_type_allows_lto(crate_type: CrateType) -> bool {
4646
match crate_type {
47-
CrateType::Executable | CrateType::Dylib | CrateType::Staticlib | CrateType::Cdylib => true,
47+
CrateType::Executable
48+
| CrateType::Dylib
49+
| CrateType::Staticlib
50+
| CrateType::Cdylib
51+
| CrateType::Sdylib => true,
4852
CrateType::Rlib | CrateType::ProcMacro => false,
4953
}
5054
}

compiler/rustc_codegen_llvm/src/back/lto.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ fn crate_type_allows_lto(crate_type: CrateType) -> bool {
4040
| CrateType::Dylib
4141
| CrateType::Staticlib
4242
| CrateType::Cdylib
43-
| CrateType::ProcMacro => true,
43+
| CrateType::ProcMacro
44+
| CrateType::Sdylib => true,
4445
CrateType::Rlib => false,
4546
}
4647
}

0 commit comments

Comments
 (0)