1use std::sync::Arc;
5
6use rustc_ast::attr::AttrIdGenerator;
7use rustc_ast::node_id::NodeId;
8use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
9use rustc_data_structures::sync::{AppendOnlyVec, DynSend, DynSync, Lock};
10use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitter;
11use rustc_errors::emitter::{EmitterWithNote, stderr_destination};
12use rustc_errors::{
13 BufferedEarlyLint, ColorConfig, DecorateDiagCompat, Diag, DiagCtxt, DiagCtxtHandle, Level,
14 MultiSpan,
15};
16use rustc_span::edition::Edition;
17use rustc_span::hygiene::ExpnId;
18use rustc_span::source_map::{FilePathMapping, SourceMap};
19use rustc_span::{Span, Symbol};
20
21use crate::Session;
22use crate::lint::{Lint, LintId};
23
24#[derive(#[automatically_derived]
impl ::core::default::Default for GatedSpans {
#[inline]
fn default() -> GatedSpans {
GatedSpans { spans: ::core::default::Default::default() }
}
}Default)]
27pub struct GatedSpans {
28 pub spans: Lock<FxHashMap<Symbol, Vec<Span>>>,
29}
30
31impl GatedSpans {
32 pub fn gate(&self, feature: Symbol, span: Span) {
35 self.spans.borrow_mut().entry(feature).or_default().push(span);
36 }
37
38 pub fn ungate_last(&self, feature: Symbol, span: Span) {
43 let removed_span = self.spans.borrow_mut().entry(feature).or_default().pop().unwrap();
44 if true {
match (&span, &removed_span) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
};
};debug_assert_eq!(span, removed_span);
45 }
46
47 pub fn merge(&self, mut spans: FxHashMap<Symbol, Vec<Span>>) {
49 let mut inner = self.spans.borrow_mut();
50 #[allow(rustc::potential_query_instability)]
53 for (gate, mut gate_spans) in inner.drain() {
54 spans.entry(gate).or_default().append(&mut gate_spans);
55 }
56 *inner = spans;
57 }
58}
59
60#[derive(#[automatically_derived]
impl ::core::default::Default for SymbolGallery {
#[inline]
fn default() -> SymbolGallery {
SymbolGallery { symbols: ::core::default::Default::default() }
}
}Default)]
61pub struct SymbolGallery {
62 pub symbols: Lock<FxIndexMap<Symbol, Span>>,
64}
65
66impl SymbolGallery {
67 pub fn insert(&self, symbol: Symbol, span: Span) {
70 self.symbols.lock().entry(symbol).or_insert(span);
71 }
72}
73
74pub struct ParseSess {
76 dcx: DiagCtxt,
77 pub edition: Edition,
78 pub raw_identifier_spans: AppendOnlyVec<Span>,
81 pub bad_unicode_identifiers: Lock<FxIndexMap<Symbol, Vec<Span>>>,
85 source_map: Arc<SourceMap>,
86 pub buffered_lints: Lock<Vec<BufferedEarlyLint>>,
87 pub ambiguous_block_expr_parse: Lock<FxIndexMap<Span, Span>>,
91 pub gated_spans: GatedSpans,
92 pub symbol_gallery: SymbolGallery,
93 pub attr_id_generator: AttrIdGenerator,
95}
96
97impl ParseSess {
98 pub fn new() -> Self {
100 let sm = Arc::new(SourceMap::new(FilePathMapping::empty()));
101 let emitter = Box::new(
102 AnnotateSnippetEmitter::new(stderr_destination(ColorConfig::Auto))
103 .sm(Some(Arc::clone(&sm))),
104 );
105 let dcx = DiagCtxt::new(emitter);
106 ParseSess::with_dcx(dcx, sm)
107 }
108
109 pub fn with_dcx(dcx: DiagCtxt, source_map: Arc<SourceMap>) -> Self {
110 Self {
111 dcx,
112 edition: ExpnId::root().expn_data().edition,
113 raw_identifier_spans: Default::default(),
114 bad_unicode_identifiers: Lock::new(Default::default()),
115 source_map,
116 buffered_lints: Lock::new(::alloc::vec::Vec::new()vec![]),
117 ambiguous_block_expr_parse: Lock::new(Default::default()),
118 gated_spans: GatedSpans::default(),
119 symbol_gallery: SymbolGallery::default(),
120 attr_id_generator: AttrIdGenerator::new(),
121 }
122 }
123
124 pub fn emitter_with_note(note: String) -> Self {
125 let sm = Arc::new(SourceMap::new(FilePathMapping::empty()));
126 let emitter = Box::new(AnnotateSnippetEmitter::new(stderr_destination(ColorConfig::Auto)));
127 let dcx = DiagCtxt::new(Box::new(EmitterWithNote { emitter, note }));
128 ParseSess::with_dcx(dcx, sm)
129 }
130
131 #[inline]
132 pub fn source_map(&self) -> &SourceMap {
133 &self.source_map
134 }
135
136 pub fn clone_source_map(&self) -> Arc<SourceMap> {
137 Arc::clone(&self.source_map)
138 }
139
140 pub fn buffer_lint(
141 &self,
142 lint: &'static Lint,
143 span: impl Into<MultiSpan>,
144 node_id: NodeId,
145 diagnostic: impl Into<DecorateDiagCompat>,
146 ) {
147 self.opt_span_buffer_lint(lint, Some(span.into()), node_id, diagnostic.into())
148 }
149
150 pub fn dyn_buffer_lint<
151 F: for<'a> FnOnce(DiagCtxtHandle<'a>, Level) -> Diag<'a, ()> + DynSync + DynSend + 'static,
152 >(
153 &self,
154 lint: &'static Lint,
155 span: impl Into<MultiSpan>,
156 node_id: NodeId,
157 callback: F,
158 ) {
159 self.opt_span_buffer_lint(
160 lint,
161 Some(span.into()),
162 node_id,
163 DecorateDiagCompat(Box::new(|dcx, level, _| callback(dcx, level))),
164 )
165 }
166
167 pub fn dyn_buffer_lint_sess<
168 F: for<'a> FnOnce(DiagCtxtHandle<'a>, Level, &Session) -> Diag<'a, ()>
169 + DynSync
170 + DynSend
171 + 'static,
172 >(
173 &self,
174 lint: &'static Lint,
175 span: impl Into<MultiSpan>,
176 node_id: NodeId,
177 callback: F,
178 ) {
179 self.opt_span_buffer_lint(
180 lint,
181 Some(span.into()),
182 node_id,
183 DecorateDiagCompat(Box::new(|dcx, level, sess| {
184 let sess = sess.downcast_ref::<Session>().expect("expected a `Session`");
185 callback(dcx, level, sess)
186 })),
187 )
188 }
189
190 pub(crate) fn opt_span_buffer_lint(
191 &self,
192 lint: &'static Lint,
193 span: Option<MultiSpan>,
194 node_id: NodeId,
195 diagnostic: DecorateDiagCompat,
196 ) {
197 self.buffered_lints.with_lock(|buffered_lints| {
198 buffered_lints.push(BufferedEarlyLint {
199 span,
200 node_id,
201 lint_id: LintId::of(lint),
202 diagnostic,
203 });
204 });
205 }
206
207 pub fn dcx(&self) -> DiagCtxtHandle<'_> {
208 self.dcx.handle()
209 }
210}