Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 41 additions & 2 deletions compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use rustc_ast::{AttrStyle, MetaItemLit, Safety};
use rustc_attr_ir::target::Target;
use rustc_attr_ir::{AttrPath, Attribute, AttributeKind};
use rustc_data_structures::sync::{DynSend, DynSync};
use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, Level, MultiSpan};
use rustc_errors::{Diag, DiagCtxtHandle, DiagLocation, Diagnostic, Level, MultiSpan};
use rustc_feature::AttributeStability;
use rustc_lint_defs::builtin::UNUSED_ATTRIBUTES;
use rustc_lint_defs::{Lint, LintId};
Expand Down Expand Up @@ -408,22 +408,29 @@ pub struct AcceptContext<'f, 'sess> {
}

impl<'f, 'sess: 'f> SharedContext<'f, 'sess> {
#[track_caller]
pub(crate) fn emit_err(&self, diag: impl for<'x> Diagnostic<'x>) -> ErrorGuaranteed {
self.cx.emit_err(diag)
}

/// Emit a lint. This method is somewhat special, since lints emitted during attribute parsing
/// must be delayed until after HIR is built. This method will take care of the details of
/// that.
#[track_caller]
pub(crate) fn emit_lint(
&mut self,
lint: &'static Lint,
diagnostic: impl for<'x> Diagnostic<'x> + DynSend + DynSync + 'static,
span: impl Into<MultiSpan>,
) {
let emitted_at = DiagLocation::caller();
self.emit_lint_inner(
lint,
EmitAttribute(Box::new(move |dcx, level, _| diagnostic.into_diag(dcx, level))),
EmitAttribute(Box::new(move |dcx, level, _| {
let mut diag = diagnostic.into_diag(dcx, level);
diag.emitted_at = emitted_at;
diag
})),
span,
);
}
Expand Down Expand Up @@ -497,6 +504,7 @@ impl<'f, 'sess: 'f> AcceptContext<'f, 'sess> {
///
/// The provided span is used as a fallback for diagnostic generation in case `arg` does not
/// contain any. It should be the span of the node that contains `arg`.
#[track_caller]
pub(crate) fn expect_single_element_list<'arg>(
&mut self,
arg: &'arg ArgParser,
Expand Down Expand Up @@ -529,6 +537,7 @@ impl<'f, 'sess: 'f> AcceptContext<'f, 'sess> {
///
/// - You want to emit your own diagnostics (for instance, with [`SharedContext::emit_err`]).
/// - The attribute can be parsed in multiple ways and it does not make sense to emit an error.
#[track_caller]
pub(crate) fn expect_list<'arg>(
&mut self,
args: &'arg ArgParser,
Expand All @@ -550,6 +559,7 @@ impl<'f, 'sess: 'f> AcceptContext<'f, 'sess> {
///
/// - You want to emit your own diagnostics (for instance, with [`SharedContext::emit_err`]).
/// - The attribute can be parsed in multiple ways and it does not make sense to emit an error.
#[track_caller]
pub(crate) fn expect_single<'arg>(
&mut self,
list: &'arg MetaItemListParser,
Expand Down Expand Up @@ -589,6 +599,7 @@ impl<'f, 'sess: 'f> AcceptContext<'f, 'sess> {
///
/// - You want to emit your own diagnostics (for instance, with [`SharedContext::emit_err`]).
/// - The attribute can be parsed in multiple ways and it does not make sense to emit an error.
#[track_caller]
pub(crate) fn expect_name_value<'arg, Arg>(
&mut self,
arg: &'arg Arg,
Expand All @@ -609,6 +620,7 @@ impl<'f, 'sess: 'f> AcceptContext<'f, 'sess> {
///
/// - You want to emit your own diagnostics (for instance, with [`SharedContext::emit_err`]).
/// - The attribute can be parsed in multiple ways and it does not make sense to emit an error.
#[track_caller]
pub(crate) fn expect_no_args<'arg>(&mut self, arg: &'arg ArgParser) -> Option<()> {
if let Err(span) = arg.as_no_args() {
self.adcx().expected_no_args(span);
Expand All @@ -631,6 +643,7 @@ impl<'f, 'sess: 'f> AcceptContext<'f, 'sess> {
///
/// - You want to emit your own diagnostics (for instance, with [`SharedContext::emit_err`]).
/// - The attribute can be parsed in multiple ways and it does not make sense to emit an error.
#[track_caller]
pub(crate) fn expect_string_literal<'arg, Arg>(&mut self, arg: &'arg Arg) -> Option<Symbol>
where
Arg: ExpectStringLiteral,
Expand All @@ -644,6 +657,7 @@ pub(crate) trait ExpectNameValue {
where
Self: 'a;

#[track_caller]
fn expect_name_value<'a, 'f, 'sess>(
&'a self,
cx: &mut AcceptContext<'f, 'sess>,
Expand All @@ -655,6 +669,7 @@ pub(crate) trait ExpectNameValue {
impl ExpectNameValue for MetaItemOrLitParser {
type Output<'a> = (Ident, &'a NameValueParser);

#[track_caller]
fn expect_name_value<'a, 'f, 'sess>(
&'a self,
cx: &mut AcceptContext<'f, 'sess>,
Expand All @@ -673,6 +688,7 @@ impl ExpectNameValue for MetaItemOrLitParser {
impl ExpectNameValue for MetaItemParser {
type Output<'a> = (Ident, &'a NameValueParser);

#[track_caller]
fn expect_name_value<'a, 'f, 'sess>(
&'a self,
cx: &mut AcceptContext<'f, 'sess>,
Expand All @@ -697,6 +713,7 @@ impl ExpectNameValue for MetaItemParser {
impl ExpectNameValue for ArgParser {
type Output<'a> = &'a NameValueParser;

#[track_caller]
fn expect_name_value<'a, 'f, 'sess>(
&'a self,
cx: &mut AcceptContext<'f, 'sess>,
Expand All @@ -713,11 +730,13 @@ impl ExpectNameValue for ArgParser {
}

pub(crate) trait ExpectStringLiteral {
#[track_caller]
fn expect_string_literal<'f, 'sess>(&self, cx: &mut AcceptContext<'f, 'sess>)
-> Option<Symbol>;
}

impl ExpectStringLiteral for NameValueParser {
#[track_caller]
fn expect_string_literal<'f, 'sess>(
&self,
cx: &mut AcceptContext<'f, 'sess>,
Expand All @@ -731,6 +750,7 @@ impl ExpectStringLiteral for NameValueParser {
}

impl ExpectStringLiteral for MetaItemOrLitParser {
#[track_caller]
fn expect_string_literal<'f, 'sess>(
&self,
cx: &mut AcceptContext<'f, 'sess>,
Expand Down Expand Up @@ -893,6 +913,7 @@ pub enum ShouldEmit {
}

impl ShouldEmit {
#[track_caller]
pub(crate) fn emit_err(self, diag: Diag<'_>) -> ErrorGuaranteed {
match self {
ShouldEmit::EarlyFatal { .. } if diag.level() == Level::DelayedBug => diag.emit_err(),
Expand All @@ -912,6 +933,7 @@ pub(crate) struct AttributeDiagnosticContext<'a, 'f, 'sess> {
}

impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> {
#[track_caller]
fn emit_parse_error(
&mut self,
mut span: Span,
Expand Down Expand Up @@ -950,6 +972,7 @@ impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> {

/// Helpers that can be used to generate errors during attribute parsing.
impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> {
#[track_caller]
pub(crate) fn expected_integer_literal_in_range(
&mut self,
span: Span,
Expand All @@ -964,6 +987,7 @@ impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> {

/// The provided span is used as a fallback in case `args` does not contain any. It should be
/// the span of the node that contains `args`.
#[track_caller]
pub(crate) fn expected_list(&mut self, span: Span, args: &ArgParser) -> ErrorGuaranteed {
let span = match args {
ArgParser::NoArgs => span,
Expand All @@ -973,6 +997,7 @@ impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> {
self.emit_parse_error(span, AttributeParseErrorReason::ExpectedList)
}

#[track_caller]
pub(crate) fn expected_list_with_num_args_or_more(
&mut self,
args: usize,
Expand All @@ -984,45 +1009,54 @@ impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> {
)
}

#[track_caller]
pub(crate) fn expected_list_or_no_args(&mut self, span: Span) -> ErrorGuaranteed {
self.emit_parse_error(span, AttributeParseErrorReason::ExpectedListOrNoArgs)
}

#[track_caller]
pub(crate) fn expected_nv_or_no_args(&mut self, span: Span) -> ErrorGuaranteed {
self.emit_parse_error(span, AttributeParseErrorReason::ExpectedNameValueOrNoArgs)
}

#[track_caller]
pub(crate) fn expected_non_empty_string_literal(&mut self, span: Span) -> ErrorGuaranteed {
self.emit_parse_error(span, AttributeParseErrorReason::ExpectedNonEmptyStringLiteral)
}

#[track_caller]
pub(crate) fn expected_no_args(&mut self, span: Span) -> ErrorGuaranteed {
self.emit_parse_error(span, AttributeParseErrorReason::ExpectedNoArgs)
}

/// Emit an error that a `name` was expected here
#[track_caller]
pub(crate) fn expected_identifier(&mut self, span: Span) -> ErrorGuaranteed {
self.emit_parse_error(span, AttributeParseErrorReason::ExpectedIdentifier)
}

/// Emit an error that a `name = value` pair was expected at this span. The symbol can be given for
/// a nicer error message talking about the specific name that was found lacking a value.
#[track_caller]
fn expected_name_value(&mut self, span: Span, name: Option<Symbol>) -> ErrorGuaranteed {
self.emit_parse_error(span, AttributeParseErrorReason::ExpectedNameValue(name))
}

/// Emit an error that a `name = value` argument is missing in a list of name-value pairs.
#[track_caller]
pub(crate) fn missing_name_value(&mut self, span: Span, name: Symbol) -> ErrorGuaranteed {
self.emit_parse_error(span, AttributeParseErrorReason::MissingNameValue(name))
}

/// Emit an error that a `name = value` pair was found where that name was already seen.
#[track_caller]
pub(crate) fn duplicate_key(&mut self, span: Span, key: Symbol) -> ErrorGuaranteed {
self.emit_parse_error(span, AttributeParseErrorReason::DuplicateKey(key))
}

/// An error that should be emitted when a [`MetaItemOrLitParser`]
/// was expected *not* to be a literal, but instead a meta item.
#[track_caller]
pub(crate) fn expected_not_literal(&mut self, span: Span) -> ErrorGuaranteed {
self.emit_parse_error(span, AttributeParseErrorReason::ExpectedNotLiteral)
}
Expand All @@ -1031,6 +1065,7 @@ impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> {
/// The `provided_arguments` argument allows distinguishing between "expected an argument here"
/// (when zero arguments are provided) and "expect a single argument here" (when two or more
/// arguments are provided).
#[track_caller]
pub(crate) fn expected_single_argument(
&mut self,
span: Span,
Expand All @@ -1045,11 +1080,13 @@ impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> {
self.emit_parse_error(span, reason)
}

#[track_caller]
pub(crate) fn expected_at_least_one_argument(&mut self, span: Span) -> ErrorGuaranteed {
self.emit_parse_error(span, AttributeParseErrorReason::ExpectedAtLeastOneArgument)
}

/// Produces an error along the lines of `expected one of [foo, meow]`
#[track_caller]
pub(crate) fn expected_specific_argument(
&mut self,
span: Span,
Expand All @@ -1067,6 +1104,7 @@ impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> {

/// Produces an error along the lines of `expected one of [foo, meow] as an argument`.
/// i.e. slightly different wording to [`expected_specific_argument`](Self::expected_specific_argument).
#[track_caller]
pub(crate) fn expected_specific_argument_and_list(
&mut self,
span: Span,
Expand All @@ -1083,6 +1121,7 @@ impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> {
}

/// produces an error along the lines of `expected one of ["foo", "meow"]`
#[track_caller]
pub(crate) fn expected_specific_argument_strings(
&mut self,
span: Span,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_attr_parsing/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@ impl<'sess> AttributeParser<'sess> {
self.sess().dcx()
}

#[track_caller]
pub(crate) fn emit_err(&self, diag: impl for<'x> Diagnostic<'x>) -> ErrorGuaranteed {
self.should_emit.emit_err(self.sess.dcx().create_err(diag))
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![allow(rustc::direct_use_of_rustc_type_ir)]
#![cfg_attr(bootstrap, feature(debug_closure_helpers))]
#![cfg_attr(doc, feature(intra_doc_pointers))]
#![feature(allocator_ext)]
#![feature(associated_type_defaults)]
#![feature(closure_track_caller)]
#![feature(const_default)]
#![feature(const_trait_impl)]
#![feature(core_intrinsics)]
#![feature(debug_closure_helpers)]
#![feature(decl_macro)]
#![feature(default_field_values)]
#![feature(deref_patterns)]
Expand Down
4 changes: 1 addition & 3 deletions compiler/rustc_middle/src/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::cmp::min;

use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::sorted_map::SortedMap;
use rustc_errors::{Diag, DiagLocation, Diagnostic, EmissionOverride, MultiSpan};
use rustc_errors::{Diag, Diagnostic, EmissionOverride, MultiSpan};
use rustc_hir::{HirId, ItemLocalId};
use rustc_lint_defs::{
EditionFcw, FutureIncompatibilityReason, Level, Lint, LintExpectationId, LintId,
Expand Down Expand Up @@ -494,8 +494,6 @@ pub fn emit_lint_base<'a, D: Diagnostic<'a> + 'a>(
} else {
Diag::new(sess.dcx(), err_level, "")
};
// FIXME: Find a nicer way to expose the `DiagLocation`
err.emitted_at = DiagLocation::caller();

if let Some(span) = span
&& err.span.primary_span().is_none()
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_parse/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//! The main parser interface.

// tidy-alphabetical-start
#![cfg_attr(bootstrap, feature(debug_closure_helpers))]
#![cfg_attr(test, feature(iter_order_by))]
#![feature(debug_closure_helpers)]
#![feature(default_field_values)]
#![feature(deref_patterns)]
#![feature(iter_intersperse)]
Expand Down
Loading
Loading