Skip to content

Commit 4c9d2bf

Browse files
committed
Auto merge of #158663 - JonathanBrouwer:rollup-vypSRyC, r=JonathanBrouwer
Rollup of 8 pull requests Successful merges: - #158294 (Use .drectve for MSVC DLL exports) - #156716 (tests: fix: parallel frontend test failures: different alloc ids) - #158397 (delegation: support simplest output `Self` mapping) - #158613 (Fix getrandom fallback test on platforms with `panic=abort`) - #158620 (Remove skip_norm_w/i/p().def_id with a helper) - #158633 (Remove unnecessary `Clone` derives on resolver types) - #158634 (Add missing `needs_drop` check to `DroplessArena`.) - #158647 (Document `strip_circumfix` behavior on overlapping prefix and suffix.)
2 parents e2b71ad + ddf0d0f commit 4c9d2bf

132 files changed

Lines changed: 1818 additions & 678 deletions

File tree

Some content is hidden

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

‎compiler/rustc_arena/src/lib.rs‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -542,11 +542,12 @@ impl DroplessArena {
542542

543543
#[inline]
544544
pub fn alloc_from_iter<T, I: IntoIterator<Item = T>>(&self, iter: I) -> &mut [T] {
545+
assert!(!mem::needs_drop::<T>());
546+
assert!(size_of::<T>() != 0);
547+
545548
// Warning: this function is reentrant: `iter` could hold a reference to `&self` and
546549
// allocate additional elements while we're iterating.
547550
let iter = iter.into_iter();
548-
assert!(size_of::<T>() != 0);
549-
assert!(!mem::needs_drop::<T>());
550551

551552
let size_hint = iter.size_hint();
552553

@@ -577,6 +578,7 @@ impl DroplessArena {
577578
) -> Result<&mut [T], E> {
578579
// Despite the similarity with `alloc_from_iter`, we cannot reuse their fast case, as we
579580
// cannot know the minimum length of the iterator in this case.
581+
assert!(!mem::needs_drop::<T>());
580582
assert!(size_of::<T>() != 0);
581583

582584
// Takes care of reentrancy.

‎compiler/rustc_ast_lowering/src/delegation.rs‎

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ use rustc_middle::span_bug;
5353
use rustc_middle::ty::{Asyncness, PerOwnerResolverData};
5454
use rustc_span::def_id::{DefId, LocalDefId};
5555
use rustc_span::symbol::kw;
56-
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol};
56+
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, sym};
5757

5858
use crate::delegation::generics::{
5959
GenericsGenerationResult, GenericsGenerationResults, GenericsPosition,
@@ -664,11 +664,34 @@ impl<'hir> LoweringContext<'_, 'hir> {
664664

665665
let callee_path = self.arena.alloc(self.mk_expr(hir::ExprKind::Path(new_path), span));
666666
let args = self.arena.alloc_from_iter(args);
667-
let call = self.arena.alloc(self.mk_expr(hir::ExprKind::Call(callee_path, args), span));
667+
let call = self.mk_expr(hir::ExprKind::Call(callee_path, args), span);
668+
669+
let expr = if let Some((parent, of_trait)) = self.should_wrap_return_value(delegation) {
670+
let res = Res::SelfTyAlias { alias_to: parent.to_def_id(), is_trait_impl: of_trait };
671+
let ident = Ident::new(kw::SelfUpper, span);
672+
let path = self.create_resolved_path(res, ident, span);
673+
674+
// FIXME(fn_delegation): add default `..` for all other fields.
675+
let initializer = hir::ExprKind::Struct(
676+
self.arena.alloc(path),
677+
self.arena.alloc_slice(&[hir::ExprField {
678+
hir_id: self.next_id(),
679+
is_shorthand: false,
680+
ident: Ident::new(sym::integer(0), span),
681+
expr: self.arena.alloc(call),
682+
span,
683+
}]),
684+
hir::StructTailExpr::None,
685+
);
686+
687+
self.arena.alloc(self.mk_expr(initializer, span))
688+
} else {
689+
self.arena.alloc(call)
690+
};
668691

669692
let block = self.arena.alloc(hir::Block {
670693
stmts,
671-
expr: Some(call),
694+
expr: Some(expr),
672695
hir_id: self.next_id(),
673696
rules: hir::BlockCheckMode::DefaultBlock,
674697
span,
@@ -678,6 +701,45 @@ impl<'hir> LoweringContext<'_, 'hir> {
678701
(self.mk_expr(hir::ExprKind::Block(block, None), span), call.hir_id)
679702
}
680703

704+
fn should_wrap_return_value(&self, delegation: &Delegation) -> Option<(LocalDefId, bool)> {
705+
// Heuristic: don't do wrapping if there is no target expression.
706+
if delegation.body.is_none() {
707+
return None;
708+
}
709+
710+
let tcx = self.tcx;
711+
let parent = tcx.local_parent(self.owner.def_id);
712+
let parent_kind = tcx.def_kind(parent);
713+
714+
// Apply wrapping for delegations inside
715+
// 1) Trait impls, as the return type of both signature function
716+
// and generated delegation has `Self` generic param returned
717+
// (checked below).
718+
// FIXME(fn_delegation): think of enabling wrapping in more scenarios:
719+
// trait-(impl)-to-free
720+
// trait-(impl)-to-inherent
721+
// inherent-to-free
722+
// 2) Inherent methods when delegating to trait, as we change the type of
723+
// `Self` to type of struct or enum we delegate from.
724+
if !matches!(tcx.def_kind(parent), DefKind::Impl { .. }) {
725+
return None;
726+
}
727+
728+
let is_trait_impl = parent_kind == DefKind::Impl { of_trait: true };
729+
730+
// Check that delegation path resolves to a trait AssocFn, not to a free method.
731+
Some((parent, is_trait_impl)).filter(|_| {
732+
self.get_resolution_id(delegation.id).is_some_and(|id| {
733+
tcx.def_kind(id) == DefKind::AssocFn
734+
// Check that the return type of the callee is `Self` param.
735+
// After previous check we are sure that `sig_id` and `delegation.id`
736+
// point to the same function.
737+
&& tcx.def_kind(tcx.parent(id)) == DefKind::Trait
738+
&& tcx.fn_sig(id).skip_binder().output().skip_binder().is_param(0)
739+
})
740+
})
741+
}
742+
681743
fn process_segment(
682744
&mut self,
683745
span: Span,

‎compiler/rustc_ast_lowering/src/delegation/generics.rs‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -588,19 +588,28 @@ impl<'hir> LoweringContext<'_, 'hir> {
588588
p.def_id.to_def_id(),
589589
);
590590

591+
self.create_resolved_path(res, p.name.ident(), p.span)
592+
}
593+
594+
pub(super) fn create_resolved_path(
595+
&mut self,
596+
res: Res,
597+
ident: Ident,
598+
span: Span,
599+
) -> hir::QPath<'hir> {
591600
hir::QPath::Resolved(
592601
None,
593602
self.arena.alloc(hir::Path {
594603
segments: self.arena.alloc_slice(&[hir::PathSegment {
595604
args: None,
596605
hir_id: self.next_id(),
597-
ident: p.name.ident(),
606+
ident,
598607
infer_args: false,
599608
res,
600609
delegation_child_segment: false,
601610
}]),
602611
res,
603-
span: p.span,
612+
span,
604613
}),
605614
)
606615
}

‎compiler/rustc_codegen_ssa/src/back/link.rs‎

Lines changed: 59 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,10 @@ use super::rmeta_link::RmetaLinkCache;
6363
use super::rpath::{self, RPathConfig};
6464
use super::{apple, rmeta_link, versioned_llvm_target};
6565
use crate::base::needs_allocator_shim_for_linking;
66-
use crate::{CodegenLintLevelSpecs, CompiledModule, CompiledModules, CrateInfo, NativeLib, errors};
66+
use crate::{
67+
CodegenLintLevelSpecs, CompiledModule, CompiledModules, CrateInfo, NativeLib, SymbolExport,
68+
errors,
69+
};
6770

6871
pub fn ensure_removed(dcx: DiagCtxtHandle<'_>, path: &Path) {
6972
if let Err(e) = fs::remove_file(path) {
@@ -593,7 +596,7 @@ fn link_staticlib(
593596
crate_info
594597
.exported_symbols
595598
.get(&CrateType::StaticLib)
596-
.map(|symbols| symbols.iter().map(|(s, _)| s.clone()).collect())
599+
.map(|symbols| symbols.iter().map(|symbol| symbol.name.clone()).collect())
597600
}
598601
} else {
599602
None
@@ -2196,9 +2199,15 @@ fn add_linked_symbol_object(
21962199
cmd: &mut dyn Linker,
21972200
sess: &Session,
21982201
tmpdir: &Path,
2199-
symbols: &[(String, SymbolExportKind)],
2202+
crate_type: CrateType,
2203+
linked_symbols: &[(String, SymbolExportKind)],
2204+
exported_symbols: &[SymbolExport],
22002205
) {
2201-
if symbols.is_empty() {
2206+
let should_export_symbols = sess.target.is_like_msvc
2207+
&& !exported_symbols.is_empty()
2208+
&& (crate_type != CrateType::Executable
2209+
|| sess.opts.unstable_opts.export_executable_symbols);
2210+
if linked_symbols.is_empty() && !should_export_symbols {
22022211
return;
22032212
}
22042213

@@ -2235,7 +2244,7 @@ fn add_linked_symbol_object(
22352244
None
22362245
};
22372246

2238-
for (sym, kind) in symbols.iter() {
2247+
for (sym, kind) in linked_symbols.iter() {
22392248
let symbol = file.add_symbol(object::write::Symbol {
22402249
name: sym.clone().into(),
22412250
value: 0,
@@ -2293,6 +2302,37 @@ fn add_linked_symbol_object(
22932302
}
22942303
}
22952304

2305+
if should_export_symbols {
2306+
// Currently the compiler doesn't use `dllexport` (an LLVM attribute) to
2307+
// export symbols from a dynamic library. When building a dynamic library,
2308+
// however, we're going to want some symbols exported, so this adds a
2309+
// `.drectve` section which lists all the symbols using /EXPORT arguments.
2310+
//
2311+
// The linker will read these arguments from the `.drectve` section and
2312+
// export all the symbols from the dynamic library. Note that this is not
2313+
// as simple as just exporting all the symbols in the current crate (as
2314+
// specified by `codegen.reachable`) but rather we also need to possibly
2315+
// export the symbols of upstream crates. Upstream rlibs may be linked
2316+
// statically to this dynamic library, in which case they may continue to
2317+
// transitively be used and hence need their symbols exported.
2318+
fn msvc_drectve_export(symbol: &SymbolExport) -> String {
2319+
let data = if symbol.kind == SymbolExportKind::Data { ",DATA" } else { "" };
2320+
2321+
if let Some(link_name) = symbol.link_name.as_deref() {
2322+
// The first name is the decorated symbol used by the import library, while
2323+
// EXPORTAS gives the public name written to the DLL export table.
2324+
format!(" /EXPORT:\"{link_name}\"{data},EXPORTAS,\"{}\"", symbol.name)
2325+
} else {
2326+
format!(" /EXPORT:\"{}\"{data}", symbol.name)
2327+
}
2328+
}
2329+
2330+
let drectve = exported_symbols.iter().map(msvc_drectve_export).collect::<String>();
2331+
2332+
let section = file.add_section(vec![], b".drectve".to_vec(), object::SectionKind::Linker);
2333+
file.append_section_data(section, drectve.as_bytes(), 1);
2334+
}
2335+
22962336
let path = tmpdir.join("symbols.o");
22972337
let result = std::fs::write(&path, file.write().unwrap());
22982338
if let Err(error) = result {
@@ -2486,7 +2526,7 @@ fn undecorate_c_symbol<'a>(
24862526
fn add_c_staticlib_symbols(
24872527
sess: &Session,
24882528
lib: &NativeLib,
2489-
out: &mut Vec<(String, SymbolExportKind)>,
2529+
out: &mut Vec<SymbolExport>,
24902530
) -> io::Result<()> {
24912531
let file_path = find_native_static_library(lib.name.as_str(), lib.verbatim, sess);
24922532

@@ -2549,7 +2589,11 @@ fn add_c_staticlib_symbols(
25492589
let Some(undecorated) = undecorate_c_symbol(name, sess, export_kind) else {
25502590
continue;
25512591
};
2552-
out.push((undecorated.to_string(), export_kind));
2592+
out.push(SymbolExport::with_link_name(
2593+
undecorated.to_string(),
2594+
export_kind,
2595+
name.to_string(),
2596+
));
25532597
}
25542598
}
25552599

@@ -2629,7 +2673,14 @@ fn linker_with_args(
26292673
// Pre-link CRT objects.
26302674
add_pre_link_objects(cmd, sess, flavor, link_output_kind, self_contained_crt_objects);
26312675

2632-
add_linked_symbol_object(cmd, sess, tmpdir, &crate_info.linked_symbols[&crate_type]);
2676+
add_linked_symbol_object(
2677+
cmd,
2678+
sess,
2679+
tmpdir,
2680+
crate_type,
2681+
&crate_info.linked_symbols[&crate_type],
2682+
&export_symbols,
2683+
);
26332684

26342685
// Sanitizer libraries.
26352686
add_sanitizer_libraries(sess, flavor, crate_type, cmd);

0 commit comments

Comments
 (0)