Skip to content

Commit 18398f3

Browse files
committed
Documentation and finishing touches
1 parent 87aef4b commit 18398f3

File tree

4 files changed

+215
-79
lines changed

4 files changed

+215
-79
lines changed

compiler/rustc_span/src/hygiene.rs

+19
Original file line numberDiff line numberDiff line change
@@ -1270,6 +1270,25 @@ impl DesugaringKind {
12701270
DesugaringKind::PatTyRange => "pattern type",
12711271
}
12721272
}
1273+
1274+
/// For use with `rustc_unimplemented` to support conditions
1275+
// like `from_desugaring = "QuestionMark"`
1276+
pub fn matches(&self, value: &str) -> bool {
1277+
match self {
1278+
DesugaringKind::CondTemporary => value == "CondTemporary",
1279+
DesugaringKind::Async => value == "Async",
1280+
DesugaringKind::Await => value == "Await",
1281+
DesugaringKind::QuestionMark => value == "QuestionMark",
1282+
DesugaringKind::TryBlock => value == "TryBlock",
1283+
DesugaringKind::YeetExpr => value == "YeetExpr",
1284+
DesugaringKind::OpaqueTy => value == "OpaqueTy",
1285+
DesugaringKind::ForLoop => value == "ForLoop",
1286+
DesugaringKind::WhileLoop => value == "WhileLoop",
1287+
DesugaringKind::BoundModifier => value == "BoundModifier",
1288+
DesugaringKind::Contract => value == "Contract",
1289+
DesugaringKind::PatTyRange => value == "PatTyRange",
1290+
}
1291+
}
12731292
}
12741293

12751294
#[derive(Default)]

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

+66-10
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use rustc_errors::codes::*;
66
use rustc_errors::{ErrorGuaranteed, struct_span_code_err};
77
use rustc_hir::def_id::{DefId, LocalDefId};
88
use rustc_hir::{AttrArgs, Attribute};
9+
use rustc_macros::LintDiagnostic;
910
use rustc_middle::bug;
1011
use rustc_middle::ty::print::PrintTraitRefExt;
1112
use rustc_middle::ty::{self, GenericArgsRef, GenericParamDef, GenericParamDefKind, TyCtxt};
@@ -17,7 +18,6 @@ use {rustc_attr_parsing as attr, rustc_hir as hir};
1718
use super::{ObligationCauseCode, PredicateObligation};
1819
use crate::error_reporting::TypeErrCtxt;
1920
use crate::error_reporting::traits::on_unimplemented_condition::{Condition, ConditionOptions};
20-
use crate::error_reporting::traits::on_unimplemented_format::errors::*;
2121
use crate::error_reporting::traits::on_unimplemented_format::{Ctx, FormatArgs, FormatString};
2222
use crate::errors::{
2323
EmptyOnClauseInOnUnimplemented, InvalidOnClauseInOnUnimplemented, NoValueInOnUnimplemented,
@@ -112,10 +112,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
112112
// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): HIR is not present for RPITITs,
113113
// but I guess we could synthesize one here. We don't see any errors that rely on
114114
// that yet, though.
115-
let item_context = self
116-
.describe_enclosure(obligation.cause.body_id)
117-
.map(|t| t.to_owned())
118-
.unwrap_or(String::new());
115+
let item_context = self.describe_enclosure(obligation.cause.body_id).unwrap_or("");
119116

120117
let direct = match obligation.cause.code() {
121118
ObligationCauseCode::BuiltinDerived(..)
@@ -128,7 +125,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
128125
}
129126
};
130127

131-
let from_desugaring = obligation.cause.span.desugaring_kind().map(|k| format!("{k:?}"));
128+
let from_desugaring = obligation.cause.span.desugaring_kind();
132129

133130
let cause = if let ObligationCauseCode::MainFunctionType = obligation.cause.code() {
134131
Some("MainFunctionType".to_string())
@@ -253,8 +250,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
253250
}
254251
}));
255252

256-
let this = self.tcx.def_path_str(trait_pred.trait_ref.def_id).to_string();
257-
let trait_sugared = trait_pred.trait_ref.print_trait_sugared().to_string();
253+
let this = self.tcx.def_path_str(trait_pred.trait_ref.def_id);
254+
let trait_sugared = trait_pred.trait_ref.print_trait_sugared();
258255

259256
let condition_options = ConditionOptions {
260257
self_types,
@@ -268,6 +265,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
268265
// Unlike the generic_args earlier,
269266
// this one is *not* collected under `with_no_trimmed_paths!`
270267
// for printing the type to the user
268+
//
269+
// This includes `Self`, as it is the first parameter in `own_params`.
271270
let generic_args = self
272271
.tcx
273272
.generics_of(trait_pred.trait_ref.def_id)
@@ -341,6 +340,63 @@ pub enum AppendConstMessage {
341340
Custom(Symbol, Span),
342341
}
343342

343+
#[derive(LintDiagnostic)]
344+
#[diag(trait_selection_malformed_on_unimplemented_attr)]
345+
#[help]
346+
pub struct MalformedOnUnimplementedAttrLint {
347+
#[label]
348+
pub span: Span,
349+
}
350+
351+
impl MalformedOnUnimplementedAttrLint {
352+
pub fn new(span: Span) -> Self {
353+
Self { span }
354+
}
355+
}
356+
357+
#[derive(LintDiagnostic)]
358+
#[diag(trait_selection_missing_options_for_on_unimplemented_attr)]
359+
#[help]
360+
pub struct MissingOptionsForOnUnimplementedAttr;
361+
362+
#[derive(LintDiagnostic)]
363+
#[diag(trait_selection_ignored_diagnostic_option)]
364+
pub struct IgnoredDiagnosticOption {
365+
pub option_name: &'static str,
366+
#[label]
367+
pub span: Span,
368+
#[label(trait_selection_other_label)]
369+
pub prev_span: Span,
370+
}
371+
372+
impl IgnoredDiagnosticOption {
373+
pub fn maybe_emit_warning<'tcx>(
374+
tcx: TyCtxt<'tcx>,
375+
item_def_id: DefId,
376+
new: Option<Span>,
377+
old: Option<Span>,
378+
option_name: &'static str,
379+
) {
380+
if let (Some(new_item), Some(old_item)) = (new, old) {
381+
if let Some(item_def_id) = item_def_id.as_local() {
382+
tcx.emit_node_span_lint(
383+
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
384+
tcx.local_def_id_to_hir_id(item_def_id),
385+
new_item,
386+
IgnoredDiagnosticOption { span: new_item, prev_span: old_item, option_name },
387+
);
388+
}
389+
}
390+
}
391+
}
392+
393+
#[derive(LintDiagnostic)]
394+
#[diag(trait_selection_wrapped_parser_error)]
395+
pub struct WrappedParserError {
396+
pub description: String,
397+
pub label: String,
398+
}
399+
344400
impl<'tcx> OnUnimplementedDirective {
345401
fn parse(
346402
tcx: TyCtxt<'tcx>,
@@ -664,7 +720,7 @@ impl<'tcx> OnUnimplementedDirective {
664720
tcx: TyCtxt<'tcx>,
665721
trait_ref: ty::TraitRef<'tcx>,
666722
condition_options: &ConditionOptions,
667-
args: &FormatArgs,
723+
args: &FormatArgs<'tcx>,
668724
) -> OnUnimplementedNote {
669725
let mut message = None;
670726
let mut label = None;
@@ -784,7 +840,7 @@ impl<'tcx> OnUnimplementedFormatString {
784840
&self,
785841
tcx: TyCtxt<'tcx>,
786842
trait_ref: ty::TraitRef<'tcx>,
787-
args: &FormatArgs,
843+
args: &FormatArgs<'tcx>,
788844
) -> String {
789845
let trait_def_id = trait_ref.def_id;
790846
let ctx = if self.is_diagnostic_namespace_variant {

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

+51-18
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,10 @@ use rustc_ast::MetaItemInner;
22
use rustc_attr_parsing as attr;
33
use rustc_middle::ty::{self, TyCtxt};
44
use rustc_parse_format::{ParseMode, Parser, Piece, Position};
5-
use rustc_span::{Span, Symbol, kw, sym};
6-
7-
pub static ALLOWED_CONDITION_SYMBOLS: &[Symbol] = &[
8-
sym::from_desugaring,
9-
sym::direct,
10-
sym::cause,
11-
sym::integral,
12-
sym::integer_,
13-
sym::float,
14-
sym::_Self,
15-
sym::crate_local,
16-
];
5+
use rustc_span::{DesugaringKind, Span, Symbol, kw, sym};
176

7+
/// A predicate in an attribute using on, all, any,
8+
/// similar to a cfg predicate.
189
#[derive(Debug)]
1910
pub struct Condition {
2011
pub inner: MetaItemInner,
@@ -31,8 +22,7 @@ impl Condition {
3122
// `with_no_visible_paths` is also used when generating the options,
3223
// so we need to match it here.
3324
ty::print::with_no_visible_paths!({
34-
let mut parser = Parser::new(v.as_str(), None, None, false, ParseMode::Format);
35-
let constructed_message = (&mut parser)
25+
Parser::new(v.as_str(), None, None, false, ParseMode::Format)
3626
.map(|p| match p {
3727
Piece::Lit(s) => s.to_owned(),
3828
Piece::NextArgument(a) => match a.position {
@@ -47,8 +37,7 @@ impl Condition {
4737
Position::ArgumentIs(idx) => format!("{{{idx}}}"),
4838
},
4939
})
50-
.collect();
51-
constructed_message
40+
.collect()
5241
})
5342
});
5443

@@ -57,13 +46,57 @@ impl Condition {
5746
}
5847
}
5948

49+
/// Used with `Condition::matches_predicate` to test whether the condition applies
50+
///
51+
/// For example, given a
52+
/// ```rust,ignore (just an example)
53+
/// #[rustc_on_unimplemented(
54+
/// on(all(from_desugaring = "QuestionMark"),
55+
/// message = "the `?` operator can only be used in {ItemContext} \
56+
/// that returns `Result` or `Option` \
57+
/// (or another type that implements `{FromResidual}`)",
58+
/// label = "cannot use the `?` operator in {ItemContext} that returns `{Self}`",
59+
/// parent_label = "this function should return `Result` or `Option` to accept `?`"
60+
/// ),
61+
/// )]
62+
/// pub trait FromResidual<R = <Self as Try>::Residual> {
63+
/// ...
64+
/// }
65+
///
66+
/// async fn an_async_function() -> u32 {
67+
/// let x: Option<u32> = None;
68+
/// x?; //~ ERROR the `?` operator
69+
/// 22
70+
/// }
71+
/// ```
72+
/// it will look like this:
73+
///
74+
/// ```rust,ignore (just an example)
75+
/// ConditionOptions {
76+
/// self_types: ["u32", "{integral}"],
77+
/// from_desugaring: Some("QuestionMark"),
78+
/// cause: None,
79+
/// crate_local: false,
80+
/// direct: true,
81+
/// generic_args: [("Self","u32"),
82+
/// ("R", "core::option::Option<core::convert::Infallible>"),
83+
/// ("R", "core::option::Option<T>" ),
84+
/// ],
85+
/// }
86+
/// ```
6087
#[derive(Debug)]
6188
pub struct ConditionOptions {
89+
/// All the self types that may apply.
90+
/// for example
6291
pub self_types: Vec<String>,
63-
pub from_desugaring: Option<String>,
92+
// The kind of compiler desugaring.
93+
pub from_desugaring: Option<DesugaringKind>,
94+
/// Match on a variant of [rustc_infer::traits::ObligationCauseCode]
6495
pub cause: Option<String>,
6596
pub crate_local: bool,
97+
/// Is the obligation "directly" user-specified, rather than derived?
6698
pub direct: bool,
99+
// A list of the generic arguments and their reified types
67100
pub generic_args: Vec<(Symbol, String)>,
68101
}
69102

@@ -74,7 +107,7 @@ impl ConditionOptions {
74107
// from_desugaring as a flag
75108
(sym::from_desugaring, None) => self.from_desugaring.is_some(),
76109
// from_desugaring as key == value
77-
(sym::from_desugaring, v) => *v == self.from_desugaring,
110+
(sym::from_desugaring, Some(v)) if let Some(ds) = self.from_desugaring => ds.matches(v),
78111
(sym::cause, Some(value)) => self.cause.as_deref() == Some(value),
79112
(sym::crate_local, None) => self.crate_local,
80113
(sym::direct, None) => self.direct,

0 commit comments

Comments
 (0)