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