Skip to content
Open
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
f51fb91
kcfi: only reify trait methods when dyn-compatible
folkertdev Sep 21, 2025
ce20876
Add a new `wasm32-wasip3` target to Rust
alexcrichton Sep 30, 2025
7e1c00d
Prevent downstream impl DerefMut for Pin<LocalType>
Darksonn Sep 17, 2025
cd44cd0
Improve docs for module
Darksonn Sep 25, 2025
f65250b
Document workaround in docs
Darksonn Sep 29, 2025
76dcb39
Adjust error messages
Darksonn Oct 1, 2025
bc930cd
collect-license-metadata: Print a diff of the expected output
jyn514 Oct 6, 2025
525ed4c
Read the whole test file before parsing directives
Zalathar Oct 7, 2025
a3ba8d8
Use globals instead of metadata, since metadata isn't emitted in debu…
ZuseZ4 Oct 6, 2025
5f9ee17
add incremental/debug test for autodiff
ZuseZ4 Oct 6, 2025
6ce845a
update ui test since the new frontend is a bit more lenient
ZuseZ4 Oct 6, 2025
0fe466c
Fix doc comment
theemathas Oct 7, 2025
43f7eaa
Fix; correct placement of type inference error for method calls
Jamesbarford Oct 6, 2025
1fb7f3d
Rollup merge of #145608 - Darksonn:derefmut-pin-fix, r=lcnr
Zalathar Oct 7, 2025
b222013
Rollup merge of #146865 - folkertdev:kcfi-only-reify-dyn-compatible, …
Zalathar Oct 7, 2025
fe7add8
Rollup merge of #147205 - alexcrichton:wasip3, r=davidtwco
Zalathar Oct 7, 2025
605e3e1
Rollup merge of #147390 - ZuseZ4:autodiff-dbg, r=jieyouxu
Zalathar Oct 7, 2025
79ad10e
Rollup merge of #147398 - Jamesbarford:fix/method-call-type-inference…
Zalathar Oct 7, 2025
9211c44
Rollup merge of #147422 - jyn514:license-diff, r=Kobzol
Zalathar Oct 7, 2025
32404a3
Rollup merge of #147431 - Zalathar:directive, r=jieyouxu
Zalathar Oct 7, 2025
d9904b8
Rollup merge of #147433 - theemathas:theemathas-patch-1, r=chenyukang
Zalathar Oct 7, 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
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,7 @@ dependencies = [
"anyhow",
"serde",
"serde_json",
"similar",
"spdx-rs",
]

Expand Down
52 changes: 28 additions & 24 deletions compiler/rustc_codegen_llvm/src/builder/autodiff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::builder::{Builder, PlaceRef, UNNAMED};
use crate::context::SimpleCx;
use crate::declare::declare_simple_fn;
use crate::llvm;
use crate::llvm::{Metadata, TRUE, Type};
use crate::llvm::{TRUE, Type};
use crate::value::Value;

pub(crate) fn adjust_activity_to_abi<'tcx>(
Expand Down Expand Up @@ -159,32 +159,36 @@ fn match_args_from_caller_to_enzyme<'ll, 'tcx>(
let mut outer_pos: usize = 0;
let mut activity_pos = 0;

let enzyme_const = cx.create_metadata(b"enzyme_const");
let enzyme_out = cx.create_metadata(b"enzyme_out");
let enzyme_dup = cx.create_metadata(b"enzyme_dup");
let enzyme_dupv = cx.create_metadata(b"enzyme_dupv");
let enzyme_dupnoneed = cx.create_metadata(b"enzyme_dupnoneed");
let enzyme_dupnoneedv = cx.create_metadata(b"enzyme_dupnoneedv");
// We used to use llvm's metadata to instruct enzyme how to differentiate a function.
// In debug mode we would use incremental compilation which caused the metadata to be
// dropped. This is prevented by now using named globals, which are also understood
// by Enzyme.
let global_const = cx.declare_global("enzyme_const", cx.type_ptr());
let global_out = cx.declare_global("enzyme_out", cx.type_ptr());
let global_dup = cx.declare_global("enzyme_dup", cx.type_ptr());
let global_dupv = cx.declare_global("enzyme_dupv", cx.type_ptr());
let global_dupnoneed = cx.declare_global("enzyme_dupnoneed", cx.type_ptr());
let global_dupnoneedv = cx.declare_global("enzyme_dupnoneedv", cx.type_ptr());

while activity_pos < inputs.len() {
let diff_activity = inputs[activity_pos as usize];
// Duplicated arguments received a shadow argument, into which enzyme will write the
// gradient.
let (activity, duplicated): (&Metadata, bool) = match diff_activity {
let (activity, duplicated): (&llvm::Value, bool) = match diff_activity {
DiffActivity::None => panic!("not a valid input activity"),
DiffActivity::Const => (enzyme_const, false),
DiffActivity::Active => (enzyme_out, false),
DiffActivity::ActiveOnly => (enzyme_out, false),
DiffActivity::Dual => (enzyme_dup, true),
DiffActivity::Dualv => (enzyme_dupv, true),
DiffActivity::DualOnly => (enzyme_dupnoneed, true),
DiffActivity::DualvOnly => (enzyme_dupnoneedv, true),
DiffActivity::Duplicated => (enzyme_dup, true),
DiffActivity::DuplicatedOnly => (enzyme_dupnoneed, true),
DiffActivity::FakeActivitySize(_) => (enzyme_const, false),
DiffActivity::Const => (global_const, false),
DiffActivity::Active => (global_out, false),
DiffActivity::ActiveOnly => (global_out, false),
DiffActivity::Dual => (global_dup, true),
DiffActivity::Dualv => (global_dupv, true),
DiffActivity::DualOnly => (global_dupnoneed, true),
DiffActivity::DualvOnly => (global_dupnoneedv, true),
DiffActivity::Duplicated => (global_dup, true),
DiffActivity::DuplicatedOnly => (global_dupnoneed, true),
DiffActivity::FakeActivitySize(_) => (global_const, false),
};
let outer_arg = outer_args[outer_pos];
args.push(cx.get_metadata_value(activity));
args.push(activity);
if matches!(diff_activity, DiffActivity::Dualv) {
let next_outer_arg = outer_args[outer_pos + 1];
let elem_bytes_size: u64 = match inputs[activity_pos + 1] {
Expand Down Expand Up @@ -244,7 +248,7 @@ fn match_args_from_caller_to_enzyme<'ll, 'tcx>(
assert_eq!(cx.type_kind(next_outer_ty3), TypeKind::Integer);
args.push(next_outer_arg2);
}
args.push(cx.get_metadata_value(enzyme_const));
args.push(global_const);
args.push(next_outer_arg);
outer_pos += 2 + 2 * iterations;
activity_pos += 2;
Expand Down Expand Up @@ -353,13 +357,13 @@ pub(crate) fn generate_enzyme_call<'ll, 'tcx>(
let mut args = Vec::with_capacity(num_args as usize + 1);
args.push(fn_to_diff);

let enzyme_primal_ret = cx.create_metadata(b"enzyme_primal_return");
let global_primal_ret = cx.declare_global("enzyme_primal_return", cx.type_ptr());
if matches!(attrs.ret_activity, DiffActivity::Dual | DiffActivity::Active) {
args.push(cx.get_metadata_value(enzyme_primal_ret));
args.push(global_primal_ret);
}
if attrs.width > 1 {
let enzyme_width = cx.create_metadata(b"enzyme_width");
args.push(cx.get_metadata_value(enzyme_width));
let global_width = cx.declare_global("enzyme_width", cx.type_ptr());
args.push(global_width);
args.push(cx.get_const_int(cx.type_i64(), attrs.width as u64));
}

Expand Down
21 changes: 16 additions & 5 deletions compiler/rustc_hir_typeck/src/method/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ use rustc_attr_parsing::is_doc_alias_attrs_contain_symbol;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::sso::SsoHashSet;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::HirId;
use rustc_hir::def::DefKind;
use rustc_hir::{self as hir, ExprKind, HirId, Node};
use rustc_hir_analysis::autoderef::{self, Autoderef};
use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk, TyCtxtInferExt};
Expand Down Expand Up @@ -486,13 +485,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let ty = self.resolve_vars_if_possible(ty.value);
let guar = match *ty.kind() {
ty::Infer(ty::TyVar(_)) => {
// We want to get the variable name that the method
// is being called on. If it is a method call.
let err_span = match (mode, self.tcx.hir_node(scope_expr_id)) {
(
Mode::MethodCall,
Node::Expr(hir::Expr {
kind: ExprKind::MethodCall(_, recv, ..),
..
}),
) => recv.span,
_ => span,
};

let raw_ptr_call = bad_ty.reached_raw_pointer
&& !self.tcx.features().arbitrary_self_types();
// FIXME: Ideally we'd use the span of the self-expr here,
// not of the method path.

let mut err = self.err_ctxt().emit_inference_failure_err(
self.body_id,
span,
err_span,
ty.into(),
TypeAnnotationNeeded::E0282,
!raw_ptr_call,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/thir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -839,7 +839,7 @@ pub enum PatKind<'tcx> {
/// exhaustiveness to cover exactly its own value, similar to `&str`, but these values are
/// much simpler.
/// * raw pointers derived from integers, other raw pointers will have already resulted in an
// error.
/// error.
/// * `String`, if `string_deref_patterns` is enabled.
Constant {
value: ty::Value<'tcx>,
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_middle/src/ty/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -618,11 +618,11 @@ impl<'tcx> Instance<'tcx> {
// be directly reified because it's closure-like. The reify can handle the
// unresolved instance.
resolved = Instance { def: InstanceKind::ReifyShim(def_id, reason), args }
// Reify `Trait::method` implementations
// FIXME(maurer) only reify it if it is a vtable-safe function
// Reify `Trait::method` implementations if the trait is dyn-compatible.
} else if let Some(assoc) = tcx.opt_associated_item(def_id)
&& let AssocContainer::Trait | AssocContainer::TraitImpl(Ok(_)) =
assoc.container
&& tcx.is_dyn_compatible(assoc.container_id(tcx))
{
// If this function could also go in a vtable, we need to `ReifyShim` it with
// KCFI because it can only attach one type per function.
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ symbols! {
PathBuf,
Pending,
PinCoerceUnsized,
PinDerefMutHelper,
Pointer,
Poll,
ProcMacro,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_target/src/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1624,6 +1624,7 @@ supported_targets! {
("wasm32v1-none", wasm32v1_none),
("wasm32-wasip1", wasm32_wasip1),
("wasm32-wasip2", wasm32_wasip2),
("wasm32-wasip3", wasm32_wasip3),
("wasm32-wasip1-threads", wasm32_wasip1_threads),
("wasm32-wali-linux-musl", wasm32_wali_linux_musl),
("wasm64-unknown-unknown", wasm64_unknown_unknown),
Expand Down
20 changes: 20 additions & 0 deletions compiler/rustc_target/src/spec/targets/wasm32_wasip3.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//! The `wasm32-wasip3` target is the next in the chain of `wasm32-wasip1`, then
//! `wasm32-wasip2`, then WASIp3. The main feature of WASIp3 is native async
//! support in the component model itself.
//!
//! Like `wasm32-wasip2` this target produces a component by default. Support
//! for `wasm32-wasip3` is very early as of the time of this writing so
//! components produced will still import WASIp2 APIs, but that's ok since it's
//! all component-model-level imports anyway. Over time the imports of the
//! standard library will change to WASIp3.

use crate::spec::Target;

pub(crate) fn target() -> Target {
// As of now WASIp3 is a lightly edited wasip2 target, so start with that
// and this may grow over time as more features are supported.
let mut target = super::wasm32_wasip2::target();
target.llvm_target = "wasm32-wasip3".into();
target.options.env = "p3".into();
target
}
Original file line number Diff line number Diff line change
Expand Up @@ -3476,6 +3476,24 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
// can do about it. As far as they are concerned, `?` is compiler magic.
return;
}
if tcx.is_diagnostic_item(sym::PinDerefMutHelper, parent_def_id) {
let parent_predicate =
self.resolve_vars_if_possible(data.derived.parent_trait_pred);

// Skip PinDerefMutHelper in suggestions, but still show downstream suggestions.
ensure_sufficient_stack(|| {
self.note_obligation_cause_code(
body_id,
err,
parent_predicate,
param_env,
&data.derived.parent_code,
obligated_types,
seen_requirements,
)
});
return;
}
let self_ty_str =
tcx.short_string(parent_trait_pred.skip_binder().self_ty(), err.long_ty_path());
let trait_name = tcx.short_string(
Expand Down
82 changes: 81 additions & 1 deletion library/core/src/pin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1689,9 +1689,89 @@ impl<Ptr: [const] Deref> const Deref for Pin<Ptr> {
}
}

mod helper {
/// Helper that prevents downstream crates from implementing `DerefMut` for `Pin`.
///
/// The `Pin` type implements the unsafe trait `PinCoerceUnsized`, which essentially requires
/// that the type does not have a malicious `Deref` or `DerefMut` impl. However, without this
/// helper module, downstream crates are able to write `impl DerefMut for Pin<LocalType>` as
/// long as it does not overlap with the impl provided by stdlib. This is because `Pin` is
/// `#[fundamental]`, so stdlib promises to never implement traits for `Pin` that it does not
/// implement today.
///
/// However, this is problematic. Downstream crates could implement `DerefMut` for
/// `Pin<&LocalType>`, and they could do so maliciously. To prevent this, the implementation for
/// `Pin` delegates to this helper module. Since `helper::Pin` is not `#[fundamental]`, the
/// orphan rules assume that stdlib might implement `helper::DerefMut` for `helper::Pin<&_>` in
/// the future. Because of this, downstream crates can no longer provide an implementation of
/// `DerefMut` for `Pin<&_>`, as it might overlap with a trait impl that, according to the
/// orphan rules, the stdlib could introduce without a breaking change in a future release.
///
/// See <https://github.com/rust-lang/rust/issues/85099> for the issue this fixes.
#[repr(transparent)]
#[unstable(feature = "pin_derefmut_internals", issue = "none")]
#[allow(missing_debug_implementations)]
pub struct PinHelper<Ptr> {
pointer: Ptr,
}

#[unstable(feature = "pin_derefmut_internals", issue = "none")]
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
#[rustc_diagnostic_item = "PinDerefMutHelper"]
pub const trait PinDerefMutHelper {
type Target: ?Sized;
fn deref_mut(&mut self) -> &mut Self::Target;
}

#[unstable(feature = "pin_derefmut_internals", issue = "none")]
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
impl<Ptr: [const] super::DerefMut> const PinDerefMutHelper for PinHelper<Ptr>
where
Ptr::Target: crate::marker::Unpin,
{
type Target = Ptr::Target;

#[inline(always)]
fn deref_mut(&mut self) -> &mut Ptr::Target {
&mut self.pointer
}
}
}

#[stable(feature = "pin", since = "1.33.0")]
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
impl<Ptr: [const] DerefMut<Target: Unpin>> const DerefMut for Pin<Ptr> {
#[cfg(not(doc))]
impl<Ptr> const DerefMut for Pin<Ptr>
where
Ptr: [const] Deref,
helper::PinHelper<Ptr>: [const] helper::PinDerefMutHelper<Target = Self::Target>,
{
#[inline]
fn deref_mut(&mut self) -> &mut Ptr::Target {
// SAFETY: Pin and PinHelper have the same layout, so this is equivalent to
// `&mut self.pointer` which is safe because `Target: Unpin`.
helper::PinDerefMutHelper::deref_mut(unsafe {
&mut *(self as *mut Pin<Ptr> as *mut helper::PinHelper<Ptr>)
})
}
}

/// The `Target` type is restricted to `Unpin` types as it's not safe to obtain a mutable reference
/// to a pinned value.
///
/// For soundness reasons, implementations of `DerefMut` for `Pin<T>` are rejected even when `T` is
/// a local type not covered by this impl block. (Since `Pin` is [fundamental], such implementations
/// would normally be possible.)
///
/// [fundamental]: ../../reference/items/implementations.html#r-items.impl.trait.fundamental
#[stable(feature = "pin", since = "1.33.0")]
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
#[cfg(doc)]
impl<Ptr> const DerefMut for Pin<Ptr>
where
Ptr: [const] DerefMut,
<Ptr as Deref>::Target: Unpin,
{
fn deref_mut(&mut self) -> &mut Ptr::Target {
Pin::get_mut(Pin::as_mut(self))
}
Expand Down
5 changes: 5 additions & 0 deletions library/std/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@ wasip2 = { version = '0.14.4', features = [
'rustc-dep-of-std',
], default-features = false, package = 'wasi' }

[target.'cfg(all(target_os = "wasi", target_env = "p3"))'.dependencies]
wasip2 = { version = '0.14.4', features = [
'rustc-dep-of-std',
], default-features = false, package = 'wasi' }

[target.'cfg(target_os = "uefi")'.dependencies]
r-efi = { version = "5.2.0", features = ['rustc-dep-of-std'] }
r-efi-alloc = { version = "2.0.0", features = ['rustc-dep-of-std'] }
Expand Down
2 changes: 1 addition & 1 deletion library/std/src/os/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ pub mod linux;
all(target_vendor = "fortanix", target_env = "sgx")
)
)))]
#[cfg(any(target_os = "wasi", doc))]
#[cfg(any(target_os = "wasi", any(target_env = "p1", target_env = "p2"), doc))]
pub mod wasi;

#[cfg(any(all(target_os = "wasi", target_env = "p2"), doc))]
Expand Down
2 changes: 1 addition & 1 deletion library/std/src/sys/args/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ cfg_select! {
mod wasip1;
pub use wasip1::*;
}
all(target_os = "wasi", target_env = "p2") => {
all(target_os = "wasi", any(target_env = "p2", target_env = "p3")) => {
mod wasip2;
pub use wasip2::*;
}
Expand Down
2 changes: 1 addition & 1 deletion library/std/src/sys/net/connection/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ cfg_select! {
all(target_family = "unix", not(target_os = "l4re")),
target_os = "windows",
target_os = "hermit",
all(target_os = "wasi", target_env = "p2"),
all(target_os = "wasi", any(target_env = "p2", target_env = "p3")),
target_os = "solid_asp3",
) => {
mod socket;
Expand Down
2 changes: 1 addition & 1 deletion library/std/src/sys/net/connection/socket/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ cfg_select! {
mod unix;
pub use unix::*;
}
all(target_os = "wasi", target_env = "p2") => {
all(target_os = "wasi", any(target_env = "p2", target_env = "p3")) => {
mod wasip2;
pub use wasip2::*;
}
Expand Down
2 changes: 1 addition & 1 deletion library/std/src/sys/pal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ cfg_select! {
mod vexos;
pub use self::vexos::*;
}
all(target_os = "wasi", target_env = "p2") => {
all(target_os = "wasi", any(target_env = "p2", target_env = "p3")) => {
mod wasip2;
pub use self::wasip2::*;
}
Expand Down
4 changes: 2 additions & 2 deletions library/std/src/sys/random/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ cfg_select! {
mod wasip1;
pub use wasip1::fill_bytes;
}
all(target_os = "wasi", target_env = "p2") => {
all(target_os = "wasi", any(target_env = "p2", target_env = "p3")) => {
mod wasip2;
pub use wasip2::{fill_bytes, hashmap_random_keys};
}
Expand All @@ -115,7 +115,7 @@ cfg_select! {
target_os = "linux",
target_os = "android",
all(target_family = "wasm", target_os = "unknown"),
all(target_os = "wasi", target_env = "p2"),
all(target_os = "wasi", not(target_env = "p1")),
target_os = "xous",
target_os = "vexos",
)))]
Expand Down
2 changes: 1 addition & 1 deletion library/std/src/sys/stdio/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ cfg_select! {
mod wasip1;
pub use wasip1::*;
}
all(target_os = "wasi", target_env = "p2") => {
all(target_os = "wasi", any(target_env = "p2", target_env = "p3")) => {
mod wasip2;
pub use wasip2::*;
}
Expand Down
Loading
Loading