Skip to content

Commit 906ca7f

Browse files
committed
Auto merge of rust-lang#154877 - JonathanBrouwer:rollup-rbarkwZ, r=JonathanBrouwer
Rollup of 3 pull requests Successful merges: - rust-lang#154554 (emit error on `#[track_caller]` with `extern fn`) - rust-lang#154858 (Change api of formatting diagnostic attribute strings.) - rust-lang#154876 (attr parsing: make sure we pass the right target when errors could be emitted)
2 parents 5a0d572 + 2973fd5 commit 906ca7f

File tree

10 files changed

+111
-60
lines changed

10 files changed

+111
-60
lines changed

compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1683,19 +1683,28 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
16831683
self.check_item_safety(span, safety);
16841684
}
16851685

1686-
if let FnKind::Fn(ctxt, _, fun) = fk
1687-
&& let Extern::Explicit(str_lit, extern_abi_span) = fun.sig.header.ext
1688-
&& let Ok(abi) = ExternAbi::from_str(str_lit.symbol.as_str())
1689-
{
1690-
self.check_extern_fn_signature(abi, ctxt, &fun.ident, &fun.sig);
1686+
if let FnKind::Fn(ctxt, _, fun) = fk {
1687+
let ext = match fun.sig.header.ext {
1688+
Extern::None => None,
1689+
Extern::Implicit(span) => Some((ExternAbi::FALLBACK, span)),
1690+
Extern::Explicit(str_lit, span) => {
1691+
ExternAbi::from_str(str_lit.symbol.as_str()).ok().map(|abi| (abi, span))
1692+
}
1693+
};
16911694

1692-
if let Some(attr) = attr::find_by_name(attrs, sym::track_caller)
1693-
&& abi != ExternAbi::Rust
1694-
{
1695-
self.dcx().emit_err(errors::RequiresRustAbi {
1696-
track_caller_span: attr.span,
1697-
extern_abi_span,
1698-
});
1695+
if let Some((extern_abi, extern_abi_span)) = ext {
1696+
// Some ABIs impose special restrictions on the signature.
1697+
self.check_extern_fn_signature(extern_abi, ctxt, &fun.ident, &fun.sig);
1698+
1699+
// #[track_caller] can only be used with the rust ABI.
1700+
if let Some(attr) = attr::find_by_name(attrs, sym::track_caller)
1701+
&& extern_abi != ExternAbi::Rust
1702+
{
1703+
self.dcx().emit_err(errors::RequiresRustAbi {
1704+
track_caller_span: attr.span,
1705+
extern_abi_span,
1706+
});
1707+
}
16991708
}
17001709
}
17011710

compiler/rustc_attr_parsing/src/interface.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ impl<'sess> AttributeParser<'sess, Early> {
6464
sym,
6565
target_span,
6666
target_node_id,
67+
Target::Crate, // Does not matter, we're not going to emit errors anyways
6768
features,
6869
ShouldEmit::Nothing,
6970
)
@@ -79,14 +80,15 @@ impl<'sess> AttributeParser<'sess, Early> {
7980
sym: Symbol,
8081
target_span: Span,
8182
target_node_id: NodeId,
83+
target: Target,
8284
features: Option<&'sess Features>,
8385
should_emit: ShouldEmit,
8486
) -> Option<Attribute> {
8587
let mut parsed = Self::parse_limited_all(
8688
sess,
8789
attrs,
8890
Some(sym),
89-
Target::Crate, // Does not matter, we're not going to emit errors anyways
91+
target,
9092
target_span,
9193
target_node_id,
9294
features,

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,10 @@ use std::ops::ControlFlow;
66
use either::Either;
77
use hir::{ClosureKind, Path};
88
use rustc_data_structures::fx::FxIndexSet;
9-
use rustc_data_structures::thin_vec::ThinVec;
109
use rustc_errors::codes::*;
1110
use rustc_errors::{Applicability, Diag, MultiSpan, struct_span_code_err};
1211
use rustc_hir as hir;
13-
use rustc_hir::attrs::diagnostic::FormatArgs;
12+
use rustc_hir::attrs::diagnostic::{CustomDiagnostic, FormatArgs};
1413
use rustc_hir::def::{DefKind, Res};
1514
use rustc_hir::intravisit::{Visitor, walk_block, walk_expr};
1615
use rustc_hir::{
@@ -146,7 +145,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
146145
self.body.local_decls[moved_place.local].ty.kind()
147146
&& let Some(Some(directive)) = find_attr!(self.infcx.tcx, item_def.did(), OnMove { directive, .. } => directive)
148147
{
149-
let item_name = self.infcx.tcx.item_name(item_def.did()).to_string();
148+
let this = self.infcx.tcx.item_name(item_def.did()).to_string();
150149
let mut generic_args: Vec<_> = self
151150
.infcx
152151
.tcx
@@ -155,21 +154,22 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
155154
.iter()
156155
.filter_map(|param| Some((param.name, args[param.index as usize].to_string())))
157156
.collect();
158-
generic_args.push((kw::SelfUpper, item_name));
157+
generic_args.push((kw::SelfUpper, this.clone()));
159158

160159
let args = FormatArgs {
161-
this: String::new(),
162-
trait_sugared: String::new(),
160+
this,
161+
// Unused
162+
this_sugared: String::new(),
163+
// Unused
163164
item_context: "",
164165
generic_args,
165166
};
166-
(
167-
directive.message.as_ref().map(|e| e.1.format(&args)),
168-
directive.label.as_ref().map(|e| e.1.format(&args)),
169-
directive.notes.iter().map(|e| e.format(&args)).collect(),
170-
)
167+
let CustomDiagnostic { message, label, notes, parent_label: _ } =
168+
directive.eval(None, &args);
169+
170+
(message, label, notes)
171171
} else {
172-
(None, None, ThinVec::new())
172+
(None, None, Vec::new())
173173
};
174174

175175
let mut err = self.cannot_act_on_moved_value(

compiler/rustc_hir/src/attrs/diagnostic.rs

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -52,30 +52,40 @@ impl Directive {
5252
}
5353
}
5454

55-
pub fn evaluate_directive(
55+
pub fn eval(
5656
&self,
57-
trait_name: impl Debug,
58-
condition_options: &ConditionOptions,
57+
condition_options: Option<&ConditionOptions>,
5958
args: &FormatArgs,
60-
) -> OnUnimplementedNote {
59+
) -> CustomDiagnostic {
60+
let this = &args.this;
61+
info!("eval({self:?}, this={this}, options={condition_options:?}, args ={args:?})");
62+
63+
let Some(condition_options) = condition_options else {
64+
debug_assert!(
65+
!self.is_rustc_attr,
66+
"Directive::eval called for `rustc_on_unimplemented` without `condition_options`"
67+
);
68+
return CustomDiagnostic {
69+
label: self.label.as_ref().map(|l| l.1.format(args)),
70+
message: self.message.as_ref().map(|m| m.1.format(args)),
71+
notes: self.notes.iter().map(|n| n.format(args)).collect(),
72+
parent_label: None,
73+
};
74+
};
6175
let mut message = None;
6276
let mut label = None;
6377
let mut notes = Vec::new();
6478
let mut parent_label = None;
65-
info!(
66-
"evaluate_directive({:?}, trait_ref={:?}, options={:?}, args ={:?})",
67-
self, trait_name, condition_options, args
68-
);
6979

7080
for command in self.subcommands.iter().chain(Some(self)).rev() {
7181
debug!(?command);
7282
if let Some(ref condition) = command.condition
7383
&& !condition.matches_predicate(condition_options)
7484
{
75-
debug!("evaluate_directive: skipping {:?} due to condition", command);
85+
debug!("eval: skipping {command:?} due to condition");
7686
continue;
7787
}
78-
debug!("evaluate_directive: {:?} succeeded", command);
88+
debug!("eval: {command:?} succeeded");
7989
if let Some(ref message_) = command.message {
8090
message = Some(message_.clone());
8191
}
@@ -91,7 +101,7 @@ impl Directive {
91101
}
92102
}
93103

94-
OnUnimplementedNote {
104+
CustomDiagnostic {
95105
label: label.map(|l| l.1.format(args)),
96106
message: message.map(|m| m.1.format(args)),
97107
notes: notes.into_iter().map(|n| n.format(args)).collect(),
@@ -100,8 +110,9 @@ impl Directive {
100110
}
101111
}
102112

113+
/// A custom diagnostic, created from a diagnostic attribute.
103114
#[derive(Default, Debug)]
104-
pub struct OnUnimplementedNote {
115+
pub struct CustomDiagnostic {
105116
pub message: Option<String>,
106117
pub label: Option<String>,
107118
pub notes: Vec<String>,
@@ -116,8 +127,13 @@ pub struct FormatString {
116127
pub span: Span,
117128
pub pieces: ThinVec<Piece>,
118129
}
130+
119131
impl FormatString {
120-
pub fn format(&self, args: &FormatArgs) -> String {
132+
/// Formats the format string.
133+
///
134+
/// This is a private method, use `Directive::eval` instead. A diagnostic attribute being used
135+
/// should issue a `tracing` event, which `Directive::eval` does.
136+
fn format(&self, args: &FormatArgs) -> String {
121137
let mut ret = String::new();
122138
for piece in &self.pieces {
123139
match piece {
@@ -147,7 +163,7 @@ impl FormatString {
147163
// It's only `rustc_onunimplemented` from here
148164
Piece::Arg(FormatArg::This) => ret.push_str(&args.this),
149165
Piece::Arg(FormatArg::Trait) => {
150-
let _ = fmt::write(&mut ret, format_args!("{}", &args.trait_sugared));
166+
let _ = fmt::write(&mut ret, format_args!("{}", &args.this_sugared));
151167
}
152168
Piece::Arg(FormatArg::ItemContext) => ret.push_str(args.item_context),
153169
}
@@ -193,15 +209,15 @@ impl FormatString {
193209
/// ```rust,ignore (just an example)
194210
/// FormatArgs {
195211
/// this: "FromResidual",
196-
/// trait_sugared: "FromResidual<Option<Infallible>>",
212+
/// this_sugared: "FromResidual<Option<Infallible>>",
197213
/// item_context: "an async function",
198214
/// generic_args: [("Self", "u32"), ("R", "Option<Infallible>")],
199215
/// }
200216
/// ```
201217
#[derive(Debug)]
202218
pub struct FormatArgs {
203219
pub this: String,
204-
pub trait_sugared: String,
220+
pub this_sugared: String,
205221
pub item_context: &'static str,
206222
pub generic_args: Vec<(Symbol, String)>,
207223
}

compiler/rustc_hir_typeck/src/method/suggest.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use rustc_errors::codes::*;
1616
use rustc_errors::{
1717
Applicability, Diag, MultiSpan, StashKey, StringPart, listify, pluralize, struct_span_code_err,
1818
};
19-
use rustc_hir::attrs::diagnostic::OnUnimplementedNote;
19+
use rustc_hir::attrs::diagnostic::CustomDiagnostic;
2020
use rustc_hir::def::{CtorKind, DefKind, Res};
2121
use rustc_hir::def_id::DefId;
2222
use rustc_hir::intravisit::{self, Visitor};
@@ -2067,7 +2067,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
20672067
// Avoid crashing.
20682068
return (None, None, Vec::new());
20692069
}
2070-
let OnUnimplementedNote { message, label, notes, .. } = self
2070+
let CustomDiagnostic { message, label, notes, .. } = self
20712071
.err_ctxt()
20722072
.on_unimplemented_note(trait_ref, &obligation, err.long_ty_path());
20732073
(message, label, notes)

compiler/rustc_interface/src/passes.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use rustc_hir::def_id::{LOCAL_CRATE, StableCrateId, StableCrateIdMap};
2222
use rustc_hir::definitions::Definitions;
2323
use rustc_hir::limit::Limit;
2424
use rustc_hir::lints::DelayedLint;
25-
use rustc_hir::{Attribute, MaybeOwner, find_attr};
25+
use rustc_hir::{Attribute, MaybeOwner, Target, find_attr};
2626
use rustc_incremental::setup_dep_graph;
2727
use rustc_lint::{
2828
BufferedEarlyLint, DecorateAttrLint, EarlyCheckNode, LintStore, unerased_lint_store,
@@ -1372,6 +1372,7 @@ pub(crate) fn parse_crate_name(
13721372
sym::crate_name,
13731373
DUMMY_SP,
13741374
rustc_ast::node_id::CRATE_NODE_ID,
1375+
Target::Crate,
13751376
None,
13761377
emit_errors,
13771378
)?
@@ -1421,6 +1422,7 @@ pub fn collect_crate_types(
14211422
sym::crate_type,
14221423
crate_span,
14231424
CRATE_NODE_ID,
1425+
Target::Crate,
14241426
None,
14251427
ShouldEmit::EarlyFatal { also_emit_lints: false },
14261428
)
@@ -1477,6 +1479,7 @@ fn get_recursion_limit(krate_attrs: &[ast::Attribute], sess: &Session) -> Limit
14771479
sym::recursion_limit,
14781480
DUMMY_SP,
14791481
rustc_ast::node_id::CRATE_NODE_ID,
1482+
Target::Crate,
14801483
None,
14811484
// errors are fatal here, but lints aren't.
14821485
// If things aren't fatal we continue, and will parse this again.

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

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use rustc_errors::{
1414
Applicability, Diag, ErrorGuaranteed, Level, MultiSpan, StashKey, StringPart, Suggestions, msg,
1515
pluralize, struct_span_code_err,
1616
};
17-
use rustc_hir::attrs::diagnostic::OnUnimplementedNote;
17+
use rustc_hir::attrs::diagnostic::CustomDiagnostic;
1818
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
1919
use rustc_hir::intravisit::Visitor;
2020
use rustc_hir::{self as hir, LangItem, Node, find_attr};
@@ -188,7 +188,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
188188
})
189189
.unwrap_or_default();
190190

191-
let OnUnimplementedNote {
191+
let CustomDiagnostic {
192192
message,
193193
label,
194194
notes,
@@ -907,12 +907,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
907907
);
908908

909909
if let Some(command) = find_attr!(self.tcx, impl_did, OnConst {directive, ..} => directive.as_deref()).flatten(){
910-
let note = command.evaluate_directive(
911-
predicate.skip_binder().trait_ref,
912-
&condition_options,
910+
let note = command.eval(
911+
Some(&condition_options),
913912
&format_args,
914913
);
915-
let OnUnimplementedNote {
914+
let CustomDiagnostic {
916915
message,
917916
label,
918917
notes,

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

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::path::PathBuf;
22

33
use rustc_hir as hir;
4-
use rustc_hir::attrs::diagnostic::{ConditionOptions, FormatArgs, OnUnimplementedNote};
4+
use rustc_hir::attrs::diagnostic::{ConditionOptions, CustomDiagnostic, FormatArgs};
55
use rustc_hir::def_id::LocalDefId;
66
use rustc_hir::find_attr;
77
pub use rustc_hir::lints::FormatWarning;
@@ -37,20 +37,19 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
3737
trait_pred: ty::PolyTraitPredicate<'tcx>,
3838
obligation: &PredicateObligation<'tcx>,
3939
long_ty_path: &mut Option<PathBuf>,
40-
) -> OnUnimplementedNote {
40+
) -> CustomDiagnostic {
4141
if trait_pred.polarity() != ty::PredicatePolarity::Positive {
42-
return OnUnimplementedNote::default();
42+
return CustomDiagnostic::default();
4343
}
4444
let (condition_options, format_args) =
4545
self.on_unimplemented_components(trait_pred, obligation, long_ty_path);
4646
if let Some(command) = find_attr!(self.tcx, trait_pred.def_id(), OnUnimplemented {directive, ..} => directive.as_deref()).flatten() {
47-
command.evaluate_directive(
48-
trait_pred.skip_binder().trait_ref,
49-
&condition_options,
47+
command.eval(
48+
Some(&condition_options),
5049
&format_args,
5150
)
5251
} else {
53-
OnUnimplementedNote::default()
52+
CustomDiagnostic::default()
5453
}
5554
}
5655

@@ -211,7 +210,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
211210
}));
212211

213212
let this = self.tcx.def_path_str(trait_pred.trait_ref.def_id);
214-
let trait_sugared = trait_pred.trait_ref.print_trait_sugared().to_string();
213+
let this_sugared = trait_pred.trait_ref.print_trait_sugared().to_string();
215214

216215
let condition_options = ConditionOptions {
217216
self_types,
@@ -249,7 +248,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
249248
})
250249
.collect();
251250

252-
let format_args = FormatArgs { this, trait_sugared, generic_args, item_context };
251+
let format_args = FormatArgs { this, this_sugared, generic_args, item_context };
253252
(condition_options, format_args)
254253
}
255254
}

tests/ui/rfcs/rfc-2091-track-caller/error-with-invalid-abi.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,10 @@ impl S {
2727
extern "Rust" fn rust_method() {}
2828
}
2929

30+
#[rustfmt::skip] // rustfmt will insert the implicit "C"
31+
#[track_caller]
32+
//~^ ERROR `#[track_caller]` can only be used with the Rust ABI
33+
pub extern fn extern_missing_abi() {}
34+
//~^ WARN `extern` declarations without an explicit ABI are deprecated
35+
3036
fn main() {}

0 commit comments

Comments
 (0)