Skip to content

Commit 8111a2d

Browse files
committed
Auto merge of #147397 - Zalathar:rollup-mioe9m4, r=Zalathar
Rollup of 3 pull requests Successful merges: - #146027 (support link modifier `as-needed` for raw-dylib-elf) - #146874 (compiler: Hint at multiple crate versions if trait impl is for wrong ADT ) - #147237 ([rustdoc] Cleanup "highlight::end_expansion") r? `@ghost` `@rustbot` modify labels: rollup
2 parents d2acb42 + c8113a7 commit 8111a2d

File tree

16 files changed

+266
-60
lines changed

16 files changed

+266
-60
lines changed

compiler/rustc_attr_parsing/messages.ftl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
attr_parsing_as_needed_compatibility =
2-
linking modifier `as-needed` is only compatible with `dylib` and `framework` linking kinds
2+
linking modifier `as-needed` is only compatible with `dylib`, `framework` and `raw-dylib` linking kinds
33
44
attr_parsing_bundle_needs_static =
55
linking modifier `bundle` is only compatible with `static` linking kind

compiler/rustc_attr_parsing/src/attributes/link_attrs.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,8 @@ impl<S: Stage> CombineAttributeParser<S> for LinkParser {
180180
}
181181

182182
(sym::as_dash_needed, Some(NativeLibKind::Dylib { as_needed }))
183-
| (sym::as_dash_needed, Some(NativeLibKind::Framework { as_needed })) => {
183+
| (sym::as_dash_needed, Some(NativeLibKind::Framework { as_needed }))
184+
| (sym::as_dash_needed, Some(NativeLibKind::RawDylib { as_needed })) => {
184185
report_unstable_modifier!(native_link_modifiers_as_needed);
185186
assign_modifier(as_needed)
186187
}
@@ -219,12 +220,12 @@ impl<S: Stage> CombineAttributeParser<S> for LinkParser {
219220

220221
// Do this outside of the loop so that `import_name_type` can be specified before `kind`.
221222
if let Some((_, span)) = import_name_type {
222-
if kind != Some(NativeLibKind::RawDylib) {
223+
if !matches!(kind, Some(NativeLibKind::RawDylib { .. })) {
223224
cx.emit_err(ImportNameTypeRaw { span });
224225
}
225226
}
226227

227-
if let Some(NativeLibKind::RawDylib) = kind
228+
if let Some(NativeLibKind::RawDylib { .. }) = kind
228229
&& name.as_str().contains('\0')
229230
{
230231
cx.emit_err(RawDylibNoNul { span: name_span });
@@ -315,7 +316,7 @@ impl LinkParser {
315316
cx.emit_err(RawDylibOnlyWindows { span: nv.value_span });
316317
}
317318

318-
NativeLibKind::RawDylib
319+
NativeLibKind::RawDylib { as_needed: None }
319320
}
320321
sym::link_dash_arg => {
321322
if !features.link_arg_attribute() {

compiler/rustc_codegen_ssa/src/back/link.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1490,7 +1490,7 @@ fn print_native_static_libs(
14901490
NativeLibKind::Static { bundle: None | Some(true), .. }
14911491
| NativeLibKind::LinkArg
14921492
| NativeLibKind::WasmImportModule
1493-
| NativeLibKind::RawDylib => None,
1493+
| NativeLibKind::RawDylib { .. } => None,
14941494
}
14951495
})
14961496
// deduplication of consecutive repeated libraries, see rust-lang/rust#113209
@@ -2364,13 +2364,13 @@ fn linker_with_args(
23642364
cmd.add_object(&output_path);
23652365
}
23662366
} else {
2367-
for link_path in raw_dylib::create_raw_dylib_elf_stub_shared_objects(
2367+
for (link_path, as_needed) in raw_dylib::create_raw_dylib_elf_stub_shared_objects(
23682368
sess,
23692369
codegen_results.crate_info.used_libraries.iter(),
23702370
&raw_dylib_dir,
23712371
) {
23722372
// Always use verbatim linkage, see comments in create_raw_dylib_elf_stub_shared_objects.
2373-
cmd.link_dylib_by_name(&link_path, true, false);
2373+
cmd.link_dylib_by_name(&link_path, true, as_needed);
23742374
}
23752375
}
23762376
// As with add_upstream_native_libraries, we need to add the upstream raw-dylib symbols in case
@@ -2411,13 +2411,13 @@ fn linker_with_args(
24112411
cmd.add_object(&output_path);
24122412
}
24132413
} else {
2414-
for link_path in raw_dylib::create_raw_dylib_elf_stub_shared_objects(
2414+
for (link_path, as_needed) in raw_dylib::create_raw_dylib_elf_stub_shared_objects(
24152415
sess,
24162416
native_libraries_from_nonstatics,
24172417
&raw_dylib_dir,
24182418
) {
24192419
// Always use verbatim linkage, see comments in create_raw_dylib_elf_stub_shared_objects.
2420-
cmd.link_dylib_by_name(&link_path, true, false);
2420+
cmd.link_dylib_by_name(&link_path, true, as_needed);
24212421
}
24222422
}
24232423

@@ -2726,7 +2726,7 @@ fn add_native_libs_from_crate(
27262726
cmd.link_framework_by_name(name, verbatim, as_needed.unwrap_or(true))
27272727
}
27282728
}
2729-
NativeLibKind::RawDylib => {
2729+
NativeLibKind::RawDylib { as_needed: _ } => {
27302730
// Handled separately in `linker_with_args`.
27312731
}
27322732
NativeLibKind::WasmImportModule => {}

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

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ fn collate_raw_dylibs_windows<'a>(
3131
let mut dylib_table = FxIndexMap::<String, FxIndexMap<Symbol, &DllImport>>::default();
3232

3333
for lib in used_libraries {
34-
if lib.kind == NativeLibKind::RawDylib {
34+
if let NativeLibKind::RawDylib { .. } = lib.kind {
3535
let ext = if lib.verbatim { "" } else { ".dll" };
3636
let name = format!("{}{}", lib.name, ext);
3737
let imports = dylib_table.entry(name.clone()).or_default();
@@ -128,12 +128,12 @@ pub(super) fn create_raw_dylib_dll_import_libs<'a>(
128128
fn collate_raw_dylibs_elf<'a>(
129129
sess: &Session,
130130
used_libraries: impl IntoIterator<Item = &'a NativeLib>,
131-
) -> Vec<(String, Vec<DllImport>)> {
131+
) -> Vec<(String, Vec<DllImport>, bool)> {
132132
// Use index maps to preserve original order of imports and libraries.
133-
let mut dylib_table = FxIndexMap::<String, FxIndexMap<Symbol, &DllImport>>::default();
133+
let mut dylib_table = FxIndexMap::<String, (FxIndexMap<Symbol, &DllImport>, bool)>::default();
134134

135135
for lib in used_libraries {
136-
if lib.kind == NativeLibKind::RawDylib {
136+
if let NativeLibKind::RawDylib { as_needed } = lib.kind {
137137
let filename = if lib.verbatim {
138138
lib.name.as_str().to_owned()
139139
} else {
@@ -142,17 +142,19 @@ fn collate_raw_dylibs_elf<'a>(
142142
format!("{prefix}{}{ext}", lib.name)
143143
};
144144

145-
let imports = dylib_table.entry(filename.clone()).or_default();
145+
let (stub_imports, stub_as_needed) =
146+
dylib_table.entry(filename.clone()).or_insert((Default::default(), true));
146147
for import in &lib.dll_imports {
147-
imports.insert(import.name, import);
148+
stub_imports.insert(import.name, import);
148149
}
150+
*stub_as_needed = *stub_as_needed && as_needed.unwrap_or(true);
149151
}
150152
}
151153
sess.dcx().abort_if_errors();
152154
dylib_table
153155
.into_iter()
154-
.map(|(name, imports)| {
155-
(name, imports.into_iter().map(|(_, import)| import.clone()).collect())
156+
.map(|(name, (imports, as_needed))| {
157+
(name, imports.into_iter().map(|(_, import)| import.clone()).collect(), as_needed)
156158
})
157159
.collect()
158160
}
@@ -161,10 +163,10 @@ pub(super) fn create_raw_dylib_elf_stub_shared_objects<'a>(
161163
sess: &Session,
162164
used_libraries: impl IntoIterator<Item = &'a NativeLib>,
163165
raw_dylib_so_dir: &Path,
164-
) -> Vec<String> {
166+
) -> Vec<(String, bool)> {
165167
collate_raw_dylibs_elf(sess, used_libraries)
166168
.into_iter()
167-
.map(|(load_filename, raw_dylib_imports)| {
169+
.map(|(load_filename, raw_dylib_imports, as_needed)| {
168170
use std::hash::Hash;
169171

170172
// `load_filename` is the *target/loader* filename that will end up in NEEDED.
@@ -205,7 +207,7 @@ pub(super) fn create_raw_dylib_elf_stub_shared_objects<'a>(
205207
});
206208
};
207209

208-
temporary_lib_name
210+
(temporary_lib_name, as_needed)
209211
})
210212
.collect()
211213
}

compiler/rustc_hir/src/attrs/data_structures.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,10 @@ pub enum NativeLibKind {
309309
},
310310
/// Dynamic library (e.g. `foo.dll` on Windows) without a corresponding import library.
311311
/// On Linux, it refers to a generated shared library stub.
312-
RawDylib,
312+
RawDylib {
313+
/// Whether the dynamic library will be linked only if it satisfies some undefined symbols
314+
as_needed: Option<bool>,
315+
},
313316
/// A macOS-specific kind of dynamic libraries.
314317
Framework {
315318
/// Whether the framework will be linked only if it satisfies some undefined symbols
@@ -332,11 +335,10 @@ impl NativeLibKind {
332335
NativeLibKind::Static { bundle, whole_archive } => {
333336
bundle.is_some() || whole_archive.is_some()
334337
}
335-
NativeLibKind::Dylib { as_needed } | NativeLibKind::Framework { as_needed } => {
336-
as_needed.is_some()
337-
}
338-
NativeLibKind::RawDylib
339-
| NativeLibKind::Unspecified
338+
NativeLibKind::Dylib { as_needed }
339+
| NativeLibKind::Framework { as_needed }
340+
| NativeLibKind::RawDylib { as_needed } => as_needed.is_some(),
341+
NativeLibKind::Unspecified
340342
| NativeLibKind::LinkArg
341343
| NativeLibKind::WasmImportModule => false,
342344
}
@@ -349,7 +351,9 @@ impl NativeLibKind {
349351
pub fn is_dllimport(&self) -> bool {
350352
matches!(
351353
self,
352-
NativeLibKind::Dylib { .. } | NativeLibKind::RawDylib | NativeLibKind::Unspecified
354+
NativeLibKind::Dylib { .. }
355+
| NativeLibKind::RawDylib { .. }
356+
| NativeLibKind::Unspecified
353357
)
354358
}
355359
}

compiler/rustc_metadata/src/native_libs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ impl<'tcx> Collector<'tcx> {
218218
.flatten()
219219
{
220220
let dll_imports = match attr.kind {
221-
NativeLibKind::RawDylib => foreign_items
221+
NativeLibKind::RawDylib { .. } => foreign_items
222222
.iter()
223223
.map(|&child_item| {
224224
self.build_dll_import(

compiler/rustc_session/src/config/native_libs.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,8 @@ fn parse_and_apply_modifier(cx: &ParseNativeLibCx<'_>, modifier: &str, native_li
135135
),
136136

137137
("as-needed", NativeLibKind::Dylib { as_needed })
138-
| ("as-needed", NativeLibKind::Framework { as_needed }) => {
138+
| ("as-needed", NativeLibKind::Framework { as_needed })
139+
| ("as-needed", NativeLibKind::RawDylib { as_needed }) => {
139140
cx.on_unstable_value(
140141
"linking modifier `as-needed` is unstable",
141142
", the `-Z unstable-options` flag must also be passed to use it",

compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs

Lines changed: 79 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
467467
span,
468468
leaf_trait_predicate,
469469
);
470-
self.note_version_mismatch(&mut err, leaf_trait_predicate);
470+
self.note_trait_version_mismatch(&mut err, leaf_trait_predicate);
471+
self.note_adt_version_mismatch(&mut err, leaf_trait_predicate);
471472
self.suggest_remove_await(&obligation, &mut err);
472473
self.suggest_derive(&obligation, &mut err, leaf_trait_predicate);
473474

@@ -2424,7 +2425,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
24242425
/// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait
24252426
/// with the same path as `trait_ref`, a help message about
24262427
/// a probable version mismatch is added to `err`
2427-
fn note_version_mismatch(
2428+
fn note_trait_version_mismatch(
24282429
&self,
24292430
err: &mut Diag<'_>,
24302431
trait_pred: ty::PolyTraitPredicate<'tcx>,
@@ -2464,15 +2465,87 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
24642465
impl_spans,
24652466
format!("trait impl{} with same name found", pluralize!(trait_impls.len())),
24662467
);
2467-
let trait_crate = self.tcx.crate_name(trait_with_same_path.krate);
2468-
let crate_msg =
2469-
format!("perhaps two different versions of crate `{trait_crate}` are being used?");
2470-
err.note(crate_msg);
2468+
self.note_two_crate_versions(trait_with_same_path, err);
24712469
suggested = true;
24722470
}
24732471
suggested
24742472
}
24752473

2474+
fn note_two_crate_versions(&self, did: DefId, err: &mut Diag<'_>) {
2475+
let crate_name = self.tcx.crate_name(did.krate);
2476+
let crate_msg =
2477+
format!("perhaps two different versions of crate `{crate_name}` are being used?");
2478+
err.note(crate_msg);
2479+
}
2480+
2481+
fn note_adt_version_mismatch(
2482+
&self,
2483+
err: &mut Diag<'_>,
2484+
trait_pred: ty::PolyTraitPredicate<'tcx>,
2485+
) {
2486+
let ty::Adt(impl_self_def, _) = trait_pred.self_ty().skip_binder().peel_refs().kind()
2487+
else {
2488+
return;
2489+
};
2490+
2491+
let impl_self_did = impl_self_def.did();
2492+
2493+
// We only want to warn about different versions of a dependency.
2494+
// If no dependency is involved, bail.
2495+
if impl_self_did.krate == LOCAL_CRATE {
2496+
return;
2497+
}
2498+
2499+
let impl_self_path = self.comparable_path(impl_self_did);
2500+
let impl_self_crate_name = self.tcx.crate_name(impl_self_did.krate);
2501+
let similar_items: UnordSet<_> = self
2502+
.tcx
2503+
.visible_parent_map(())
2504+
.items()
2505+
.filter_map(|(&item, _)| {
2506+
// If we found ourselves, ignore.
2507+
if impl_self_did == item {
2508+
return None;
2509+
}
2510+
// We only want to warn about different versions of a dependency.
2511+
// Ignore items from our own crate.
2512+
if item.krate == LOCAL_CRATE {
2513+
return None;
2514+
}
2515+
// We want to warn about different versions of a dependency.
2516+
// So make sure the crate names are the same.
2517+
if impl_self_crate_name != self.tcx.crate_name(item.krate) {
2518+
return None;
2519+
}
2520+
// Filter out e.g. constructors that often have the same path
2521+
// str as the relevant ADT.
2522+
if !self.tcx.def_kind(item).is_adt() {
2523+
return None;
2524+
}
2525+
let path = self.comparable_path(item);
2526+
// We don't know if our item or the one we found is the re-exported one.
2527+
// Check both cases.
2528+
let is_similar = path.ends_with(&impl_self_path) || impl_self_path.ends_with(&path);
2529+
is_similar.then_some((item, path))
2530+
})
2531+
.collect();
2532+
2533+
let mut similar_items =
2534+
similar_items.into_items().into_sorted_stable_ord_by_key(|(_, path)| path);
2535+
similar_items.dedup();
2536+
2537+
for (similar_item, _) in similar_items {
2538+
err.span_help(self.tcx.def_span(similar_item), "item with same name found");
2539+
self.note_two_crate_versions(similar_item, err);
2540+
}
2541+
}
2542+
2543+
/// Add a `::` prefix when comparing paths so that paths with just one item
2544+
/// like "Foo" does not equal the end of "OtherFoo".
2545+
fn comparable_path(&self, did: DefId) -> String {
2546+
format!("::{}", self.tcx.def_path_str(did))
2547+
}
2548+
24762549
/// Creates a `PredicateObligation` with `new_self_ty` replacing the existing type in the
24772550
/// `trait_ref`.
24782551
///

src/librustdoc/html/highlight.rs

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
use std::borrow::Cow;
99
use std::collections::VecDeque;
1010
use std::fmt::{self, Display, Write};
11-
use std::iter;
11+
use std::{cmp, iter};
1212

1313
use rustc_data_structures::fx::FxIndexMap;
1414
use rustc_lexer::{Cursor, FrontmatterAllowed, LiteralKind, TokenKind};
@@ -345,33 +345,26 @@ fn end_expansion<'a, W: Write>(
345345
token_handler.pending_elems.push((Cow::Borrowed("</span>"), Some(Class::Expansion)));
346346
return Some(expanded_code);
347347
}
348-
if expansion_start_tags.is_empty() && token_handler.closing_tags.is_empty() {
349-
// No need tag opened so we can just close expansion.
350-
token_handler.pending_elems.push((Cow::Borrowed("</span></span>"), Some(Class::Expansion)));
351-
return None;
352-
}
353348

354-
// If tags were opened inside the expansion, we need to close them and re-open them outside
355-
// of the expansion span.
356-
let mut out = String::new();
357-
let mut end = String::new();
349+
let skip = iter::zip(token_handler.closing_tags.as_slice(), expansion_start_tags)
350+
.position(|(tag, start_tag)| tag != start_tag)
351+
.unwrap_or_else(|| cmp::min(token_handler.closing_tags.len(), expansion_start_tags.len()));
358352

359-
let mut closing_tags = token_handler.closing_tags.iter().peekable();
360-
let mut start_closing_tags = expansion_start_tags.iter().peekable();
353+
let tags = iter::chain(
354+
expansion_start_tags.iter().skip(skip),
355+
token_handler.closing_tags.iter().skip(skip),
356+
);
361357

362-
while let (Some(tag), Some(start_tag)) = (closing_tags.peek(), start_closing_tags.peek())
363-
&& tag == start_tag
364-
{
365-
closing_tags.next();
366-
start_closing_tags.next();
358+
let mut elem = Cow::Borrowed("</span></span>");
359+
360+
for (tag, _) in tags.clone() {
361+
elem.to_mut().push_str(tag);
367362
}
368-
for (tag, class) in start_closing_tags.chain(closing_tags) {
369-
out.push_str(tag);
370-
end.push_str(&format!("<span class=\"{}\">", class.as_html()));
363+
for (_, class) in tags {
364+
write!(elem.to_mut(), "<span class=\"{}\">", class.as_html()).unwrap();
371365
}
372-
token_handler
373-
.pending_elems
374-
.push((Cow::Owned(format!("</span></span>{out}{end}")), Some(Class::Expansion)));
366+
367+
token_handler.pending_elems.push((elem, Some(Class::Expansion)));
375368
None
376369
}
377370

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub struct Foo;

0 commit comments

Comments
 (0)