]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_session/src/parse.rs
New upstream version 1.70.0+dfsg1
[rustc.git] / compiler / rustc_session / src / parse.rs
CommitLineData
e74abb32
XL
1//! Contains `ParseSess` which holds state living beyond what one `Parser` might.
2//! It also serves as an input to the parser itself.
3
5099ac24 4use crate::config::CheckCfg;
f2b60f7d
FG
5use crate::errors::{FeatureDiagnosticForIssue, FeatureDiagnosticHelp, FeatureGateError};
6use crate::lint::{
7 builtin::UNSTABLE_SYNTAX_PRE_EXPANSION, BufferedEarlyLint, BuiltinLintDiagnostics, Lint, LintId,
8};
74b04a01 9use rustc_ast::node_id::NodeId;
f2b60f7d 10use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
353b0b11 11use rustc_data_structures::sync::{AppendOnlyVec, AtomicBool, Lock, Lrc};
dfeec247 12use rustc_errors::{emitter::SilentEmitter, ColorConfig, Handler};
04454e1e 13use rustc_errors::{
2b03887a
FG
14 fallback_fluent_bundle, Diagnostic, DiagnosticBuilder, DiagnosticId, DiagnosticMessage,
15 EmissionGuarantee, ErrorGuaranteed, IntoDiagnostic, MultiSpan, Noted, StashKey,
04454e1e 16};
dfeec247
XL
17use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures};
18use rustc_span::edition::Edition;
19use rustc_span::hygiene::ExpnId;
20use rustc_span::source_map::{FilePathMapping, SourceMap};
04454e1e 21use rustc_span::{Span, Symbol};
e74abb32 22
f2b60f7d 23use rustc_ast::attr::AttrIdGenerator;
e74abb32
XL
24use std::str;
25
60c5eb7d
XL
26/// The set of keys (and, optionally, values) that define the compilation
27/// environment of the crate, used to drive conditional compilation.
f2b60f7d 28pub type CrateConfig = FxIndexSet<(Symbol, Option<Symbol>)>;
5099ac24 29pub type CrateCheckConfig = CheckCfg<Symbol>;
60c5eb7d 30
e74abb32
XL
31/// Collected spans during parsing for places where a certain feature was
32/// used and should be feature gated accordingly in `check_crate`.
33#[derive(Default)]
60c5eb7d
XL
34pub struct GatedSpans {
35 pub spans: Lock<FxHashMap<Symbol, Vec<Span>>>,
36}
37
38impl GatedSpans {
39 /// Feature gate the given `span` under the given `feature`
40 /// which is same `Symbol` used in `active.rs`.
41 pub fn gate(&self, feature: Symbol, span: Span) {
dfeec247 42 self.spans.borrow_mut().entry(feature).or_default().push(span);
60c5eb7d
XL
43 }
44
45 /// Ungate the last span under the given `feature`.
46 /// Panics if the given `span` wasn't the last one.
47 ///
48 /// Using this is discouraged unless you have a really good reason to.
49 pub fn ungate_last(&self, feature: Symbol, span: Span) {
dfeec247 50 let removed_span = self.spans.borrow_mut().entry(feature).or_default().pop().unwrap();
60c5eb7d
XL
51 debug_assert_eq!(span, removed_span);
52 }
53
54 /// Is the provided `feature` gate ungated currently?
55 ///
56 /// Using this is discouraged unless you have a really good reason to.
57 pub fn is_ungated(&self, feature: Symbol) -> bool {
dfeec247 58 self.spans.borrow().get(&feature).map_or(true, |spans| spans.is_empty())
60c5eb7d
XL
59 }
60
61 /// Prepend the given set of `spans` onto the set in `self`.
62 pub fn merge(&self, mut spans: FxHashMap<Symbol, Vec<Span>>) {
63 let mut inner = self.spans.borrow_mut();
64 for (gate, mut gate_spans) in inner.drain() {
65 spans.entry(gate).or_default().append(&mut gate_spans);
66 }
67 *inner = spans;
68 }
e74abb32
XL
69}
70
f9f354fc
XL
71#[derive(Default)]
72pub struct SymbolGallery {
3dfed10e
XL
73 /// All symbols occurred and their first occurrence span.
74 pub symbols: Lock<FxHashMap<Symbol, Span>>,
f9f354fc
XL
75}
76
77impl SymbolGallery {
78 /// Insert a symbol and its span into symbol gallery.
5e7ed085 79 /// If the symbol has occurred before, ignore the new occurrence.
f9f354fc
XL
80 pub fn insert(&self, symbol: Symbol, span: Span) {
81 self.symbols.lock().entry(symbol).or_insert(span);
82 }
83}
84
dfeec247
XL
85/// Construct a diagnostic for a language feature error due to the given `span`.
86/// The `feature`'s `Symbol` is the one you used in `active.rs` and `rustc_span::symbols`.
353b0b11
FG
87pub fn feature_err(
88 sess: &ParseSess,
dfeec247
XL
89 feature: Symbol,
90 span: impl Into<MultiSpan>,
9ffffee4 91 explain: impl Into<DiagnosticMessage>,
353b0b11 92) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
dfeec247
XL
93 feature_err_issue(sess, feature, span, GateIssue::Language, explain)
94}
95
96/// Construct a diagnostic for a feature gate error.
97///
98/// This variant allows you to control whether it is a library or language feature.
99/// Almost always, you want to use this for a language feature. If so, prefer `feature_err`.
487cf647 100#[track_caller]
353b0b11
FG
101pub fn feature_err_issue(
102 sess: &ParseSess,
dfeec247
XL
103 feature: Symbol,
104 span: impl Into<MultiSpan>,
105 issue: GateIssue,
9ffffee4 106 explain: impl Into<DiagnosticMessage>,
353b0b11 107) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
f2b60f7d
FG
108 let span = span.into();
109
110 // Cancel an earlier warning for this same error, if it exists.
111 if let Some(span) = span.primary_span() {
353b0b11
FG
112 if let Some(err) = sess.span_diagnostic.steal_diagnostic(span, StashKey::EarlySyntaxWarning)
113 {
114 err.cancel()
115 }
f2b60f7d
FG
116 }
117
9ffffee4 118 let mut err = sess.create_err(FeatureGateError { span, explain: explain.into() });
5e7ed085
FG
119 add_feature_diagnostics_for_issue(&mut err, sess, feature, issue);
120 err
121}
122
f2b60f7d
FG
123/// Construct a future incompatibility diagnostic for a feature gate.
124///
125/// This diagnostic is only a warning and *does not cause compilation to fail*.
9c376795 126pub fn feature_warn(sess: &ParseSess, feature: Symbol, span: Span, explain: &str) {
f2b60f7d
FG
127 feature_warn_issue(sess, feature, span, GateIssue::Language, explain);
128}
129
130/// Construct a future incompatibility diagnostic for a feature gate.
131///
132/// This diagnostic is only a warning and *does not cause compilation to fail*.
133///
134/// This variant allows you to control whether it is a library or language feature.
135/// Almost always, you want to use this for a language feature. If so, prefer `feature_warn`.
136#[allow(rustc::diagnostic_outside_of_impl)]
137#[allow(rustc::untranslatable_diagnostic)]
9c376795
FG
138pub fn feature_warn_issue(
139 sess: &ParseSess,
f2b60f7d
FG
140 feature: Symbol,
141 span: Span,
142 issue: GateIssue,
143 explain: &str,
144) {
145 let mut err = sess.span_diagnostic.struct_span_warn(span, explain);
146 add_feature_diagnostics_for_issue(&mut err, sess, feature, issue);
147
148 // Decorate this as a future-incompatibility lint as in rustc_middle::lint::struct_lint_level
149 let lint = UNSTABLE_SYNTAX_PRE_EXPANSION;
150 let future_incompatible = lint.future_incompatible.as_ref().unwrap();
151 err.code(DiagnosticId::Lint {
152 name: lint.name_lower(),
153 has_future_breakage: false,
154 is_force_warn: false,
155 });
156 err.warn(lint.desc);
157 err.note(format!("for more information, see {}", future_incompatible.reference));
158
159 // A later feature_err call can steal and cancel this warning.
160 err.stash(span, StashKey::EarlySyntaxWarning);
161}
162
5e7ed085 163/// Adds the diagnostics for a feature to an existing error.
9c376795 164pub fn add_feature_diagnostics(err: &mut Diagnostic, sess: &ParseSess, feature: Symbol) {
5e7ed085
FG
165 add_feature_diagnostics_for_issue(err, sess, feature, GateIssue::Language);
166}
dfeec247 167
5e7ed085
FG
168/// Adds the diagnostics for a feature to an existing error.
169///
170/// This variant allows you to control whether it is a library or language feature.
171/// Almost always, you want to use this for a language feature. If so, prefer
172/// `add_feature_diagnostics`.
9c376795 173pub fn add_feature_diagnostics_for_issue(
5e7ed085 174 err: &mut Diagnostic,
9c376795 175 sess: &ParseSess,
5e7ed085
FG
176 feature: Symbol,
177 issue: GateIssue,
178) {
dfeec247 179 if let Some(n) = find_feature_issue(feature, issue) {
f2b60f7d 180 err.subdiagnostic(FeatureDiagnosticForIssue { n });
dfeec247
XL
181 }
182
183 // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
184 if sess.unstable_features.is_nightly_build() {
f2b60f7d 185 err.subdiagnostic(FeatureDiagnosticHelp { feature });
dfeec247 186 }
dfeec247
XL
187}
188
e74abb32
XL
189/// Info about a parsing session.
190pub struct ParseSess {
191 pub span_diagnostic: Handler,
60c5eb7d 192 pub unstable_features: UnstableFeatures,
e74abb32 193 pub config: CrateConfig,
5099ac24 194 pub check_config: CrateCheckConfig,
e74abb32 195 pub edition: Edition,
3c0e092e
XL
196 /// Places where raw identifiers were used. This is used to avoid complaining about idents
197 /// clashing with keywords in new editions.
353b0b11 198 pub raw_identifier_spans: AppendOnlyVec<Span>,
3c0e092e
XL
199 /// Places where identifiers that contain invalid Unicode codepoints but that look like they
200 /// should be. Useful to avoid bad tokenization when encountering emoji. We group them to
201 /// provide a single error per unique incorrect identifier.
202 pub bad_unicode_identifiers: Lock<FxHashMap<Symbol, Vec<Span>>>,
e74abb32
XL
203 source_map: Lrc<SourceMap>,
204 pub buffered_lints: Lock<Vec<BufferedEarlyLint>>,
205 /// Contains the spans of block expressions that could have been incomplete based on the
206 /// operation token that followed it, but that the parser cannot identify without further
207 /// analysis.
208 pub ambiguous_block_expr_parse: Lock<FxHashMap<Span, Span>>,
60c5eb7d 209 pub gated_spans: GatedSpans,
f9f354fc 210 pub symbol_gallery: SymbolGallery,
e74abb32 211 /// The parser has reached `Eof` due to an unclosed brace. Used to silence unnecessary errors.
353b0b11 212 pub reached_eof: AtomicBool,
f035d41b
XL
213 /// Environment variables accessed during the build and their values when they exist.
214 pub env_depinfo: Lock<FxHashSet<(Symbol, Option<Symbol>)>>,
136023e0
XL
215 /// File paths accessed during the build.
216 pub file_depinfo: Lock<FxHashSet<Symbol>>,
3dfed10e
XL
217 /// All the type ascriptions expressions that have had a suggestion for likely path typo.
218 pub type_ascription_path_suggestions: Lock<FxHashSet<Span>>,
5869c6ff
XL
219 /// Whether cfg(version) should treat the current release as incomplete
220 pub assume_incomplete_release: bool,
17df50a5
XL
221 /// Spans passed to `proc_macro::quote_span`. Each span has a numerical
222 /// identifier represented by its position in the vector.
353b0b11 223 pub proc_macro_quoted_spans: AppendOnlyVec<Span>,
f2b60f7d
FG
224 /// Used to generate new `AttrId`s. Every `AttrId` is unique.
225 pub attr_id_generator: AttrIdGenerator,
e74abb32
XL
226}
227
228impl ParseSess {
cdc7bbd5 229 /// Used for testing.
9ffffee4
FG
230 pub fn new(locale_resources: Vec<&'static str>, file_path_mapping: FilePathMapping) -> Self {
231 let fallback_bundle = fallback_fluent_bundle(locale_resources, false);
74b04a01 232 let sm = Lrc::new(SourceMap::new(file_path_mapping));
04454e1e
FG
233 let handler = Handler::with_tty_emitter(
234 ColorConfig::Auto,
235 true,
236 None,
237 Some(sm.clone()),
238 None,
239 fallback_bundle,
240 );
74b04a01 241 ParseSess::with_span_handler(handler, sm)
e74abb32
XL
242 }
243
dfeec247 244 pub fn with_span_handler(handler: Handler, source_map: Lrc<SourceMap>) -> Self {
e74abb32
XL
245 Self {
246 span_diagnostic: handler,
fc512014 247 unstable_features: UnstableFeatures::from_environment(None),
f2b60f7d 248 config: FxIndexSet::default(),
5099ac24 249 check_config: CrateCheckConfig::default(),
e74abb32 250 edition: ExpnId::root().expn_data().edition,
353b0b11 251 raw_identifier_spans: Default::default(),
3c0e092e 252 bad_unicode_identifiers: Lock::new(Default::default()),
e74abb32
XL
253 source_map,
254 buffered_lints: Lock::new(vec![]),
255 ambiguous_block_expr_parse: Lock::new(FxHashMap::default()),
e74abb32 256 gated_spans: GatedSpans::default(),
f9f354fc 257 symbol_gallery: SymbolGallery::default(),
353b0b11 258 reached_eof: AtomicBool::new(false),
f035d41b 259 env_depinfo: Default::default(),
136023e0 260 file_depinfo: Default::default(),
3dfed10e 261 type_ascription_path_suggestions: Default::default(),
5869c6ff 262 assume_incomplete_release: false,
17df50a5 263 proc_macro_quoted_spans: Default::default(),
f2b60f7d 264 attr_id_generator: AttrIdGenerator::new(),
e74abb32
XL
265 }
266 }
267
3c0e092e 268 pub fn with_silent_emitter(fatal_note: Option<String>) -> Self {
9ffffee4 269 let fallback_bundle = fallback_fluent_bundle(Vec::new(), false);
74b04a01 270 let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
04454e1e
FG
271 let fatal_handler =
272 Handler::with_tty_emitter(ColorConfig::Auto, false, None, None, None, fallback_bundle);
3c0e092e
XL
273 let handler = Handler::with_emitter(
274 false,
275 None,
276 Box::new(SilentEmitter { fatal_handler, fatal_note }),
277 );
74b04a01 278 ParseSess::with_span_handler(handler, sm)
60c5eb7d
XL
279 }
280
e74abb32
XL
281 #[inline]
282 pub fn source_map(&self) -> &SourceMap {
283 &self.source_map
284 }
285
f9f354fc
XL
286 pub fn clone_source_map(&self) -> Lrc<SourceMap> {
287 self.source_map.clone()
288 }
289
e74abb32
XL
290 pub fn buffer_lint(
291 &self,
dfeec247 292 lint: &'static Lint,
e74abb32 293 span: impl Into<MultiSpan>,
dfeec247 294 node_id: NodeId,
e74abb32
XL
295 msg: &str,
296 ) {
297 self.buffered_lints.with_lock(|buffered_lints| {
dfeec247 298 buffered_lints.push(BufferedEarlyLint {
e74abb32 299 span: span.into(),
dfeec247 300 node_id,
e74abb32 301 msg: msg.into(),
dfeec247
XL
302 lint_id: LintId::of(lint),
303 diagnostic: BuiltinLintDiagnostics::Normal,
e74abb32
XL
304 });
305 });
306 }
307
74b04a01
XL
308 pub fn buffer_lint_with_diagnostic(
309 &self,
310 lint: &'static Lint,
311 span: impl Into<MultiSpan>,
312 node_id: NodeId,
313 msg: &str,
314 diagnostic: BuiltinLintDiagnostics,
315 ) {
316 self.buffered_lints.with_lock(|buffered_lints| {
317 buffered_lints.push(BufferedEarlyLint {
318 span: span.into(),
319 node_id,
320 msg: msg.into(),
321 lint_id: LintId::of(lint),
322 diagnostic,
323 });
324 });
325 }
326
17df50a5 327 pub fn save_proc_macro_span(&self, span: Span) -> usize {
353b0b11 328 self.proc_macro_quoted_spans.push(span)
17df50a5
XL
329 }
330
353b0b11
FG
331 pub fn proc_macro_quoted_spans(&self) -> impl Iterator<Item = (usize, Span)> + '_ {
332 // This is equivalent to `.iter().copied().enumerate()`, but that isn't possible for
333 // AppendOnlyVec, so we resort to this scheme.
334 self.proc_macro_quoted_spans.iter_enumerated()
17df50a5 335 }
04454e1e 336
487cf647 337 #[track_caller]
04454e1e
FG
338 pub fn create_err<'a>(
339 &'a self,
2b03887a 340 err: impl IntoDiagnostic<'a>,
04454e1e 341 ) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
f2b60f7d 342 err.into_diagnostic(&self.span_diagnostic)
04454e1e
FG
343 }
344
487cf647 345 #[track_caller]
2b03887a 346 pub fn emit_err<'a>(&'a self, err: impl IntoDiagnostic<'a>) -> ErrorGuaranteed {
04454e1e
FG
347 self.create_err(err).emit()
348 }
349
487cf647 350 #[track_caller]
04454e1e
FG
351 pub fn create_warning<'a>(
352 &'a self,
2b03887a 353 warning: impl IntoDiagnostic<'a, ()>,
04454e1e 354 ) -> DiagnosticBuilder<'a, ()> {
f2b60f7d 355 warning.into_diagnostic(&self.span_diagnostic)
04454e1e
FG
356 }
357
487cf647 358 #[track_caller]
2b03887a 359 pub fn emit_warning<'a>(&'a self, warning: impl IntoDiagnostic<'a, ()>) {
04454e1e
FG
360 self.create_warning(warning).emit()
361 }
362
2b03887a
FG
363 pub fn create_note<'a>(
364 &'a self,
365 note: impl IntoDiagnostic<'a, Noted>,
366 ) -> DiagnosticBuilder<'a, Noted> {
367 note.into_diagnostic(&self.span_diagnostic)
368 }
369
370 pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, Noted>) -> Noted {
371 self.create_note(note).emit()
372 }
373
f2b60f7d
FG
374 pub fn create_fatal<'a>(
375 &'a self,
2b03887a 376 fatal: impl IntoDiagnostic<'a, !>,
f2b60f7d
FG
377 ) -> DiagnosticBuilder<'a, !> {
378 fatal.into_diagnostic(&self.span_diagnostic)
379 }
380
2b03887a 381 pub fn emit_fatal<'a>(&'a self, fatal: impl IntoDiagnostic<'a, !>) -> ! {
f2b60f7d
FG
382 self.create_fatal(fatal).emit()
383 }
384
064997fb 385 #[rustc_lint_diagnostics]
487cf647 386 #[track_caller]
04454e1e
FG
387 pub fn struct_err(
388 &self,
389 msg: impl Into<DiagnosticMessage>,
390 ) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
391 self.span_diagnostic.struct_err(msg)
392 }
393
064997fb 394 #[rustc_lint_diagnostics]
04454e1e
FG
395 pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
396 self.span_diagnostic.struct_warn(msg)
397 }
f2b60f7d
FG
398
399 #[rustc_lint_diagnostics]
f2b60f7d
FG
400 pub fn struct_fatal(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, !> {
401 self.span_diagnostic.struct_fatal(msg)
402 }
403
404 #[rustc_lint_diagnostics]
f2b60f7d
FG
405 pub fn struct_diagnostic<G: EmissionGuarantee>(
406 &self,
407 msg: impl Into<DiagnosticMessage>,
408 ) -> DiagnosticBuilder<'_, G> {
409 self.span_diagnostic.struct_diagnostic(msg)
410 }
e74abb32 411}