1use std::borrow::Cow;
27use std::fmt;
28
29use rustc_data_structures::unord::{UnordMap, UnordSet};
30use rustc_errors::{DiagArgValue, IntoDiagArg};
31use rustc_hir as hir;
32use rustc_hir::def_id::LOCAL_CRATE;
33use rustc_middle::mir::mono::CodegenUnitNameBuilder;
34use rustc_middle::ty::TyCtxt;
35use rustc_session::Session;
36use rustc_span::{Span, Symbol, sym};
37use thin_vec::ThinVec;
38use tracing::debug;
39
40use crate::errors;
41
42#[allow(missing_docs)]
43pub fn assert_module_sources(tcx: TyCtxt<'_>, set_reuse: &dyn Fn(&mut CguReuseTracker)) {
44 tcx.dep_graph.with_ignore(|| {
45 if tcx.sess.opts.incremental.is_none() {
46 return;
47 }
48
49 let available_cgus = tcx
50 .collect_and_partition_mono_items(())
51 .codegen_units
52 .iter()
53 .map(|cgu| cgu.name())
54 .collect();
55
56 let mut ams = AssertModuleSource {
57 tcx,
58 available_cgus,
59 cgu_reuse_tracker: if tcx.sess.opts.unstable_opts.query_dep_graph {
60 CguReuseTracker::new()
61 } else {
62 CguReuseTracker::new_disabled()
63 },
64 };
65
66 for attr in tcx.hir_attrs(rustc_hir::CRATE_HIR_ID) {
67 ams.check_attr(attr);
68 }
69
70 set_reuse(&mut ams.cgu_reuse_tracker);
71
72 if tcx.sess.opts.unstable_opts.print_mono_items
73 && let Some(data) = &ams.cgu_reuse_tracker.data
74 {
75 data.actual_reuse.items().all(|(cgu, reuse)| {
76 { ::std::io::_print(format_args!("CGU_REUSE {0} {1}\n", cgu, reuse)); };println!("CGU_REUSE {cgu} {reuse}");
77 true
78 });
79 }
80
81 ams.cgu_reuse_tracker.check_expected_reuse(tcx.sess);
82 });
83}
84
85struct AssertModuleSource<'tcx> {
86 tcx: TyCtxt<'tcx>,
87 available_cgus: UnordSet<Symbol>,
88 cgu_reuse_tracker: CguReuseTracker,
89}
90
91impl<'tcx> AssertModuleSource<'tcx> {
92 fn check_attr(&mut self, attr: &hir::Attribute) {
93 let (expected_reuse, comp_kind) = if attr.has_name(sym::rustc_partition_reused) {
94 (CguReuse::PreLto, ComparisonKind::AtLeast)
95 } else if attr.has_name(sym::rustc_partition_codegened) {
96 (CguReuse::No, ComparisonKind::Exact)
97 } else if attr.has_name(sym::rustc_expected_cgu_reuse) {
98 match self.field(attr, sym::kind) {
99 sym::no => (CguReuse::No, ComparisonKind::Exact),
100 sym::pre_dash_lto => (CguReuse::PreLto, ComparisonKind::Exact),
101 sym::post_dash_lto => (CguReuse::PostLto, ComparisonKind::Exact),
102 sym::any => (CguReuse::PreLto, ComparisonKind::AtLeast),
103 other => {
104 self.tcx
105 .dcx()
106 .emit_fatal(errors::UnknownReuseKind { span: attr.span(), kind: other });
107 }
108 }
109 } else {
110 return;
111 };
112
113 if !self.tcx.sess.opts.unstable_opts.query_dep_graph {
114 self.tcx.dcx().emit_fatal(errors::MissingQueryDepGraph { span: attr.span() });
115 }
116
117 if !self.check_config(attr) {
118 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_codegen_ssa/src/assert_module_sources.rs:118",
"rustc_codegen_ssa::assert_module_sources",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_codegen_ssa/src/assert_module_sources.rs"),
::tracing_core::__macro_support::Option::Some(118u32),
::tracing_core::__macro_support::Option::Some("rustc_codegen_ssa::assert_module_sources"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("check_attr: config does not match, ignoring attr")
as &dyn Value))])
});
} else { ; }
};debug!("check_attr: config does not match, ignoring attr");
119 return;
120 }
121
122 let user_path = self.field(attr, sym::module).to_string();
123 let crate_name = self.tcx.crate_name(LOCAL_CRATE).to_string();
124
125 if !user_path.starts_with(&crate_name) {
126 self.tcx.dcx().emit_fatal(errors::MalformedCguName {
127 span: attr.span(),
128 user_path,
129 crate_name,
130 });
131 }
132
133 let (user_path, cgu_special_suffix) = if let Some(index) = user_path.rfind('.') {
135 (&user_path[..index], Some(&user_path[index + 1..]))
136 } else {
137 (&user_path[..], None)
138 };
139
140 let mut iter = user_path.split('-');
141
142 match (&iter.next().unwrap(), &crate_name) {
(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);
}
}
};assert_eq!(iter.next().unwrap(), crate_name);
144
145 let cgu_path_components = iter.collect::<Vec<_>>();
146
147 let cgu_name_builder = &mut CodegenUnitNameBuilder::new(self.tcx);
148 let cgu_name =
149 cgu_name_builder.build_cgu_name(LOCAL_CRATE, cgu_path_components, cgu_special_suffix);
150
151 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_codegen_ssa/src/assert_module_sources.rs:151",
"rustc_codegen_ssa::assert_module_sources",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_codegen_ssa/src/assert_module_sources.rs"),
::tracing_core::__macro_support::Option::Some(151u32),
::tracing_core::__macro_support::Option::Some("rustc_codegen_ssa::assert_module_sources"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("mapping \'{0}\' to cgu name \'{1}\'",
self.field(attr, sym::module), cgu_name) as &dyn Value))])
});
} else { ; }
};debug!("mapping '{}' to cgu name '{}'", self.field(attr, sym::module), cgu_name);
152
153 if !self.available_cgus.contains(&cgu_name) {
154 let cgu_names: Vec<&str> =
155 self.available_cgus.items().map(|cgu| cgu.as_str()).into_sorted_stable_ord();
156 self.tcx.dcx().emit_err(errors::NoModuleNamed {
157 span: attr.span(),
158 user_path,
159 cgu_name,
160 cgu_names: cgu_names.join(", "),
161 });
162 }
163
164 self.cgu_reuse_tracker.set_expectation(
165 cgu_name,
166 user_path,
167 attr.span(),
168 expected_reuse,
169 comp_kind,
170 );
171 }
172
173 fn field(&self, attr: &hir::Attribute, name: Symbol) -> Symbol {
174 for item in attr.meta_item_list().unwrap_or_else(ThinVec::new) {
175 if item.has_name(name) {
176 if let Some(value) = item.value_str() {
177 return value;
178 } else {
179 self.tcx.dcx().emit_fatal(errors::FieldAssociatedValueExpected {
180 span: item.span(),
181 name,
182 });
183 }
184 }
185 }
186
187 self.tcx.dcx().emit_fatal(errors::NoField { span: attr.span(), name });
188 }
189
190 fn check_config(&self, attr: &hir::Attribute) -> bool {
193 let config = &self.tcx.sess.psess.config;
194 let value = self.field(attr, sym::cfg);
195 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_codegen_ssa/src/assert_module_sources.rs:195",
"rustc_codegen_ssa::assert_module_sources",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_codegen_ssa/src/assert_module_sources.rs"),
::tracing_core::__macro_support::Option::Some(195u32),
::tracing_core::__macro_support::Option::Some("rustc_codegen_ssa::assert_module_sources"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("check_config(config={0:?}, value={1:?})",
config, value) as &dyn Value))])
});
} else { ; }
};debug!("check_config(config={:?}, value={:?})", config, value);
196 if config.iter().any(|&(name, _)| name == value) {
197 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_codegen_ssa/src/assert_module_sources.rs:197",
"rustc_codegen_ssa::assert_module_sources",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_codegen_ssa/src/assert_module_sources.rs"),
::tracing_core::__macro_support::Option::Some(197u32),
::tracing_core::__macro_support::Option::Some("rustc_codegen_ssa::assert_module_sources"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("check_config: matched")
as &dyn Value))])
});
} else { ; }
};debug!("check_config: matched");
198 return true;
199 }
200 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_codegen_ssa/src/assert_module_sources.rs:200",
"rustc_codegen_ssa::assert_module_sources",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_codegen_ssa/src/assert_module_sources.rs"),
::tracing_core::__macro_support::Option::Some(200u32),
::tracing_core::__macro_support::Option::Some("rustc_codegen_ssa::assert_module_sources"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("check_config: no match found")
as &dyn Value))])
});
} else { ; }
};debug!("check_config: no match found");
201 false
202 }
203}
204
205#[derive(#[automatically_derived]
impl ::core::marker::Copy for CguReuse { }Copy, #[automatically_derived]
impl ::core::clone::Clone for CguReuse {
#[inline]
fn clone(&self) -> CguReuse { *self }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for CguReuse {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
CguReuse::No => "No",
CguReuse::PreLto => "PreLto",
CguReuse::PostLto => "PostLto",
})
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for CguReuse {
#[inline]
fn eq(&self, other: &CguReuse) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::PartialOrd for CguReuse {
#[inline]
fn partial_cmp(&self, other: &CguReuse)
-> ::core::option::Option<::core::cmp::Ordering> {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
::core::cmp::PartialOrd::partial_cmp(&__self_discr, &__arg1_discr)
}
}PartialOrd)]
206pub enum CguReuse {
207 No,
208 PreLto,
209 PostLto,
210}
211
212impl fmt::Display for CguReuse {
213 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
214 match *self {
215 CguReuse::No => f.write_fmt(format_args!("No"))write!(f, "No"),
216 CguReuse::PreLto => f.write_fmt(format_args!("PreLto"))write!(f, "PreLto"),
217 CguReuse::PostLto => f.write_fmt(format_args!("PostLto"))write!(f, "PostLto"),
218 }
219 }
220}
221
222impl IntoDiagArg for CguReuse {
223 fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
224 DiagArgValue::Str(Cow::Owned(self.to_string()))
225 }
226}
227
228#[derive(#[automatically_derived]
impl ::core::marker::Copy for ComparisonKind { }Copy, #[automatically_derived]
impl ::core::clone::Clone for ComparisonKind {
#[inline]
fn clone(&self) -> ComparisonKind { *self }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for ComparisonKind {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
ComparisonKind::Exact => "Exact",
ComparisonKind::AtLeast => "AtLeast",
})
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for ComparisonKind {
#[inline]
fn eq(&self, other: &ComparisonKind) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq)]
229pub enum ComparisonKind {
230 Exact,
231 AtLeast,
232}
233
234struct TrackerData {
235 actual_reuse: UnordMap<String, CguReuse>,
236 expected_reuse: UnordMap<String, (String, Span, CguReuse, ComparisonKind)>,
237}
238
239pub struct CguReuseTracker {
240 data: Option<TrackerData>,
241}
242
243impl CguReuseTracker {
244 fn new() -> CguReuseTracker {
245 let data =
246 TrackerData { actual_reuse: Default::default(), expected_reuse: Default::default() };
247
248 CguReuseTracker { data: Some(data) }
249 }
250
251 fn new_disabled() -> CguReuseTracker {
252 CguReuseTracker { data: None }
253 }
254
255 pub fn set_actual_reuse(&mut self, cgu_name: &str, kind: CguReuse) {
256 if let Some(data) = &mut self.data {
257 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_codegen_ssa/src/assert_module_sources.rs:257",
"rustc_codegen_ssa::assert_module_sources",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_codegen_ssa/src/assert_module_sources.rs"),
::tracing_core::__macro_support::Option::Some(257u32),
::tracing_core::__macro_support::Option::Some("rustc_codegen_ssa::assert_module_sources"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("set_actual_reuse({0:?}, {1:?})",
cgu_name, kind) as &dyn Value))])
});
} else { ; }
};debug!("set_actual_reuse({cgu_name:?}, {kind:?})");
258
259 let prev_reuse = data.actual_reuse.insert(cgu_name.to_string(), kind);
260 if !prev_reuse.is_none() {
::core::panicking::panic("assertion failed: prev_reuse.is_none()")
};assert!(prev_reuse.is_none());
261 }
262 }
263
264 fn set_expectation(
265 &mut self,
266 cgu_name: Symbol,
267 cgu_user_name: &str,
268 error_span: Span,
269 expected_reuse: CguReuse,
270 comparison_kind: ComparisonKind,
271 ) {
272 if let Some(data) = &mut self.data {
273 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_codegen_ssa/src/assert_module_sources.rs:273",
"rustc_codegen_ssa::assert_module_sources",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_codegen_ssa/src/assert_module_sources.rs"),
::tracing_core::__macro_support::Option::Some(273u32),
::tracing_core::__macro_support::Option::Some("rustc_codegen_ssa::assert_module_sources"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("set_expectation({0:?}, {1:?}, {2:?})",
cgu_name, expected_reuse, comparison_kind) as &dyn Value))])
});
} else { ; }
};debug!("set_expectation({cgu_name:?}, {expected_reuse:?}, {comparison_kind:?})");
274
275 data.expected_reuse.insert(
276 cgu_name.to_string(),
277 (cgu_user_name.to_string(), error_span, expected_reuse, comparison_kind),
278 );
279 }
280 }
281
282 fn check_expected_reuse(&self, sess: &Session) {
283 if let Some(ref data) = self.data {
284 let keys = data.expected_reuse.keys().into_sorted_stable_ord();
285 for cgu_name in keys {
286 let &(ref cgu_user_name, ref error_span, expected_reuse, comparison_kind) =
287 data.expected_reuse.get(cgu_name).unwrap();
288
289 if let Some(&actual_reuse) = data.actual_reuse.get(cgu_name) {
290 let (error, at_least) = match comparison_kind {
291 ComparisonKind::Exact => (expected_reuse != actual_reuse, false),
292 ComparisonKind::AtLeast => (actual_reuse < expected_reuse, true),
293 };
294
295 if error {
296 let at_least = if at_least { 1 } else { 0 };
297 sess.dcx().emit_err(errors::IncorrectCguReuseType {
298 span: *error_span,
299 cgu_user_name,
300 actual_reuse,
301 expected_reuse,
302 at_least,
303 });
304 }
305 } else {
306 sess.dcx().emit_fatal(errors::CguNotRecorded { cgu_user_name, cgu_name });
307 }
308 }
309 }
310 }
311}