Skip to content

Rollup of 7 pull requests #142817

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Jun 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
367c8fe
fix(linkcheck): Build using the lockfile
epage Jun 20, 2025
6a9f223
Add diagnostic items for Clippy
samueltardieu Jun 20, 2025
07338a4
clippy: replace path uses by diagnostic items
samueltardieu Jun 20, 2025
8d18f3d
add doc(alias("AsciiChar")) to core::ascii::Char
lolbinarycat Jun 20, 2025
a32d085
error on calls to ABIs that cannot be called
folkertdev Jun 16, 2025
890ade5
Bless UI tests: do not print alternate implementors of `Step`
samueltardieu Jun 20, 2025
78c2ef2
compiler: Rename LayoutS to LayoutData in comments
zachs18 Jun 20, 2025
a7ff98e
rust-analyzer: Rename LayoutS to LayoutData in comments
zachs18 Jun 20, 2025
48060c9
Use gen blocks in the compiler instead of from_coroutine
compiler-errors Jun 20, 2025
2b5fd9a
rustdoc_json: Add static asserts for the size of important types.
nnethercote Jun 14, 2025
18d742b
rustdoc_json: Add a test for some `GenericArgs` cases.
nnethercote Jun 15, 2025
40ba791
rustdoc_json: Fix handling of paths with no generic args.
nnethercote Jun 14, 2025
59a3399
Fix some comments.
nnethercote Jun 14, 2025
7fa8901
rustdoc_json: represent generic args consistently.
nnethercote Jun 14, 2025
5f72706
Rollup merge of #142502 - nnethercote:rustdoc-json-GenericArgs, r=aDo…
matthiaskrgr Jun 21, 2025
504092f
Rollup merge of #142597 - folkertdev:abi-cannot-be-called, r=workingj…
matthiaskrgr Jun 21, 2025
06cc41b
Rollup merge of #142785 - epage:link, r=ehuss
matthiaskrgr Jun 21, 2025
24f797e
Rollup merge of #142787 - samueltardieu:diag-items-for-clippy, r=Mani…
matthiaskrgr Jun 21, 2025
1176413
Rollup merge of #142788 - lolbinarycat:core-AsciiChar-alias, r=tgross35
matthiaskrgr Jun 21, 2025
6a49a35
Rollup merge of #142801 - compiler-errors:gen-blocks, r=oli-obk
matthiaskrgr Jun 21, 2025
4e87031
Rollup merge of #142804 - zachs18:rename-layouts-to-layoutdata-in-com…
matthiaskrgr Jun 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions compiler/rustc_abi/src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
align = align.min(AbiAlign::new(pack));
}
// The unadjusted ABI alignment does not include repr(align), but does include repr(pack).
// See documentation on `LayoutS::unadjusted_abi_align`.
// See documentation on `LayoutData::unadjusted_abi_align`.
let unadjusted_abi_align = align.abi;
if let Some(repr_align) = repr.align {
align = align.max(AbiAlign::new(repr_align));
Expand Down Expand Up @@ -602,10 +602,10 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
dont_niche_optimize_enum: bool,
) -> LayoutCalculatorResult<FieldIdx, VariantIdx, F> {
// Until we've decided whether to use the tagged or
// niche filling LayoutS, we don't want to intern the
// niche filling LayoutData, we don't want to intern the
// variant layouts, so we can't store them in the
// overall LayoutS. Store the overall LayoutS
// and the variant LayoutSs here until then.
// overall LayoutData. Store the overall LayoutData
// and the variant LayoutDatas here until then.
struct TmpLayout<FieldIdx: Idx, VariantIdx: Idx> {
layout: LayoutData<FieldIdx, VariantIdx>,
variants: IndexVec<VariantIdx, LayoutData<FieldIdx, VariantIdx>>,
Expand Down Expand Up @@ -1214,7 +1214,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {

match kind {
StructKind::AlwaysSized | StructKind::MaybeUnsized => {
// Currently `LayoutS` only exposes a single niche so sorting is usually
// Currently `LayoutData` only exposes a single niche so sorting is usually
// sufficient to get one niche into the preferred position. If it ever
// supported multiple niches then a more advanced pick-and-pack approach could
// provide better results. But even for the single-niche cache it's not
Expand Down Expand Up @@ -1333,7 +1333,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
}

// The unadjusted ABI alignment does not include repr(align), but does include repr(pack).
// See documentation on `LayoutS::unadjusted_abi_align`.
// See documentation on `LayoutData::unadjusted_abi_align`.
let unadjusted_abi_align = align.abi;
if let Some(repr_align) = repr.align {
align = align.max(AbiAlign::new(repr_align));
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_abi/src/layout/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ pub struct Layout<'a>(pub Interned<'a, LayoutData<FieldIdx, VariantIdx>>);

impl<'a> fmt::Debug for Layout<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// See comment on `<LayoutS as Debug>::fmt` above.
// See comment on `<LayoutData as Debug>::fmt` above.
self.0.0.fmt(f)
}
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_abi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1785,7 +1785,7 @@ where
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// This is how `Layout` used to print before it become
// `Interned<LayoutS>`. We print it like this to avoid having to update
// `Interned<LayoutData>`. We print it like this to avoid having to update
// expected output in a lot of tests.
let LayoutData {
size,
Expand Down
132 changes: 64 additions & 68 deletions compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2177,84 +2177,80 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
/// Walk the generics of the item for a trait bound whose self type
/// corresponds to the expected res, and return the trait def id.
fn for_each_trait_bound_on_res(&self, expected_res: Res) -> impl Iterator<Item = DefId> {
std::iter::from_coroutine(
#[coroutine]
move || {
let mut scope = self.scope;
loop {
let hir_id = match *scope {
Scope::Binder { hir_id, .. } => Some(hir_id),
Scope::Root { opt_parent_item: Some(parent_def_id) } => {
Some(self.tcx.local_def_id_to_hir_id(parent_def_id))
}
Scope::Body { .. }
| Scope::ObjectLifetimeDefault { .. }
| Scope::Supertrait { .. }
| Scope::TraitRefBoundary { .. }
| Scope::LateBoundary { .. }
| Scope::Opaque { .. }
| Scope::Root { opt_parent_item: None } => None,
};
gen move {
let mut scope = self.scope;
loop {
let hir_id = match *scope {
Scope::Binder { hir_id, .. } => Some(hir_id),
Scope::Root { opt_parent_item: Some(parent_def_id) } => {
Some(self.tcx.local_def_id_to_hir_id(parent_def_id))
}
Scope::Body { .. }
| Scope::ObjectLifetimeDefault { .. }
| Scope::Supertrait { .. }
| Scope::TraitRefBoundary { .. }
| Scope::LateBoundary { .. }
| Scope::Opaque { .. }
| Scope::Root { opt_parent_item: None } => None,
};

if let Some(hir_id) = hir_id {
let node = self.tcx.hir_node(hir_id);
// If this is a `Self` bound in a trait, yield the trait itself.
// Specifically, we don't need to look at any supertraits since
// we already do that in `BoundVarContext::supertrait_hrtb_vars`.
if let Res::SelfTyParam { trait_: _ } = expected_res
&& let hir::Node::Item(item) = node
&& let hir::ItemKind::Trait(..) = item.kind
{
// Yield the trait's def id. Supertraits will be
// elaborated from that.
yield item.owner_id.def_id.to_def_id();
} else if let Some(generics) = node.generics() {
for pred in generics.predicates {
let hir::WherePredicateKind::BoundPredicate(pred) = pred.kind
else {
continue;
};
let hir::TyKind::Path(hir::QPath::Resolved(None, bounded_path)) =
pred.bounded_ty.kind
else {
continue;
};
// Match the expected res.
if bounded_path.res != expected_res {
continue;
}
for pred in pred.bounds {
match pred {
hir::GenericBound::Trait(poly_trait_ref) => {
if let Some(def_id) =
poly_trait_ref.trait_ref.trait_def_id()
{
yield def_id;
}
if let Some(hir_id) = hir_id {
let node = self.tcx.hir_node(hir_id);
// If this is a `Self` bound in a trait, yield the trait itself.
// Specifically, we don't need to look at any supertraits since
// we already do that in `BoundVarContext::supertrait_hrtb_vars`.
if let Res::SelfTyParam { trait_: _ } = expected_res
&& let hir::Node::Item(item) = node
&& let hir::ItemKind::Trait(..) = item.kind
{
// Yield the trait's def id. Supertraits will be
// elaborated from that.
yield item.owner_id.def_id.to_def_id();
} else if let Some(generics) = node.generics() {
for pred in generics.predicates {
let hir::WherePredicateKind::BoundPredicate(pred) = pred.kind else {
continue;
};
let hir::TyKind::Path(hir::QPath::Resolved(None, bounded_path)) =
pred.bounded_ty.kind
else {
continue;
};
// Match the expected res.
if bounded_path.res != expected_res {
continue;
}
for pred in pred.bounds {
match pred {
hir::GenericBound::Trait(poly_trait_ref) => {
if let Some(def_id) =
poly_trait_ref.trait_ref.trait_def_id()
{
yield def_id;
}
hir::GenericBound::Outlives(_)
| hir::GenericBound::Use(_, _) => {}
}
hir::GenericBound::Outlives(_)
| hir::GenericBound::Use(_, _) => {}
}
}
}
}
}

match *scope {
Scope::Binder { s, .. }
| Scope::Body { s, .. }
| Scope::ObjectLifetimeDefault { s, .. }
| Scope::Supertrait { s, .. }
| Scope::TraitRefBoundary { s }
| Scope::LateBoundary { s, .. }
| Scope::Opaque { s, .. } => {
scope = s;
}
Scope::Root { .. } => break,
match *scope {
Scope::Binder { s, .. }
| Scope::Body { s, .. }
| Scope::ObjectLifetimeDefault { s, .. }
| Scope::Supertrait { s, .. }
| Scope::TraitRefBoundary { s }
| Scope::LateBoundary { s, .. }
| Scope::Opaque { s, .. } => {
scope = s;
}
Scope::Root { .. } => break,
}
},
)
}
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ This API is completely unstable and subject to change.
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(assert_matches)]
#![feature(coroutines)]
#![feature(debug_closure_helpers)]
#![feature(gen_blocks)]
#![feature(if_let_guard)]
#![feature(iter_from_coroutine)]
#![feature(iter_intersperse)]
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_hir_typeck/messages.ftl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
hir_typeck_abi_custom_call =
functions with the `"custom"` ABI cannot be called
.note = an `extern "custom"` function can only be called from within inline assembly
hir_typeck_abi_cannot_be_called =
functions with the {$abi} ABI cannot be called
.note = an `extern {$abi}` function can only be called using inline assembly
hir_typeck_add_missing_parentheses_in_range = you must surround the range in parentheses to call its `{$func_name}` function
Expand Down
54 changes: 42 additions & 12 deletions compiler/rustc_hir_typeck/src/callee.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::iter;

use rustc_abi::ExternAbi;
use rustc_abi::{CanonAbi, ExternAbi};
use rustc_ast::util::parser::ExprPrecedence;
use rustc_errors::{Applicability, Diag, ErrorGuaranteed, StashKey};
use rustc_hir::def::{self, CtorKind, Namespace, Res};
Expand All @@ -16,6 +16,7 @@ use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt};
use rustc_middle::{bug, span_bug};
use rustc_span::def_id::LocalDefId;
use rustc_span::{Span, sym};
use rustc_target::spec::{AbiMap, AbiMapping};
use rustc_trait_selection::error_reporting::traits::DefIdOrName;
use rustc_trait_selection::infer::InferCtxtExt as _;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
Expand Down Expand Up @@ -84,7 +85,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
while result.is_none() && autoderef.next().is_some() {
result = self.try_overloaded_call_step(call_expr, callee_expr, arg_exprs, &autoderef);
}
self.check_call_custom_abi(autoderef.final_ty(false), call_expr.span);

match autoderef.final_ty(false).kind() {
ty::FnDef(def_id, _) => {
let abi = self.tcx.fn_sig(def_id).skip_binder().skip_binder().abi;
self.check_call_abi(abi, call_expr.span);
}
ty::FnPtr(_, header) => {
self.check_call_abi(header.abi, call_expr.span);
}
_ => { /* cannot have a non-rust abi */ }
}

self.register_predicates(autoderef.into_obligations());

let output = match result {
Expand Down Expand Up @@ -137,19 +149,37 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
output
}

/// Functions of type `extern "custom" fn(/* ... */)` cannot be called using `ExprKind::Call`.
/// Can a function with this ABI be called with a rust call expression?
///
/// These functions have a calling convention that is unknown to rust, hence it cannot generate
/// code for the call. The only way to execute such a function is via inline assembly.
fn check_call_custom_abi(&self, callee_ty: Ty<'tcx>, span: Span) {
let abi = match callee_ty.kind() {
ty::FnDef(def_id, _) => self.tcx.fn_sig(def_id).skip_binder().skip_binder().abi,
ty::FnPtr(_, header) => header.abi,
_ => return,
/// Some ABIs cannot be called from rust, either because rust does not know how to generate
/// code for the call, or because a call does not semantically make sense.
pub(crate) fn check_call_abi(&self, abi: ExternAbi, span: Span) {
let canon_abi = match AbiMap::from_target(&self.sess().target).canonize_abi(abi, false) {
AbiMapping::Direct(canon_abi) | AbiMapping::Deprecated(canon_abi) => canon_abi,
AbiMapping::Invalid => return,
};

let valid = match canon_abi {
// Rust doesn't know how to call functions with this ABI.
CanonAbi::Custom => false,

// These is an entry point for the host, and cannot be called on the GPU.
CanonAbi::GpuKernel => false,

// The interrupt ABIs should only be called by the CPU. They have complex
// pre- and postconditions, and can use non-standard instructions like `iret` on x86.
CanonAbi::Interrupt(_) => false,

CanonAbi::C
| CanonAbi::Rust
| CanonAbi::RustCold
| CanonAbi::Arm(_)
| CanonAbi::X86(_) => true,
};

if let ExternAbi::Custom = abi {
self.tcx.dcx().emit_err(errors::AbiCustomCall { span });
if !valid {
let err = crate::errors::AbiCannotBeCalled { span, abi };
self.tcx.dcx().emit_err(err);
}
}

Expand Down
7 changes: 5 additions & 2 deletions compiler/rustc_hir_typeck/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
use std::borrow::Cow;

use rustc_abi::ExternAbi;
use rustc_ast::Label;
use rustc_errors::codes::*;
use rustc_errors::{
Expand Down Expand Up @@ -1159,8 +1160,10 @@ pub(crate) struct NakedFunctionsMustNakedAsm {
}

#[derive(Diagnostic)]
#[diag(hir_typeck_abi_custom_call)]
pub(crate) struct AbiCustomCall {
#[diag(hir_typeck_abi_cannot_be_called)]
pub(crate) struct AbiCannotBeCalled {
#[primary_span]
#[note]
pub span: Span,
pub abi: ExternAbi,
}
10 changes: 2 additions & 8 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
//!
//! See [`rustc_hir_analysis::check`] for more context on type checking in general.
use rustc_abi::{ExternAbi, FIRST_VARIANT, FieldIdx};
use rustc_abi::{FIRST_VARIANT, FieldIdx};
use rustc_ast::util::parser::ExprPrecedence;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::stack::ensure_sufficient_stack;
Expand Down Expand Up @@ -1650,13 +1650,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Some(method.def_id),
);

// Functions of type `extern "custom" fn(/* ... */)` cannot be called using
// `ExprKind::MethodCall`. These functions have a calling convention that is
// unknown to rust, hence it cannot generate code for the call. The only way
// to execute such a function is via inline assembly.
if let ExternAbi::Custom = method.sig.abi {
self.tcx.dcx().emit_err(crate::errors::AbiCustomCall { span: expr.span });
}
self.check_call_abi(method.sig.abi, expr.span);

method.sig.output()
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_metadata/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
#![allow(internal_features)]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(coroutines)]
#![feature(decl_macro)]
#![feature(error_iter)]
#![feature(file_buffered)]
#![feature(gen_blocks)]
#![feature(if_let_guard)]
#![feature(iter_from_coroutine)]
#![feature(macro_metavar_expr)]
Expand Down
Loading
Loading