Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
bc6c103
mailmap: add redddy
reddevilmidzy Feb 18, 2026
fe7dc48
Add UI test for duplicate `requirement` diag args in compare-impl-item
TaKO8Ki Feb 24, 2026
3f76a0d
avoid duplicate `requirement` diag args in `RegionOriginNote`
TaKO8Ki Feb 24, 2026
5b99fcd
Revert "Move aarch64-apple dist builder to dynamic llvm linking and e…
RalfJung Feb 25, 2026
508801c
Pass the `QueryVTable` to functions that were taking `execute_query_fn`
Zalathar Feb 25, 2026
cd7bbac
Add some docs for `QueryVTable::execute_query_fn`
Zalathar Feb 25, 2026
fb42537
Rename some query plumbing to match `QueryVTable::execute_query_fn`
Zalathar Feb 26, 2026
6ba5b1a
Move `trait DepNodeKey`.
nnethercote Feb 18, 2026
fbea6dd
Rename `trait Key` as `trait `QueryKey`
nnethercote Feb 18, 2026
b284b04
Remove unnecessary `Clone` bounds.
nnethercote Feb 18, 2026
4499407
Merge `trait QueryCacheKey` into `trait QueryKey`.
nnethercote Feb 18, 2026
9ba101f
Rename `Storage` as `Cache`.
nnethercote Feb 18, 2026
5edbf6a
Remove unused `TyCtxt::emit_node_lint` method
GuillaumeGomez Feb 25, 2026
4803bb9
Replace `TyCtxt::node_span_lint` with `emit_node_span_lint` in `rustc…
GuillaumeGomez Feb 25, 2026
3f71fd0
Add new `LintContext::opt_span_diag_lint` and `LintContext::emit_diag…
GuillaumeGomez Feb 25, 2026
bca1cb4
Replace `emit_span_lint` with `emit_span_diag_lint` in `rustc_lint`
GuillaumeGomez Feb 25, 2026
b409cb1
Replace `emit_span_lint` with `emit_span_diag_lint` in `rustc_lint`
GuillaumeGomez Feb 25, 2026
90c93ab
Move `rustc_ast::AutoDiffAttrs` to `rustc_hir::RustcAutodiff`
JonathanBrouwer Feb 22, 2026
f9b70f0
Migrate `rustc_lint::EqInternalMethodImplemented` to `Diagnostic`
GuillaumeGomez Feb 26, 2026
5cd5b90
Port `rustc_autodiff` to the attribute parsers
JonathanBrouwer Feb 22, 2026
d5b6474
Remove attributes from check_attr that were already parsed
JonathanBrouwer Feb 25, 2026
7aa4f04
Rollup merge of #153079 - RalfJung:revert-macos-dyn, r=jieyouxu
JonathanBrouwer Feb 26, 2026
81aa532
Rollup merge of #152651 - TaKO8Ki:fix-143872-compare-impl-item-diag-a…
JonathanBrouwer Feb 26, 2026
51492d0
Rollup merge of #152978 - JonathanBrouwer:autodiff_attrs, r=jdonszelmann
JonathanBrouwer Feb 26, 2026
c902bc1
Rollup merge of #153091 - GuillaumeGomez:migrate-diag, r=JonathanBrouwer
JonathanBrouwer Feb 26, 2026
8386f94
Rollup merge of #153112 - nnethercote:query-key-stuff, r=nnethercote
JonathanBrouwer Feb 26, 2026
272d523
Rollup merge of #153118 - reddevilmidzy:mailmap, r=jieyouxu
JonathanBrouwer Feb 26, 2026
3eafea8
Rollup merge of #153120 - Zalathar:execute, r=nnethercote
JonathanBrouwer Feb 26, 2026
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
3 changes: 3 additions & 0 deletions .mailmap
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,9 @@ Ralph Giles <giles@thaumas.net> Ralph Giles <giles@mozilla.com>
Ramkumar Ramachandra <r@artagnon.com> <artagnon@gmail.com>
Raphaël Huchet <rap2hpoutre@users.noreply.github.com>
rChaser53 <tayoshizawa29@gmail.com>
Redddy <rust@redddy.com>
Redddy <rust@redddy.com> <midzy0228@gmail.com>
Redddy <rust@redddy.com> <78539407+reddevilmidzy@users.noreply.github.com>
Rémy Rakic <remy.rakic@gmail.com>
Rémy Rakic <remy.rakic@gmail.com> <remy.rakic+github@gmail.com>
Rémy Rakic <remy.rakic@gmail.com> <remy.rakic+rust@gmail.com>
Expand Down
116 changes: 22 additions & 94 deletions compiler/rustc_ast/src/expand/autodiff_attrs.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
//! This crate handles the user facing autodiff macro. For each `#[autodiff(...)]` attribute,
//! we create an [`AutoDiffItem`] which contains the source and target function names. The source
//! we create an `RustcAutodiff` which contains the source and target function names. The source
//! is the function to which the autodiff attribute is applied, and the target is the function
//! getting generated by us (with a name given by the user as the first autodiff arg).

use std::fmt::{self, Display, Formatter};
use std::str::FromStr;

use crate::expand::typetree::TypeTree;
use rustc_span::{Symbol, sym};

use crate::expand::{Decodable, Encodable, HashStable_Generic};
use crate::{Ty, TyKind};

Expand All @@ -31,6 +32,12 @@ pub enum DiffMode {
Reverse,
}

impl DiffMode {
pub fn all_modes() -> &'static [Symbol] {
&[sym::Source, sym::Forward, sym::Reverse]
}
}

/// Dual and Duplicated (and their Only variants) are getting lowered to the same Enzyme Activity.
/// However, under forward mode we overwrite the previous shadow value, while for reverse mode
/// we add to the previous shadow value. To not surprise users, we picked different names.
Expand Down Expand Up @@ -76,43 +83,20 @@ impl DiffActivity {
use DiffActivity::*;
matches!(self, |Dual| DualOnly | Dualv | DualvOnly | Const)
}
}
/// We generate one of these structs for each `#[autodiff(...)]` attribute.
#[derive(Clone, Eq, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct AutoDiffItem {
/// The name of the function getting differentiated
pub source: String,
/// The name of the function being generated
pub target: String,
pub attrs: AutoDiffAttrs,
pub inputs: Vec<TypeTree>,
pub output: TypeTree,
}

#[derive(Clone, Eq, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct AutoDiffAttrs {
/// Conceptually either forward or reverse mode AD, as described in various autodiff papers and
/// e.g. in the [JAX
/// Documentation](https://jax.readthedocs.io/en/latest/_tutorials/advanced-autodiff.html#how-it-s-made-two-foundational-autodiff-functions).
pub mode: DiffMode,
/// A user-provided, batching width. If not given, we will default to 1 (no batching).
/// Calling a differentiated, non-batched function through a loop 100 times is equivalent to:
/// - Calling the function 50 times with a batch size of 2
/// - Calling the function 25 times with a batch size of 4,
/// etc. A batched function takes more (or longer) arguments, and might be able to benefit from
/// cache locality, better re-usal of primal values, and other optimizations.
/// We will (before LLVM's vectorizer runs) just generate most LLVM-IR instructions `width`
/// times, so this massively increases code size. As such, values like 1024 are unlikely to
/// work. We should consider limiting this to u8 or u16, but will leave it at u32 for
/// experiments for now and focus on documenting the implications of a large width.
pub width: u32,
pub ret_activity: DiffActivity,
pub input_activity: Vec<DiffActivity>,
}

impl AutoDiffAttrs {
pub fn has_primal_ret(&self) -> bool {
matches!(self.ret_activity, DiffActivity::Active | DiffActivity::Dual)
pub fn all_activities() -> &'static [Symbol] {
&[
sym::None,
sym::Active,
sym::ActiveOnly,
sym::Const,
sym::Dual,
sym::Dualv,
sym::DualOnly,
sym::DualvOnly,
sym::Duplicated,
sym::DuplicatedOnly,
]
}
}

Expand Down Expand Up @@ -241,59 +225,3 @@ impl FromStr for DiffActivity {
}
}
}

impl AutoDiffAttrs {
pub fn has_ret_activity(&self) -> bool {
self.ret_activity != DiffActivity::None
}
pub fn has_active_only_ret(&self) -> bool {
self.ret_activity == DiffActivity::ActiveOnly
}

pub const fn error() -> Self {
AutoDiffAttrs {
mode: DiffMode::Error,
width: 0,
ret_activity: DiffActivity::None,
input_activity: Vec::new(),
}
}
pub fn source() -> Self {
AutoDiffAttrs {
mode: DiffMode::Source,
width: 0,
ret_activity: DiffActivity::None,
input_activity: Vec::new(),
}
}

pub fn is_active(&self) -> bool {
self.mode != DiffMode::Error
}

pub fn is_source(&self) -> bool {
self.mode == DiffMode::Source
}
pub fn apply_autodiff(&self) -> bool {
!matches!(self.mode, DiffMode::Error | DiffMode::Source)
}

pub fn into_item(
self,
source: String,
target: String,
inputs: Vec<TypeTree>,
output: TypeTree,
) -> AutoDiffItem {
AutoDiffItem { source, target, inputs, output, attrs: self }
}
}

impl fmt::Display for AutoDiffItem {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Differentiating {} -> {}", self.source, self.target)?;
write!(f, " with attributes: {:?}", self.attrs)?;
write!(f, " with inputs: {:?}", self.inputs)?;
write!(f, " with output: {:?}", self.output)
}
}
117 changes: 117 additions & 0 deletions compiler/rustc_attr_parsing/src/attributes/autodiff.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
use std::str::FromStr;

use rustc_ast::LitKind;
use rustc_ast::expand::autodiff_attrs::{DiffActivity, DiffMode};
use rustc_feature::{AttributeTemplate, template};
use rustc_hir::attrs::{AttributeKind, RustcAutodiff};
use rustc_hir::{MethodKind, Target};
use rustc_span::{Symbol, sym};
use thin_vec::ThinVec;

use crate::attributes::prelude::Allow;
use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
use crate::context::{AcceptContext, Stage};
use crate::parser::{ArgParser, MetaItemOrLitParser};
use crate::target_checking::AllowedTargets;

pub(crate) struct RustcAutodiffParser;

impl<S: Stage> SingleAttributeParser<S> for RustcAutodiffParser {
const PATH: &[Symbol] = &[sym::rustc_autodiff];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
Allow(Target::Fn),
Allow(Target::Method(MethodKind::Inherent)),
Allow(Target::Method(MethodKind::Trait { body: true })),
Allow(Target::Method(MethodKind::TraitImpl)),
]);
const TEMPLATE: AttributeTemplate = template!(
List: &["MODE", "WIDTH", "INPUT_ACTIVITIES", "OUTPUT_ACTIVITY"],
"https://doc.rust-lang.org/std/autodiff/index.html"
);

fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let list = match args {
ArgParser::NoArgs => return Some(AttributeKind::RustcAutodiff(None)),
ArgParser::List(list) => list,
ArgParser::NameValue(_) => {
cx.expected_list_or_no_args(cx.attr_span);
return None;
}
};

let mut items = list.mixed().peekable();

// Parse name
let Some(mode) = items.next() else {
cx.expected_at_least_one_argument(list.span);
return None;
};
let Some(mode) = mode.meta_item() else {
cx.expected_identifier(mode.span());
return None;
};
let Ok(()) = mode.args().no_args() else {
cx.expected_identifier(mode.span());
return None;
};
let Some(mode) = mode.path().word() else {
cx.expected_identifier(mode.span());
return None;
};
let Ok(mode) = DiffMode::from_str(mode.as_str()) else {
cx.expected_specific_argument(mode.span, DiffMode::all_modes());
return None;
};

// Parse width
let width = if let Some(width) = items.peek()
&& let MetaItemOrLitParser::Lit(width) = width
&& let LitKind::Int(width, _) = width.kind
&& let Ok(width) = width.0.try_into()
{
_ = items.next();
width
} else {
1
};

// Parse activities
let mut activities = ThinVec::new();
for activity in items {
let MetaItemOrLitParser::MetaItemParser(activity) = activity else {
cx.expected_specific_argument(activity.span(), DiffActivity::all_activities());
return None;
};
let Ok(()) = activity.args().no_args() else {
cx.expected_specific_argument(activity.span(), DiffActivity::all_activities());
return None;
};
let Some(activity) = activity.path().word() else {
cx.expected_specific_argument(activity.span(), DiffActivity::all_activities());
return None;
};
let Ok(activity) = DiffActivity::from_str(activity.as_str()) else {
cx.expected_specific_argument(activity.span, DiffActivity::all_activities());
return None;
};

activities.push(activity);
}
let Some(ret_activity) = activities.pop() else {
cx.expected_specific_argument(
list.span.with_lo(list.span.hi()),
DiffActivity::all_activities(),
);
return None;
};

Some(AttributeKind::RustcAutodiff(Some(Box::new(RustcAutodiff {
mode,
width,
input_activity: activities,
ret_activity,
}))))
}
}
1 change: 1 addition & 0 deletions compiler/rustc_attr_parsing/src/attributes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use crate::target_checking::AllowedTargets;
mod prelude;

pub(crate) mod allow_unstable;
pub(crate) mod autodiff;
pub(crate) mod body;
pub(crate) mod cfg;
pub(crate) mod cfg_select;
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use rustc_span::{ErrorGuaranteed, Span, Symbol};
use crate::AttributeParser;
// Glob imports to avoid big, bitrotty import lists
use crate::attributes::allow_unstable::*;
use crate::attributes::autodiff::*;
use crate::attributes::body::*;
use crate::attributes::cfi_encoding::*;
use crate::attributes::codegen_attrs::*;
Expand Down Expand Up @@ -204,6 +205,7 @@ attribute_parsers!(
Single<ReexportTestHarnessMainParser>,
Single<RustcAbiParser>,
Single<RustcAllocatorZeroedVariantParser>,
Single<RustcAutodiffParser>,
Single<RustcBuiltinMacroParser>,
Single<RustcDefPathParser>,
Single<RustcDeprecatedSafe2024Parser>,
Expand Down
13 changes: 7 additions & 6 deletions compiler/rustc_borrowck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ use rustc_abi::FieldIdx;
use rustc_data_structures::frozen::Frozen;
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_data_structures::graph::dominators::Dominators;
use rustc_errors::LintDiagnostic;
use rustc_hir as hir;
use rustc_hir::CRATE_HIR_ID;
use rustc_hir::def_id::LocalDefId;
Expand Down Expand Up @@ -715,7 +714,7 @@ impl<'tcx> Deref for BorrowckInferCtxt<'tcx> {
}
}

struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
pub(crate) struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
root_cx: &'a mut BorrowCheckRootCtxt<'tcx>,
infcx: &'infcx BorrowckInferCtxt<'tcx>,
body: &'a Body<'tcx>,
Expand Down Expand Up @@ -1428,13 +1427,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
borrow,
Some((WriteKind::StorageDeadOrDrop, place)),
);
this.infcx.tcx.node_span_lint(
this.infcx.tcx.emit_node_span_lint(
TAIL_EXPR_DROP_ORDER,
CRATE_HIR_ID,
borrowed,
|diag| {
session_diagnostics::TailExprDropOrder { borrowed }.decorate_lint(diag);
explain.add_explanation_to_diagnostic(&this, diag, "", None, None);
session_diagnostics::TailExprDropOrder {
borrowed,
callback: |diag| {
explain.add_explanation_to_diagnostic(&this, diag, "", None, None);
},
},
);
// We may stop at the first case
Expand Down
23 changes: 17 additions & 6 deletions compiler/rustc_borrowck/src/session_diagnostics.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use rustc_errors::MultiSpan;
use rustc_errors::codes::*;
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, Level, MultiSpan};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_middle::ty::{GenericArg, Ty};
use rustc_span::Span;

Expand Down Expand Up @@ -595,9 +595,20 @@ pub(crate) struct SimdIntrinsicArgConst {
pub intrinsic: String,
}

#[derive(LintDiagnostic)]
#[diag("relative drop order changing in Rust 2024")]
pub(crate) struct TailExprDropOrder {
#[label("this temporary value will be dropped at the end of the block")]
pub(crate) struct TailExprDropOrder<F: FnOnce(&mut Diag<'_, ()>)> {
pub borrowed: Span,
pub callback: F,
}

impl<'a, F: FnOnce(&mut Diag<'_, ()>)> Diagnostic<'a, ()> for TailExprDropOrder<F> {
fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
let Self { borrowed, callback } = self;
let mut diag = Diag::new(dcx, level, "relative drop order changing in Rust 2024")
.with_span_label(
borrowed,
"this temporary value will be dropped at the end of the block",
);
callback(&mut diag);
diag
}
}
Loading
Loading