Skip to content

Commit a94b36b

Browse files
committed
Auto merge of #127646 - matthiaskrgr:rollup-51vclzh, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #124944 (On trait bound mismatch, detect multiple crate versions in dep tree) - #124980 (Generalize `fn allocator` for Rc/Arc.) - #126639 (Add AMX target-features and `x86_amx_intrinsics` feature flag) - #126827 (Use pidfd_spawn for faster process spawning when a PidFd is requested) - #127433 (Stabilize const_cstr_from_ptr (CStr::from_ptr, CStr::count_bytes)) - #127613 (Update dist-riscv64-linux to binutils 2.40) r? `@ghost` `@rustbot` modify labels: rollup
2 parents b286722 + 0d3fdbc commit a94b36b

File tree

27 files changed

+710
-77
lines changed

27 files changed

+710
-77
lines changed

compiler/rustc_codegen_ssa/src/target_features.rs

+1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ pub fn from_target_feature(
8080
Some(sym::loongarch_target_feature) => rust_features.loongarch_target_feature,
8181
Some(sym::lahfsahf_target_feature) => rust_features.lahfsahf_target_feature,
8282
Some(sym::prfchw_target_feature) => rust_features.prfchw_target_feature,
83+
Some(sym::x86_amx_intrinsics) => rust_features.x86_amx_intrinsics,
8384
Some(name) => bug!("unknown target feature gate {}", name),
8485
None => true,
8586
};

compiler/rustc_errors/src/diagnostic.rs

+21
Original file line numberDiff line numberDiff line change
@@ -740,6 +740,16 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
740740
self
741741
}
742742

743+
#[rustc_lint_diagnostics]
744+
pub fn highlighted_span_note(
745+
&mut self,
746+
span: impl Into<MultiSpan>,
747+
msg: Vec<StringPart>,
748+
) -> &mut Self {
749+
self.sub_with_highlights(Level::Note, msg, span.into());
750+
self
751+
}
752+
743753
/// This is like [`Diag::note()`], but it's only printed once.
744754
#[rustc_lint_diagnostics]
745755
pub fn note_once(&mut self, msg: impl Into<SubdiagMessage>) -> &mut Self {
@@ -814,6 +824,17 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
814824
self
815825
}
816826

827+
/// Add a help message attached to this diagnostic with a customizable highlighted message.
828+
#[rustc_lint_diagnostics]
829+
pub fn highlighted_span_help(
830+
&mut self,
831+
span: impl Into<MultiSpan>,
832+
msg: Vec<StringPart>,
833+
) -> &mut Self {
834+
self.sub_with_highlights(Level::Help, msg, span.into());
835+
self
836+
}
837+
817838
/// Prints the span with some help above it.
818839
/// This is like [`Diag::help()`], but it gets its own span.
819840
#[rustc_lint_diagnostics]

compiler/rustc_errors/src/emitter.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -1353,7 +1353,7 @@ impl HumanEmitter {
13531353
buffer.append(0, ": ", header_style);
13541354
label_width += 2;
13551355
}
1356-
for (text, _) in msgs.iter() {
1356+
for (text, style) in msgs.iter() {
13571357
let text = self.translate_message(text, args).map_err(Report::new).unwrap();
13581358
// Account for newlines to align output to its label.
13591359
for (line, text) in normalize_whitespace(&text).lines().enumerate() {
@@ -1364,7 +1364,10 @@ impl HumanEmitter {
13641364
if line == 0 { String::new() } else { " ".repeat(label_width) },
13651365
text
13661366
),
1367-
header_style,
1367+
match style {
1368+
Style::Highlight => *style,
1369+
_ => header_style,
1370+
},
13681371
);
13691372
}
13701373
}

compiler/rustc_feature/src/unstable.rs

+2
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,8 @@ declare_features! (
640640
(unstable, unsized_tuple_coercion, "1.20.0", Some(42877)),
641641
/// Allows using the `#[used(linker)]` (or `#[used(compiler)]`) attribute.
642642
(unstable, used_with_arg, "1.60.0", Some(93798)),
643+
/// Allows use of x86 `AMX` target-feature attributes and intrinsics
644+
(unstable, x86_amx_intrinsics, "CURRENT_RUSTC_VERSION", Some(126622)),
643645
/// Allows `do yeet` expressions
644646
(unstable, yeet_expr, "1.62.0", Some(96373)),
645647
// !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2072,6 +2072,7 @@ symbols! {
20722072
write_str,
20732073
write_via_move,
20742074
writeln_macro,
2075+
x86_amx_intrinsics,
20752076
x87_reg,
20762077
xer,
20772078
xmm_reg,

compiler/rustc_target/src/target_features.rs

+5
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,11 @@ const X86_ALLOWED_FEATURES: &[(&str, Stability)] = &[
192192
// tidy-alphabetical-start
193193
("adx", Stable),
194194
("aes", Stable),
195+
("amx-bf16", Unstable(sym::x86_amx_intrinsics)),
196+
("amx-complex", Unstable(sym::x86_amx_intrinsics)),
197+
("amx-fp16", Unstable(sym::x86_amx_intrinsics)),
198+
("amx-int8", Unstable(sym::x86_amx_intrinsics)),
199+
("amx-tile", Unstable(sym::x86_amx_intrinsics)),
195200
("avx", Stable),
196201
("avx2", Stable),
197202
("avx512bf16", Unstable(sym::avx512_target_feature)),

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

+130-42
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@ use core::ops::ControlFlow;
1818
use rustc_data_structures::fx::FxHashMap;
1919
use rustc_data_structures::unord::UnordSet;
2020
use rustc_errors::codes::*;
21-
use rustc_errors::{pluralize, struct_span_code_err, Applicability, StringPart};
22-
use rustc_errors::{Diag, ErrorGuaranteed, StashKey};
21+
use rustc_errors::{
22+
pluralize, struct_span_code_err, Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey,
23+
StringPart,
24+
};
2325
use rustc_hir::def::Namespace;
24-
use rustc_hir::def_id::{DefId, LocalDefId};
26+
use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
2527
use rustc_hir::intravisit::Visitor;
2628
use rustc_hir::Node;
2729
use rustc_hir::{self as hir, LangItem};
@@ -1624,9 +1626,131 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
16241626
other: bool,
16251627
param_env: ty::ParamEnv<'tcx>,
16261628
) -> bool {
1627-
// If we have a single implementation, try to unify it with the trait ref
1628-
// that failed. This should uncover a better hint for what *is* implemented.
1629+
let alternative_candidates = |def_id: DefId| {
1630+
let mut impl_candidates: Vec<_> = self
1631+
.tcx
1632+
.all_impls(def_id)
1633+
// ignore `do_not_recommend` items
1634+
.filter(|def_id| {
1635+
!self
1636+
.tcx
1637+
.has_attrs_with_path(*def_id, &[sym::diagnostic, sym::do_not_recommend])
1638+
})
1639+
// Ignore automatically derived impls and `!Trait` impls.
1640+
.filter_map(|def_id| self.tcx.impl_trait_header(def_id))
1641+
.filter_map(|header| {
1642+
(header.polarity != ty::ImplPolarity::Negative
1643+
|| self.tcx.is_automatically_derived(def_id))
1644+
.then(|| header.trait_ref.instantiate_identity())
1645+
})
1646+
.filter(|trait_ref| {
1647+
let self_ty = trait_ref.self_ty();
1648+
// Avoid mentioning type parameters.
1649+
if let ty::Param(_) = self_ty.kind() {
1650+
false
1651+
}
1652+
// Avoid mentioning types that are private to another crate
1653+
else if let ty::Adt(def, _) = self_ty.peel_refs().kind() {
1654+
// FIXME(compiler-errors): This could be generalized, both to
1655+
// be more granular, and probably look past other `#[fundamental]`
1656+
// types, too.
1657+
self.tcx.visibility(def.did()).is_accessible_from(body_def_id, self.tcx)
1658+
} else {
1659+
true
1660+
}
1661+
})
1662+
.collect();
1663+
1664+
impl_candidates.sort_by_key(|tr| tr.to_string());
1665+
impl_candidates.dedup();
1666+
impl_candidates
1667+
};
1668+
1669+
// We'll check for the case where the reason for the mismatch is that the trait comes from
1670+
// one crate version and the type comes from another crate version, even though they both
1671+
// are from the same crate.
1672+
let trait_def_id = trait_ref.def_id();
1673+
if let ty::Adt(def, _) = trait_ref.self_ty().skip_binder().peel_refs().kind()
1674+
&& let found_type = def.did()
1675+
&& trait_def_id.krate != found_type.krate
1676+
&& self.tcx.crate_name(trait_def_id.krate) == self.tcx.crate_name(found_type.krate)
1677+
{
1678+
let name = self.tcx.crate_name(trait_def_id.krate);
1679+
let spans: Vec<_> = [trait_def_id, found_type]
1680+
.into_iter()
1681+
.filter_map(|def_id| self.tcx.extern_crate(def_id))
1682+
.map(|data| {
1683+
let dependency = if data.dependency_of == LOCAL_CRATE {
1684+
"direct dependency of the current crate".to_string()
1685+
} else {
1686+
let dep = self.tcx.crate_name(data.dependency_of);
1687+
format!("dependency of crate `{dep}`")
1688+
};
1689+
(
1690+
data.span,
1691+
format!("one version of crate `{name}` is used here, as a {dependency}"),
1692+
)
1693+
})
1694+
.collect();
1695+
let mut span: MultiSpan = spans.iter().map(|(sp, _)| *sp).collect::<Vec<Span>>().into();
1696+
for (sp, label) in spans.into_iter() {
1697+
span.push_span_label(sp, label);
1698+
}
1699+
err.highlighted_span_help(
1700+
span,
1701+
vec![
1702+
StringPart::normal("you have ".to_string()),
1703+
StringPart::highlighted("multiple different versions".to_string()),
1704+
StringPart::normal(" of crate `".to_string()),
1705+
StringPart::highlighted(format!("{name}")),
1706+
StringPart::normal("` in your dependency graph".to_string()),
1707+
],
1708+
);
1709+
let candidates = if impl_candidates.is_empty() {
1710+
alternative_candidates(trait_def_id)
1711+
} else {
1712+
impl_candidates.into_iter().map(|cand| cand.trait_ref).collect()
1713+
};
1714+
if let Some((sp_candidate, sp_found)) = candidates.iter().find_map(|trait_ref| {
1715+
if let ty::Adt(def, _) = trait_ref.self_ty().peel_refs().kind()
1716+
&& let candidate_def_id = def.did()
1717+
&& let Some(name) = self.tcx.opt_item_name(candidate_def_id)
1718+
&& let Some(found) = self.tcx.opt_item_name(found_type)
1719+
&& name == found
1720+
&& candidate_def_id.krate != found_type.krate
1721+
&& self.tcx.crate_name(candidate_def_id.krate)
1722+
== self.tcx.crate_name(found_type.krate)
1723+
{
1724+
// A candidate was found of an item with the same name, from two separate
1725+
// versions of the same crate, let's clarify.
1726+
Some((self.tcx.def_span(candidate_def_id), self.tcx.def_span(found_type)))
1727+
} else {
1728+
None
1729+
}
1730+
}) {
1731+
let mut span: MultiSpan = vec![sp_candidate, sp_found].into();
1732+
span.push_span_label(self.tcx.def_span(trait_def_id), "this is the required trait");
1733+
span.push_span_label(sp_candidate, "this type implements the required trait");
1734+
span.push_span_label(sp_found, "this type doesn't implement the required trait");
1735+
err.highlighted_span_note(
1736+
span,
1737+
vec![
1738+
StringPart::normal(
1739+
"two types coming from two different versions of the same crate are \
1740+
different types "
1741+
.to_string(),
1742+
),
1743+
StringPart::highlighted("even if they look the same".to_string()),
1744+
],
1745+
);
1746+
}
1747+
err.help("you can use `cargo tree` to explore your dependency tree");
1748+
return true;
1749+
}
1750+
16291751
if let [single] = &impl_candidates {
1752+
// If we have a single implementation, try to unify it with the trait ref
1753+
// that failed. This should uncover a better hint for what *is* implemented.
16301754
if self.probe(|_| {
16311755
let ocx = ObligationCtxt::new(self);
16321756

@@ -1798,43 +1922,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
17981922
// Mentioning implementers of `Copy`, `Debug` and friends is not useful.
17991923
return false;
18001924
}
1801-
let mut impl_candidates: Vec<_> = self
1802-
.tcx
1803-
.all_impls(def_id)
1804-
// ignore `do_not_recommend` items
1805-
.filter(|def_id| {
1806-
!self
1807-
.tcx
1808-
.has_attrs_with_path(*def_id, &[sym::diagnostic, sym::do_not_recommend])
1809-
})
1810-
// Ignore automatically derived impls and `!Trait` impls.
1811-
.filter_map(|def_id| self.tcx.impl_trait_header(def_id))
1812-
.filter_map(|header| {
1813-
(header.polarity != ty::ImplPolarity::Negative
1814-
|| self.tcx.is_automatically_derived(def_id))
1815-
.then(|| header.trait_ref.instantiate_identity())
1816-
})
1817-
.filter(|trait_ref| {
1818-
let self_ty = trait_ref.self_ty();
1819-
// Avoid mentioning type parameters.
1820-
if let ty::Param(_) = self_ty.kind() {
1821-
false
1822-
}
1823-
// Avoid mentioning types that are private to another crate
1824-
else if let ty::Adt(def, _) = self_ty.peel_refs().kind() {
1825-
// FIXME(compiler-errors): This could be generalized, both to
1826-
// be more granular, and probably look past other `#[fundamental]`
1827-
// types, too.
1828-
self.tcx.visibility(def.did()).is_accessible_from(body_def_id, self.tcx)
1829-
} else {
1830-
true
1831-
}
1832-
})
1833-
.collect();
1834-
1835-
impl_candidates.sort_by_key(|tr| tr.to_string());
1836-
impl_candidates.dedup();
1837-
return report(impl_candidates, err);
1925+
return report(alternative_candidates(def_id), err);
18381926
}
18391927

18401928
// Sort impl candidates so that ordering is consistent for UI tests.

library/alloc/src/rc.rs

+18-10
Original file line numberDiff line numberDiff line change
@@ -665,16 +665,6 @@ impl<T> Rc<T> {
665665
}
666666

667667
impl<T, A: Allocator> Rc<T, A> {
668-
/// Returns a reference to the underlying allocator.
669-
///
670-
/// Note: this is an associated function, which means that you have
671-
/// to call it as `Rc::allocator(&r)` instead of `r.allocator()`. This
672-
/// is so that there is no conflict with a method on the inner type.
673-
#[inline]
674-
#[unstable(feature = "allocator_api", issue = "32838")]
675-
pub fn allocator(this: &Self) -> &A {
676-
&this.alloc
677-
}
678668
/// Constructs a new `Rc` in the provided allocator.
679669
///
680670
/// # Examples
@@ -1331,6 +1321,17 @@ impl<T: ?Sized> Rc<T> {
13311321
}
13321322

13331323
impl<T: ?Sized, A: Allocator> Rc<T, A> {
1324+
/// Returns a reference to the underlying allocator.
1325+
///
1326+
/// Note: this is an associated function, which means that you have
1327+
/// to call it as `Rc::allocator(&r)` instead of `r.allocator()`. This
1328+
/// is so that there is no conflict with a method on the inner type.
1329+
#[inline]
1330+
#[unstable(feature = "allocator_api", issue = "32838")]
1331+
pub fn allocator(this: &Self) -> &A {
1332+
&this.alloc
1333+
}
1334+
13341335
/// Consumes the `Rc`, returning the wrapped pointer.
13351336
///
13361337
/// To avoid a memory leak the pointer must be converted back to an `Rc` using
@@ -2994,6 +2995,13 @@ impl<T: ?Sized> Weak<T> {
29942995
}
29952996

29962997
impl<T: ?Sized, A: Allocator> Weak<T, A> {
2998+
/// Returns a reference to the underlying allocator.
2999+
#[inline]
3000+
#[unstable(feature = "allocator_api", issue = "32838")]
3001+
pub fn allocator(&self) -> &A {
3002+
&self.alloc
3003+
}
3004+
29973005
/// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`.
29983006
///
29993007
/// The pointer is valid only if there are some strong references. The pointer may be dangling,

library/alloc/src/sync.rs

+18-10
Original file line numberDiff line numberDiff line change
@@ -677,16 +677,6 @@ impl<T> Arc<T> {
677677
}
678678

679679
impl<T, A: Allocator> Arc<T, A> {
680-
/// Returns a reference to the underlying allocator.
681-
///
682-
/// Note: this is an associated function, which means that you have
683-
/// to call it as `Arc::allocator(&a)` instead of `a.allocator()`. This
684-
/// is so that there is no conflict with a method on the inner type.
685-
#[inline]
686-
#[unstable(feature = "allocator_api", issue = "32838")]
687-
pub fn allocator(this: &Self) -> &A {
688-
&this.alloc
689-
}
690680
/// Constructs a new `Arc<T>` in the provided allocator.
691681
///
692682
/// # Examples
@@ -1470,6 +1460,17 @@ impl<T: ?Sized> Arc<T> {
14701460
}
14711461

14721462
impl<T: ?Sized, A: Allocator> Arc<T, A> {
1463+
/// Returns a reference to the underlying allocator.
1464+
///
1465+
/// Note: this is an associated function, which means that you have
1466+
/// to call it as `Arc::allocator(&a)` instead of `a.allocator()`. This
1467+
/// is so that there is no conflict with a method on the inner type.
1468+
#[inline]
1469+
#[unstable(feature = "allocator_api", issue = "32838")]
1470+
pub fn allocator(this: &Self) -> &A {
1471+
&this.alloc
1472+
}
1473+
14731474
/// Consumes the `Arc`, returning the wrapped pointer.
14741475
///
14751476
/// To avoid a memory leak the pointer must be converted back to an `Arc` using
@@ -2715,6 +2716,13 @@ impl<T: ?Sized> Weak<T> {
27152716
}
27162717

27172718
impl<T: ?Sized, A: Allocator> Weak<T, A> {
2719+
/// Returns a reference to the underlying allocator.
2720+
#[inline]
2721+
#[unstable(feature = "allocator_api", issue = "32838")]
2722+
pub fn allocator(&self) -> &A {
2723+
&self.alloc
2724+
}
2725+
27182726
/// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`.
27192727
///
27202728
/// The pointer is valid only if there are some strong references. The pointer may be dangling,

0 commit comments

Comments
 (0)