use crate::cgu_reuse_tracker::CguReuseTracker;
use crate::code_stats::CodeStats;
pub use crate::code_stats::{DataTypeKind, FieldInfo, SizeKind, VariantInfo};
-use crate::config::{self, CrateType, OutputType, PrintRequest, SanitizerSet, SwitchWithOptPath};
+use crate::config::{self, CrateType, OutputType, PrintRequest, SwitchWithOptPath};
use crate::filesearch;
use crate::lint::{self, LintId};
use crate::parse::ParseSess;
use rustc_errors::emitter::{Emitter, EmitterWriter, HumanReadableErrorType};
use rustc_errors::json::JsonEmitter;
use rustc_errors::registry::Registry;
-use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId, ErrorReported};
+use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticId, ErrorReported};
use rustc_lint_defs::FutureBreakage;
pub use rustc_span::crate_disambiguator::CrateDisambiguator;
use rustc_span::edition::Edition;
use rustc_span::{sym, SourceFileHashAlgorithm, Symbol};
use rustc_target::asm::InlineAsmArch;
use rustc_target::spec::{CodeModel, PanicStrategy, RelocModel, RelroLevel};
-use rustc_target::spec::{SplitDebuginfo, Target, TargetTriple, TlsModel};
+use rustc_target::spec::{SanitizerSet, SplitDebuginfo, Target, TargetTriple, TlsModel};
use std::cell::{self, RefCell};
use std::env;
}
}
+impl From<usize> for Limit {
+ fn from(value: usize) -> Self {
+ Self::new(value)
+ }
+}
+
impl fmt::Display for Limit {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
/// operations such as auto-dereference and monomorphization.
pub recursion_limit: OnceCell<Limit>,
+ /// The size at which the `large_assignments` lint starts
+ /// being emitted.
+ pub move_size_limit: OnceCell<usize>,
+
/// The maximum length of types during monomorphization.
pub type_length_limit: OnceCell<Limit>,
/// drown everything else in noise.
miri_unleashed_features: Lock<Vec<(Span, Option<Symbol>)>>,
- /// Base directory containing the `src/` for the Rust standard library, and
- /// potentially `rustc` as well, if we can can find it. Right now it's always
- /// `$sysroot/lib/rustlib/src/rust` (i.e. the `rustup` `rust-src` component).
- ///
- /// This directory is what the virtual `/rustc/$hash` is translated back to,
- /// if Rust was built with path remapping to `/rustc/$hash` enabled
- /// (the `rust.remap-debuginfo` option in `config.toml`).
- pub real_rust_source_base_dir: Option<PathBuf>,
-
/// Architecture to use for interpreting asm!.
pub asm_arch: Option<InlineAsmArch>,
enum DiagnosticBuilderMethod {
Note,
SpanNote,
- SpanSuggestion(String), // suggestion
- // Add more variants as needed to support one-time diagnostics.
+ // Add more variants as needed to support one-time diagnostics.
}
/// Trait implemented by error types. This should not be implemented manually. Instead, use
self.recursion_limit.get().copied().unwrap()
}
+ #[inline]
+ pub fn move_size_limit(&self) -> usize {
+ self.move_size_limit.get().copied().unwrap()
+ }
+
#[inline]
pub fn type_length_limit(&self) -> Limit {
self.type_length_limit.get().copied().unwrap()
let span = span_maybe.expect("`span_note` needs a span");
diag_builder.span_note(span, message);
}
- DiagnosticBuilderMethod::SpanSuggestion(suggestion) => {
- let span = span_maybe.expect("`span_suggestion_*` needs a span");
- diag_builder.span_suggestion(
- span,
- message,
- suggestion,
- Applicability::Unspecified,
- );
- }
}
}
}
self.diag_once(diag_builder, DiagnosticBuilderMethod::Note, msg_id, message, None);
}
- pub fn diag_span_suggestion_once<'a, 'b>(
- &'a self,
- diag_builder: &'b mut DiagnosticBuilder<'a>,
- msg_id: DiagnosticMessageId,
- span: Span,
- message: &str,
- suggestion: String,
- ) {
- self.diag_once(
- diag_builder,
- DiagnosticBuilderMethod::SpanSuggestion(suggestion),
- msg_id,
- message,
- Some(span),
- );
- }
-
#[inline]
pub fn source_map(&self) -> &SourceMap {
self.parse_sess.source_map()
pub fn verify_llvm_ir(&self) -> bool {
self.opts.debugging_opts.verify_llvm_ir || option_env!("RUSTC_VERIFY_LLVM_IR").is_some()
}
- pub fn borrowck_stats(&self) -> bool {
- self.opts.debugging_opts.borrowck_stats
- }
pub fn print_llvm_passes(&self) -> bool {
self.opts.debugging_opts.print_llvm_passes
}
}
}
- pub fn inline_asm_dialect(&self) -> rustc_ast::LlvmAsmDialect {
- match self.asm_arch {
- Some(InlineAsmArch::X86 | InlineAsmArch::X86_64) => rustc_ast::LlvmAsmDialect::Intel,
- _ => rustc_ast::LlvmAsmDialect::Att,
- }
- }
-
pub fn relocation_model(&self) -> RelocModel {
self.opts.cg.relocation_model.unwrap_or(self.target.relocation_model)
}
// This is used to control the emission of the `uwtable` attribute on
// LLVM functions.
//
- // At the very least, unwind tables are needed when compiling with
- // `-C panic=unwind`.
+ // Unwind tables are needed when compiling with `-C panic=unwind`, but
+ // LLVM won't omit unwind tables unless the function is also marked as
+ // `nounwind`, so users are allowed to disable `uwtable` emission.
+ // Historically rustc always emits `uwtable` attributes by default, so
+ // even they can be disabled, they're still emitted by default.
//
// On some targets (including windows), however, exceptions include
// other events such as illegal instructions, segfaults, etc. This means
// If a target requires unwind tables, then they must be emitted.
// Otherwise, we can defer to the `-C force-unwind-tables=<yes/no>`
// value, if it is provided, or disable them, if not.
- if self.panic_strategy() == PanicStrategy::Unwind {
- true
- } else if self.target.requires_uwtable {
- true
- } else {
- self.opts.cg.force_unwind_tables.unwrap_or(false)
- }
+ self.target.requires_uwtable
+ || self.opts.cg.force_unwind_tables.unwrap_or(
+ self.panic_strategy() == PanicStrategy::Unwind || self.target.default_uwtable,
+ )
}
/// Returns the symbol name for the registrar function,
)
}
- pub fn set_incr_session_load_dep_graph(&self, load: bool) {
- let mut incr_comp_session = self.incr_comp_session.borrow_mut();
-
- if let IncrCompSession::Active { ref mut load_dep_graph, .. } = *incr_comp_session {
- *load_dep_graph = load;
- }
- }
-
- pub fn incr_session_load_dep_graph(&self) -> bool {
- let incr_comp_session = self.incr_comp_session.borrow();
- match *incr_comp_session {
- IncrCompSession::Active { load_dep_graph, .. } => load_dep_graph,
- _ => false,
- }
- }
-
pub fn init_incr_comp_session(
&self,
session_dir: PathBuf,
self.opts.cg.link_dead_code.unwrap_or(false)
}
+ pub fn instrument_coverage(&self) -> bool {
+ self.opts.debugging_opts.instrument_coverage.unwrap_or(config::InstrumentCoverage::Off)
+ != config::InstrumentCoverage::Off
+ }
+
+ pub fn instrument_coverage_except_unused_generics(&self) -> bool {
+ self.opts.debugging_opts.instrument_coverage.unwrap_or(config::InstrumentCoverage::Off)
+ == config::InstrumentCoverage::ExceptUnusedGenerics
+ }
+
+ pub fn instrument_coverage_except_unused_functions(&self) -> bool {
+ self.opts.debugging_opts.instrument_coverage.unwrap_or(config::InstrumentCoverage::Off)
+ == config::InstrumentCoverage::ExceptUnusedFunctions
+ }
+
pub fn mark_attr_known(&self, attr: &Attribute) {
self.known_attrs.lock().mark(attr)
}
_ => CtfeBacktrace::Disabled,
});
- // Try to find a directory containing the Rust `src`, for more details see
- // the doc comment on the `real_rust_source_base_dir` field.
- let real_rust_source_base_dir = {
- // This is the location used by the `rust-src` `rustup` component.
- let mut candidate = sysroot.join("lib/rustlib/src/rust");
- if let Ok(metadata) = candidate.symlink_metadata() {
- // Replace the symlink rustbuild creates, with its destination.
- // We could try to use `fs::canonicalize` instead, but that might
- // produce unnecessarily verbose path.
- if metadata.file_type().is_symlink() {
- if let Ok(symlink_dest) = std::fs::read_link(&candidate) {
- candidate = symlink_dest;
- }
- }
- }
-
- // Only use this directory if it has a file we can expect to always find.
- if candidate.join("library/std/src/lib.rs").is_file() { Some(candidate) } else { None }
- };
-
let asm_arch =
if target_cfg.allow_asm { InlineAsmArch::from_str(&target_cfg.arch).ok() } else { None };
features: OnceCell::new(),
lint_store: OnceCell::new(),
recursion_limit: OnceCell::new(),
+ move_size_limit: OnceCell::new(),
type_length_limit: OnceCell::new(),
const_eval_limit: OnceCell::new(),
incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)),
system_library_path: OneThread::new(RefCell::new(Default::default())),
ctfe_backtrace,
miri_unleashed_features: Lock::new(Default::default()),
- real_rust_source_base_dir,
asm_arch,
target_features: FxHashSet::default(),
known_attrs: Lock::new(MarkedAttrs::new()),
// Unwind tables cannot be disabled if the target requires them.
if let Some(include_uwtables) = sess.opts.cg.force_unwind_tables {
- if sess.panic_strategy() == PanicStrategy::Unwind && !include_uwtables {
- sess.err(
- "panic=unwind requires unwind tables, they cannot be disabled \
- with `-C force-unwind-tables=no`.",
- );
- }
-
if sess.target.requires_uwtable && !include_uwtables {
sess.err(
"target requires unwind tables, they cannot be disabled with \
);
}
- const ASAN_SUPPORTED_TARGETS: &[&str] = &[
- "aarch64-apple-darwin",
- "aarch64-fuchsia",
- "aarch64-unknown-linux-gnu",
- "x86_64-apple-darwin",
- "x86_64-fuchsia",
- "x86_64-unknown-freebsd",
- "x86_64-unknown-linux-gnu",
- ];
- const LSAN_SUPPORTED_TARGETS: &[&str] = &[
- "aarch64-apple-darwin",
- "aarch64-unknown-linux-gnu",
- "x86_64-apple-darwin",
- "x86_64-unknown-linux-gnu",
- ];
- const MSAN_SUPPORTED_TARGETS: &[&str] =
- &["aarch64-unknown-linux-gnu", "x86_64-unknown-freebsd", "x86_64-unknown-linux-gnu"];
- const TSAN_SUPPORTED_TARGETS: &[&str] = &[
- "aarch64-apple-darwin",
- "aarch64-unknown-linux-gnu",
- "x86_64-apple-darwin",
- "x86_64-unknown-freebsd",
- "x86_64-unknown-linux-gnu",
- ];
- const HWASAN_SUPPORTED_TARGETS: &[&str] =
- &["aarch64-linux-android", "aarch64-unknown-linux-gnu"];
-
- // Sanitizers can only be used on some tested platforms.
- for s in sess.opts.debugging_opts.sanitizer {
- let supported_targets = match s {
- SanitizerSet::ADDRESS => ASAN_SUPPORTED_TARGETS,
- SanitizerSet::LEAK => LSAN_SUPPORTED_TARGETS,
- SanitizerSet::MEMORY => MSAN_SUPPORTED_TARGETS,
- SanitizerSet::THREAD => TSAN_SUPPORTED_TARGETS,
- SanitizerSet::HWADDRESS => HWASAN_SUPPORTED_TARGETS,
- _ => panic!("unrecognized sanitizer {}", s),
- };
- if !supported_targets.contains(&&*sess.opts.target_triple.triple()) {
- sess.err(&format!(
- "`-Zsanitizer={}` only works with targets: {}",
- s,
- supported_targets.join(", ")
- ));
- }
- let conflicting = sess.opts.debugging_opts.sanitizer - s;
- if !conflicting.is_empty() {
- sess.err(&format!(
- "`-Zsanitizer={}` is incompatible with `-Zsanitizer={}`",
- s, conflicting,
- ));
- // Don't report additional errors.
- break;
- }
+ // Sanitizers can only be used on platforms that we know have working sanitizer codegen.
+ let supported_sanitizers = sess.target.options.supported_sanitizers;
+ let unsupported_sanitizers = sess.opts.debugging_opts.sanitizer - supported_sanitizers;
+ match unsupported_sanitizers.into_iter().count() {
+ 0 => {}
+ 1 => sess
+ .err(&format!("{} sanitizer is not supported for this target", unsupported_sanitizers)),
+ _ => sess.err(&format!(
+ "{} sanitizers are not supported for this target",
+ unsupported_sanitizers
+ )),
+ }
+ // Cannot mix and match sanitizers.
+ let mut sanitizer_iter = sess.opts.debugging_opts.sanitizer.into_iter();
+ if let (Some(first), Some(second)) = (sanitizer_iter.next(), sanitizer_iter.next()) {
+ sess.err(&format!("`-Zsanitizer={}` is incompatible with `-Zsanitizer={}`", first, second));
}
}