Auto merge of #153124 - JonathanBrouwer:rollup-3OajkjU, r=JonathanBrouwer

Rollup of 7 pull requests

Successful merges:

 - rust-lang/rust#153079 (Revert "Move aarch64-apple dist builder to dynamic llvm linking")
 - rust-lang/rust#152651 (Avoid duplicate `requirement` diag args in `RegionOriginNote`)
 - rust-lang/rust#152978 (Port `#[rustc_autodiff]` to the attribute parser infrastructure)
 - rust-lang/rust#153091 (Migration of `LintDiagnostic` - part 4)
 - rust-lang/rust#153112 (Query key cleanups)
 - rust-lang/rust#153118 (mailmap: add redddy)
 - rust-lang/rust#153120 (Clean up some code related to `QueryVTable::execute_query_fn`)
This commit is contained in:
bors
2026-02-26 12:20:45 +00:00
57 changed files with 923 additions and 722 deletions
+3
View File
@@ -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>
+22 -94
View File
@@ -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};
@@ -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.
@@ -76,43 +83,20 @@ pub fn is_dual_or_const(&self) -> bool {
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,
]
}
}
@@ -241,59 +225,3 @@ fn from_str(s: &str) -> Result<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)
}
}
@@ -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,
}))))
}
}
@@ -30,6 +30,7 @@
mod prelude;
pub(crate) mod allow_unstable;
pub(crate) mod autodiff;
pub(crate) mod body;
pub(crate) mod cfg;
pub(crate) mod cfg_select;
@@ -19,6 +19,7 @@
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::*;
@@ -204,6 +205,7 @@ mod late {
Single<ReexportTestHarnessMainParser>,
Single<RustcAbiParser>,
Single<RustcAllocatorZeroedVariantParser>,
Single<RustcAutodiffParser>,
Single<RustcBuiltinMacroParser>,
Single<RustcDefPathParser>,
Single<RustcDeprecatedSafe2024Parser>,
+7 -6
View File
@@ -27,7 +27,6 @@
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;
@@ -715,7 +714,7 @@ fn deref(&self) -> &Self::Target {
}
}
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>,
@@ -1428,13 +1427,15 @@ fn check_backward_incompatible_drop(
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
@@ -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;
@@ -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
}
}
@@ -8,8 +8,7 @@ mod llvm_enzyme {
use std::string::String;
use rustc_ast::expand::autodiff_attrs::{
AutoDiffAttrs, DiffActivity, DiffMode, valid_input_activity, valid_ret_activity,
valid_ty_for_activity,
DiffActivity, DiffMode, valid_input_activity, valid_ret_activity, valid_ty_for_activity,
};
use rustc_ast::token::{Lit, LitKind, Token, TokenKind};
use rustc_ast::tokenstream::*;
@@ -20,6 +19,7 @@ mod llvm_enzyme {
MetaItemInner, MgcaDisambiguation, PatKind, Path, PathSegment, TyKind, Visibility,
};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_hir::attrs::RustcAutodiff;
use rustc_span::{Ident, Span, Symbol, sym};
use thin_vec::{ThinVec, thin_vec};
use tracing::{debug, trace};
@@ -87,7 +87,7 @@ pub(crate) fn from_ast(
meta_item: &ThinVec<MetaItemInner>,
has_ret: bool,
mode: DiffMode,
) -> AutoDiffAttrs {
) -> RustcAutodiff {
let dcx = ecx.sess.dcx();
// Now we check, whether the user wants autodiff in batch/vector mode, or scalar mode.
@@ -105,7 +105,7 @@ pub(crate) fn from_ast(
span: meta_item[1].span(),
width: x,
});
return AutoDiffAttrs::error();
return RustcAutodiff::error();
}
}
} else {
@@ -129,7 +129,7 @@ pub(crate) fn from_ast(
};
}
if errors {
return AutoDiffAttrs::error();
return RustcAutodiff::error();
}
// If a return type exist, we need to split the last activity,
@@ -145,11 +145,11 @@ pub(crate) fn from_ast(
(&DiffActivity::None, activities.as_slice())
};
AutoDiffAttrs {
RustcAutodiff {
mode,
width,
ret_activity: *ret_activity,
input_activity: input_activity.to_vec(),
input_activity: input_activity.iter().cloned().collect(),
}
}
@@ -309,7 +309,7 @@ pub(crate) fn expand_with_mode(
ts.pop();
let ts: TokenStream = TokenStream::from_iter(ts);
let x: AutoDiffAttrs = from_ast(ecx, &meta_item_vec, has_ret, mode);
let x: RustcAutodiff = from_ast(ecx, &meta_item_vec, has_ret, mode);
if !x.is_active() {
// We encountered an error, so we return the original item.
// This allows us to potentially parse other attributes.
@@ -603,7 +603,7 @@ fn gen_turbofish_expr(
fn gen_enzyme_decl(
ecx: &ExtCtxt<'_>,
sig: &ast::FnSig,
x: &AutoDiffAttrs,
x: &RustcAutodiff,
span: Span,
) -> ast::FnSig {
let dcx = ecx.sess.dcx();
@@ -1,9 +1,11 @@
use std::ptr;
use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, DiffActivity, DiffMode};
use rustc_ast::expand::autodiff_attrs::{DiffActivity, DiffMode};
use rustc_ast::expand::typetree::FncTree;
use rustc_codegen_ssa::common::TypeKind;
use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods};
use rustc_data_structures::thin_vec::ThinVec;
use rustc_hir::attrs::RustcAutodiff;
use rustc_middle::ty::{Instance, PseudoCanonicalInput, TyCtxt, TypingEnv};
use rustc_middle::{bug, ty};
use rustc_target::callconv::PassMode;
@@ -18,7 +20,7 @@ pub(crate) fn adjust_activity_to_abi<'tcx>(
tcx: TyCtxt<'tcx>,
instance: Instance<'tcx>,
typing_env: TypingEnv<'tcx>,
da: &mut Vec<DiffActivity>,
da: &mut ThinVec<DiffActivity>,
) {
let fn_ty = instance.ty(tcx, typing_env);
@@ -295,7 +297,7 @@ pub(crate) fn generate_enzyme_call<'ll, 'tcx>(
outer_name: &str,
ret_ty: &'ll Type,
fn_args: &[&'ll Value],
attrs: AutoDiffAttrs,
attrs: &RustcAutodiff,
dest: PlaceRef<'tcx, &'ll Value>,
fnc_tree: FncTree,
) {
+5 -3
View File
@@ -6,7 +6,6 @@
Align, BackendRepr, ExternAbi, Float, HasDataLayout, Primitive, Size, WrappingRange,
};
use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh, wants_wasm_eh};
use rustc_codegen_ssa::codegen_attrs::autodiff_attrs;
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
use rustc_codegen_ssa::errors::{ExpectedPointerMutability, InvalidMonomorphization};
use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
@@ -15,6 +14,7 @@
use rustc_data_structures::assert_matches;
use rustc_hir as hir;
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_hir::find_attr;
use rustc_middle::mir::BinOp;
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, LayoutOf};
use rustc_middle::ty::offload_meta::OffloadMetadata;
@@ -1367,7 +1367,9 @@ fn codegen_autodiff<'ll, 'tcx>(
let val_arr = get_args_from_tuple(bx, args[2], fn_diff);
let diff_symbol = symbol_name_for_instance_in_crate(tcx, fn_diff.clone(), LOCAL_CRATE);
let Some(mut diff_attrs) = autodiff_attrs(tcx, fn_diff.def_id()) else {
let Some(Some(mut diff_attrs)) =
find_attr!(tcx, fn_diff.def_id(), RustcAutodiff(attr) => attr.clone())
else {
bug!("could not find autodiff attrs")
};
@@ -1389,7 +1391,7 @@ fn codegen_autodiff<'ll, 'tcx>(
&diff_symbol,
llret_ty,
&val_arr,
diff_attrs.clone(),
&diff_attrs,
result,
fnc_tree,
);
@@ -1,8 +1,4 @@
use std::str::FromStr;
use rustc_abi::{Align, ExternAbi};
use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, DiffActivity, DiffMode};
use rustc_ast::{LitKind, MetaItem, MetaItemInner};
use rustc_hir::attrs::{
AttributeKind, EiiImplResolution, InlineAttr, Linkage, RtsanSetting, UsedBy,
};
@@ -14,7 +10,6 @@
};
use rustc_middle::mir::mono::Visibility;
use rustc_middle::query::Providers;
use rustc_middle::span_bug;
use rustc_middle::ty::{self as ty, TyCtxt};
use rustc_session::lint;
use rustc_session::parse::feature_err;
@@ -614,116 +609,6 @@ fn inherited_align<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<Align> {
tcx.codegen_fn_attrs(tcx.trait_item_of(def_id)?).alignment
}
/// We now check the #\[rustc_autodiff\] attributes which we generated from the #[autodiff(...)]
/// macros. There are two forms. The pure one without args to mark primal functions (the functions
/// being differentiated). The other form is #[rustc_autodiff(Mode, ActivityList)] on top of the
/// placeholder functions. We wrote the rustc_autodiff attributes ourself, so this should never
/// panic, unless we introduced a bug when parsing the autodiff macro.
//FIXME(jdonszelmann): put in the main loop. No need to have two..... :/ Let's do that when we make autodiff parsed.
pub fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option<AutoDiffAttrs> {
#[allow(deprecated)]
let attrs = tcx.get_attrs(id, sym::rustc_autodiff);
let attrs = attrs.filter(|attr| attr.has_name(sym::rustc_autodiff)).collect::<Vec<_>>();
// check for exactly one autodiff attribute on placeholder functions.
// There should only be one, since we generate a new placeholder per ad macro.
let attr = match &attrs[..] {
[] => return None,
[attr] => attr,
_ => {
span_bug!(attrs[1].span(), "cg_ssa: rustc_autodiff should only exist once per source");
}
};
let list = attr.meta_item_list().unwrap_or_default();
// empty autodiff attribute macros (i.e. `#[autodiff]`) are used to mark source functions
if list.is_empty() {
return Some(AutoDiffAttrs::source());
}
let [mode, width_meta, input_activities @ .., ret_activity] = &list[..] else {
span_bug!(attr.span(), "rustc_autodiff attribute must contain mode, width and activities");
};
let mode = if let MetaItemInner::MetaItem(MetaItem { path: p1, .. }) = mode {
p1.segments.first().unwrap().ident
} else {
span_bug!(attr.span(), "rustc_autodiff attribute must contain mode");
};
// parse mode
let mode = match mode.as_str() {
"Forward" => DiffMode::Forward,
"Reverse" => DiffMode::Reverse,
_ => {
span_bug!(mode.span, "rustc_autodiff attribute contains invalid mode");
}
};
let width: u32 = match width_meta {
MetaItemInner::MetaItem(MetaItem { path: p1, .. }) => {
let w = p1.segments.first().unwrap().ident;
match w.as_str().parse() {
Ok(val) => val,
Err(_) => {
span_bug!(w.span, "rustc_autodiff width should fit u32");
}
}
}
MetaItemInner::Lit(lit) => {
if let LitKind::Int(val, _) = lit.kind {
match val.get().try_into() {
Ok(val) => val,
Err(_) => {
span_bug!(lit.span, "rustc_autodiff width should fit u32");
}
}
} else {
span_bug!(lit.span, "rustc_autodiff width should be an integer");
}
}
};
// First read the ret symbol from the attribute
let MetaItemInner::MetaItem(MetaItem { path: p1, .. }) = ret_activity else {
span_bug!(attr.span(), "rustc_autodiff attribute must contain the return activity");
};
let ret_symbol = p1.segments.first().unwrap().ident;
// Then parse it into an actual DiffActivity
let Ok(ret_activity) = DiffActivity::from_str(ret_symbol.as_str()) else {
span_bug!(ret_symbol.span, "invalid return activity");
};
// Now parse all the intermediate (input) activities
let mut arg_activities: Vec<DiffActivity> = vec![];
for arg in input_activities {
let arg_symbol = if let MetaItemInner::MetaItem(MetaItem { path: p2, .. }) = arg {
match p2.segments.first() {
Some(x) => x.ident,
None => {
span_bug!(
arg.span(),
"rustc_autodiff attribute must contain the input activity"
);
}
}
} else {
span_bug!(arg.span(), "rustc_autodiff attribute must contain the input activity");
};
match DiffActivity::from_str(arg_symbol.as_str()) {
Ok(arg_activity) => arg_activities.push(arg_activity),
Err(_) => {
span_bug!(arg_symbol.span, "invalid input activity");
}
}
}
Some(AutoDiffAttrs { mode, width, ret_activity, input_activity: arg_activities })
}
pub(crate) fn provide(providers: &mut Providers) {
*providers = Providers {
codegen_fn_attrs,
@@ -1,9 +1,12 @@
use std::borrow::Cow;
use std::fmt;
use std::path::PathBuf;
pub use ReprAttr::*;
use rustc_abi::Align;
pub use rustc_ast::attr::data_structures::*;
use rustc_ast::expand::autodiff_attrs::{DiffActivity, DiffMode};
use rustc_ast::expand::typetree::TypeTree;
use rustc_ast::token::DocFragmentKind;
use rustc_ast::{AttrStyle, Path, ast};
use rustc_data_structures::fx::FxIndexMap;
@@ -794,6 +797,103 @@ pub struct RustcCleanQueries {
pub span: Span,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[derive(HashStable_Generic, Encodable, Decodable, PrintAttribute)]
pub struct RustcAutodiff {
/// 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 input_activity: ThinVec<DiffActivity>,
pub ret_activity: DiffActivity,
}
impl RustcAutodiff {
pub fn has_primal_ret(&self) -> bool {
matches!(self.ret_activity, DiffActivity::Active | DiffActivity::Dual)
}
}
impl RustcAutodiff {
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 fn error() -> Self {
RustcAutodiff {
mode: DiffMode::Error,
width: 0,
ret_activity: DiffActivity::None,
input_activity: ThinVec::new(),
}
}
pub fn source() -> Self {
RustcAutodiff {
mode: DiffMode::Source,
width: 0,
ret_activity: DiffActivity::None,
input_activity: ThinVec::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 }
}
}
/// 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: RustcAutodiff,
pub inputs: Vec<TypeTree>,
pub output: TypeTree,
}
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)
}
}
/// Represents parsed *built-in* inert attributes.
///
/// ## Overview
@@ -1186,6 +1286,9 @@ pub enum AttributeKind {
/// Represents `#[rustc_as_ptr]` (used by the `dangling_pointers_from_temporaries` lint).
RustcAsPtr(Span),
/// Represents `#[rustc_autodiff]`.
RustcAutodiff(Option<Box<RustcAutodiff>>),
/// Represents `#[rustc_default_body_unstable]`.
RustcBodyStability {
stability: DefaultBodyStability,
@@ -102,6 +102,7 @@ pub fn encode_cross_crate(&self) -> EncodeCrossCrate {
RustcAllowConstFnUnstable(..) => No,
RustcAllowIncoherentImpl(..) => No,
RustcAsPtr(..) => Yes,
RustcAutodiff(..) => Yes,
RustcBodyStability { .. } => No,
RustcBuiltinMacro { .. } => Yes,
RustcCaptureAnalysis => No,
@@ -6,6 +6,7 @@
use rustc_ast::ast::{Path, join_path_idents};
use rustc_ast::attr::data_structures::CfgEntry;
use rustc_ast::attr::version::RustcVersion;
use rustc_ast::expand::autodiff_attrs::{DiffActivity, DiffMode};
use rustc_ast::token::{CommentKind, DocFragmentKind};
use rustc_ast::{AttrId, AttrStyle, IntTy, UintTy};
use rustc_ast_pretty::pp::Printer;
@@ -191,7 +192,7 @@ fn print_attribute(&self, p: &mut Printer) {
print_tup!(A B C D E F G H);
print_skip!(Span, (), ErrorGuaranteed, AttrId);
print_disp!(u8, u16, u128, usize, bool, NonZero<u32>, Limit);
print_disp!(u8, u16, u32, u128, usize, bool, NonZero<u32>, Limit);
print_debug!(
Symbol,
Ident,
@@ -206,4 +207,6 @@ fn print_attribute(&self, p: &mut Printer) {
DefId,
RustcVersion,
CfgEntry,
DiffActivity,
DiffMode,
);
+2 -2
View File
@@ -22,7 +22,7 @@
use rustc_ast::{self as ast, *};
use rustc_ast_pretty::pprust::expr_to_string;
use rustc_attr_parsing::AttributeParser;
use rustc_errors::{Applicability, LintDiagnostic, msg};
use rustc_errors::{Applicability, Diagnostic, msg};
use rustc_feature::GateIssue;
use rustc_hir::attrs::{AttributeKind, DocAttribute};
use rustc_hir::def::{DefKind, Res};
@@ -235,7 +235,7 @@ fn report_unsafe(
&self,
cx: &EarlyContext<'_>,
span: Span,
decorate: impl for<'a> LintDiagnostic<'a, ()>,
decorate: impl for<'a> Diagnostic<'a, ()>,
) {
// This comes from a macro that has `#[allow_internal_unsafe]`.
if span.allows_unsafe() {
+45 -5
View File
@@ -11,7 +11,7 @@
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::sync;
use rustc_data_structures::unord::UnordMap;
use rustc_errors::{Diag, LintBuffer, LintDiagnostic, MultiSpan};
use rustc_errors::{Diag, Diagnostic, LintBuffer, LintDiagnostic, MultiSpan};
use rustc_feature::Features;
use rustc_hir::def::Res;
use rustc_hir::def_id::{CrateNum, DefId};
@@ -522,17 +522,28 @@ fn opt_span_lint<S: Into<MultiSpan>>(
decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>),
);
// FIXME: These methods should not take an Into<MultiSpan> -- instead, callers should need to
// set the span in their `decorate` function (preferably using set_span).
/// Emit a lint at the appropriate level, with an optional associated span.
///
/// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature
#[track_caller]
fn opt_span_diag_lint<S: Into<MultiSpan>>(
&self,
lint: &'static Lint,
span: Option<S>,
decorate: impl for<'a> Diagnostic<'a, ()>,
);
/// Emit a lint at `span` from a lint struct (some type that implements `LintDiagnostic`,
/// typically generated by `#[derive(LintDiagnostic)]`).
fn emit_span_lint<S: Into<MultiSpan>>(
&self,
lint: &'static Lint,
span: S,
decorator: impl for<'a> LintDiagnostic<'a, ()>,
decorator: impl for<'a> Diagnostic<'a, ()>,
) {
self.opt_span_lint(lint, Some(span), |lint| {
decorator.decorate_lint(lint);
});
self.opt_span_diag_lint(lint, Some(span), decorator);
}
/// Emit a lint at `span` from a lazily-constructed lint struct (some type that implements
@@ -570,6 +581,12 @@ fn emit_lint(&self, lint: &'static Lint, decorator: impl for<'a> LintDiagnostic<
});
}
/// Emit a lint from a lint struct (some type that implements `LintDiagnostic`, typically
/// generated by `#[derive(LintDiagnostic)]`).
fn emit_diag_lint(&self, lint: &'static Lint, decorator: impl for<'a> Diagnostic<'a, ()>) {
self.opt_span_diag_lint(lint, None as Option<Span>, decorator);
}
/// Emit a lint at the appropriate level, with no associated span.
///
/// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature
@@ -644,6 +661,20 @@ fn opt_span_lint<S: Into<MultiSpan>>(
}
}
fn opt_span_diag_lint<S: Into<MultiSpan>>(
&self,
lint: &'static Lint,
span: Option<S>,
decorate: impl for<'a> Diagnostic<'a, ()>,
) {
let hir_id = self.last_node_with_lint_attrs;
match span {
Some(s) => self.tcx.emit_node_span_lint(lint, hir_id, s, decorate),
None => self.tcx.emit_node_lint(lint, hir_id, decorate),
}
}
fn get_lint_level(&self, lint: &'static Lint) -> LevelAndSource {
self.tcx.lint_level_at_node(lint, self.last_node_with_lint_attrs)
}
@@ -664,6 +695,15 @@ fn opt_span_lint<S: Into<MultiSpan>>(
self.builder.opt_span_lint(lint, span.map(|s| s.into()), decorate)
}
fn opt_span_diag_lint<S: Into<MultiSpan>>(
&self,
lint: &'static Lint,
span: Option<S>,
decorator: impl for<'a> Diagnostic<'a, ()>,
) {
self.builder.opt_span_diag_lint(lint, span.map(|s| s.into()), decorator)
}
fn get_lint_level(&self, lint: &'static Lint) -> LevelAndSource {
self.builder.lint_level(lint)
}
-1
View File
@@ -269,7 +269,6 @@ fn lint_expr(cx: &LateContext<'_>, expr: &Expr<'_>) {
&& let Some(fn_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
&& find_attr!(cx.tcx, fn_id, RustcAsPtr(_))
{
// FIXME: use `emit_node_lint` when `#[primary_span]` is added.
cx.tcx.emit_node_span_lint(
DANGLING_POINTERS_FROM_TEMPORARIES,
expr.hir_id,
+1 -1
View File
@@ -638,7 +638,7 @@ fn path_contains_attribute_kind(cx: &EarlyContext<'_>, path: &Path) {
cx.emit_span_lint(
BAD_USE_OF_FIND_ATTR,
segment.span(),
AttributeKindInFindAttr {},
AttributeKindInFindAttr,
);
}
}
+35 -19
View File
@@ -2,7 +2,7 @@
use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_data_structures::unord::UnordSet;
use rustc_errors::{Diag, LintDiagnostic, MultiSpan, msg};
use rustc_errors::{Diag, Diagnostic, MultiSpan, msg};
use rustc_feature::{Features, GateIssue};
use rustc_hir::HirId;
use rustc_hir::intravisit::{self, Visitor};
@@ -10,8 +10,8 @@
use rustc_middle::bug;
use rustc_middle::hir::nested_filter;
use rustc_middle::lint::{
LevelAndSource, LintExpectation, LintLevelSource, ShallowLintLevelMap, lint_level,
reveal_actual_level,
LevelAndSource, LintExpectation, LintLevelSource, ShallowLintLevelMap, diag_lint_level,
lint_level, reveal_actual_level,
};
use rustc_middle::query::Providers;
use rustc_middle::ty::{RegisteredTools, TyCtxt};
@@ -822,8 +822,11 @@ fn add(
RenamedLintSuggestion::WithSpan { suggestion: sp, replace };
let name =
tool_ident.map(|tool| format!("{tool}::{name}")).unwrap_or(name);
let lint = RenamedLint { name: name.as_str(), replace, suggestion };
self.emit_span_lint(RENAMED_AND_REMOVED_LINTS, sp.into(), lint);
self.emit_span_lint(
RENAMED_AND_REMOVED_LINTS,
sp.into(),
RenamedLint { name: name.as_str(), replace, suggestion },
);
}
// If this lint was renamed, apply the new lint instead of ignoring the
@@ -844,8 +847,11 @@ fn add(
if self.lint_added_lints {
let name =
tool_ident.map(|tool| format!("{tool}::{name}")).unwrap_or(name);
let lint = RemovedLint { name: name.as_str(), reason };
self.emit_span_lint(RENAMED_AND_REMOVED_LINTS, sp.into(), lint);
self.emit_span_lint(
RENAMED_AND_REMOVED_LINTS,
sp.into(),
RemovedLint { name: name.as_str(), reason },
);
}
continue;
}
@@ -861,8 +867,11 @@ fn add(
from_rustc,
}
});
let lint = UnknownLint { name, suggestion };
self.emit_span_lint(UNKNOWN_LINTS, sp.into(), lint);
self.emit_span_lint(
UNKNOWN_LINTS,
sp.into(),
UnknownLint { name, suggestion },
);
}
continue;
}
@@ -967,8 +976,6 @@ pub fn lint_level(&self, lint: &'static Lint) -> LevelAndSource {
/// Used to emit a lint-related diagnostic based on the current state of
/// this lint context.
///
/// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature
#[track_caller]
pub(crate) fn opt_span_lint(
&self,
@@ -980,25 +987,34 @@ pub(crate) fn opt_span_lint(
lint_level(self.sess, lint, level, span, decorate)
}
/// Used to emit a lint-related diagnostic based on the current state of
/// this lint context.
#[track_caller]
pub(crate) fn opt_span_diag_lint(
&self,
lint: &'static Lint,
span: Option<MultiSpan>,
decorator: impl for<'a> Diagnostic<'a, ()>,
) {
let level = self.lint_level(lint);
diag_lint_level(self.sess, lint, level, span, decorator)
}
#[track_caller]
pub fn emit_span_lint(
&self,
lint: &'static Lint,
span: MultiSpan,
decorate: impl for<'a> LintDiagnostic<'a, ()>,
decorator: impl for<'a> Diagnostic<'a, ()>,
) {
let level = self.lint_level(lint);
lint_level(self.sess, lint, level, Some(span), |lint| {
decorate.decorate_lint(lint);
});
diag_lint_level(self.sess, lint, level, Some(span), decorator);
}
#[track_caller]
pub fn emit_lint(&self, lint: &'static Lint, decorate: impl for<'a> LintDiagnostic<'a, ()>) {
pub fn emit_lint(&self, lint: &'static Lint, decorator: impl for<'a> Diagnostic<'a, ()>) {
let level = self.lint_level(lint);
lint_level(self.sess, lint, level, None, |lint| {
decorate.decorate_lint(lint);
});
diag_lint_level(self.sess, lint, level, None, decorator);
}
}
+192 -174
View File
@@ -5,8 +5,8 @@
use rustc_errors::codes::*;
use rustc_errors::{
Applicability, Diag, DiagArgValue, DiagCtxtHandle, DiagMessage, DiagStyledString, Diagnostic,
ElidedLifetimeInPathSubdiag, EmissionGuarantee, Level, LintDiagnostic, MultiSpan,
Subdiagnostic, SuggestionStyle, msg,
ElidedLifetimeInPathSubdiag, EmissionGuarantee, Level, MultiSpan, Subdiagnostic,
SuggestionStyle, msg,
};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
@@ -24,7 +24,7 @@
use crate::lifetime_syntax::LifetimeSyntaxCategories;
// array_into_iter.rs
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag(
"this method call resolves to `<&{$target} as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<{$target} as IntoIterator>::into_iter` in Rust {$edition}"
)]
@@ -65,7 +65,7 @@ pub(crate) enum ShadowedIntoIterDiagSub {
}
// autorefs.rs
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("implicit autoref creates a reference to the dereference of a raw pointer")]
#[note(
"creating a reference requires the pointer target to be valid and imposes aliasing requirements"
@@ -119,7 +119,7 @@ pub(crate) struct ImplicitUnsafeAutorefsSuggestion {
}
// builtin.rs
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("denote infinite loops with `loop {\"{\"} ... {\"}\"}`")]
pub(crate) struct BuiltinWhileTrue {
#[suggestion(
@@ -132,7 +132,7 @@ pub(crate) struct BuiltinWhileTrue {
pub replace: String,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("the `{$ident}:` in this pattern is redundant")]
pub(crate) struct BuiltinNonShorthandFieldPatterns {
pub ident: Ident,
@@ -145,7 +145,7 @@ pub(crate) struct BuiltinNonShorthandFieldPatterns {
pub prefix: &'static str,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
pub(crate) enum BuiltinUnsafe {
#[diag(
"`allow_internal_unsafe` allows defining macros using unsafe without triggering the `unsafe_code` lint at their call site"
@@ -210,14 +210,14 @@ pub(crate) enum BuiltinUnsafe {
GlobalAsm,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("missing documentation for {$article} {$desc}")]
pub(crate) struct BuiltinMissingDoc<'a> {
pub article: &'a str,
pub desc: &'a str,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("type could implement `Copy`; consider adding `impl Copy`")]
pub(crate) struct BuiltinMissingCopyImpl;
@@ -227,14 +227,18 @@ pub(crate) struct BuiltinMissingDebugImpl<'a> {
}
// Needed for def_path_str
impl<'a> LintDiagnostic<'a, ()> for BuiltinMissingDebugImpl<'_> {
fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::Diag<'a, ()>) {
diag.primary_message(msg!("type does not implement `{$debug}`; consider adding `#[derive(Debug)]` or a manual implementation"));
diag.arg("debug", self.tcx.def_path_str(self.def_id));
impl<'a> Diagnostic<'a, ()> for BuiltinMissingDebugImpl<'_> {
fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
let Self { tcx, def_id } = self;
Diag::new(
dcx,
level,
msg!("type does not implement `{$debug}`; consider adding `#[derive(Debug)]` or a manual implementation"),
).with_arg("debug", tcx.def_path_str(def_id))
}
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("anonymous parameters are deprecated and will be removed in the next edition")]
pub(crate) struct BuiltinAnonymousParams<'a> {
#[suggestion("try naming the parameter or explicitly ignoring it", code = "_: {ty_snip}")]
@@ -242,7 +246,7 @@ pub(crate) struct BuiltinAnonymousParams<'a> {
pub ty_snip: &'a str,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("unused doc comment")]
pub(crate) struct BuiltinUnusedDocComment<'a> {
pub kind: &'a str,
@@ -260,7 +264,7 @@ pub(crate) enum BuiltinUnusedDocCommentSub {
BlockHelp,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("functions generic over types or consts must be mangled")]
pub(crate) struct BuiltinNoMangleGeneric {
// Use of `#[no_mangle]` suggests FFI intent; correct
@@ -274,20 +278,20 @@ pub(crate) struct BuiltinNoMangleGeneric {
pub suggestion: Span,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("const items should never be `#[no_mangle]`")]
pub(crate) struct BuiltinConstNoMangle {
#[suggestion("try a static value", code = "pub static ", applicability = "machine-applicable")]
pub suggestion: Option<Span>,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag(
"transmuting &T to &mut T is undefined behavior, even if the reference is unused, consider instead using an UnsafeCell"
)]
pub(crate) struct BuiltinMutablesTransmutes;
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("use of an unstable feature")]
pub(crate) struct BuiltinUnstableFeatures;
@@ -297,19 +301,20 @@ pub(crate) struct BuiltinUngatedAsyncFnTrackCaller<'a> {
pub session: &'a Session,
}
impl<'a> LintDiagnostic<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> {
fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
diag.primary_message(msg!("`#[track_caller]` on async functions is a no-op"));
diag.span_label(self.label, msg!("this function will not propagate the caller location"));
impl<'a> Diagnostic<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> {
fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
let mut diag = Diag::new(dcx, level, "`#[track_caller]` on async functions is a no-op")
.with_span_label(self.label, "this function will not propagate the caller location");
rustc_session::parse::add_feature_diagnostics(
diag,
&mut diag,
self.session,
sym::async_fn_track_caller,
);
diag
}
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("unreachable `pub` {$what}")]
pub(crate) struct BuiltinUnreachablePub<'a> {
pub what: &'a str,
@@ -320,7 +325,7 @@ pub(crate) struct BuiltinUnreachablePub<'a> {
pub help: bool,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("the `expr` fragment specifier will accept more expressions in the 2024 edition")]
pub(crate) struct MacroExprFragment2024 {
#[suggestion(
@@ -340,18 +345,18 @@ pub(crate) struct BuiltinTypeAliasBounds<'hir> {
pub ty: Option<&'hir hir::Ty<'hir>>,
}
impl<'a> LintDiagnostic<'a, ()> for BuiltinTypeAliasBounds<'_> {
fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
diag.primary_message(if self.in_where_clause {
impl<'a> Diagnostic<'a, ()> for BuiltinTypeAliasBounds<'_> {
fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
let mut diag = Diag::new(dcx, level, if self.in_where_clause {
msg!("where clauses on type aliases are not enforced")
} else {
msg!("bounds on generic parameters in type aliases are not enforced")
});
diag.span_label(self.label, msg!("will not be checked at usage sites of the type alias"));
diag.note(msg!(
"this is a known limitation of the type checker that may be lifted in a future edition.
see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information"
));
})
.with_span_label(self.label, msg!("will not be checked at usage sites of the type alias"))
.with_note(msg!(
"this is a known limitation of the type checker that may be lifted in a future edition.
see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information"
));
if self.enable_feat_help {
diag.help(msg!("add `#![feature(lazy_type_alias)]` to the crate attributes to enable the desired semantics"));
}
@@ -413,10 +418,11 @@ fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
Applicability::HasPlaceholders,
);
}
diag
}
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag(
"{$predicate_kind_name} bound {$predicate} does not depend on any type or lifetime parameters"
)]
@@ -425,7 +431,7 @@ pub(crate) struct BuiltinTrivialBounds<'a> {
pub predicate: Clause<'a>,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("use of a double negation")]
#[note(
"the prefix `--` could be misinterpreted as a decrement operator which exists in other languages"
@@ -445,7 +451,7 @@ pub(crate) struct BuiltinDoubleNegationsAddParens {
pub end_span: Span,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
pub(crate) enum BuiltinEllipsisInclusiveRangePatternsLint {
#[diag("`...` range patterns are deprecated")]
Parenthesise {
@@ -469,7 +475,7 @@ pub(crate) enum BuiltinEllipsisInclusiveRangePatternsLint {
},
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("`{$kw}` is a keyword in the {$next} edition")]
pub(crate) struct BuiltinKeywordIdents {
pub kw: Ident,
@@ -483,7 +489,7 @@ pub(crate) struct BuiltinKeywordIdents {
pub prefix: &'static str,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("outlives requirements can be inferred")]
pub(crate) struct BuiltinExplicitOutlives {
pub count: usize,
@@ -505,7 +511,7 @@ pub(crate) struct BuiltinExplicitOutlivesSuggestion {
pub applicability: Applicability,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag(
"the feature `{$name}` is incomplete and may not be safe to use and/or cause compiler crashes"
)]
@@ -517,7 +523,7 @@ pub(crate) struct BuiltinIncompleteFeatures {
pub help: Option<BuiltinIncompleteFeaturesHelp>,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("the feature `{$name}` is internal to the compiler or standard library")]
#[note("using it is strongly discouraged")]
pub(crate) struct BuiltinInternalFeatures {
@@ -542,11 +548,11 @@ pub(crate) struct BuiltinUnpermittedTypeInit<'a> {
pub tcx: TyCtxt<'a>,
}
impl<'a> LintDiagnostic<'a, ()> for BuiltinUnpermittedTypeInit<'_> {
fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
diag.primary_message(self.msg);
diag.arg("ty", self.ty);
diag.span_label(self.label, msg!("this code causes undefined behavior when executed"));
impl<'a> Diagnostic<'a, ()> for BuiltinUnpermittedTypeInit<'_> {
fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
let mut diag = Diag::new(dcx, level, self.msg)
.with_arg("ty", self.ty)
.with_span_label(self.label, msg!("this code causes undefined behavior when executed"));
if let InhabitedPredicate::True = self.ty.inhabited_predicate(self.tcx) {
// Only suggest late `MaybeUninit::assume_init` initialization if the type is inhabited.
diag.span_label(
@@ -554,7 +560,8 @@ fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
msg!("help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done"),
);
}
self.sub.add_to_diag(diag);
self.sub.add_to_diag(&mut diag);
diag
}
}
@@ -624,7 +631,7 @@ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
}
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("dereferencing a null pointer")]
pub(crate) struct BuiltinDerefNullptr {
#[label("this code causes undefined behavior when executed")]
@@ -633,7 +640,7 @@ pub(crate) struct BuiltinDerefNullptr {
// FIXME: migrate fluent::lint::builtin_asm_labels
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
pub(crate) enum BuiltinSpecialModuleNameUsed {
#[diag("found module declaration for lib.rs")]
#[note("lib.rs is the root of this crate's library target")]
@@ -645,7 +652,7 @@ pub(crate) enum BuiltinSpecialModuleNameUsed {
}
// deref_into_dyn_supertrait.rs
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("this `Deref` implementation is covered by an implicit supertrait coercion")]
pub(crate) struct SupertraitAsDerefTarget<'a> {
pub self_ty: Ty<'a>,
@@ -667,7 +674,7 @@ pub(crate) struct SupertraitAsDerefTargetLabel {
}
// enum_intrinsics_non_enums.rs
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("the return value of `mem::discriminant` is unspecified when called with a non-enum type")]
pub(crate) struct EnumIntrinsicsMemDiscriminate<'a> {
pub ty_param: Ty<'a>,
@@ -677,7 +684,7 @@ pub(crate) struct EnumIntrinsicsMemDiscriminate<'a> {
pub note: Span,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("the return value of `mem::variant_count` is unspecified when called with a non-enum type")]
#[note(
"the type parameter of `variant_count` should be an enum, but it was instantiated with the type `{$ty_param}`, which is not an enum"
@@ -705,7 +712,7 @@ pub(crate) struct ExpectationNote {
}
// ptr_nulls.rs
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
pub(crate) enum UselessPtrNullChecksDiag<'a> {
#[diag(
"function pointers are not nullable, so checking them for null will always return false"
@@ -730,7 +737,7 @@ pub(crate) enum UselessPtrNullChecksDiag<'a> {
FnRet { fn_name: Ident },
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
pub(crate) enum InvalidNullArgumentsDiag {
#[diag(
"calling this function with a null pointer is undefined behavior, even if the result of the function is unused"
@@ -755,7 +762,7 @@ pub(crate) enum InvalidNullArgumentsDiag {
}
// for_loops_over_fallibles.rs
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag(
"for loop over {$article} `{$ref_prefix}{$ty}`. This is more readably written as an `if let` statement"
)]
@@ -838,7 +845,7 @@ pub(crate) enum UseLetUnderscoreIgnoreSuggestion {
}
// drop_forget_useless.rs
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("calls to `std::mem::drop` with a reference instead of an owned value does nothing")]
pub(crate) struct DropRefDiag<'a> {
pub arg_ty: Ty<'a>,
@@ -848,7 +855,7 @@ pub(crate) struct DropRefDiag<'a> {
pub sugg: UseLetUnderscoreIgnoreSuggestion,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("calls to `std::mem::drop` with a value that implements `Copy` does nothing")]
pub(crate) struct DropCopyDiag<'a> {
pub arg_ty: Ty<'a>,
@@ -858,7 +865,7 @@ pub(crate) struct DropCopyDiag<'a> {
pub sugg: UseLetUnderscoreIgnoreSuggestion,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("calls to `std::mem::forget` with a reference instead of an owned value does nothing")]
pub(crate) struct ForgetRefDiag<'a> {
pub arg_ty: Ty<'a>,
@@ -868,7 +875,7 @@ pub(crate) struct ForgetRefDiag<'a> {
pub sugg: UseLetUnderscoreIgnoreSuggestion,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("calls to `std::mem::forget` with a value that implements `Copy` does nothing")]
pub(crate) struct ForgetCopyDiag<'a> {
pub arg_ty: Ty<'a>,
@@ -878,7 +885,7 @@ pub(crate) struct ForgetCopyDiag<'a> {
pub sugg: UseLetUnderscoreIgnoreSuggestion,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag(
"calls to `std::mem::drop` with `std::mem::ManuallyDrop` instead of the inner value does nothing"
)]
@@ -903,7 +910,7 @@ pub(crate) struct UndroppedManuallyDropsSuggestion {
}
// invalid_from_utf8.rs
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
pub(crate) enum InvalidFromUtf8Diag {
#[diag("calls to `{$method}` with an invalid literal are undefined behavior")]
Unchecked {
@@ -922,7 +929,7 @@ pub(crate) enum InvalidFromUtf8Diag {
}
// interior_mutable_consts.rs
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("mutation of an interior mutable `const` item with call to `{$method_name}`")]
#[note("each usage of a `const` item creates a new temporary")]
#[note("only the temporaries and never the original `const {$const_name}` will be modified")]
@@ -957,7 +964,7 @@ pub(crate) enum ConstItemInteriorMutationsSuggestionStatic {
}
// reference_casting.rs
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
pub(crate) enum InvalidReferenceCastingDiag<'tcx> {
#[diag(
"casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`"
@@ -1002,7 +1009,7 @@ pub(crate) enum InvalidReferenceCastingDiag<'tcx> {
}
// map_unit_fn.rs
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("`Iterator::map` call that discard the iterator's values")]
#[note(
"`Iterator::map`, like many of the methods on `Iterator`, gets executed lazily, meaning that its effects won't be visible until it is iterated"
@@ -1026,7 +1033,7 @@ pub(crate) struct MappingToUnit {
}
// internal.rs
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("prefer `{$preferred}` over `{$used}`, it has better performance")]
#[note("a `use rustc_data_structures::fx::{$preferred}` may be necessary")]
pub(crate) struct DefaultHashTypesDiag<'a> {
@@ -1034,7 +1041,7 @@ pub(crate) struct DefaultHashTypesDiag<'a> {
pub used: Symbol,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("using `{$query}` can result in unstable query results")]
#[note(
"if you believe this case to be fine, allow this lint and add a comment explaining your rationale"
@@ -1043,7 +1050,7 @@ pub(crate) struct QueryInstability {
pub query: Symbol,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("`{$method}` accesses information that is not tracked by the query system")]
#[note(
"if you believe this case to be fine, allow this lint and add a comment explaining your rationale"
@@ -1052,16 +1059,16 @@ pub(crate) struct QueryUntracked {
pub method: Symbol,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("use `.eq_ctxt()` instead of `.ctxt() == .ctxt()`")]
pub(crate) struct SpanUseEqCtxtDiag;
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("using `Symbol::intern` on a string literal")]
#[help("consider adding the symbol to `compiler/rustc_span/src/symbol.rs`")]
pub(crate) struct SymbolInternStringLiteralDiag;
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("usage of `ty::TyKind::<kind>`")]
pub(crate) struct TykindKind {
#[suggestion(
@@ -1072,12 +1079,12 @@ pub(crate) struct TykindKind {
pub suggestion: Span,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("usage of `ty::TyKind`")]
#[help("try using `Ty` instead")]
pub(crate) struct TykindDiag;
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("usage of qualified `ty::{$ty}`")]
pub(crate) struct TyQualified {
pub ty: String,
@@ -1089,14 +1096,14 @@ pub(crate) struct TyQualified {
pub suggestion: Span,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("do not use `rustc_type_ir::inherent` unless you're inside of the trait solver")]
#[note(
"the method or struct you're looking for is likely defined somewhere else downstream in the compiler"
)]
pub(crate) struct TypeIrInherentUsage;
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag(
"do not use `rustc_type_ir::Interner` or `rustc_type_ir::InferCtxtLike` unless you're inside of the trait solver"
)]
@@ -1105,12 +1112,12 @@ pub(crate) struct TyQualified {
)]
pub(crate) struct TypeIrTraitUsage;
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("do not use `rustc_type_ir` unless you are implementing type system internals")]
#[note("use `rustc_middle::ty` instead")]
pub(crate) struct TypeIrDirectUse;
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("non-glob import of `rustc_type_ir::inherent`")]
pub(crate) struct NonGlobImportTypeIrInherent {
#[suggestion(
@@ -1122,18 +1129,18 @@ pub(crate) struct NonGlobImportTypeIrInherent {
pub snippet: &'static str,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("implementing `LintPass` by hand")]
#[help("try using `declare_lint_pass!` or `impl_lint_pass!` instead")]
pub(crate) struct LintPassByHand;
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("{$msg}")]
pub(crate) struct BadOptAccessDiag<'a> {
pub msg: &'a str,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag(
"dangerous use of `extern crate {$name}` which is not guaranteed to exist exactly once in the sysroot"
)]
@@ -1144,14 +1151,14 @@ pub(crate) struct ImplicitSysrootCrateImportDiag<'a> {
pub name: &'a str,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("use of `AttributeKind` in `find_attr!(...)` invocation")]
#[note("`find_attr!(...)` already imports `AttributeKind::*`")]
#[help("remove `AttributeKind`")]
pub(crate) struct AttributeKindInFindAttr {}
pub(crate) struct AttributeKindInFindAttr;
// let_underscore.rs
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
pub(crate) enum NonBindingLet {
#[diag("non-binding let on a synchronization lock")]
SyncLock {
@@ -1213,7 +1220,7 @@ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
}
// levels.rs
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("{$lint_level}({$lint_source}) incompatible with previous forbid")]
pub(crate) struct OverruledAttributeLint<'a> {
#[label("overruled by previous forbid")]
@@ -1224,7 +1231,7 @@ pub(crate) struct OverruledAttributeLint<'a> {
pub sub: OverruledAttributeSub,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("lint name `{$name}` is deprecated and may not have an effect in the future")]
pub(crate) struct DeprecatedLintName<'a> {
pub name: String,
@@ -1233,7 +1240,7 @@ pub(crate) struct DeprecatedLintName<'a> {
pub replace: &'a str,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("lint name `{$name}` is deprecated and may not have an effect in the future")]
#[help("change it to {$replace}")]
pub(crate) struct DeprecatedLintNameFromCommandLine<'a> {
@@ -1243,7 +1250,7 @@ pub(crate) struct DeprecatedLintNameFromCommandLine<'a> {
pub requested_level: RequestedLevel<'a>,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("lint `{$name}` has been renamed to `{$replace}`")]
pub(crate) struct RenamedLint<'a> {
pub name: &'a str,
@@ -1264,7 +1271,7 @@ pub(crate) enum RenamedLintSuggestion<'a> {
WithoutSpan { replace: &'a str },
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("lint `{$name}` has been renamed to `{$replace}`")]
pub(crate) struct RenamedLintFromCommandLine<'a> {
pub name: &'a str,
@@ -1275,14 +1282,14 @@ pub(crate) struct RenamedLintFromCommandLine<'a> {
pub requested_level: RequestedLevel<'a>,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("lint `{$name}` has been removed: {$reason}")]
pub(crate) struct RemovedLint<'a> {
pub name: &'a str,
pub reason: &'a str,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("lint `{$name}` has been removed: {$reason}")]
pub(crate) struct RemovedLintFromCommandLine<'a> {
pub name: &'a str,
@@ -1291,7 +1298,7 @@ pub(crate) struct RemovedLintFromCommandLine<'a> {
pub requested_level: RequestedLevel<'a>,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("unknown lint: `{$name}`")]
pub(crate) struct UnknownLint {
pub name: String,
@@ -1324,7 +1331,7 @@ pub(crate) enum UnknownLintSuggestion {
WithoutSpan { replace: Symbol, from_rustc: bool },
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("unknown lint: `{$name}`", code = E0602)]
pub(crate) struct UnknownLintFromCommandLine<'a> {
pub name: String,
@@ -1334,7 +1341,7 @@ pub(crate) struct UnknownLintFromCommandLine<'a> {
pub requested_level: RequestedLevel<'a>,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("{$level}({$name}) is ignored unless specified at crate level")]
pub(crate) struct IgnoredUnlessCrateSpecified<'a> {
pub level: &'a str,
@@ -1376,18 +1383,18 @@ pub(crate) struct DanglingPointersFromLocals<'tcx> {
}
// multiple_supertrait_upcastable.rs
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("`{$ident}` is dyn-compatible and has multiple supertraits")]
pub(crate) struct MultipleSupertraitUpcastable {
pub ident: Ident,
}
// non_ascii_idents.rs
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("identifier contains non-ASCII characters")]
pub(crate) struct IdentifierNonAsciiChar;
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag(
"identifier contains {$codepoints_len ->
[one] { $identifier_type ->
@@ -1421,7 +1428,7 @@ pub(crate) struct IdentifierUncommonCodepoints {
pub identifier_type: &'static str,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("found both `{$existing_sym}` and `{$sym}` as identifiers, which look alike")]
pub(crate) struct ConfusableIdentifierPair {
pub existing_sym: Symbol,
@@ -1432,7 +1439,7 @@ pub(crate) struct ConfusableIdentifierPair {
pub main_label: Span,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag(
"the usage of Script Group `{$set}` in this crate consists solely of mixed script confusables"
)]
@@ -1450,9 +1457,9 @@ pub(crate) struct NonFmtPanicUnused {
}
// Used because of two suggestions based on one Option<Span>
impl<'a> LintDiagnostic<'a, ()> for NonFmtPanicUnused {
fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
diag.primary_message(msg!(
impl<'a> Diagnostic<'a, ()> for NonFmtPanicUnused {
fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
let mut diag = Diag::new(dcx, level, msg!(
"panic message contains {$count ->
[one] an unused
*[other] unused
@@ -1460,9 +1467,9 @@ fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
[one] placeholder
*[other] placeholders
}"
));
diag.arg("count", self.count);
diag.note(msg!("this message is not used as a format string when given without arguments, but will be in Rust 2021"));
))
.with_arg("count", self.count)
.with_note(msg!("this message is not used as a format string when given without arguments, but will be in Rust 2021"));
if let Some(span) = self.suggestion {
diag.span_suggestion(
span.shrink_to_hi(),
@@ -1482,10 +1489,11 @@ fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
Applicability::MachineApplicable,
);
}
diag
}
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag(
"panic message contains {$count ->
[one] a brace
@@ -1504,7 +1512,7 @@ pub(crate) struct NonFmtPanicBraces {
}
// nonstandard_style.rs
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("{$sort} `{$name}` should have an upper camel case name")]
pub(crate) struct NonCamelCaseType<'a> {
pub sort: &'a str,
@@ -1532,7 +1540,7 @@ pub(crate) enum NonCamelCaseTypeSub {
},
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("{$sort} `{$name}` should have a snake case name")]
pub(crate) struct NonSnakeCaseDiag<'a> {
pub sort: &'a str,
@@ -1630,7 +1638,7 @@ pub(crate) struct NonUpperCaseGlobalSubTool {
}
// noop_method_call.rs
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("call to `.{$method}()` on a reference in this situation does nothing")]
#[note(
"the type `{$orig_ty}` does not implement `{$trait_}`, so calling `{$method}` on `&{$orig_ty}` copies the reference, which does not do anything and can be removed"
@@ -1649,7 +1657,7 @@ pub(crate) struct NoopMethodCallDiag<'a> {
pub suggest_derive: Option<Span>,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag(
"using `.deref()` on a double reference, which returns `{$ty}` instead of dereferencing the inner type"
)]
@@ -1657,7 +1665,7 @@ pub(crate) struct SuspiciousDoubleRefDerefDiag<'a> {
pub ty: Ty<'a>,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag(
"using `.clone()` on a double reference, which returns `{$ty}` instead of cloning the inner type"
)]
@@ -1685,8 +1693,9 @@ pub(crate) enum NonLocalDefinitionsDiag {
},
}
impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag {
fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
impl<'a> Diagnostic<'a, ()> for NonLocalDefinitionsDiag {
fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
let mut diag = Diag::new(dcx, level, "");
match self {
NonLocalDefinitionsDiag::Impl {
depth,
@@ -1759,6 +1768,7 @@ fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
}
}
}
diag
}
}
@@ -1773,7 +1783,7 @@ pub(crate) struct NonLocalDefinitionsCargoUpdateNote {
}
// precedence.rs
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("`-` has lower precedence than method calls, which might be unexpected")]
#[note("e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4`")]
pub(crate) struct AmbiguousNegativeLiteralsDiag {
@@ -1808,7 +1818,7 @@ pub(crate) struct AmbiguousNegativeLiteralsCurrentBehaviorSuggestion {
}
// disallowed_pass_by_ref.rs
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("passing `{$ty}` by reference")]
pub(crate) struct DisallowedPassByRefDiag {
pub ty: String,
@@ -1817,7 +1827,7 @@ pub(crate) struct DisallowedPassByRefDiag {
}
// redundant_semicolon.rs
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag(
"unnecessary trailing {$multiple ->
[true] semicolons
@@ -1853,11 +1863,11 @@ pub(crate) struct DropTraitConstraintsDiag<'a> {
}
// Needed for def_path_str
impl<'a> LintDiagnostic<'a, ()> for DropTraitConstraintsDiag<'_> {
fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
diag.primary_message(msg!("bounds on `{$predicate}` are most likely incorrect, consider instead using `{$needs_drop}` to detect whether a type can be trivially dropped"));
diag.arg("predicate", self.predicate);
diag.arg("needs_drop", self.tcx.def_path_str(self.def_id));
impl<'a> Diagnostic<'a, ()> for DropTraitConstraintsDiag<'_> {
fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
Diag::new(dcx, level, msg!("bounds on `{$predicate}` are most likely incorrect, consider instead using `{$needs_drop}` to detect whether a type can be trivially dropped"))
.with_arg("predicate", self.predicate)
.with_arg("needs_drop", self.tcx.def_path_str(self.def_id))
}
}
@@ -1867,10 +1877,10 @@ pub(crate) struct DropGlue<'a> {
}
// Needed for def_path_str
impl<'a> LintDiagnostic<'a, ()> for DropGlue<'_> {
fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
diag.primary_message(msg!("types that do not implement `Drop` can still have drop glue, consider instead using `{$needs_drop}` to detect whether a type is trivially dropped"));
diag.arg("needs_drop", self.tcx.def_path_str(self.def_id));
impl<'a> Diagnostic<'a, ()> for DropGlue<'_> {
fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
Diag::new(dcx, level, msg!("types that do not implement `Drop` can still have drop glue, consider instead using `{$needs_drop}` to detect whether a type is trivially dropped"))
.with_arg("needs_drop", self.tcx.def_path_str(self.def_id))
}
}
@@ -1925,7 +1935,7 @@ pub(crate) enum IntegerToPtrTransmutesSuggestion<'tcx> {
}
// types.rs
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("range endpoint is out of range for `{$ty}`")]
pub(crate) struct RangeEndpointOutOfRange<'a> {
pub ty: &'a str,
@@ -1958,7 +1968,7 @@ pub(crate) enum UseInclusiveRange<'a> {
},
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("literal out of range for `{$ty}`")]
pub(crate) struct OverflowingBinHex<'a> {
pub ty: &'a str,
@@ -2016,7 +2026,7 @@ pub(crate) struct OverflowingBinHexSignBitSub<'a> {
pub int_ty: &'a str,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("literal out of range for `{$ty}`")]
#[note("the literal `{$lit}` does not fit into the type `{$ty}` whose range is `{$min}..={$max}`")]
pub(crate) struct OverflowingInt<'a> {
@@ -2034,7 +2044,7 @@ pub(crate) struct OverflowingIntHelp<'a> {
pub suggestion_ty: &'a str,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("only `u8` can be cast into `char`")]
pub(crate) struct OnlyCastu8ToChar {
#[suggestion(
@@ -2046,7 +2056,7 @@ pub(crate) struct OnlyCastu8ToChar {
pub literal: u128,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("literal out of range for `{$ty}`")]
#[note("the literal `{$lit}` does not fit into the type `{$ty}` whose range is `{$min}..={$max}`")]
pub(crate) struct OverflowingUInt<'a> {
@@ -2056,7 +2066,7 @@ pub(crate) struct OverflowingUInt<'a> {
pub max: u128,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("literal out of range for `{$ty}`")]
#[note(
"the literal `{$lit}` does not fit into the type `{$ty}` and will be converted to `{$ty}::INFINITY`"
@@ -2066,31 +2076,31 @@ pub(crate) struct OverflowingLiteral<'a> {
pub lit: String,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("surrogate values are not valid for `char`")]
#[note("`0xD800..=0xDFFF` are reserved for Unicode surrogates and are not valid `char` values")]
pub(crate) struct SurrogateCharCast {
pub literal: u128,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("value exceeds maximum `char` value")]
#[note("maximum valid `char` value is `0x10FFFF`")]
pub(crate) struct TooLargeCharCast {
pub literal: u128,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag(
"repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type"
)]
pub(crate) struct UsesPowerAlignment;
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("comparison is useless due to type limits")]
pub(crate) struct UnusedComparisons;
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
pub(crate) enum InvalidNanComparisons {
#[diag("incorrect NaN comparison, NaN cannot be directly compared to itself")]
EqNe {
@@ -2120,7 +2130,7 @@ pub(crate) enum InvalidNanComparisonsSuggestion {
Spanless,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
pub(crate) enum AmbiguousWidePointerComparisons<'a> {
#[diag(
"ambiguous wide pointer comparison, the comparison includes metadata which may not be expected"
@@ -2233,7 +2243,7 @@ pub(crate) struct AmbiguousWidePointerComparisonsExpectSuggestion<'a> {
pub(crate) after: Span,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
pub(crate) enum UnpredictableFunctionPointerComparisons<'a, 'tcx> {
#[diag(
"function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique"
@@ -2309,12 +2319,16 @@ pub(crate) struct ImproperCTypes<'a> {
}
// Used because of the complexity of Option<DiagMessage>, DiagMessage, and Option<Span>
impl<'a> LintDiagnostic<'a, ()> for ImproperCTypes<'_> {
fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
diag.primary_message(msg!("`extern` {$desc} uses type `{$ty}`, which is not FFI-safe"));
diag.arg("ty", self.ty);
diag.arg("desc", self.desc);
diag.span_label(self.label, msg!("not FFI-safe"));
impl<'a> Diagnostic<'a, ()> for ImproperCTypes<'_> {
fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
let mut diag = Diag::new(
dcx,
level,
msg!("`extern` {$desc} uses type `{$ty}`, which is not FFI-safe"),
)
.with_arg("ty", self.ty)
.with_arg("desc", self.desc)
.with_span_label(self.label, msg!("not FFI-safe"));
if let Some(help) = self.help {
diag.help(help);
}
@@ -2322,6 +2336,7 @@ fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
if let Some(note) = self.span_note {
diag.span_note(note, msg!("the type is defined here"));
}
diag
}
}
@@ -2332,34 +2347,34 @@ pub(crate) struct ImproperGpuKernelArg<'a> {
pub ty: Ty<'a>,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("function with the \"gpu-kernel\" ABI has a mangled name")]
#[help("use `unsafe(no_mangle)` or `unsafe(export_name = \"<name>\")`")]
#[note("mangled names make it hard to find the kernel, this is usually not intended")]
pub(crate) struct MissingGpuKernelExportName;
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("enum variant is more than three times larger ({$largest} bytes) than the next largest")]
pub(crate) struct VariantSizeDifferencesDiag {
pub largest: u64,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("atomic loads cannot have `Release` or `AcqRel` ordering")]
#[help("consider using ordering modes `Acquire`, `SeqCst` or `Relaxed`")]
pub(crate) struct AtomicOrderingLoad;
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("atomic stores cannot have `Acquire` or `AcqRel` ordering")]
#[help("consider using ordering modes `Release`, `SeqCst` or `Relaxed`")]
pub(crate) struct AtomicOrderingStore;
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("memory fences cannot have `Relaxed` ordering")]
#[help("consider using ordering modes `Acquire`, `Release`, `AcqRel` or `SeqCst`")]
pub(crate) struct AtomicOrderingFence;
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag(
"`{$method}`'s failure ordering may not be `Release` or `AcqRel`, since a failed `{$method}` does not result in a write"
)]
@@ -2371,7 +2386,7 @@ pub(crate) struct InvalidAtomicOrderingDiag {
}
// unused.rs
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("unused {$op} that must be used")]
pub(crate) struct UnusedOp<'a> {
pub op: &'a str,
@@ -2406,7 +2421,7 @@ pub(crate) enum UnusedOpSuggestion {
},
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("unused result of type `{$ty}`")]
pub(crate) struct UnusedResult<'a> {
pub ty: Ty<'a>,
@@ -2414,7 +2429,7 @@ pub(crate) struct UnusedResult<'a> {
// FIXME(davidtwco): this isn't properly translatable because of the
// pre/post strings
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag(
"unused {$pre}{$count ->
[one] closure
@@ -2430,7 +2445,7 @@ pub(crate) struct UnusedClosure<'a> {
// FIXME(davidtwco): this isn't properly translatable because of the
// pre/post strings
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag(
"unused {$pre}{$count ->
[one] coroutine
@@ -2481,12 +2496,13 @@ pub(crate) enum UnusedDefSuggestion {
}
// Needed because of def_path_str
impl<'a> LintDiagnostic<'a, ()> for UnusedDef<'_, '_> {
fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
diag.primary_message(msg!("unused {$pre}`{$def}`{$post} that must be used"));
diag.arg("pre", self.pre);
diag.arg("post", self.post);
diag.arg("def", self.cx.tcx.def_path_str(self.def_id));
impl<'a> Diagnostic<'a, ()> for UnusedDef<'_, '_> {
fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
let mut diag =
Diag::new(dcx, level, msg!("unused {$pre}`{$def}`{$post} that must be used"))
.with_arg("pre", self.pre)
.with_arg("post", self.post)
.with_arg("def", self.cx.tcx.def_path_str(self.def_id));
// check for #[must_use = "..."]
if let Some(note) = self.note {
diag.note(note.to_string());
@@ -2494,10 +2510,11 @@ fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
if let Some(sugg) = self.suggestion {
diag.subdiagnostic(sugg);
}
diag
}
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("path statement drops value")]
pub(crate) struct PathStatementDrop {
#[subdiagnostic]
@@ -2523,11 +2540,11 @@ pub(crate) enum PathStatementDropSub {
},
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("path statement with no effect")]
pub(crate) struct PathStatementNoEffect;
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("unnecessary {$delim} around {$item}")]
pub(crate) struct UnusedDelim<'a> {
pub delim: &'static str,
@@ -2547,17 +2564,17 @@ pub(crate) struct UnusedDelimSuggestion {
pub end_replace: &'static str,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("braces around {$node} is unnecessary")]
pub(crate) struct UnusedImportBracesDiag {
pub node: Symbol,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("unnecessary allocation, use `&` instead")]
pub(crate) struct UnusedAllocationDiag;
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("unnecessary allocation, use `&mut` instead")]
pub(crate) struct UnusedAllocationMutDiag;
@@ -2580,14 +2597,14 @@ fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
}
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("binding has unit type `()`")]
pub(crate) struct UnitBindingsDiag {
#[label("this pattern is inferred to be the unit type `()`")]
pub label: Span,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
pub(crate) enum InvalidAsmLabel {
#[diag("avoid using named labels in inline assembly")]
#[help("only local labels of the form `<number>:` should be used in inline asm")]
@@ -3344,7 +3361,7 @@ pub(crate) struct AssociatedConstElidedLifetime {
pub lifetimes_in_scope: MultiSpan,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("creating a {$shared_label}reference to mutable static")]
pub(crate) struct RefOfMutStatic<'a> {
#[label("{$shared_label}reference to mutable static")]
@@ -3384,9 +3401,9 @@ pub(crate) enum MutRefSugg {
},
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("`use` of a local item without leading `self::`, `super::`, or `crate::`")]
pub(crate) struct UnqualifiedLocalImportsDiag {}
pub(crate) struct UnqualifiedLocalImportsDiag;
#[derive(LintDiagnostic)]
#[diag("will be parsed as a guarded string in Rust 2024")]
@@ -3438,8 +3455,8 @@ pub(crate) struct MismatchedLifetimeSyntaxes {
pub suggestions: Vec<MismatchedLifetimeSyntaxesSuggestion>,
}
impl<'a, G: EmissionGuarantee> LintDiagnostic<'a, G> for MismatchedLifetimeSyntaxes {
fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>) {
impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for MismatchedLifetimeSyntaxes {
fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> {
let counts = self.inputs.len() + self.outputs.len();
let message = match counts {
LifetimeSyntaxCategories { hidden: 0, elided: 0, named: 0 } => {
@@ -3462,7 +3479,7 @@ fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>) {
msg!("hiding or eliding a lifetime that's named elsewhere is confusing")
}
};
diag.primary_message(message);
let mut diag = Diag::new(dcx, level, message);
for s in self.inputs.hidden {
diag.span_label(s, msg!("the lifetime is hidden here"));
@@ -3497,6 +3514,7 @@ fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>) {
diag.subdiagnostic(s);
}
}
diag
}
}
@@ -3933,7 +3951,7 @@ pub(crate) struct MalformedOnConstAttrLint {
pub span: Span,
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("`Eq::assert_receiver_is_total_eq` should never be implemented by hand")]
#[note("this method was used to add checks to the `Eq` derive macro")]
pub(crate) struct EqInternalMethodImplemented;
@@ -1,6 +1,6 @@
use rustc_hir::{self as hir, AmbigArg};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_macros::{LintDiagnostic, Subdiagnostic};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_middle::ty::print::{PrintTraitPredicateExt as _, TraitPredPrintModifiersAndPath};
use rustc_middle::ty::{self, BottomUpFolder, Ty, TypeFoldable};
use rustc_session::{declare_lint, declare_lint_pass};
@@ -201,7 +201,7 @@ fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx hir::Ty<'tcx, AmbigArg>
}
}
#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag("opaque type `{$ty}` does not satisfy its associated type bounds")]
struct OpaqueHiddenInferredBoundLint<'tcx> {
ty: Ty<'tcx>,
@@ -77,7 +77,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
cx.emit_span_lint(
UNQUALIFIED_LOCAL_IMPORTS,
first_seg.ident.span,
lints::UnqualifiedLocalImportsDiag {},
lints::UnqualifiedLocalImportsDiag,
);
}
}
+1 -1
View File
@@ -90,7 +90,7 @@ macro_rules! arena_types {
[] codegen_unit: rustc_middle::mir::mono::CodegenUnit<'tcx>,
[decode] attribute: rustc_hir::Attribute,
[] name_set: rustc_data_structures::unord::UnordSet<rustc_span::Symbol>,
[] autodiff_item: rustc_ast::expand::autodiff_attrs::AutoDiffItem,
[] autodiff_item: rustc_hir::attrs::AutoDiffItem,
[] ordered_name_set: rustc_data_structures::fx::FxIndexSet<rustc_span::Symbol>,
[] valtree: rustc_middle::ty::ValTreeKind<rustc_middle::ty::TyCtxt<'tcx>>,
[] stable_order_of_exportable_impls:
@@ -51,14 +51,14 @@
use std::hash::Hash;
use rustc_data_structures::fingerprint::{Fingerprint, PackedFingerprint};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd, ToStableHashKey};
use rustc_data_structures::stable_hasher::{StableHasher, StableOrd, ToStableHashKey};
use rustc_hir::def_id::DefId;
use rustc_hir::definitions::DefPathHash;
use rustc_macros::{Decodable, Encodable, HashStable};
use rustc_span::Symbol;
use super::{KeyFingerprintStyle, SerializedDepNodeIndex};
use crate::ich::StableHashingContext;
use crate::dep_graph::DepNodeKey;
use crate::mir::mono::MonoItem;
use crate::ty::{TyCtxt, tls};
@@ -168,58 +168,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
/// Trait for query keys as seen by dependency-node tracking.
pub trait DepNodeKey<'tcx>: fmt::Debug + Sized {
fn key_fingerprint_style() -> KeyFingerprintStyle;
/// This method turns a query key into an opaque `Fingerprint` to be used
/// in `DepNode`.
fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint;
fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String;
/// This method tries to recover the query key from the given `DepNode`,
/// something which is needed when forcing `DepNode`s during red-green
/// evaluation. The query system will only call this method if
/// `fingerprint_style()` is not `FingerprintStyle::Opaque`.
/// It is always valid to return `None` here, in which case incremental
/// compilation will treat the query as having changed instead of forcing it.
fn try_recover_key(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self>;
}
// Blanket impl of `DepNodeKey`, which is specialized by other impls elsewhere.
impl<'tcx, T> DepNodeKey<'tcx> for T
where
T: for<'a> HashStable<StableHashingContext<'a>> + fmt::Debug,
{
#[inline(always)]
default fn key_fingerprint_style() -> KeyFingerprintStyle {
KeyFingerprintStyle::Opaque
}
#[inline(always)]
default fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
tcx.with_stable_hashing_context(|mut hcx| {
let mut hasher = StableHasher::new();
self.hash_stable(&mut hcx, &mut hasher);
hasher.finish()
})
}
#[inline(always)]
default fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
// Make sure to print dep node params with reduced queries since printing
// may themselves call queries, which may lead to (possibly untracked!)
// query cycles.
tcx.with_reduced_queries(|| format!("{self:?}"))
}
#[inline(always)]
default fn try_recover_key(_: TyCtxt<'tcx>, _: &DepNode) -> Option<Self> {
None
}
}
/// This struct stores function pointers and other metadata for a particular DepKind.
///
/// Information is retrieved by indexing the `DEP_KINDS` array using the integer value
@@ -1,11 +1,67 @@
use std::fmt::Debug;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId, ModDefId};
use rustc_hir::definitions::DefPathHash;
use rustc_hir::{HirId, ItemLocalId, OwnerId};
use crate::dep_graph::{DepNode, DepNodeKey, KeyFingerprintStyle};
use crate::dep_graph::{DepNode, KeyFingerprintStyle};
use crate::ich::StableHashingContext;
use crate::ty::TyCtxt;
/// Trait for query keys as seen by dependency-node tracking.
pub trait DepNodeKey<'tcx>: Debug + Sized {
fn key_fingerprint_style() -> KeyFingerprintStyle;
/// This method turns a query key into an opaque `Fingerprint` to be used
/// in `DepNode`.
fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint;
fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String;
/// This method tries to recover the query key from the given `DepNode`,
/// something which is needed when forcing `DepNode`s during red-green
/// evaluation. The query system will only call this method if
/// `fingerprint_style()` is not `FingerprintStyle::Opaque`.
/// It is always valid to return `None` here, in which case incremental
/// compilation will treat the query as having changed instead of forcing it.
fn try_recover_key(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self>;
}
// Blanket impl of `DepNodeKey`, which is specialized by other impls elsewhere.
impl<'tcx, T> DepNodeKey<'tcx> for T
where
T: for<'a> HashStable<StableHashingContext<'a>> + Debug,
{
#[inline(always)]
default fn key_fingerprint_style() -> KeyFingerprintStyle {
KeyFingerprintStyle::Opaque
}
#[inline(always)]
default fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
tcx.with_stable_hashing_context(|mut hcx| {
let mut hasher = StableHasher::new();
self.hash_stable(&mut hcx, &mut hasher);
hasher.finish()
})
}
#[inline(always)]
default fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
// Make sure to print dep node params with reduced queries since printing
// may themselves call queries, which may lead to (possibly untracked!)
// query cycles.
tcx.with_reduced_queries(|| format!("{self:?}"))
}
#[inline(always)]
default fn try_recover_key(_: TyCtxt<'tcx>, _: &DepNode) -> Option<Self> {
None
}
}
impl<'tcx> DepNodeKey<'tcx> for () {
#[inline(always)]
fn key_fingerprint_style() -> KeyFingerprintStyle {
+2 -1
View File
@@ -3,8 +3,9 @@
use tracing::instrument;
pub use self::dep_node::{
DepKind, DepKindVTable, DepNode, DepNodeKey, WorkProductId, dep_kind_from_label, label_strs,
DepKind, DepKindVTable, DepNode, WorkProductId, dep_kind_from_label, label_strs,
};
pub use self::dep_node_key::DepNodeKey;
pub use self::graph::{
DepGraph, DepGraphData, DepNodeIndex, QuerySideEffect, TaskDepsRef, WorkProduct,
WorkProductMap, hash_result,
-2
View File
@@ -299,7 +299,6 @@ fn explain_lint_level_source(
/// for example:
/// - [`TyCtxt::emit_node_span_lint`]
/// - [`TyCtxt::node_span_lint`]
/// - [`TyCtxt::emit_node_lint`]
/// - [`TyCtxt::node_lint`]
/// - `LintContext::opt_span_lint`
///
@@ -490,7 +489,6 @@ fn lint_level_impl(
///
/// - [`TyCtxt::emit_node_span_lint`]
/// - [`TyCtxt::node_span_lint`]
/// - [`TyCtxt::emit_node_lint`]
/// - [`TyCtxt::node_lint`]
/// - `LintContext::opt_span_lint`
///
+4 -10
View File
@@ -1,19 +1,13 @@
use std::fmt::Debug;
use std::hash::Hash;
use std::sync::OnceLock;
use rustc_data_structures::sharded::ShardedHashMap;
use rustc_data_structures::stable_hasher::HashStable;
pub use rustc_data_structures::vec_cache::VecCache;
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_index::Idx;
use rustc_span::def_id::{DefId, DefIndex};
use crate::dep_graph::DepNodeIndex;
use crate::ich::StableHashingContext;
/// Traits that all query keys must satisfy.
pub trait QueryCacheKey = Hash + Eq + Copy + Debug + for<'a> HashStable<StableHashingContext<'a>>;
use crate::query::keys::QueryKey;
/// Trait for types that serve as an in-memory cache for query results,
/// for a given key (argument) type and value (return) type.
@@ -21,7 +15,7 @@
/// Types implementing this trait are associated with actual key/value types
/// by the `Cache` associated type of the `rustc_middle::query::Key` trait.
pub trait QueryCache: Sized {
type Key: QueryCacheKey;
type Key: QueryKey;
type Value: Copy;
/// Returns the cached value (and other information) associated with the
@@ -53,7 +47,7 @@ fn default() -> Self {
impl<K, V> QueryCache for DefaultCache<K, V>
where
K: QueryCacheKey,
K: QueryKey,
V: Copy,
{
type Key = K;
@@ -180,7 +174,7 @@ fn len(&self) -> usize {
impl<K, V> QueryCache for VecCache<K, V, DepNodeIndex>
where
K: Idx + QueryCacheKey,
K: Idx + QueryKey,
V: Copy,
{
type Key = K;
+9 -12
View File
@@ -35,17 +35,16 @@ fn try_get_cached<'tcx, C>(tcx: TyCtxt<'tcx>, cache: &C, key: &C::Key) -> Option
#[inline(always)]
pub(crate) fn query_get_at<'tcx, C>(
tcx: TyCtxt<'tcx>,
execute_query: fn(TyCtxt<'tcx>, Span, C::Key, QueryMode) -> Option<C::Value>,
query_cache: &C,
span: Span,
query: &'tcx QueryVTable<'tcx, C>,
key: C::Key,
) -> C::Value
where
C: QueryCache,
{
match try_get_cached(tcx, query_cache, &key) {
match try_get_cached(tcx, &query.cache, &key) {
Some(value) => value,
None => execute_query(tcx, span, key, QueryMode::Get).unwrap(),
None => (query.execute_query_fn)(tcx, span, key, QueryMode::Get).unwrap(),
}
}
@@ -54,15 +53,14 @@ pub(crate) fn query_get_at<'tcx, C>(
#[inline]
pub(crate) fn query_ensure<'tcx, C>(
tcx: TyCtxt<'tcx>,
execute_query: fn(TyCtxt<'tcx>, Span, C::Key, QueryMode) -> Option<C::Value>,
query_cache: &C,
query: &'tcx QueryVTable<'tcx, C>,
key: C::Key,
ensure_mode: EnsureMode,
) where
C: QueryCache,
{
if try_get_cached(tcx, query_cache, &key).is_none() {
execute_query(tcx, DUMMY_SP, key, QueryMode::Ensure { ensure_mode });
if try_get_cached(tcx, &query.cache, &key).is_none() {
(query.execute_query_fn)(tcx, DUMMY_SP, key, QueryMode::Ensure { ensure_mode });
}
}
@@ -71,8 +69,7 @@ pub(crate) fn query_ensure<'tcx, C>(
#[inline]
pub(crate) fn query_ensure_error_guaranteed<'tcx, C, T>(
tcx: TyCtxt<'tcx>,
execute_query: fn(TyCtxt<'tcx>, Span, C::Key, QueryMode) -> Option<C::Value>,
query_cache: &C,
query: &'tcx QueryVTable<'tcx, C>,
key: C::Key,
// This arg is needed to match the signature of `query_ensure`,
// but should always be `EnsureMode::Ok`.
@@ -84,10 +81,10 @@ pub(crate) fn query_ensure_error_guaranteed<'tcx, C, T>(
{
assert_matches!(ensure_mode, EnsureMode::Ok);
if let Some(res) = try_get_cached(tcx, query_cache, &key) {
if let Some(res) = try_get_cached(tcx, &query.cache, &key) {
erase::restore_val(res).map(drop)
} else {
execute_query(tcx, DUMMY_SP, key, QueryMode::Ensure { ensure_mode })
(query.execute_query_fn)(tcx, DUMMY_SP, key, QueryMode::Ensure { ensure_mode })
.map(erase::restore_val)
.map(|res| res.map(drop))
// Either we actually executed the query, which means we got a full `Result`,
+62 -57
View File
@@ -1,13 +1,17 @@
//! Defines the set of legal keys that can be used in queries.
use std::ffi::OsStr;
use std::fmt::Debug;
use std::hash::Hash;
use rustc_ast::tokenstream::TokenStream;
use rustc_data_structures::stable_hasher::HashStable;
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId};
use rustc_hir::hir_id::OwnerId;
use rustc_span::{DUMMY_SP, Ident, LocalExpnId, Span, Symbol};
use crate::dep_graph::DepNodeIndex;
use crate::ich::StableHashingContext;
use crate::infer::canonical::CanonicalQueryInput;
use crate::mir::mono::CollectionMode;
use crate::query::{DefIdCache, DefaultCache, SingleCache, VecCache};
@@ -20,9 +24,10 @@
#[derive(Copy, Clone, Debug)]
pub struct LocalCrate;
/// The `Key` trait controls what types can legally be used as the key
/// for a query.
pub trait Key: Sized {
pub trait QueryKeyBounds = Copy + Debug + Eq + Hash + for<'a> HashStable<StableHashingContext<'a>>;
/// Controls what types can legally be used as the key for a query.
pub trait QueryKey: Sized + QueryKeyBounds {
/// The type of in-memory cache to use for queries with this key type.
///
/// In practice the cache type must implement [`QueryCache`], though that
@@ -47,15 +52,15 @@ fn def_id_for_ty_in_cycle(&self) -> Option<DefId> {
}
}
pub trait AsLocalKey: Key {
type LocalKey;
pub trait AsLocalQueryKey: QueryKey {
type LocalQueryKey;
/// Given an instance of this key, what crate is it referring to?
/// This is used to find the provider.
fn as_local_key(&self) -> Option<Self::LocalKey>;
fn as_local_key(&self) -> Option<Self::LocalQueryKey>;
}
impl Key for () {
impl QueryKey for () {
type Cache<V> = SingleCache<V>;
fn default_span(&self, _: TyCtxt<'_>) -> Span {
@@ -63,37 +68,37 @@ fn default_span(&self, _: TyCtxt<'_>) -> Span {
}
}
impl<'tcx> Key for ty::InstanceKind<'tcx> {
impl<'tcx> QueryKey for ty::InstanceKind<'tcx> {
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
tcx.def_span(self.def_id())
}
}
impl<'tcx> Key for ty::Instance<'tcx> {
impl<'tcx> QueryKey for ty::Instance<'tcx> {
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
tcx.def_span(self.def_id())
}
}
impl<'tcx> Key for mir::interpret::GlobalId<'tcx> {
impl<'tcx> QueryKey for mir::interpret::GlobalId<'tcx> {
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
self.instance.default_span(tcx)
}
}
impl<'tcx> Key for (Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>) {
impl<'tcx> QueryKey for (Ty<'tcx>, Option<ty::ExistentialTraitRef<'tcx>>) {
fn default_span(&self, _: TyCtxt<'_>) -> Span {
DUMMY_SP
}
}
impl<'tcx> Key for ty::LitToConstInput<'tcx> {
impl<'tcx> QueryKey for ty::LitToConstInput<'tcx> {
fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
DUMMY_SP
}
}
impl Key for CrateNum {
impl QueryKey for CrateNum {
type Cache<V> = VecCache<Self, V, DepNodeIndex>;
fn default_span(&self, _: TyCtxt<'_>) -> Span {
@@ -101,16 +106,16 @@ fn default_span(&self, _: TyCtxt<'_>) -> Span {
}
}
impl AsLocalKey for CrateNum {
type LocalKey = LocalCrate;
impl AsLocalQueryKey for CrateNum {
type LocalQueryKey = LocalCrate;
#[inline(always)]
fn as_local_key(&self) -> Option<Self::LocalKey> {
fn as_local_key(&self) -> Option<Self::LocalQueryKey> {
(*self == LOCAL_CRATE).then_some(LocalCrate)
}
}
impl Key for OwnerId {
impl QueryKey for OwnerId {
type Cache<V> = VecCache<Self, V, DepNodeIndex>;
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
@@ -122,7 +127,7 @@ fn key_as_def_id(&self) -> Option<DefId> {
}
}
impl Key for LocalDefId {
impl QueryKey for LocalDefId {
type Cache<V> = VecCache<Self, V, DepNodeIndex>;
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
@@ -134,7 +139,7 @@ fn key_as_def_id(&self) -> Option<DefId> {
}
}
impl Key for DefId {
impl QueryKey for DefId {
type Cache<V> = DefIdCache<V>;
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
@@ -147,16 +152,16 @@ fn key_as_def_id(&self) -> Option<DefId> {
}
}
impl AsLocalKey for DefId {
type LocalKey = LocalDefId;
impl AsLocalQueryKey for DefId {
type LocalQueryKey = LocalDefId;
#[inline(always)]
fn as_local_key(&self) -> Option<Self::LocalKey> {
fn as_local_key(&self) -> Option<Self::LocalQueryKey> {
self.as_local()
}
}
impl Key for LocalModDefId {
impl QueryKey for LocalModDefId {
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
tcx.def_span(*self)
}
@@ -167,19 +172,19 @@ fn key_as_def_id(&self) -> Option<DefId> {
}
}
impl Key for SimplifiedType {
impl QueryKey for SimplifiedType {
fn default_span(&self, _: TyCtxt<'_>) -> Span {
DUMMY_SP
}
}
impl Key for (DefId, DefId) {
impl QueryKey for (DefId, DefId) {
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
self.1.default_span(tcx)
}
}
impl Key for (DefId, Ident) {
impl QueryKey for (DefId, Ident) {
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
tcx.def_span(self.0)
}
@@ -190,73 +195,73 @@ fn key_as_def_id(&self) -> Option<DefId> {
}
}
impl Key for (LocalDefId, LocalDefId, Ident) {
impl QueryKey for (LocalDefId, LocalDefId, Ident) {
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
self.1.default_span(tcx)
}
}
impl Key for (CrateNum, DefId) {
impl QueryKey for (CrateNum, DefId) {
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
self.1.default_span(tcx)
}
}
impl AsLocalKey for (CrateNum, DefId) {
type LocalKey = DefId;
impl AsLocalQueryKey for (CrateNum, DefId) {
type LocalQueryKey = DefId;
#[inline(always)]
fn as_local_key(&self) -> Option<Self::LocalKey> {
fn as_local_key(&self) -> Option<Self::LocalQueryKey> {
(self.0 == LOCAL_CRATE).then(|| self.1)
}
}
impl Key for (CrateNum, SimplifiedType) {
impl QueryKey for (CrateNum, SimplifiedType) {
fn default_span(&self, _: TyCtxt<'_>) -> Span {
DUMMY_SP
}
}
impl AsLocalKey for (CrateNum, SimplifiedType) {
type LocalKey = SimplifiedType;
impl AsLocalQueryKey for (CrateNum, SimplifiedType) {
type LocalQueryKey = SimplifiedType;
#[inline(always)]
fn as_local_key(&self) -> Option<Self::LocalKey> {
fn as_local_key(&self) -> Option<Self::LocalQueryKey> {
(self.0 == LOCAL_CRATE).then(|| self.1)
}
}
impl Key for (DefId, ty::SizedTraitKind) {
impl QueryKey for (DefId, ty::SizedTraitKind) {
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
self.0.default_span(tcx)
}
}
impl<'tcx> Key for GenericArgsRef<'tcx> {
impl<'tcx> QueryKey for GenericArgsRef<'tcx> {
fn default_span(&self, _: TyCtxt<'_>) -> Span {
DUMMY_SP
}
}
impl<'tcx> Key for (DefId, GenericArgsRef<'tcx>) {
impl<'tcx> QueryKey for (DefId, GenericArgsRef<'tcx>) {
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
self.0.default_span(tcx)
}
}
impl<'tcx> Key for ty::TraitRef<'tcx> {
impl<'tcx> QueryKey for ty::TraitRef<'tcx> {
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
tcx.def_span(self.def_id)
}
}
impl<'tcx> Key for GenericArg<'tcx> {
impl<'tcx> QueryKey for GenericArg<'tcx> {
fn default_span(&self, _: TyCtxt<'_>) -> Span {
DUMMY_SP
}
}
impl<'tcx> Key for Ty<'tcx> {
impl<'tcx> QueryKey for Ty<'tcx> {
fn default_span(&self, _: TyCtxt<'_>) -> Span {
DUMMY_SP
}
@@ -270,19 +275,19 @@ fn def_id_for_ty_in_cycle(&self) -> Option<DefId> {
}
}
impl<'tcx> Key for (Ty<'tcx>, Ty<'tcx>) {
impl<'tcx> QueryKey for (Ty<'tcx>, Ty<'tcx>) {
fn default_span(&self, _: TyCtxt<'_>) -> Span {
DUMMY_SP
}
}
impl<'tcx> Key for ty::Clauses<'tcx> {
impl<'tcx> QueryKey for ty::Clauses<'tcx> {
fn default_span(&self, _: TyCtxt<'_>) -> Span {
DUMMY_SP
}
}
impl<'tcx, T: Key> Key for ty::PseudoCanonicalInput<'tcx, T> {
impl<'tcx, T: QueryKey> QueryKey for ty::PseudoCanonicalInput<'tcx, T> {
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
self.value.default_span(tcx)
}
@@ -292,19 +297,19 @@ fn def_id_for_ty_in_cycle(&self) -> Option<DefId> {
}
}
impl Key for Symbol {
impl QueryKey for Symbol {
fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
DUMMY_SP
}
}
impl Key for Option<Symbol> {
impl QueryKey for Option<Symbol> {
fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
DUMMY_SP
}
}
impl<'tcx> Key for &'tcx OsStr {
impl<'tcx> QueryKey for &'tcx OsStr {
fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
DUMMY_SP
}
@@ -312,55 +317,55 @@ fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
/// Canonical query goals correspond to abstract trait operations that
/// are not tied to any crate in particular.
impl<'tcx, T: Clone> Key for CanonicalQueryInput<'tcx, T> {
impl<'tcx, T: QueryKeyBounds> QueryKey for CanonicalQueryInput<'tcx, T> {
fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
DUMMY_SP
}
}
impl<'tcx, T: Clone> Key for (CanonicalQueryInput<'tcx, T>, bool) {
impl<'tcx, T: QueryKeyBounds> QueryKey for (CanonicalQueryInput<'tcx, T>, bool) {
fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
DUMMY_SP
}
}
impl<'tcx> Key for (Ty<'tcx>, rustc_abi::VariantIdx) {
impl<'tcx> QueryKey for (Ty<'tcx>, rustc_abi::VariantIdx) {
fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
DUMMY_SP
}
}
impl<'tcx> Key for (ty::Predicate<'tcx>, traits::WellFormedLoc) {
impl<'tcx> QueryKey for (ty::Predicate<'tcx>, traits::WellFormedLoc) {
fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
DUMMY_SP
}
}
impl<'tcx> Key for (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>) {
impl<'tcx> QueryKey for (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>) {
fn default_span(&self, _: TyCtxt<'_>) -> Span {
DUMMY_SP
}
}
impl<'tcx> Key for (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>) {
impl<'tcx> QueryKey for (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>) {
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
self.0.default_span(tcx)
}
}
impl<'tcx> Key for ty::Value<'tcx> {
impl<'tcx> QueryKey for ty::Value<'tcx> {
fn default_span(&self, _: TyCtxt<'_>) -> Span {
DUMMY_SP
}
}
impl<'tcx> Key for (LocalExpnId, &'tcx TokenStream) {
impl<'tcx> QueryKey for (LocalExpnId, &'tcx TokenStream) {
fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
self.0.expn_data().call_site
}
}
impl<'tcx> Key for (ValidityRequirement, ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) {
impl<'tcx> QueryKey for (ValidityRequirement, ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) {
// Just forward to `Ty<'tcx>`
fn default_span(&self, _: TyCtxt<'_>) -> Span {
@@ -375,7 +380,7 @@ fn def_id_for_ty_in_cycle(&self) -> Option<DefId> {
}
}
impl<'tcx> Key for (ty::Instance<'tcx>, CollectionMode) {
impl<'tcx> QueryKey for (ty::Instance<'tcx>, CollectionMode) {
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
self.0.default_span(tcx)
}
+2 -4
View File
@@ -1,10 +1,8 @@
use rustc_hir::def_id::LocalDefId;
pub use self::caches::{
DefIdCache, DefaultCache, QueryCache, QueryCacheKey, SingleCache, VecCache,
};
pub use self::caches::{DefIdCache, DefaultCache, QueryCache, SingleCache, VecCache};
pub use self::job::{QueryInfo, QueryJob, QueryJobId, QueryLatch, QueryWaiter};
pub use self::keys::{AsLocalKey, Key, LocalCrate};
pub use self::keys::{AsLocalQueryKey, LocalCrate, QueryKey};
pub use self::plumbing::{
ActiveKeyStatus, CycleError, CycleErrorHandling, EnsureMode, IntoQueryParam, QueryMode,
QueryState, TyCtxtAt, TyCtxtEnsureDone, TyCtxtEnsureOk,
+16 -10
View File
@@ -157,6 +157,15 @@ pub struct QueryVTable<'tcx, C: QueryCache> {
/// Used when reporting query cycle errors and similar problems.
pub description_fn: fn(TyCtxt<'tcx>, C::Key) -> String,
/// Function pointer that is called by the query methods on [`TyCtxt`] and
/// friends[^1], after they have checked the in-memory cache and found no
/// existing value for this key.
///
/// Transitive responsibilities include trying to load a disk-cached value
/// if possible (incremental only), invoking the query provider if necessary,
/// and putting the obtained value into the in-memory cache.
///
/// [^1]: [`TyCtxt`], [`TyCtxtAt`], [`TyCtxtEnsureOk`], [`TyCtxtEnsureDone`]
pub execute_query_fn: fn(TyCtxt<'tcx>, Span, C::Key, QueryMode) -> Option<C::Value>,
}
@@ -383,7 +392,7 @@ pub mod $name {
pub type LocalKey<'tcx> = if_separate_provide_extern!(
[$($modifiers)*]
(<Key<'tcx> as $crate::query::AsLocalKey>::LocalKey)
(<Key<'tcx> as $crate::query::AsLocalQueryKey>::LocalQueryKey)
(Key<'tcx>)
);
@@ -427,8 +436,8 @@ pub fn provided_to_erased<'tcx>(
erase::erase_val(value)
}
pub type Storage<'tcx> =
<Key<'tcx> as $crate::query::Key>::Cache<Erased<Value<'tcx>>>;
pub type Cache<'tcx> =
<Key<'tcx> as $crate::query::QueryKey>::Cache<Erased<Value<'tcx>>>;
// Ensure that keys grow no larger than 88 bytes by accident.
// Increase this limit if necessary, but do try to keep the size low if possible
@@ -495,8 +504,7 @@ pub fn $name(
(crate::query::inner::query_ensure)
)(
self.tcx,
self.tcx.query_system.query_vtables.$name.execute_query_fn,
&self.tcx.query_system.query_vtables.$name.cache,
&self.tcx.query_system.query_vtables.$name,
$crate::query::IntoQueryParam::into_query_param(key),
$crate::query::EnsureMode::Ok,
)
@@ -511,8 +519,7 @@ impl<'tcx> $crate::query::TyCtxtEnsureDone<'tcx> {
pub fn $name(self, key: query_helper_param_ty!($($K)*)) {
crate::query::inner::query_ensure(
self.tcx,
self.tcx.query_system.query_vtables.$name.execute_query_fn,
&self.tcx.query_system.query_vtables.$name.cache,
&self.tcx.query_system.query_vtables.$name,
$crate::query::IntoQueryParam::into_query_param(key),
$crate::query::EnsureMode::Done,
);
@@ -540,9 +547,8 @@ pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V {
erase::restore_val::<$V>(inner::query_get_at(
self.tcx,
self.tcx.query_system.query_vtables.$name.execute_query_fn,
&self.tcx.query_system.query_vtables.$name.cache,
self.span,
&self.tcx.query_system.query_vtables.$name,
$crate::query::IntoQueryParam::into_query_param(key),
))
}
@@ -575,7 +581,7 @@ pub fn $name(self, value: $name::ProvidedValue<'tcx>) {
/// Holds a `QueryVTable` for each query.
pub struct QueryVTables<'tcx> {
$(
pub $name: ::rustc_middle::query::plumbing::QueryVTable<'tcx, $name::Storage<'tcx>>,
pub $name: ::rustc_middle::query::plumbing::QueryVTable<'tcx, $name::Cache<'tcx>>,
)*
}
+6 -7
View File
@@ -29,7 +29,7 @@
use rustc_data_structures::sync::{
self, DynSend, DynSync, FreezeReadGuard, Lock, RwLock, WorkerLocal,
};
use rustc_errors::{Applicability, Diag, DiagCtxtHandle, Diagnostic, LintDiagnostic, MultiSpan};
use rustc_errors::{Applicability, Diag, DiagCtxtHandle, Diagnostic, MultiSpan};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId};
use rustc_hir::definitions::{DefPathData, Definitions, DisambiguatorState};
@@ -2554,18 +2554,17 @@ pub fn disabled_nightly_features<E: rustc_errors::EmissionGuarantee>(
}
}
/// Emit a lint from a lint struct (some type that implements `LintDiagnostic`, typically
/// generated by `#[derive(LintDiagnostic)]`).
/// Emit a lint from a lint struct (some type that implements `Diagnostic`, typically generated
/// by `#[derive(Diagnostic)]`).
#[track_caller]
pub fn emit_node_lint(
self,
lint: &'static Lint,
id: HirId,
decorator: impl for<'a> LintDiagnostic<'a, ()>,
decorator: impl for<'a> Diagnostic<'a, ()>,
) {
self.node_lint(lint, id, |lint| {
decorator.decorate_lint(lint);
})
let level = self.lint_level_at_node(lint, id);
diag_lint_level(self.sess, lint, level, None, decorator);
}
/// Emit a lint at the appropriate level for a hir node.
@@ -8,7 +8,6 @@
use rustc_middle::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_session::config::{InliningThreshold, OptLevel};
use rustc_span::sym;
use crate::{inline, pass_manager as pm};
@@ -37,11 +36,7 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
}
// FIXME(autodiff): replace this as per discussion in https://github.com/rust-lang/rust/pull/149033#discussion_r2535465880
#[allow(deprecated)]
if tcx.has_attr(def_id, sym::autodiff_forward)
|| tcx.has_attr(def_id, sym::autodiff_reverse)
|| tcx.has_attr(def_id, sym::rustc_autodiff)
{
if find_attr!(tcx, def_id, RustcAutodiff(..)) {
return true;
}
+1 -1
View File
@@ -4,7 +4,7 @@
};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_middle::mir::AssertKind;
use rustc_middle::query::Key;
use rustc_middle::query::QueryKey;
use rustc_middle::ty::TyCtxt;
use rustc_session::lint::{self, Lint};
use rustc_span::def_id::DefId;
+2 -23
View File
@@ -53,7 +53,6 @@
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs};
use rustc_trait_selection::traits::ObligationCtxt;
use tracing::debug;
use crate::errors;
@@ -299,6 +298,7 @@ fn check_attributes(
| AttributeKind::RustcAllocatorZeroed
| AttributeKind::RustcAllocatorZeroedVariant { .. }
| AttributeKind::RustcAsPtr(..)
| AttributeKind::RustcAutodiff(..)
| AttributeKind::RustcBodyStability { .. }
| AttributeKind::RustcBuiltinMacro { .. }
| AttributeKind::RustcCaptureAnalysis
@@ -390,22 +390,13 @@ fn check_attributes(
Attribute::Unparsed(attr_item) => {
style = Some(attr_item.style);
match attr.path().as_slice() {
[sym::autodiff_forward, ..] | [sym::autodiff_reverse, ..] => {
self.check_autodiff(hir_id, attr, span, target)
}
[
// ok
sym::allow
| sym::expect
| sym::warn
| sym::deny
| sym::forbid
// internal
| sym::rustc_on_unimplemented
| sym::rustc_layout
| sym::rustc_autodiff
// crate-level attrs, are checked below
| sym::feature,
| sym::forbid,
..
] => {}
[name, rest@..] => {
@@ -1863,18 +1854,6 @@ fn check_mix_no_mangle_export(&self, hir_id: HirId, attrs: &[Attribute]) {
}
}
/// Checks if `#[autodiff]` is applied to an item other than a function item.
fn check_autodiff(&self, _hir_id: HirId, _attr: &Attribute, span: Span, target: Target) {
debug!("check_autodiff");
match target {
Target::Fn => {}
_ => {
self.dcx().emit_err(errors::AutoDiffAttr { attr_span: span });
self.abort.set(true);
}
}
}
fn check_loop_match(&self, hir_id: HirId, attr_span: Span, target: Target) {
let node_span = self.tcx.hir_span(hir_id);
-8
View File
@@ -19,14 +19,6 @@
#[diag("`#[diagnostic::do_not_recommend]` can only be placed on trait implementations")]
pub(crate) struct IncorrectDoNotRecommendLocation;
#[derive(Diagnostic)]
#[diag("`#[autodiff]` should be applied to a function")]
pub(crate) struct AutoDiffAttr {
#[primary_span]
#[label("not a function")]
pub attr_span: Span,
}
#[derive(Diagnostic)]
#[diag("`#[loop_match]` should be applied to a loop")]
pub(crate) struct LoopMatchAttr {
+7 -2
View File
@@ -270,6 +270,7 @@ fn wait_for_query<'tcx, C: QueryCache>(
}
}
/// Shared main part of both [`execute_query_incr_inner`] and [`execute_query_non_incr_inner`].
#[inline(never)]
fn try_execute_query<'tcx, C: QueryCache, const INCR: bool>(
query: &'tcx QueryVTable<'tcx, C>,
@@ -650,8 +651,10 @@ fn check_if_ensure_can_skip_execution<'tcx, C: QueryCache>(
}
}
/// Called by a macro-generated impl of [`QueryVTable::execute_query_fn`],
/// in non-incremental mode.
#[inline(always)]
pub(super) fn get_query_non_incr<'tcx, C: QueryCache>(
pub(super) fn execute_query_non_incr_inner<'tcx, C: QueryCache>(
query: &'tcx QueryVTable<'tcx, C>,
tcx: TyCtxt<'tcx>,
span: Span,
@@ -662,8 +665,10 @@ pub(super) fn get_query_non_incr<'tcx, C: QueryCache>(
ensure_sufficient_stack(|| try_execute_query::<C, false>(query, tcx, span, key, None).0)
}
/// Called by a macro-generated impl of [`QueryVTable::execute_query_fn`],
/// in incremental mode.
#[inline(always)]
pub(super) fn get_query_incr<'tcx, C: QueryCache>(
pub(super) fn execute_query_incr_inner<'tcx, C: QueryCache>(
query: &'tcx QueryVTable<'tcx, C>,
tcx: TyCtxt<'tcx>,
span: Span,
+1 -1
View File
@@ -13,7 +13,7 @@
use rustc_middle::queries::{self, ExternProviders, Providers};
use rustc_middle::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache};
use rustc_middle::query::plumbing::{QuerySystem, QueryVTable};
use rustc_middle::query::{AsLocalKey, QueryCache, QueryMode};
use rustc_middle::query::{AsLocalQueryKey, QueryCache, QueryMode};
use rustc_middle::ty::TyCtxt;
use rustc_span::Span;
+17 -11
View File
@@ -19,7 +19,8 @@
};
use rustc_middle::query::plumbing::QueryVTable;
use rustc_middle::query::{
Key, QueryCache, QueryJobId, QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra, erase,
QueryCache, QueryJobId, QueryKey, QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra,
erase,
};
use rustc_middle::ty::codec::TyEncoder;
use rustc_middle::ty::print::with_reduced_queries;
@@ -274,7 +275,7 @@ fn mk_query_stack_frame_extra<'tcx, Cache>(
) -> QueryStackFrameExtra
where
Cache: QueryCache,
Cache::Key: Key,
Cache::Key: QueryKey,
{
let def_id = key.key_as_def_id();
@@ -313,7 +314,7 @@ pub(crate) fn create_deferred_query_stack_frame<'tcx, C>(
) -> QueryStackFrame<QueryStackDeferred<'tcx>>
where
C: QueryCache,
C::Key: Key + DynSend + DynSync,
C::Key: QueryKey + DynSend + DynSync,
QueryVTable<'tcx, C>: DynSync,
{
let kind = vtable.dep_kind;
@@ -475,7 +476,12 @@ pub(crate) mod query_impl { $(pub(crate) mod $name {
use super::super::*;
use ::rustc_middle::query::erase::{self, Erased};
pub(crate) mod get_query_incr {
// It seems to be important that every query has its own monomorphic
// copy of `execute_query_incr` and `execute_query_non_incr`.
// Trying to inline these wrapper functions into their generic
// "inner" helpers tends to break `tests/run-make/short-ice`.
pub(crate) mod execute_query_incr {
use super::*;
// Adding `__rust_end_short_backtrace` marker to backtraces so that we emit the frames
@@ -489,7 +495,7 @@ pub(crate) fn __rust_end_short_backtrace<'tcx>(
) -> Option<Erased<queries::$name::Value<'tcx>>> {
#[cfg(debug_assertions)]
let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered();
execution::get_query_incr(
execution::execute_query_incr_inner(
&tcx.query_system.query_vtables.$name,
tcx,
span,
@@ -499,7 +505,7 @@ pub(crate) fn __rust_end_short_backtrace<'tcx>(
}
}
pub(crate) mod get_query_non_incr {
pub(crate) mod execute_query_non_incr {
use super::*;
#[inline(never)]
@@ -509,7 +515,7 @@ pub(crate) fn __rust_end_short_backtrace<'tcx>(
key: queries::$name::Key<'tcx>,
__mode: QueryMode,
) -> Option<Erased<queries::$name::Value<'tcx>>> {
Some(execution::get_query_non_incr(
Some(execution::execute_query_non_incr_inner(
&tcx.query_system.query_vtables.$name,
tcx,
span,
@@ -549,7 +555,7 @@ pub(crate) fn __rust_begin_short_backtrace<'tcx>(
}
pub(crate) fn make_query_vtable<'tcx>(incremental: bool)
-> QueryVTable<'tcx, queries::$name::Storage<'tcx>>
-> QueryVTable<'tcx, queries::$name::Cache<'tcx>>
{
QueryVTable {
name: stringify!($name),
@@ -604,9 +610,9 @@ pub(crate) fn make_query_vtable<'tcx>(incremental: bool)
format_value: |value| format!("{:?}", erase::restore_val::<queries::$name::Value<'tcx>>(*value)),
description_fn: $crate::queries::_description_fns::$name,
execute_query_fn: if incremental {
query_impl::$name::get_query_incr::__rust_end_short_backtrace
query_impl::$name::execute_query_incr::__rust_end_short_backtrace
} else {
query_impl::$name::get_query_non_incr::__rust_end_short_backtrace
query_impl::$name::execute_query_non_incr::__rust_end_short_backtrace
},
}
}
@@ -615,7 +621,7 @@ pub(crate) fn make_query_vtable<'tcx>(incremental: bool)
pub(crate) enum VTableGetter {}
impl<'tcx> GetQueryVTable<'tcx> for VTableGetter {
type Cache = rustc_middle::queries::$name::Storage<'tcx>;
type Cache = rustc_middle::queries::$name::Cache<'tcx>;
#[inline(always)]
fn query_vtable(tcx: TyCtxt<'tcx>) -> &'tcx QueryVTable<'tcx, Self::Cache> {
+9
View File
@@ -157,6 +157,8 @@
Abi,
AcqRel,
Acquire,
Active,
ActiveOnly,
Alignment,
Arc,
ArcWeak,
@@ -213,6 +215,12 @@
Deref,
DispatchFromDyn,
Display,
Dual,
DualOnly,
Dualv,
DualvOnly,
Duplicated,
DuplicatedOnly,
DynTrait,
Enum,
Eq,
@@ -310,6 +318,7 @@
Slice,
SliceIndex,
Some,
Source,
SpanCtxt,
Str,
String,
+21 -17
View File
@@ -422,7 +422,7 @@ pub enum RegionOriginNote<'a> {
impl Subdiagnostic for RegionOriginNote<'_> {
fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
let mut label_or_note = |span, msg: DiagMessage| {
let label_or_note = |diag: &mut Diag<'_, G>, span, msg: DiagMessage| {
let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count();
let expanded_sub_count = diag.children.iter().filter(|d| !d.span.is_dummy()).count();
let span_is_primary = diag.span.primary_spans().iter().all(|&sp| sp == span);
@@ -436,22 +436,26 @@ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
};
match self {
RegionOriginNote::Plain { span, msg } => {
label_or_note(span, msg);
label_or_note(diag, span, msg);
}
RegionOriginNote::WithName { span, msg, name, continues } => {
label_or_note(span, msg);
diag.arg("name", name);
diag.arg("continues", continues);
label_or_note(diag, span, msg);
}
RegionOriginNote::WithRequirement {
span,
requirement,
expected_found: Some((expected, found)),
} => {
label_or_note(
span,
msg!(
"...so that the {$requirement ->
// `RegionOriginNote` can appear multiple times on one diagnostic with different
// `requirement` values. Scope args per-note and eagerly translate to avoid
// cross-note arg collisions.
// See https://github.com/rust-lang/rust/issues/143872 for details.
diag.store_args();
diag.arg("requirement", requirement);
let msg = diag.eagerly_translate(msg!(
"...so that the {$requirement ->
[method_compat] method type is compatible with trait
[type_compat] associated type is compatible with trait
[const_compat] const is compatible with trait
@@ -464,9 +468,9 @@ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
[method_correct_type] method receiver has the correct type
*[other] types are compatible
}"
),
);
diag.arg("requirement", requirement);
));
diag.restore_args();
label_or_note(diag, span, msg);
diag.note_expected_found("", expected, "", found);
}
@@ -474,10 +478,10 @@ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
// FIXME: this really should be handled at some earlier stage. Our
// handling of region checking when type errors are present is
// *terrible*.
label_or_note(
span,
msg!(
"...so that {$requirement ->
diag.store_args();
diag.arg("requirement", requirement);
let msg = diag.eagerly_translate(msg!(
"...so that {$requirement ->
[method_compat] method type is compatible with trait
[type_compat] associated type is compatible with trait
[const_compat] const is compatible with trait
@@ -490,9 +494,9 @@ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
[method_correct_type] method receiver has the correct type
*[other] types are compatible
}"
),
);
diag.arg("requirement", requirement);
));
diag.restore_args();
label_or_note(diag, span, msg);
}
};
}
+1 -2
View File
@@ -504,7 +504,7 @@ auto:
- name: dist-aarch64-apple
env:
SCRIPT: >-
./x.py dist bootstrap enzyme
./x.py dist bootstrap
--include-default-paths
--host=aarch64-apple-darwin
--target=aarch64-apple-darwin
@@ -513,7 +513,6 @@ auto:
--enable-sanitizers
--enable-profiler
--set rust.jemalloc
--set llvm.link-shared=true
--set rust.lto=thin
--set rust.codegen-units=1
# Aarch64 tooling only needs to support macOS 11.0 and up as nothing else
@@ -4,8 +4,8 @@ warning: creating a mutable reference to mutable static
LL | let sfoo: *mut Foo = &mut SFOO;
| ^^^^^^^^^ mutable reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: `#[warn(static_mut_refs)]` (part of `#[warn(rust_2024_compatibility)]`) on by default
help: use `&raw mut` instead to create a raw pointer
|
+1 -1
View File
@@ -4,8 +4,8 @@ warning: creating a mutable reference to mutable static
LL | let ptr = unsafe { &mut BB };
| ^^^^^^^ mutable reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: `#[warn(static_mut_refs)]` (part of `#[warn(rust_2024_compatibility)]`) on by default
help: use `&raw mut` instead to create a raw pointer
|
@@ -28,9 +28,9 @@ error: `Eq::assert_receiver_is_total_eq` should never be implemented by hand
LL | fn assert_receiver_is_total_eq(&self) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this method was used to add checks to the `Eq` derive macro
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #152336 <https://github.com/rust-lang/rust/issues/152336>
= note: this method was used to add checks to the `Eq` derive macro
note: the lint level is defined here
--> $DIR/internal_eq_trait_method_impls.rs:1:21
|
+1 -1
View File
@@ -9,8 +9,8 @@ LL | | (Box::new(__static_ref_initialize()));
LL | | });
| |______________^ shared reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: `#[warn(static_mut_refs)]` (part of `#[warn(rust_2024_compatibility)]`) on by default
warning: 1 warning emitted
+12 -12
View File
@@ -4,8 +4,8 @@ warning: creating a shared reference to mutable static
LL | let _y = &X;
| ^^ shared reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: `#[warn(static_mut_refs)]` (part of `#[warn(rust_2024_compatibility)]`) on by default
help: use `&raw const` instead to create a raw pointer
|
@@ -18,8 +18,8 @@ warning: creating a mutable reference to mutable static
LL | let _y = &mut X;
| ^^^^^^ mutable reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
help: use `&raw mut` instead to create a raw pointer
|
LL | let _y = &raw mut X;
@@ -31,8 +31,8 @@ warning: creating a shared reference to mutable static
LL | let ref _a = X;
| ^ shared reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
warning: creating a shared reference to mutable static
--> $DIR/static-mut-refs.rs:54:25
@@ -40,8 +40,8 @@ warning: creating a shared reference to mutable static
LL | let (_b, _c) = (&X, &Y);
| ^^ shared reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
help: use `&raw const` instead to create a raw pointer
|
LL | let (_b, _c) = (&raw const X, &Y);
@@ -53,8 +53,8 @@ warning: creating a shared reference to mutable static
LL | let (_b, _c) = (&X, &Y);
| ^^ shared reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
help: use `&raw const` instead to create a raw pointer
|
LL | let (_b, _c) = (&X, &raw const Y);
@@ -66,8 +66,8 @@ warning: creating a shared reference to mutable static
LL | foo(&X);
| ^^ shared reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
help: use `&raw const` instead to create a raw pointer
|
LL | foo(&raw const X);
@@ -79,8 +79,8 @@ warning: creating a shared reference to mutable static
LL | let _ = Z.len();
| ^^^^^^^ shared reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
warning: creating a shared reference to mutable static
--> $DIR/static-mut-refs.rs:72:33
@@ -88,8 +88,8 @@ warning: creating a shared reference to mutable static
LL | let _ = format!("{:?}", Z);
| ^ shared reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
warning: creating a shared reference to mutable static
--> $DIR/static-mut-refs.rs:76:18
@@ -97,8 +97,8 @@ warning: creating a shared reference to mutable static
LL | let _v = &A.value;
| ^^^^^^^^ shared reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
help: use `&raw const` instead to create a raw pointer
|
LL | let _v = &raw const A.value;
@@ -110,8 +110,8 @@ warning: creating a shared reference to mutable static
LL | let _s = &A.s.value;
| ^^^^^^^^^^ shared reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
help: use `&raw const` instead to create a raw pointer
|
LL | let _s = &raw const A.s.value;
@@ -123,8 +123,8 @@ warning: creating a shared reference to mutable static
LL | let ref _v = A.value;
| ^^^^^^^ shared reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
warning: creating a mutable reference to mutable static
--> $DIR/static-mut-refs.rs:14:14
@@ -135,8 +135,8 @@ LL | &mut ($x.0)
LL | let _x = bar!(FOO);
| --------- in this macro invocation
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: this warning originates in the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: 12 warnings emitted
+12 -12
View File
@@ -4,8 +4,8 @@ error: creating a shared reference to mutable static
LL | let _y = &X;
| ^^ shared reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: `#[deny(static_mut_refs)]` (part of `#[deny(rust_2024_compatibility)]`) on by default
help: use `&raw const` instead to create a raw pointer
|
@@ -18,8 +18,8 @@ error: creating a mutable reference to mutable static
LL | let _y = &mut X;
| ^^^^^^ mutable reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
help: use `&raw mut` instead to create a raw pointer
|
LL | let _y = &raw mut X;
@@ -31,8 +31,8 @@ error: creating a shared reference to mutable static
LL | let ref _a = X;
| ^ shared reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
error: creating a shared reference to mutable static
--> $DIR/static-mut-refs.rs:54:25
@@ -40,8 +40,8 @@ error: creating a shared reference to mutable static
LL | let (_b, _c) = (&X, &Y);
| ^^ shared reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
help: use `&raw const` instead to create a raw pointer
|
LL | let (_b, _c) = (&raw const X, &Y);
@@ -53,8 +53,8 @@ error: creating a shared reference to mutable static
LL | let (_b, _c) = (&X, &Y);
| ^^ shared reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
help: use `&raw const` instead to create a raw pointer
|
LL | let (_b, _c) = (&X, &raw const Y);
@@ -66,8 +66,8 @@ error: creating a shared reference to mutable static
LL | foo(&X);
| ^^ shared reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
help: use `&raw const` instead to create a raw pointer
|
LL | foo(&raw const X);
@@ -79,8 +79,8 @@ error: creating a shared reference to mutable static
LL | let _ = Z.len();
| ^^^^^^^ shared reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
error: creating a shared reference to mutable static
--> $DIR/static-mut-refs.rs:72:33
@@ -88,8 +88,8 @@ error: creating a shared reference to mutable static
LL | let _ = format!("{:?}", Z);
| ^ shared reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
error: creating a shared reference to mutable static
--> $DIR/static-mut-refs.rs:76:18
@@ -97,8 +97,8 @@ error: creating a shared reference to mutable static
LL | let _v = &A.value;
| ^^^^^^^^ shared reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
help: use `&raw const` instead to create a raw pointer
|
LL | let _v = &raw const A.value;
@@ -110,8 +110,8 @@ error: creating a shared reference to mutable static
LL | let _s = &A.s.value;
| ^^^^^^^^^^ shared reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
help: use `&raw const` instead to create a raw pointer
|
LL | let _s = &raw const A.s.value;
@@ -123,8 +123,8 @@ error: creating a shared reference to mutable static
LL | let ref _v = A.value;
| ^^^^^^^ shared reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
error: creating a mutable reference to mutable static
--> $DIR/static-mut-refs.rs:14:14
@@ -135,8 +135,8 @@ LL | &mut ($x.0)
LL | let _x = bar!(FOO);
| --------- in this macro invocation
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: this error originates in the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 12 previous errors
+9 -9
View File
@@ -4,8 +4,8 @@ warning: panic message contains a brace
LL | panic!("here's a brace: {");
| ^
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2021/panic-macro-consistency.html>
= note: this message is not used as a format string, but will be in Rust 2021
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2021/panic-macro-consistency.html>
= note: `#[warn(non_fmt_panics)]` (part of `#[warn(rust_2021_compatibility)]`) on by default
help: add a "{}" format string to use the message literally
|
@@ -18,8 +18,8 @@ warning: panic message contains a brace
LL | unreachable!("here's a brace: {");
| ^
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2021/panic-macro-consistency.html>
= note: this message is not used as a format string, but will be in Rust 2021
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2021/panic-macro-consistency.html>
help: add a "{}" format string to use the message literally
|
LL | unreachable!("{}", "here's a brace: {");
@@ -31,8 +31,8 @@ warning: panic message contains a brace
LL | std::panic!("another one: }");
| ^
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2021/panic-macro-consistency.html>
= note: this message is not used as a format string, but will be in Rust 2021
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2021/panic-macro-consistency.html>
help: add a "{}" format string to use the message literally
|
LL | std::panic!("{}", "another one: }");
@@ -44,8 +44,8 @@ warning: panic message contains an unused formatting placeholder
LL | core::panic!("Hello {}");
| ^^
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2021/panic-macro-consistency.html>
= note: this message is not used as a format string when given without arguments, but will be in Rust 2021
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2021/panic-macro-consistency.html>
help: add the missing argument
|
LL | core::panic!("Hello {}", ...);
@@ -61,8 +61,8 @@ warning: panic message contains unused formatting placeholders
LL | assert!(false, "{:03x} {test} bla");
| ^^^^^^ ^^^^^^
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2021/panic-macro-consistency.html>
= note: this message is not used as a format string when given without arguments, but will be in Rust 2021
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2021/panic-macro-consistency.html>
help: add the missing arguments
|
LL | assert!(false, "{:03x} {test} bla", ...);
@@ -120,8 +120,8 @@ warning: panic message contains braces
LL | debug_assert!(false, "{{}} bla");
| ^^^^
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2021/panic-macro-consistency.html>
= note: this message is not used as a format string, but will be in Rust 2021
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2021/panic-macro-consistency.html>
help: add a "{}" format string to use the message literally
|
LL | debug_assert!(false, "{}", "{{}} bla");
@@ -241,8 +241,8 @@ warning: panic message contains an unused formatting placeholder
LL | panic!(concat!("{", "}"));
| ^^^^^^^^^^^^^^^^^
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2021/panic-macro-consistency.html>
= note: this message is not used as a format string when given without arguments, but will be in Rust 2021
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2021/panic-macro-consistency.html>
help: add the missing argument
|
LL | panic!(concat!("{", "}"), ...);
@@ -258,8 +258,8 @@ warning: panic message contains braces
LL | panic!(concat!("{", "{"));
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2021/panic-macro-consistency.html>
= note: this message is not used as a format string, but will be in Rust 2021
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2021/panic-macro-consistency.html>
help: add a "{}" format string to use the message literally
|
LL | panic!("{}", concat!("{", "{"));
@@ -271,8 +271,8 @@ warning: panic message contains an unused formatting placeholder
LL | fancy_panic::fancy_panic!("test {} 123");
| ^^
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2021/panic-macro-consistency.html>
= note: this message is not used as a format string when given without arguments, but will be in Rust 2021
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2021/panic-macro-consistency.html>
warning: panic message is not a string literal
--> $DIR/non-fmt-panic.rs:53:12
@@ -4,8 +4,8 @@ warning: creating a mutable reference to mutable static
LL | S1 { a: unsafe { &mut X1 } }
| ^^^^^^^ mutable reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: `#[warn(static_mut_refs)]` (part of `#[warn(rust_2024_compatibility)]`) on by default
help: use `&raw mut` instead to create a raw pointer
|
+1 -1
View File
@@ -4,8 +4,8 @@ warning: creating a shared reference to mutable static
LL | static n: &'static usize = unsafe { &n_mut };
| ^^^^^^ shared reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: `#[warn(static_mut_refs)]` (part of `#[warn(rust_2024_compatibility)]`) on by default
help: use `&raw const` instead to create a raw pointer
|
@@ -4,8 +4,8 @@ warning: creating a shared reference to mutable static
LL | let _ = unsafe { (&TEST) as *const usize };
| ^^^^^^^ shared reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: `#[warn(static_mut_refs)]` (part of `#[warn(rust_2024_compatibility)]`) on by default
help: use `&raw const` instead to create a raw pointer
|
@@ -18,8 +18,8 @@ warning: creating a mutable reference to mutable static
LL | let _ = unsafe { (&mut TEST) as *const usize };
| ^^^^^^^^^^^ mutable reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
help: use `&raw mut` instead to create a raw pointer
|
LL | let _ = unsafe { (&raw mut TEST) as *const usize };
+7 -7
View File
@@ -4,8 +4,8 @@ warning: creating a shared reference to mutable static
LL | assert_eq!(static_mut_xc::a, 3);
| ^^^^^^^^^^^^^^^^ shared reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: `#[warn(static_mut_refs)]` (part of `#[warn(rust_2024_compatibility)]`) on by default
warning: creating a shared reference to mutable static
@@ -14,8 +14,8 @@ warning: creating a shared reference to mutable static
LL | assert_eq!(static_mut_xc::a, 4);
| ^^^^^^^^^^^^^^^^ shared reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
warning: creating a shared reference to mutable static
--> $DIR/static-mut-xc.rs:25:16
@@ -23,8 +23,8 @@ warning: creating a shared reference to mutable static
LL | assert_eq!(static_mut_xc::a, 5);
| ^^^^^^^^^^^^^^^^ shared reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
warning: creating a shared reference to mutable static
--> $DIR/static-mut-xc.rs:28:16
@@ -32,8 +32,8 @@ warning: creating a shared reference to mutable static
LL | assert_eq!(static_mut_xc::a, 15);
| ^^^^^^^^^^^^^^^^ shared reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
warning: creating a shared reference to mutable static
--> $DIR/static-mut-xc.rs:31:16
@@ -41,8 +41,8 @@ warning: creating a shared reference to mutable static
LL | assert_eq!(static_mut_xc::a, -3);
| ^^^^^^^^^^^^^^^^ shared reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
warning: creating a shared reference to mutable static
--> $DIR/static-mut-xc.rs:33:18
@@ -50,8 +50,8 @@ warning: creating a shared reference to mutable static
LL | static_bound(&static_mut_xc::a);
| ^^^^^^^^^^^^^^^^^ shared reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
help: use `&raw const` instead to create a raw pointer
|
LL | static_bound(&raw const static_mut_xc::a);
@@ -63,8 +63,8 @@ warning: creating a mutable reference to mutable static
LL | static_bound_set(&mut static_mut_xc::a);
| ^^^^^^^^^^^^^^^^^^^^^ mutable reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
help: use `&raw mut` instead to create a raw pointer
|
LL | static_bound_set(&raw mut static_mut_xc::a);
+2 -2
View File
@@ -4,8 +4,8 @@ warning: creating a shared reference to mutable static
LL | static mut S: *const u8 = unsafe { &S as *const *const u8 as *const u8 };
| ^^ shared reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: `#[warn(static_mut_refs)]` (part of `#[warn(rust_2024_compatibility)]`) on by default
help: use `&raw const` instead to create a raw pointer
|
@@ -18,8 +18,8 @@ warning: creating a shared reference to mutable static
LL | assert_eq!(S, *(S as *const *const u8));
| ^ shared reference to mutable static
|
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html>
warning: 2 warnings emitted
@@ -0,0 +1,23 @@
//@ compile-flags: --crate-type=lib
// Regression test for https://github.com/rust-lang/rust/issues/143872
trait Project {
type Ty;
}
impl Project for &'_ &'static () {
type Ty = ();
}
trait Trait {
fn get<'s>(s: &'s str, _: ()) -> &'_ str;
}
impl Trait for () {
fn get<'s>(s: &'s str, _: <&&'s () as Project>::Ty) -> &'static str {
//~^ ERROR cannot infer an appropriate lifetime for lifetime parameter 's in generic type due to conflicting requirements
//~| ERROR mismatched types
//~| ERROR lifetime may not live long enough
s
}
}
@@ -0,0 +1,55 @@
error[E0803]: cannot infer an appropriate lifetime for lifetime parameter 's in generic type due to conflicting requirements
--> $DIR/compare-impl-item-conflicting-lifetime-requirements.rs:17:5
|
LL | fn get<'s>(s: &'s str, _: <&&'s () as Project>::Ty) -> &'static str {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime `'s` as defined here...
--> $DIR/compare-impl-item-conflicting-lifetime-requirements.rs:13:12
|
LL | fn get<'s>(s: &'s str, _: ()) -> &'_ str;
| ^^
note: ...so that the method type is compatible with trait
--> $DIR/compare-impl-item-conflicting-lifetime-requirements.rs:17:5
|
LL | fn get<'s>(s: &'s str, _: <&&'s () as Project>::Ty) -> &'static str {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected `fn(&'s _, ()) -> &'s _`
found `fn(&_, ()) -> &'static _`
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that the types are compatible
--> $DIR/compare-impl-item-conflicting-lifetime-requirements.rs:17:5
|
LL | fn get<'s>(s: &'s str, _: <&&'s () as Project>::Ty) -> &'static str {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected `<&&() as Project>`
found `<&&'static () as Project>`
error[E0308]: mismatched types
--> $DIR/compare-impl-item-conflicting-lifetime-requirements.rs:17:31
|
LL | fn get<'s>(s: &'s str, _: <&&'s () as Project>::Ty) -> &'static str {
| ^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
= note: expected trait `<&&'s () as Project>`
found trait `<&&'static () as Project>`
note: the lifetime `'s` as defined here...
--> $DIR/compare-impl-item-conflicting-lifetime-requirements.rs:17:12
|
LL | fn get<'s>(s: &'s str, _: <&&'s () as Project>::Ty) -> &'static str {
| ^^
= note: ...does not necessarily outlive the static lifetime
error: lifetime may not live long enough
--> $DIR/compare-impl-item-conflicting-lifetime-requirements.rs:17:5
|
LL | fn get<'s>(s: &'s str, _: <&&'s () as Project>::Ty) -> &'static str {
| ^^^^^^^--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| | |
| | lifetime `'s` defined here
| requires that `'s` must outlive `'static`
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0308, E0803.
For more information about an error, try `rustc --explain E0308`.