2019-10-09 01:23:10 +00:00
|
|
|
//! Contains `ParseSess` which holds state living beyond what one `Parser` might.
|
|
|
|
//! It also serves as an input to the parser itself.
|
|
|
|
|
Clean up config mess.
`parse_cfgspecs` and `parse_check_cfg` run very early, before the main
interner is running. They each use a short-lived interner and convert
all interned symbols to strings in their output data structures. Once
the main interner starts up, these data structures get converted into
new data structures that are identical except with the strings converted
to symbols.
All is not obvious from the current code, which is a mess, particularly
with inconsistent naming that obscures the parallel string/symbol data
structures. This commit clean things up a lot.
- The existing `CheckCfg` type is generic, allowing both
`CheckCfg<String>` and `CheckCfg<Symbol>` forms. This is really
useful, but it defaults to `String`. The commit removes the default so
we have to use `CheckCfg<String>` and `CheckCfg<Symbol>` explicitly,
which makes things clearer.
- Introduces `Cfg`, which is generic over `String` and `Symbol`, similar
to `CheckCfg`.
- Renames some things.
- `parse_cfgspecs` -> `parse_cfg`
- `CfgSpecs` -> `Cfg<String>`, plus it's used in more places, rather
than the underlying `FxHashSet` type.
- `CrateConfig` -> `Cfg<Symbol>`.
- `CrateCheckConfig` -> `CheckCfg<Symbol>`
- Adds some comments explaining the string-to-symbol conversions.
- `to_crate_check_config`, which converts `CheckCfg<String>` to
`CheckCfg<Symbol>`, is inlined and removed and combined with the
overly-general `CheckCfg::map_data` to produce
`CheckCfg::<String>::intern`.
- `build_configuration` now does the `Cfg<String>`-to-`Cfg<Symbol>`
conversion, so callers don't need to, which removes the need for
`to_crate_config`.
The diff for two of the fields in `Config` is a good example of the
improved clarity:
```
- pub crate_cfg: FxHashSet<(String, Option<String>)>,
- pub crate_check_cfg: CheckCfg,
+ pub crate_cfg: Cfg<String>,
+ pub crate_check_cfg: CheckCfg<String>,
```
Compare that with the diff for the corresponding fields in `ParseSess`,
and the relationship to `Config` is much clearer than before:
```
- pub config: CrateConfig,
- pub check_config: CrateCheckConfig,
+ pub config: Cfg<Symbol>,
+ pub check_config: CheckCfg<Symbol>,
```
2023-10-27 04:58:02 +00:00
|
|
|
use crate::config::{Cfg, CheckCfg};
|
2023-08-18 06:49:01 +00:00
|
|
|
use crate::errors::{
|
|
|
|
CliFeatureDiagnosticHelp, FeatureDiagnosticForIssue, FeatureDiagnosticHelp, FeatureGateError,
|
2023-12-16 21:23:18 +00:00
|
|
|
SuggestUpgradeCompiler,
|
2023-08-18 06:49:01 +00:00
|
|
|
};
|
2022-08-17 11:52:47 +00:00
|
|
|
use crate::lint::{
|
|
|
|
builtin::UNSTABLE_SYNTAX_PRE_EXPANSION, BufferedEarlyLint, BuiltinLintDiagnostics, Lint, LintId,
|
|
|
|
};
|
2024-01-10 05:37:30 +00:00
|
|
|
use crate::Session;
|
2020-02-29 17:37:32 +00:00
|
|
|
use rustc_ast::node_id::NodeId;
|
2023-10-27 04:49:09 +00:00
|
|
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
2023-08-13 11:30:48 +00:00
|
|
|
use rustc_data_structures::sync::{AppendOnlyVec, Lock, Lrc};
|
2023-12-17 10:48:57 +00:00
|
|
|
use rustc_errors::{emitter::SilentEmitter, DiagCtxt};
|
2022-03-24 02:03:04 +00:00
|
|
|
use rustc_errors::{
|
2024-01-13 02:11:56 +00:00
|
|
|
fallback_fluent_bundle, Diagnostic, DiagnosticBuilder, DiagnosticMessage, MultiSpan, StashKey,
|
2022-03-24 02:03:04 +00:00
|
|
|
};
|
2020-01-02 10:41:57 +00:00
|
|
|
use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures};
|
2019-12-31 17:15:40 +00:00
|
|
|
use rustc_span::edition::Edition;
|
|
|
|
use rustc_span::hygiene::ExpnId;
|
|
|
|
use rustc_span::source_map::{FilePathMapping, SourceMap};
|
2022-03-24 02:03:04 +00:00
|
|
|
use rustc_span::{Span, Symbol};
|
2019-10-09 01:23:10 +00:00
|
|
|
|
2022-09-02 08:29:40 +00:00
|
|
|
use rustc_ast::attr::AttrIdGenerator;
|
2019-10-09 01:23:10 +00:00
|
|
|
use std::str;
|
|
|
|
|
|
|
|
/// Collected spans during parsing for places where a certain feature was
|
|
|
|
/// used and should be feature gated accordingly in `check_crate`.
|
|
|
|
#[derive(Default)]
|
2019-10-30 16:34:00 +00:00
|
|
|
pub struct GatedSpans {
|
|
|
|
pub spans: Lock<FxHashMap<Symbol, Vec<Span>>>,
|
2019-10-30 15:38:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl GatedSpans {
|
|
|
|
/// Feature gate the given `span` under the given `feature`
|
2023-10-05 08:43:35 +00:00
|
|
|
/// which is same `Symbol` used in `unstable.rs`.
|
2019-10-30 15:38:16 +00:00
|
|
|
pub fn gate(&self, feature: Symbol, span: Span) {
|
|
|
|
self.spans.borrow_mut().entry(feature).or_default().push(span);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Ungate the last span under the given `feature`.
|
|
|
|
/// Panics if the given `span` wasn't the last one.
|
|
|
|
///
|
|
|
|
/// Using this is discouraged unless you have a really good reason to.
|
|
|
|
pub fn ungate_last(&self, feature: Symbol, span: Span) {
|
|
|
|
let removed_span = self.spans.borrow_mut().entry(feature).or_default().pop().unwrap();
|
|
|
|
debug_assert_eq!(span, removed_span);
|
|
|
|
}
|
|
|
|
|
2019-10-30 16:34:00 +00:00
|
|
|
/// Prepend the given set of `spans` onto the set in `self`.
|
|
|
|
pub fn merge(&self, mut spans: FxHashMap<Symbol, Vec<Span>>) {
|
|
|
|
let mut inner = self.spans.borrow_mut();
|
2023-12-03 13:37:01 +00:00
|
|
|
// The entries will be moved to another map so the drain order does not
|
|
|
|
// matter.
|
|
|
|
#[allow(rustc::potential_query_instability)]
|
2019-10-30 16:34:00 +00:00
|
|
|
for (gate, mut gate_spans) in inner.drain() {
|
|
|
|
spans.entry(gate).or_default().append(&mut gate_spans);
|
|
|
|
}
|
|
|
|
*inner = spans;
|
|
|
|
}
|
2019-10-09 01:23:10 +00:00
|
|
|
}
|
|
|
|
|
2020-04-25 01:38:31 +00:00
|
|
|
#[derive(Default)]
|
|
|
|
pub struct SymbolGallery {
|
2020-08-02 15:20:00 +00:00
|
|
|
/// All symbols occurred and their first occurrence span.
|
2020-08-05 07:29:13 +00:00
|
|
|
pub symbols: Lock<FxHashMap<Symbol, Span>>,
|
2020-04-25 01:38:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl SymbolGallery {
|
|
|
|
/// Insert a symbol and its span into symbol gallery.
|
2022-03-16 12:12:30 +00:00
|
|
|
/// If the symbol has occurred before, ignore the new occurrence.
|
2020-04-25 01:38:31 +00:00
|
|
|
pub fn insert(&self, symbol: Symbol, span: Span) {
|
|
|
|
self.symbols.lock().entry(symbol).or_insert(span);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-10 06:33:53 +00:00
|
|
|
// todo: this function now accepts `Session` instead of `ParseSess` and should be relocated
|
2020-01-02 10:55:00 +00:00
|
|
|
/// Construct a diagnostic for a language feature error due to the given `span`.
|
2023-10-05 08:43:35 +00:00
|
|
|
/// The `feature`'s `Symbol` is the one you used in `unstable.rs` and `rustc_span::symbols`.
|
2023-05-26 01:42:13 +00:00
|
|
|
#[track_caller]
|
2023-04-09 21:07:18 +00:00
|
|
|
pub fn feature_err(
|
2024-01-10 05:37:30 +00:00
|
|
|
sess: &Session,
|
2020-01-02 10:41:57 +00:00
|
|
|
feature: Symbol,
|
|
|
|
span: impl Into<MultiSpan>,
|
2023-02-04 01:59:17 +00:00
|
|
|
explain: impl Into<DiagnosticMessage>,
|
2023-12-19 04:26:24 +00:00
|
|
|
) -> DiagnosticBuilder<'_> {
|
2020-01-02 10:41:57 +00:00
|
|
|
feature_err_issue(sess, feature, span, GateIssue::Language, explain)
|
|
|
|
}
|
|
|
|
|
2020-01-02 10:55:00 +00:00
|
|
|
/// Construct a diagnostic for a feature gate error.
|
|
|
|
///
|
|
|
|
/// This variant allows you to control whether it is a library or language feature.
|
|
|
|
/// Almost always, you want to use this for a language feature. If so, prefer `feature_err`.
|
2022-10-31 15:14:29 +00:00
|
|
|
#[track_caller]
|
2023-04-09 21:07:18 +00:00
|
|
|
pub fn feature_err_issue(
|
2024-01-10 05:37:30 +00:00
|
|
|
sess: &Session,
|
2020-01-02 10:41:57 +00:00
|
|
|
feature: Symbol,
|
|
|
|
span: impl Into<MultiSpan>,
|
|
|
|
issue: GateIssue,
|
2023-02-04 01:59:17 +00:00
|
|
|
explain: impl Into<DiagnosticMessage>,
|
2023-12-19 04:26:24 +00:00
|
|
|
) -> DiagnosticBuilder<'_> {
|
2022-08-17 11:52:47 +00:00
|
|
|
let span = span.into();
|
|
|
|
|
|
|
|
// Cancel an earlier warning for this same error, if it exists.
|
|
|
|
if let Some(span) = span.primary_span() {
|
2024-01-10 05:37:30 +00:00
|
|
|
if let Some(err) = sess.parse_sess.dcx.steal_diagnostic(span, StashKey::EarlySyntaxWarning)
|
|
|
|
{
|
2023-04-09 21:07:18 +00:00
|
|
|
err.cancel()
|
|
|
|
}
|
2022-08-17 11:52:47 +00:00
|
|
|
}
|
|
|
|
|
2024-01-10 05:37:30 +00:00
|
|
|
let mut err =
|
|
|
|
sess.parse_sess.dcx.create_err(FeatureGateError { span, explain: explain.into() });
|
2023-08-18 06:49:01 +00:00
|
|
|
add_feature_diagnostics_for_issue(&mut err, sess, feature, issue, false);
|
2022-02-28 20:29:06 +00:00
|
|
|
err
|
|
|
|
}
|
|
|
|
|
2022-08-17 11:52:47 +00:00
|
|
|
/// Construct a future incompatibility diagnostic for a feature gate.
|
|
|
|
///
|
|
|
|
/// This diagnostic is only a warning and *does not cause compilation to fail*.
|
2023-07-18 15:48:07 +00:00
|
|
|
#[track_caller]
|
2024-01-10 05:37:30 +00:00
|
|
|
pub fn feature_warn(sess: &Session, feature: Symbol, span: Span, explain: &'static str) {
|
2022-08-17 11:52:47 +00:00
|
|
|
feature_warn_issue(sess, feature, span, GateIssue::Language, explain);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Construct a future incompatibility diagnostic for a feature gate.
|
|
|
|
///
|
|
|
|
/// This diagnostic is only a warning and *does not cause compilation to fail*.
|
|
|
|
///
|
|
|
|
/// This variant allows you to control whether it is a library or language feature.
|
|
|
|
/// Almost always, you want to use this for a language feature. If so, prefer `feature_warn`.
|
2022-08-22 06:28:50 +00:00
|
|
|
#[allow(rustc::diagnostic_outside_of_impl)]
|
|
|
|
#[allow(rustc::untranslatable_diagnostic)]
|
2023-07-18 15:48:07 +00:00
|
|
|
#[track_caller]
|
2022-12-20 21:10:40 +00:00
|
|
|
pub fn feature_warn_issue(
|
2024-01-10 05:37:30 +00:00
|
|
|
sess: &Session,
|
2022-08-17 11:52:47 +00:00
|
|
|
feature: Symbol,
|
|
|
|
span: Span,
|
|
|
|
issue: GateIssue,
|
Use `Cow` in `{D,Subd}iagnosticMessage`.
Each of `{D,Subd}iagnosticMessage::{Str,Eager}` has a comment:
```
// FIXME(davidtwco): can a `Cow<'static, str>` be used here?
```
This commit answers that question in the affirmative. It's not the most
compelling change ever, but it might be worth merging.
This requires changing the `impl<'a> From<&'a str>` impls to `impl
From<&'static str>`, which involves a bunch of knock-on changes that
require/result in call sites being a little more precise about exactly
what kind of string they use to create errors, and not just `&str`. This
will result in fewer unnecessary allocations, though this will not have
any notable perf effects given that these are error paths.
Note that I was lazy within Clippy, using `to_string` in a few places to
preserve the existing string imprecision. I could have used `impl
Into<{D,Subd}iagnosticMessage>` in various places as is done in the
compiler, but that would have required changes to *many* call sites
(mostly changing `&format("...")` to `format!("...")`) which didn't seem
worthwhile.
2023-05-04 00:55:21 +00:00
|
|
|
explain: &'static str,
|
2022-08-17 11:52:47 +00:00
|
|
|
) {
|
2024-01-10 05:37:30 +00:00
|
|
|
let mut err = sess.parse_sess.dcx.struct_span_warn(span, explain);
|
2023-08-18 06:49:01 +00:00
|
|
|
add_feature_diagnostics_for_issue(&mut err, sess, feature, issue, false);
|
2022-08-17 11:52:47 +00:00
|
|
|
|
2024-01-16 05:42:00 +00:00
|
|
|
// Decorate this as a future-incompatibility lint as in rustc_middle::lint::lint_level
|
2022-08-17 11:52:47 +00:00
|
|
|
let lint = UNSTABLE_SYNTAX_PRE_EXPANSION;
|
|
|
|
let future_incompatible = lint.future_incompatible.as_ref().unwrap();
|
2024-01-13 02:11:56 +00:00
|
|
|
err.is_lint(lint.name_lower(), /* has_future_breakage */ false);
|
2022-08-17 11:52:47 +00:00
|
|
|
err.warn(lint.desc);
|
|
|
|
err.note(format!("for more information, see {}", future_incompatible.reference));
|
|
|
|
|
|
|
|
// A later feature_err call can steal and cancel this warning.
|
|
|
|
err.stash(span, StashKey::EarlySyntaxWarning);
|
|
|
|
}
|
|
|
|
|
2022-02-28 20:29:06 +00:00
|
|
|
/// Adds the diagnostics for a feature to an existing error.
|
2024-01-10 05:37:30 +00:00
|
|
|
pub fn add_feature_diagnostics(err: &mut Diagnostic, sess: &Session, feature: Symbol) {
|
2023-08-18 06:49:01 +00:00
|
|
|
add_feature_diagnostics_for_issue(err, sess, feature, GateIssue::Language, false);
|
2022-02-28 20:29:06 +00:00
|
|
|
}
|
2020-01-02 10:41:57 +00:00
|
|
|
|
2022-02-28 20:29:06 +00:00
|
|
|
/// Adds the diagnostics for a feature to an existing error.
|
|
|
|
///
|
|
|
|
/// This variant allows you to control whether it is a library or language feature.
|
|
|
|
/// Almost always, you want to use this for a language feature. If so, prefer
|
|
|
|
/// `add_feature_diagnostics`.
|
2022-12-20 21:10:40 +00:00
|
|
|
pub fn add_feature_diagnostics_for_issue(
|
2022-02-28 20:29:06 +00:00
|
|
|
err: &mut Diagnostic,
|
2024-01-10 05:37:30 +00:00
|
|
|
sess: &Session,
|
2022-02-28 20:29:06 +00:00
|
|
|
feature: Symbol,
|
|
|
|
issue: GateIssue,
|
2023-08-18 06:49:01 +00:00
|
|
|
feature_from_cli: bool,
|
2022-02-28 20:29:06 +00:00
|
|
|
) {
|
2020-01-02 10:41:57 +00:00
|
|
|
if let Some(n) = find_feature_issue(feature, issue) {
|
2022-08-22 06:28:50 +00:00
|
|
|
err.subdiagnostic(FeatureDiagnosticForIssue { n });
|
2020-01-02 10:41:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// #23973: do not suggest `#![feature(...)]` if we are in beta/stable
|
2024-01-10 05:37:30 +00:00
|
|
|
if sess.parse_sess.unstable_features.is_nightly_build() {
|
2023-08-18 06:49:01 +00:00
|
|
|
if feature_from_cli {
|
|
|
|
err.subdiagnostic(CliFeatureDiagnosticHelp { feature });
|
|
|
|
} else {
|
|
|
|
err.subdiagnostic(FeatureDiagnosticHelp { feature });
|
|
|
|
}
|
2023-12-16 21:23:18 +00:00
|
|
|
|
2024-01-10 05:37:30 +00:00
|
|
|
if sess.opts.unstable_opts.ui_testing {
|
|
|
|
err.subdiagnostic(SuggestUpgradeCompiler::ui_testing());
|
|
|
|
} else if let Some(suggestion) = SuggestUpgradeCompiler::new() {
|
|
|
|
err.subdiagnostic(suggestion);
|
|
|
|
}
|
2020-01-02 10:41:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-09 01:23:10 +00:00
|
|
|
/// Info about a parsing session.
|
|
|
|
pub struct ParseSess {
|
2023-12-17 11:25:47 +00:00
|
|
|
pub dcx: DiagCtxt,
|
2019-10-15 20:48:13 +00:00
|
|
|
pub unstable_features: UnstableFeatures,
|
2023-10-30 03:05:06 +00:00
|
|
|
pub config: Cfg,
|
|
|
|
pub check_config: CheckCfg,
|
2019-10-09 01:23:10 +00:00
|
|
|
pub edition: Edition,
|
2021-08-29 08:34:23 +00:00
|
|
|
/// Places where raw identifiers were used. This is used to avoid complaining about idents
|
|
|
|
/// clashing with keywords in new editions.
|
2023-03-14 12:16:19 +00:00
|
|
|
pub raw_identifier_spans: AppendOnlyVec<Span>,
|
2021-08-29 08:34:23 +00:00
|
|
|
/// Places where identifiers that contain invalid Unicode codepoints but that look like they
|
2021-09-10 07:30:58 +00:00
|
|
|
/// should be. Useful to avoid bad tokenization when encountering emoji. We group them to
|
2021-08-29 08:34:23 +00:00
|
|
|
/// provide a single error per unique incorrect identifier.
|
|
|
|
pub bad_unicode_identifiers: Lock<FxHashMap<Symbol, Vec<Span>>>,
|
2019-10-09 01:23:10 +00:00
|
|
|
source_map: Lrc<SourceMap>,
|
|
|
|
pub buffered_lints: Lock<Vec<BufferedEarlyLint>>,
|
|
|
|
/// Contains the spans of block expressions that could have been incomplete based on the
|
|
|
|
/// operation token that followed it, but that the parser cannot identify without further
|
|
|
|
/// analysis.
|
|
|
|
pub ambiguous_block_expr_parse: Lock<FxHashMap<Span, Span>>,
|
2019-10-30 16:34:00 +00:00
|
|
|
pub gated_spans: GatedSpans,
|
2020-04-25 01:38:31 +00:00
|
|
|
pub symbol_gallery: SymbolGallery,
|
2020-05-03 17:47:51 +00:00
|
|
|
/// Environment variables accessed during the build and their values when they exist.
|
|
|
|
pub env_depinfo: Lock<FxHashSet<(Symbol, Option<Symbol>)>>,
|
2021-04-09 14:35:40 +00:00
|
|
|
/// File paths accessed during the build.
|
|
|
|
pub file_depinfo: Lock<FxHashSet<Symbol>>,
|
2021-01-28 08:24:55 +00:00
|
|
|
/// Whether cfg(version) should treat the current release as incomplete
|
|
|
|
pub assume_incomplete_release: bool,
|
Implement span quoting for proc-macros
This PR implements span quoting, allowing proc-macros to produce spans
pointing *into their own crate*. This is used by the unstable
`proc_macro::quote!` macro, allowing us to get error messages like this:
```
error[E0412]: cannot find type `MissingType` in this scope
--> $DIR/auxiliary/span-from-proc-macro.rs:37:20
|
LL | pub fn error_from_attribute(_args: TokenStream, _input: TokenStream) -> TokenStream {
| ----------------------------------------------------------------------------------- in this expansion of procedural macro `#[error_from_attribute]`
...
LL | field: MissingType
| ^^^^^^^^^^^ not found in this scope
|
::: $DIR/span-from-proc-macro.rs:8:1
|
LL | #[error_from_attribute]
| ----------------------- in this macro invocation
```
Here, `MissingType` occurs inside the implementation of the proc-macro
`#[error_from_attribute]`. Previosuly, this would always result in a
span pointing at `#[error_from_attribute]`
This will make many proc-macro-related error message much more useful -
when a proc-macro generates code containing an error, users will get an
error message pointing directly at that code (within the macro
definition), instead of always getting a span pointing at the macro
invocation site.
This is implemented as follows:
* When a proc-macro crate is being *compiled*, it causes the `quote!`
macro to get run. This saves all of the sapns in the input to `quote!`
into the metadata of *the proc-macro-crate* (which we are currently
compiling). The `quote!` macro then expands to a call to
`proc_macro::Span::recover_proc_macro_span(id)`, where `id` is an
opaque identifier for the span in the crate metadata.
* When the same proc-macro crate is *run* (e.g. it is loaded from disk
and invoked by some consumer crate), the call to
`proc_macro::Span::recover_proc_macro_span` causes us to load the span
from the proc-macro crate's metadata. The proc-macro then produces a
`TokenStream` containing a `Span` pointing into the proc-macro crate
itself.
The recursive nature of 'quote!' can be difficult to understand at
first. The file `src/test/ui/proc-macro/quote-debug.stdout` shows
the output of the `quote!` macro, which should make this eaier to
understand.
This PR also supports custom quoting spans in custom quote macros (e.g.
the `quote` crate). All span quoting goes through the
`proc_macro::quote_span` method, which can be called by a custom quote
macro to perform span quoting. An example of this usage is provided in
`src/test/ui/proc-macro/auxiliary/custom-quote.rs`
Custom quoting currently has a few limitations:
In order to quote a span, we need to generate a call to
`proc_macro::Span::recover_proc_macro_span`. However, proc-macros
support renaming the `proc_macro` crate, so we can't simply hardcode
this path. Previously, the `quote_span` method used the path
`crate::Span` - however, this only works when it is called by the
builtin `quote!` macro in the same crate. To support being called from
arbitrary crates, we need access to the name of the `proc_macro` crate
to generate a path. This PR adds an additional argument to `quote_span`
to specify the name of the `proc_macro` crate. Howver, this feels kind
of hacky, and we may want to change this before stabilizing anything
quote-related.
Additionally, using `quote_span` currently requires enabling the
`proc_macro_internals` feature. The builtin `quote!` macro
has an `#[allow_internal_unstable]` attribute, but this won't work for
custom quote implementations. This will likely require some additional
tricks to apply `allow_internal_unstable` to the span of
`proc_macro::Span::recover_proc_macro_span`.
2020-08-02 23:52:16 +00:00
|
|
|
/// Spans passed to `proc_macro::quote_span`. Each span has a numerical
|
|
|
|
/// identifier represented by its position in the vector.
|
2023-11-28 05:30:57 +00:00
|
|
|
proc_macro_quoted_spans: AppendOnlyVec<Span>,
|
2022-09-02 08:29:40 +00:00
|
|
|
/// Used to generate new `AttrId`s. Every `AttrId` is unique.
|
|
|
|
pub attr_id_generator: AttrIdGenerator,
|
2019-10-09 01:23:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl ParseSess {
|
2021-03-16 05:50:34 +00:00
|
|
|
/// Used for testing.
|
2022-10-17 13:11:26 +00:00
|
|
|
pub fn new(locale_resources: Vec<&'static str>, file_path_mapping: FilePathMapping) -> Self {
|
2022-10-13 09:13:02 +00:00
|
|
|
let fallback_bundle = fallback_fluent_bundle(locale_resources, false);
|
2020-02-22 14:07:05 +00:00
|
|
|
let sm = Lrc::new(SourceMap::new(file_path_mapping));
|
2023-12-18 00:15:13 +00:00
|
|
|
let dcx = DiagCtxt::with_tty_emitter(Some(sm.clone()), fallback_bundle);
|
|
|
|
ParseSess::with_dcx(dcx, sm)
|
2019-10-09 01:23:10 +00:00
|
|
|
}
|
|
|
|
|
2023-12-17 23:15:45 +00:00
|
|
|
pub fn with_dcx(dcx: DiagCtxt, source_map: Lrc<SourceMap>) -> Self {
|
2019-10-09 01:23:10 +00:00
|
|
|
Self {
|
2023-12-17 23:15:45 +00:00
|
|
|
dcx,
|
2020-10-10 18:27:52 +00:00
|
|
|
unstable_features: UnstableFeatures::from_environment(None),
|
Clean up config mess.
`parse_cfgspecs` and `parse_check_cfg` run very early, before the main
interner is running. They each use a short-lived interner and convert
all interned symbols to strings in their output data structures. Once
the main interner starts up, these data structures get converted into
new data structures that are identical except with the strings converted
to symbols.
All is not obvious from the current code, which is a mess, particularly
with inconsistent naming that obscures the parallel string/symbol data
structures. This commit clean things up a lot.
- The existing `CheckCfg` type is generic, allowing both
`CheckCfg<String>` and `CheckCfg<Symbol>` forms. This is really
useful, but it defaults to `String`. The commit removes the default so
we have to use `CheckCfg<String>` and `CheckCfg<Symbol>` explicitly,
which makes things clearer.
- Introduces `Cfg`, which is generic over `String` and `Symbol`, similar
to `CheckCfg`.
- Renames some things.
- `parse_cfgspecs` -> `parse_cfg`
- `CfgSpecs` -> `Cfg<String>`, plus it's used in more places, rather
than the underlying `FxHashSet` type.
- `CrateConfig` -> `Cfg<Symbol>`.
- `CrateCheckConfig` -> `CheckCfg<Symbol>`
- Adds some comments explaining the string-to-symbol conversions.
- `to_crate_check_config`, which converts `CheckCfg<String>` to
`CheckCfg<Symbol>`, is inlined and removed and combined with the
overly-general `CheckCfg::map_data` to produce
`CheckCfg::<String>::intern`.
- `build_configuration` now does the `Cfg<String>`-to-`Cfg<Symbol>`
conversion, so callers don't need to, which removes the need for
`to_crate_config`.
The diff for two of the fields in `Config` is a good example of the
improved clarity:
```
- pub crate_cfg: FxHashSet<(String, Option<String>)>,
- pub crate_check_cfg: CheckCfg,
+ pub crate_cfg: Cfg<String>,
+ pub crate_check_cfg: CheckCfg<String>,
```
Compare that with the diff for the corresponding fields in `ParseSess`,
and the relationship to `Config` is much clearer than before:
```
- pub config: CrateConfig,
- pub check_config: CrateCheckConfig,
+ pub config: Cfg<Symbol>,
+ pub check_config: CheckCfg<Symbol>,
```
2023-10-27 04:58:02 +00:00
|
|
|
config: Cfg::default(),
|
|
|
|
check_config: CheckCfg::default(),
|
2019-10-09 01:23:10 +00:00
|
|
|
edition: ExpnId::root().expn_data().edition,
|
2023-03-14 12:16:19 +00:00
|
|
|
raw_identifier_spans: Default::default(),
|
2021-08-29 08:34:23 +00:00
|
|
|
bad_unicode_identifiers: Lock::new(Default::default()),
|
2019-10-09 01:23:10 +00:00
|
|
|
source_map,
|
|
|
|
buffered_lints: Lock::new(vec![]),
|
|
|
|
ambiguous_block_expr_parse: Lock::new(FxHashMap::default()),
|
|
|
|
gated_spans: GatedSpans::default(),
|
2020-04-25 01:38:31 +00:00
|
|
|
symbol_gallery: SymbolGallery::default(),
|
2020-05-03 17:47:51 +00:00
|
|
|
env_depinfo: Default::default(),
|
2021-04-09 14:35:40 +00:00
|
|
|
file_depinfo: Default::default(),
|
2021-01-28 08:24:55 +00:00
|
|
|
assume_incomplete_release: false,
|
Implement span quoting for proc-macros
This PR implements span quoting, allowing proc-macros to produce spans
pointing *into their own crate*. This is used by the unstable
`proc_macro::quote!` macro, allowing us to get error messages like this:
```
error[E0412]: cannot find type `MissingType` in this scope
--> $DIR/auxiliary/span-from-proc-macro.rs:37:20
|
LL | pub fn error_from_attribute(_args: TokenStream, _input: TokenStream) -> TokenStream {
| ----------------------------------------------------------------------------------- in this expansion of procedural macro `#[error_from_attribute]`
...
LL | field: MissingType
| ^^^^^^^^^^^ not found in this scope
|
::: $DIR/span-from-proc-macro.rs:8:1
|
LL | #[error_from_attribute]
| ----------------------- in this macro invocation
```
Here, `MissingType` occurs inside the implementation of the proc-macro
`#[error_from_attribute]`. Previosuly, this would always result in a
span pointing at `#[error_from_attribute]`
This will make many proc-macro-related error message much more useful -
when a proc-macro generates code containing an error, users will get an
error message pointing directly at that code (within the macro
definition), instead of always getting a span pointing at the macro
invocation site.
This is implemented as follows:
* When a proc-macro crate is being *compiled*, it causes the `quote!`
macro to get run. This saves all of the sapns in the input to `quote!`
into the metadata of *the proc-macro-crate* (which we are currently
compiling). The `quote!` macro then expands to a call to
`proc_macro::Span::recover_proc_macro_span(id)`, where `id` is an
opaque identifier for the span in the crate metadata.
* When the same proc-macro crate is *run* (e.g. it is loaded from disk
and invoked by some consumer crate), the call to
`proc_macro::Span::recover_proc_macro_span` causes us to load the span
from the proc-macro crate's metadata. The proc-macro then produces a
`TokenStream` containing a `Span` pointing into the proc-macro crate
itself.
The recursive nature of 'quote!' can be difficult to understand at
first. The file `src/test/ui/proc-macro/quote-debug.stdout` shows
the output of the `quote!` macro, which should make this eaier to
understand.
This PR also supports custom quoting spans in custom quote macros (e.g.
the `quote` crate). All span quoting goes through the
`proc_macro::quote_span` method, which can be called by a custom quote
macro to perform span quoting. An example of this usage is provided in
`src/test/ui/proc-macro/auxiliary/custom-quote.rs`
Custom quoting currently has a few limitations:
In order to quote a span, we need to generate a call to
`proc_macro::Span::recover_proc_macro_span`. However, proc-macros
support renaming the `proc_macro` crate, so we can't simply hardcode
this path. Previously, the `quote_span` method used the path
`crate::Span` - however, this only works when it is called by the
builtin `quote!` macro in the same crate. To support being called from
arbitrary crates, we need access to the name of the `proc_macro` crate
to generate a path. This PR adds an additional argument to `quote_span`
to specify the name of the `proc_macro` crate. Howver, this feels kind
of hacky, and we may want to change this before stabilizing anything
quote-related.
Additionally, using `quote_span` currently requires enabling the
`proc_macro_internals` feature. The builtin `quote!` macro
has an `#[allow_internal_unstable]` attribute, but this won't work for
custom quote implementations. This will likely require some additional
tricks to apply `allow_internal_unstable` to the span of
`proc_macro::Span::recover_proc_macro_span`.
2020-08-02 23:52:16 +00:00
|
|
|
proc_macro_quoted_spans: Default::default(),
|
2022-09-02 08:29:40 +00:00
|
|
|
attr_id_generator: AttrIdGenerator::new(),
|
2019-10-09 01:23:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-02 17:15:45 +00:00
|
|
|
pub fn with_silent_emitter(fatal_note: Option<String>) -> Self {
|
2022-10-17 13:11:26 +00:00
|
|
|
let fallback_bundle = fallback_fluent_bundle(Vec::new(), false);
|
2020-02-22 14:07:05 +00:00
|
|
|
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
2023-12-17 22:12:20 +00:00
|
|
|
let fatal_dcx = DiagCtxt::with_tty_emitter(None, fallback_bundle).disable_warnings();
|
2023-12-18 00:15:13 +00:00
|
|
|
let dcx = DiagCtxt::with_emitter(Box::new(SilentEmitter { fatal_dcx, fatal_note }))
|
2023-07-25 10:27:34 +00:00
|
|
|
.disable_warnings();
|
2023-12-18 00:15:13 +00:00
|
|
|
ParseSess::with_dcx(dcx, sm)
|
2019-11-03 17:04:01 +00:00
|
|
|
}
|
|
|
|
|
2019-10-09 01:23:10 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn source_map(&self) -> &SourceMap {
|
|
|
|
&self.source_map
|
|
|
|
}
|
|
|
|
|
2020-05-27 18:34:17 +00:00
|
|
|
pub fn clone_source_map(&self) -> Lrc<SourceMap> {
|
|
|
|
self.source_map.clone()
|
|
|
|
}
|
|
|
|
|
2019-10-09 01:23:10 +00:00
|
|
|
pub fn buffer_lint(
|
|
|
|
&self,
|
2020-01-05 08:40:16 +00:00
|
|
|
lint: &'static Lint,
|
2019-10-09 01:23:10 +00:00
|
|
|
span: impl Into<MultiSpan>,
|
2020-01-05 08:40:16 +00:00
|
|
|
node_id: NodeId,
|
2023-05-16 06:04:03 +00:00
|
|
|
msg: impl Into<DiagnosticMessage>,
|
2019-10-09 01:23:10 +00:00
|
|
|
) {
|
|
|
|
self.buffered_lints.with_lock(|buffered_lints| {
|
|
|
|
buffered_lints.push(BufferedEarlyLint {
|
|
|
|
span: span.into(),
|
2020-01-05 08:40:16 +00:00
|
|
|
node_id,
|
2019-10-09 01:23:10 +00:00
|
|
|
msg: msg.into(),
|
2020-01-05 08:40:16 +00:00
|
|
|
lint_id: LintId::of(lint),
|
|
|
|
diagnostic: BuiltinLintDiagnostics::Normal,
|
2019-10-09 01:23:10 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-02-22 00:01:48 +00:00
|
|
|
pub fn buffer_lint_with_diagnostic(
|
|
|
|
&self,
|
|
|
|
lint: &'static Lint,
|
|
|
|
span: impl Into<MultiSpan>,
|
|
|
|
node_id: NodeId,
|
2023-05-16 06:04:03 +00:00
|
|
|
msg: impl Into<DiagnosticMessage>,
|
2020-02-22 00:01:48 +00:00
|
|
|
diagnostic: BuiltinLintDiagnostics,
|
|
|
|
) {
|
|
|
|
self.buffered_lints.with_lock(|buffered_lints| {
|
|
|
|
buffered_lints.push(BufferedEarlyLint {
|
|
|
|
span: span.into(),
|
|
|
|
node_id,
|
|
|
|
msg: msg.into(),
|
|
|
|
lint_id: LintId::of(lint),
|
|
|
|
diagnostic,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
Implement span quoting for proc-macros
This PR implements span quoting, allowing proc-macros to produce spans
pointing *into their own crate*. This is used by the unstable
`proc_macro::quote!` macro, allowing us to get error messages like this:
```
error[E0412]: cannot find type `MissingType` in this scope
--> $DIR/auxiliary/span-from-proc-macro.rs:37:20
|
LL | pub fn error_from_attribute(_args: TokenStream, _input: TokenStream) -> TokenStream {
| ----------------------------------------------------------------------------------- in this expansion of procedural macro `#[error_from_attribute]`
...
LL | field: MissingType
| ^^^^^^^^^^^ not found in this scope
|
::: $DIR/span-from-proc-macro.rs:8:1
|
LL | #[error_from_attribute]
| ----------------------- in this macro invocation
```
Here, `MissingType` occurs inside the implementation of the proc-macro
`#[error_from_attribute]`. Previosuly, this would always result in a
span pointing at `#[error_from_attribute]`
This will make many proc-macro-related error message much more useful -
when a proc-macro generates code containing an error, users will get an
error message pointing directly at that code (within the macro
definition), instead of always getting a span pointing at the macro
invocation site.
This is implemented as follows:
* When a proc-macro crate is being *compiled*, it causes the `quote!`
macro to get run. This saves all of the sapns in the input to `quote!`
into the metadata of *the proc-macro-crate* (which we are currently
compiling). The `quote!` macro then expands to a call to
`proc_macro::Span::recover_proc_macro_span(id)`, where `id` is an
opaque identifier for the span in the crate metadata.
* When the same proc-macro crate is *run* (e.g. it is loaded from disk
and invoked by some consumer crate), the call to
`proc_macro::Span::recover_proc_macro_span` causes us to load the span
from the proc-macro crate's metadata. The proc-macro then produces a
`TokenStream` containing a `Span` pointing into the proc-macro crate
itself.
The recursive nature of 'quote!' can be difficult to understand at
first. The file `src/test/ui/proc-macro/quote-debug.stdout` shows
the output of the `quote!` macro, which should make this eaier to
understand.
This PR also supports custom quoting spans in custom quote macros (e.g.
the `quote` crate). All span quoting goes through the
`proc_macro::quote_span` method, which can be called by a custom quote
macro to perform span quoting. An example of this usage is provided in
`src/test/ui/proc-macro/auxiliary/custom-quote.rs`
Custom quoting currently has a few limitations:
In order to quote a span, we need to generate a call to
`proc_macro::Span::recover_proc_macro_span`. However, proc-macros
support renaming the `proc_macro` crate, so we can't simply hardcode
this path. Previously, the `quote_span` method used the path
`crate::Span` - however, this only works when it is called by the
builtin `quote!` macro in the same crate. To support being called from
arbitrary crates, we need access to the name of the `proc_macro` crate
to generate a path. This PR adds an additional argument to `quote_span`
to specify the name of the `proc_macro` crate. Howver, this feels kind
of hacky, and we may want to change this before stabilizing anything
quote-related.
Additionally, using `quote_span` currently requires enabling the
`proc_macro_internals` feature. The builtin `quote!` macro
has an `#[allow_internal_unstable]` attribute, but this won't work for
custom quote implementations. This will likely require some additional
tricks to apply `allow_internal_unstable` to the span of
`proc_macro::Span::recover_proc_macro_span`.
2020-08-02 23:52:16 +00:00
|
|
|
pub fn save_proc_macro_span(&self, span: Span) -> usize {
|
2023-03-14 12:11:56 +00:00
|
|
|
self.proc_macro_quoted_spans.push(span)
|
Implement span quoting for proc-macros
This PR implements span quoting, allowing proc-macros to produce spans
pointing *into their own crate*. This is used by the unstable
`proc_macro::quote!` macro, allowing us to get error messages like this:
```
error[E0412]: cannot find type `MissingType` in this scope
--> $DIR/auxiliary/span-from-proc-macro.rs:37:20
|
LL | pub fn error_from_attribute(_args: TokenStream, _input: TokenStream) -> TokenStream {
| ----------------------------------------------------------------------------------- in this expansion of procedural macro `#[error_from_attribute]`
...
LL | field: MissingType
| ^^^^^^^^^^^ not found in this scope
|
::: $DIR/span-from-proc-macro.rs:8:1
|
LL | #[error_from_attribute]
| ----------------------- in this macro invocation
```
Here, `MissingType` occurs inside the implementation of the proc-macro
`#[error_from_attribute]`. Previosuly, this would always result in a
span pointing at `#[error_from_attribute]`
This will make many proc-macro-related error message much more useful -
when a proc-macro generates code containing an error, users will get an
error message pointing directly at that code (within the macro
definition), instead of always getting a span pointing at the macro
invocation site.
This is implemented as follows:
* When a proc-macro crate is being *compiled*, it causes the `quote!`
macro to get run. This saves all of the sapns in the input to `quote!`
into the metadata of *the proc-macro-crate* (which we are currently
compiling). The `quote!` macro then expands to a call to
`proc_macro::Span::recover_proc_macro_span(id)`, where `id` is an
opaque identifier for the span in the crate metadata.
* When the same proc-macro crate is *run* (e.g. it is loaded from disk
and invoked by some consumer crate), the call to
`proc_macro::Span::recover_proc_macro_span` causes us to load the span
from the proc-macro crate's metadata. The proc-macro then produces a
`TokenStream` containing a `Span` pointing into the proc-macro crate
itself.
The recursive nature of 'quote!' can be difficult to understand at
first. The file `src/test/ui/proc-macro/quote-debug.stdout` shows
the output of the `quote!` macro, which should make this eaier to
understand.
This PR also supports custom quoting spans in custom quote macros (e.g.
the `quote` crate). All span quoting goes through the
`proc_macro::quote_span` method, which can be called by a custom quote
macro to perform span quoting. An example of this usage is provided in
`src/test/ui/proc-macro/auxiliary/custom-quote.rs`
Custom quoting currently has a few limitations:
In order to quote a span, we need to generate a call to
`proc_macro::Span::recover_proc_macro_span`. However, proc-macros
support renaming the `proc_macro` crate, so we can't simply hardcode
this path. Previously, the `quote_span` method used the path
`crate::Span` - however, this only works when it is called by the
builtin `quote!` macro in the same crate. To support being called from
arbitrary crates, we need access to the name of the `proc_macro` crate
to generate a path. This PR adds an additional argument to `quote_span`
to specify the name of the `proc_macro` crate. Howver, this feels kind
of hacky, and we may want to change this before stabilizing anything
quote-related.
Additionally, using `quote_span` currently requires enabling the
`proc_macro_internals` feature. The builtin `quote!` macro
has an `#[allow_internal_unstable]` attribute, but this won't work for
custom quote implementations. This will likely require some additional
tricks to apply `allow_internal_unstable` to the span of
`proc_macro::Span::recover_proc_macro_span`.
2020-08-02 23:52:16 +00:00
|
|
|
}
|
|
|
|
|
2023-03-14 12:11:56 +00:00
|
|
|
pub fn proc_macro_quoted_spans(&self) -> impl Iterator<Item = (usize, Span)> + '_ {
|
|
|
|
// This is equivalent to `.iter().copied().enumerate()`, but that isn't possible for
|
|
|
|
// AppendOnlyVec, so we resort to this scheme.
|
2023-03-15 15:44:23 +00:00
|
|
|
self.proc_macro_quoted_spans.iter_enumerated()
|
Implement span quoting for proc-macros
This PR implements span quoting, allowing proc-macros to produce spans
pointing *into their own crate*. This is used by the unstable
`proc_macro::quote!` macro, allowing us to get error messages like this:
```
error[E0412]: cannot find type `MissingType` in this scope
--> $DIR/auxiliary/span-from-proc-macro.rs:37:20
|
LL | pub fn error_from_attribute(_args: TokenStream, _input: TokenStream) -> TokenStream {
| ----------------------------------------------------------------------------------- in this expansion of procedural macro `#[error_from_attribute]`
...
LL | field: MissingType
| ^^^^^^^^^^^ not found in this scope
|
::: $DIR/span-from-proc-macro.rs:8:1
|
LL | #[error_from_attribute]
| ----------------------- in this macro invocation
```
Here, `MissingType` occurs inside the implementation of the proc-macro
`#[error_from_attribute]`. Previosuly, this would always result in a
span pointing at `#[error_from_attribute]`
This will make many proc-macro-related error message much more useful -
when a proc-macro generates code containing an error, users will get an
error message pointing directly at that code (within the macro
definition), instead of always getting a span pointing at the macro
invocation site.
This is implemented as follows:
* When a proc-macro crate is being *compiled*, it causes the `quote!`
macro to get run. This saves all of the sapns in the input to `quote!`
into the metadata of *the proc-macro-crate* (which we are currently
compiling). The `quote!` macro then expands to a call to
`proc_macro::Span::recover_proc_macro_span(id)`, where `id` is an
opaque identifier for the span in the crate metadata.
* When the same proc-macro crate is *run* (e.g. it is loaded from disk
and invoked by some consumer crate), the call to
`proc_macro::Span::recover_proc_macro_span` causes us to load the span
from the proc-macro crate's metadata. The proc-macro then produces a
`TokenStream` containing a `Span` pointing into the proc-macro crate
itself.
The recursive nature of 'quote!' can be difficult to understand at
first. The file `src/test/ui/proc-macro/quote-debug.stdout` shows
the output of the `quote!` macro, which should make this eaier to
understand.
This PR also supports custom quoting spans in custom quote macros (e.g.
the `quote` crate). All span quoting goes through the
`proc_macro::quote_span` method, which can be called by a custom quote
macro to perform span quoting. An example of this usage is provided in
`src/test/ui/proc-macro/auxiliary/custom-quote.rs`
Custom quoting currently has a few limitations:
In order to quote a span, we need to generate a call to
`proc_macro::Span::recover_proc_macro_span`. However, proc-macros
support renaming the `proc_macro` crate, so we can't simply hardcode
this path. Previously, the `quote_span` method used the path
`crate::Span` - however, this only works when it is called by the
builtin `quote!` macro in the same crate. To support being called from
arbitrary crates, we need access to the name of the `proc_macro` crate
to generate a path. This PR adds an additional argument to `quote_span`
to specify the name of the `proc_macro` crate. Howver, this feels kind
of hacky, and we may want to change this before stabilizing anything
quote-related.
Additionally, using `quote_span` currently requires enabling the
`proc_macro_internals` feature. The builtin `quote!` macro
has an `#[allow_internal_unstable]` attribute, but this won't work for
custom quote implementations. This will likely require some additional
tricks to apply `allow_internal_unstable` to the span of
`proc_macro::Span::recover_proc_macro_span`.
2020-08-02 23:52:16 +00:00
|
|
|
}
|
2019-10-09 01:23:10 +00:00
|
|
|
}
|