diff options
Diffstat (limited to 'compiler/rustc_session/src')
| -rw-r--r-- | compiler/rustc_session/src/config.rs | 54 | ||||
| -rw-r--r-- | compiler/rustc_session/src/config/cfg.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_session/src/config/native_libs.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_session/src/cstore.rs | 24 | ||||
| -rw-r--r-- | compiler/rustc_session/src/errors.rs | 40 | ||||
| -rw-r--r-- | compiler/rustc_session/src/options.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_session/src/parse.rs | 14 | ||||
| -rw-r--r-- | compiler/rustc_session/src/session.rs | 44 | ||||
| -rw-r--r-- | compiler/rustc_session/src/utils.rs | 64 | 
9 files changed, 128 insertions, 122 deletions
| diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index c665c85d1fe..9793d8091e2 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -16,10 +16,11 @@ use std::{cmp, fmt, fs, iter}; use externs::{ExternOpt, split_extern_opt}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; -use rustc_data_structures::stable_hasher::{StableOrd, ToStableHashKey}; +use rustc_data_structures::stable_hasher::{StableHasher, StableOrd, ToStableHashKey}; use rustc_errors::emitter::HumanReadableErrorType; use rustc_errors::{ColorConfig, DiagArgValue, DiagCtxtFlags, IntoDiagArg}; use rustc_feature::UnstableFeatures; +use rustc_hashes::Hash64; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::edition::{DEFAULT_EDITION, EDITION_NAME_LIST, Edition, LATEST_STABLE_EDITION}; use rustc_span::source_map::FilePathMapping; @@ -1195,7 +1196,25 @@ pub struct OutputFilenames { pub const RLINK_EXT: &str = "rlink"; pub const RUST_CGU_EXT: &str = "rcgu"; pub const DWARF_OBJECT_EXT: &str = "dwo"; +pub const MAX_FILENAME_LENGTH: usize = 143; // ecryptfs limits filenames to 143 bytes see #49914 +/// Ensure the filename is not too long, as some filesystems have a limit. +/// If the filename is too long, hash part of it and append the hash to the filename. +/// This is a workaround for long crate names generating overly long filenames. +fn maybe_strip_file_name(mut path: PathBuf) -> PathBuf { + if path.file_name().map_or(0, |name| name.len()) > MAX_FILENAME_LENGTH { + let filename = path.file_name().unwrap().to_string_lossy(); + let hash_len = 64 / 4; // Hash64 is 64 bits encoded in hex + let stripped_len = filename.len() - MAX_FILENAME_LENGTH + hash_len; + + let mut hasher = StableHasher::new(); + filename[..stripped_len].hash(&mut hasher); + let hash = hasher.finish::<Hash64>(); + + path.set_file_name(format!("{:x}-{}", hash, &filename[stripped_len..])); + } + path +} impl OutputFilenames { pub fn new( out_directory: PathBuf, @@ -1288,7 +1307,7 @@ impl OutputFilenames { } let temps_directory = self.temps_directory.as_ref().unwrap_or(&self.out_directory); - self.with_directory_and_extension(temps_directory, &extension) + maybe_strip_file_name(self.with_directory_and_extension(temps_directory, &extension)) } pub fn temp_path_for_diagnostic(&self, ext: &str) -> PathBuf { @@ -2828,16 +2847,27 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M // This is the location used by the `rustc-dev` `rustup` component. real_source_base_dir("lib/rustlib/rustc-src/rust", "compiler/rustc/src/main.rs"); - let mut search_paths = vec![]; - for s in &matches.opt_strs("L") { - search_paths.push(SearchPath::from_cli_opt( - sysroot.path(), - &target_triple, - early_dcx, - s, - unstable_opts.unstable_options, - )); - } + // We eagerly scan all files in each passed -L path. If the same directory is passed multiple + // times, and the directory contains a lot of files, this can take a lot of time. + // So we remove -L paths that were passed multiple times, and keep only the first occurrence. + // We still have to keep the original order of the -L arguments. + let search_paths: Vec<SearchPath> = { + let mut seen_search_paths = FxHashSet::default(); + let search_path_matches: Vec<String> = matches.opt_strs("L"); + search_path_matches + .iter() + .filter(|p| seen_search_paths.insert(*p)) + .map(|path| { + SearchPath::from_cli_opt( + sysroot.path(), + &target_triple, + early_dcx, + &path, + unstable_opts.unstable_options, + ) + }) + .collect() + }; let working_dir = std::env::current_dir().unwrap_or_else(|e| { early_dcx.early_fatal(format!("Current directory is invalid: {e}")); diff --git a/compiler/rustc_session/src/config/cfg.rs b/compiler/rustc_session/src/config/cfg.rs index 62891eb4f26..8f63ce6f0ae 100644 --- a/compiler/rustc_session/src/config/cfg.rs +++ b/compiler/rustc_session/src/config/cfg.rs @@ -26,13 +26,12 @@ use std::iter; use rustc_abi::Align; use rustc_ast::ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; -use rustc_lint_defs::BuiltinLintDiag; use rustc_lint_defs::builtin::EXPLICIT_BUILTIN_CFGS_IN_FLAGS; use rustc_span::{Symbol, sym}; use rustc_target::spec::{PanicStrategy, RelocModel, SanitizerSet, Target}; -use crate::Session; use crate::config::{CrateType, FmtDebug}; +use crate::{Session, errors}; /// The parsed `--cfg` options that define the compilation environment of the /// crate, used to drive conditional compilation. @@ -99,7 +98,7 @@ pub(crate) fn disallow_cfgs(sess: &Session, user_cfgs: &Cfg) { EXPLICIT_BUILTIN_CFGS_IN_FLAGS, None, ast::CRATE_NODE_ID, - BuiltinLintDiag::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by }, + errors::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by }.into(), ) }; diff --git a/compiler/rustc_session/src/config/native_libs.rs b/compiler/rustc_session/src/config/native_libs.rs index f1f0aeb5e59..50a0593f887 100644 --- a/compiler/rustc_session/src/config/native_libs.rs +++ b/compiler/rustc_session/src/config/native_libs.rs @@ -5,10 +5,11 @@ //! which have their own parser in `rustc_metadata`.) use rustc_feature::UnstableFeatures; +use rustc_hir::attrs::NativeLibKind; use crate::EarlyDiagCtxt; use crate::config::UnstableOptions; -use crate::utils::{NativeLib, NativeLibKind}; +use crate::utils::NativeLib; #[cfg(test)] mod tests; diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs index 4cfc745dec2..30f6256a75e 100644 --- a/compiler/rustc_session/src/cstore.rs +++ b/compiler/rustc_session/src/cstore.rs @@ -6,8 +6,8 @@ use std::any::Any; use std::path::PathBuf; use rustc_abi::ExternAbi; -use rustc_ast as ast; use rustc_data_structures::sync::{self, AppendOnlyIndexVec, FreezeLock}; +use rustc_hir::attrs::{CfgEntry, NativeLibKind, PeImportNameType}; use rustc_hir::def_id::{ CrateNum, DefId, LOCAL_CRATE, LocalDefId, StableCrateId, StableCrateIdMap, }; @@ -16,7 +16,6 @@ use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::{Span, Symbol}; use crate::search_paths::PathKind; -use crate::utils::NativeLibKind; // lonely orphan structs and enums looking for a better home @@ -72,7 +71,7 @@ pub struct NativeLib { pub name: Symbol, /// If packed_bundled_libs enabled, actual filename of library is stored. pub filename: Option<Symbol>, - pub cfg: Option<ast::MetaItemInner>, + pub cfg: Option<CfgEntry>, pub foreign_module: Option<DefId>, pub verbatim: Option<bool>, pub dll_imports: Vec<DllImport>, @@ -88,25 +87,6 @@ impl NativeLib { } } -/// Different ways that the PE Format can decorate a symbol name. -/// From <https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-name-type> -#[derive(Copy, Clone, Debug, Encodable, Decodable, HashStable_Generic, PartialEq, Eq)] -pub enum PeImportNameType { - /// IMPORT_ORDINAL - /// Uses the ordinal (i.e., a number) rather than the name. - Ordinal(u16), - /// Same as IMPORT_NAME - /// Name is decorated with all prefixes and suffixes. - Decorated, - /// Same as IMPORT_NAME_NOPREFIX - /// Prefix (e.g., the leading `_` or `@`) is skipped, but suffix is kept. - NoPrefix, - /// Same as IMPORT_NAME_UNDECORATE - /// Prefix (e.g., the leading `_` or `@`) and suffix (the first `@` and all - /// trailing characters) are skipped. - Undecorated, -} - #[derive(Clone, Debug, Encodable, Decodable, HashStable_Generic)] pub struct DllImport { pub name: Symbol, diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index bf95014843d..50bc7348dc9 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -7,7 +7,7 @@ use rustc_errors::{ Diag, DiagCtxtHandle, DiagMessage, Diagnostic, EmissionGuarantee, ErrorGuaranteed, Level, MultiSpan, }; -use rustc_macros::{Diagnostic, Subdiagnostic}; +use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_span::{Span, Symbol}; use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTuple}; @@ -384,6 +384,10 @@ pub fn report_lit_error( lit: token::Lit, span: Span, ) -> ErrorGuaranteed { + create_lit_error(psess, err, lit, span).emit() +} + +pub fn create_lit_error(psess: &ParseSess, err: LitError, lit: token::Lit, span: Span) -> Diag<'_> { // Checks if `s` looks like i32 or u1234 etc. fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool { s.len() > 1 && s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit()) @@ -414,32 +418,32 @@ pub fn report_lit_error( let dcx = psess.dcx(); match err { LitError::InvalidSuffix(suffix) => { - dcx.emit_err(InvalidLiteralSuffix { span, kind: lit.kind.descr(), suffix }) + dcx.create_err(InvalidLiteralSuffix { span, kind: lit.kind.descr(), suffix }) } LitError::InvalidIntSuffix(suffix) => { let suf = suffix.as_str(); if looks_like_width_suffix(&['i', 'u'], suf) { // If it looks like a width, try to be helpful. - dcx.emit_err(InvalidIntLiteralWidth { span, width: suf[1..].into() }) + dcx.create_err(InvalidIntLiteralWidth { span, width: suf[1..].into() }) } else if let Some(fixed) = fix_base_capitalisation(lit.symbol.as_str(), suf) { - dcx.emit_err(InvalidNumLiteralBasePrefix { span, fixed }) + dcx.create_err(InvalidNumLiteralBasePrefix { span, fixed }) } else { - dcx.emit_err(InvalidNumLiteralSuffix { span, suffix: suf.to_string() }) + dcx.create_err(InvalidNumLiteralSuffix { span, suffix: suf.to_string() }) } } LitError::InvalidFloatSuffix(suffix) => { let suf = suffix.as_str(); if looks_like_width_suffix(&['f'], suf) { // If it looks like a width, try to be helpful. - dcx.emit_err(InvalidFloatLiteralWidth { span, width: suf[1..].to_string() }) + dcx.create_err(InvalidFloatLiteralWidth { span, width: suf[1..].to_string() }) } else { - dcx.emit_err(InvalidFloatLiteralSuffix { span, suffix: suf.to_string() }) + dcx.create_err(InvalidFloatLiteralSuffix { span, suffix: suf.to_string() }) } } LitError::NonDecimalFloat(base) => match base { - 16 => dcx.emit_err(HexadecimalFloatLiteralNotSupported { span }), - 8 => dcx.emit_err(OctalFloatLiteralNotSupported { span }), - 2 => dcx.emit_err(BinaryFloatLiteralNotSupported { span }), + 16 => dcx.create_err(HexadecimalFloatLiteralNotSupported { span }), + 8 => dcx.create_err(OctalFloatLiteralNotSupported { span }), + 2 => dcx.create_err(BinaryFloatLiteralNotSupported { span }), _ => unreachable!(), }, LitError::IntTooLarge(base) => { @@ -450,7 +454,7 @@ pub fn report_lit_error( 16 => format!("{max:#x}"), _ => format!("{max}"), }; - dcx.emit_err(IntLiteralTooLarge { span, limit }) + dcx.create_err(IntLiteralTooLarge { span, limit }) } } } @@ -472,6 +476,10 @@ pub(crate) struct FunctionReturnRequiresX86OrX8664; pub(crate) struct FunctionReturnThunkExternRequiresNonLargeCodeModel; #[derive(Diagnostic)] +#[diag(session_indirect_branch_cs_prefix_requires_x86_or_x86_64)] +pub(crate) struct IndirectBranchCsPrefixRequiresX86OrX8664; + +#[derive(Diagnostic)] #[diag(session_unsupported_regparm)] pub(crate) struct UnsupportedRegparm { pub(crate) regparm: u32, @@ -501,3 +509,13 @@ pub(crate) struct SoftFloatIgnored; #[note] #[note(session_soft_float_deprecated_issue)] pub(crate) struct SoftFloatDeprecated; + +#[derive(LintDiagnostic)] +#[diag(session_unexpected_builtin_cfg)] +#[note(session_controlled_by)] +#[note(session_incoherent)] +pub(crate) struct UnexpectedBuiltinCfg { + pub(crate) cfg: String, + pub(crate) cfg_name: Symbol, + pub(crate) controlled_by: &'static str, +} diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 0e112edc733..6d5be2d92cd 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2295,6 +2295,8 @@ options! { - hashes of green query instances - hash collisions of query keys - hash collisions when creating dep-nodes"), + indirect_branch_cs_prefix: bool = (false, parse_bool, [TRACKED TARGET_MODIFIER], + "add `cs` prefix to `call` and `jmp` to indirect thunks (default: no)"), inline_llvm: bool = (true, parse_bool, [TRACKED], "enable LLVM inlining (default: yes)"), inline_mir: Option<bool> = (None, parse_opt_bool, [TRACKED], diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 426480f0dba..9048c51d5b4 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -11,8 +11,8 @@ use rustc_data_structures::sync::{AppendOnlyVec, Lock}; use rustc_errors::emitter::{FatalOnlyEmitter, HumanEmitter, stderr_destination}; use rustc_errors::translation::Translator; use rustc_errors::{ - ColorConfig, Diag, DiagCtxt, DiagCtxtHandle, DiagMessage, EmissionGuarantee, MultiSpan, - StashKey, + BufferedEarlyLint, ColorConfig, DecorateDiagCompat, Diag, DiagCtxt, DiagCtxtHandle, + DiagMessage, EmissionGuarantee, MultiSpan, StashKey, }; use rustc_feature::{GateIssue, UnstableFeatures, find_feature_issue}; use rustc_span::edition::Edition; @@ -27,7 +27,7 @@ use crate::errors::{ FeatureDiagnosticSuggestion, FeatureGateError, SuggestUpgradeCompiler, }; use crate::lint::builtin::UNSTABLE_SYNTAX_PRE_EXPANSION; -use crate::lint::{BufferedEarlyLint, BuiltinLintDiag, Lint, LintId}; +use crate::lint::{Lint, LintId}; /// Collected spans during parsing for places where a certain feature was /// used and should be feature gated accordingly in `check_crate`. @@ -342,17 +342,17 @@ impl ParseSess { lint: &'static Lint, span: impl Into<MultiSpan>, node_id: NodeId, - diagnostic: BuiltinLintDiag, + diagnostic: impl Into<DecorateDiagCompat>, ) { - self.opt_span_buffer_lint(lint, Some(span.into()), node_id, diagnostic) + self.opt_span_buffer_lint(lint, Some(span.into()), node_id, diagnostic.into()) } - pub fn opt_span_buffer_lint( + pub(crate) fn opt_span_buffer_lint( &self, lint: &'static Lint, span: Option<MultiSpan>, node_id: NodeId, - diagnostic: BuiltinLintDiag, + diagnostic: DecorateDiagCompat, ) { self.buffered_lints.with_lock(|buffered_lints| { buffered_lints.push(BufferedEarlyLint { diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index c6956cf5f23..96767d05439 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -7,6 +7,7 @@ use std::sync::atomic::AtomicBool; use std::{env, fmt, io}; use rand::{RngCore, rng}; +use rustc_ast::NodeId; use rustc_data_structures::base_n::{CASE_INSENSITIVE, ToBaseN}; use rustc_data_structures::flock; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; @@ -22,7 +23,7 @@ use rustc_errors::timings::TimingSectionHandler; use rustc_errors::translation::Translator; use rustc_errors::{ Diag, DiagCtxt, DiagCtxtHandle, DiagMessage, Diagnostic, ErrorGuaranteed, FatalAbort, - TerminalUrl, fallback_fluent_bundle, + LintEmitter, TerminalUrl, fallback_fluent_bundle, }; use rustc_macros::HashStable_Generic; pub use rustc_span::def_id::StableCrateId; @@ -44,6 +45,7 @@ use crate::config::{ SwitchWithOptPath, }; use crate::filesearch::FileSearch; +use crate::lint::LintId; use crate::parse::{ParseSess, add_feature_diagnostics}; use crate::search_paths::SearchPath; use crate::{errors, filesearch, lint}; @@ -139,7 +141,10 @@ pub struct CompilerIO { pub temps_dir: Option<PathBuf>, } -pub trait LintStoreMarker: Any + DynSync + DynSend {} +pub trait DynLintStore: Any + DynSync + DynSend { + /// Provides a way to access lint groups without depending on `rustc_lint` + fn lint_groups_iter(&self) -> Box<dyn Iterator<Item = LintGroup> + '_>; +} /// Represents the data associated with a compilation /// session for a single crate. @@ -164,7 +169,7 @@ pub struct Session { pub code_stats: CodeStats, /// This only ever stores a `LintStore` but we don't want a dependency on that type here. - pub lint_store: Option<Arc<dyn LintStoreMarker>>, + pub lint_store: Option<Arc<dyn DynLintStore>>, /// Cap lint level specified by a driver specifically. pub driver_lint_caps: FxHashMap<lint::LintId, lint::Level>, @@ -219,6 +224,20 @@ pub struct Session { pub invocation_temp: Option<String>, } +impl LintEmitter for &'_ Session { + type Id = NodeId; + + fn emit_node_span_lint( + self, + lint: &'static rustc_lint_defs::Lint, + node_id: Self::Id, + span: impl Into<rustc_errors::MultiSpan>, + decorator: impl for<'a> rustc_errors::LintDiagnostic<'a, ()> + DynSend + 'static, + ) { + self.psess.buffer_lint(lint, span, node_id, decorator); + } +} + #[derive(Clone, Copy)] pub enum CodegenUnits { /// Specified by the user. In this case we try fairly hard to produce the @@ -240,6 +259,12 @@ impl CodegenUnits { } } +pub struct LintGroup { + pub name: &'static str, + pub lints: Vec<LintId>, + pub is_externally_loaded: bool, +} + impl Session { pub fn miri_unleashed_feature(&self, span: Span, feature_gate: Option<Symbol>) { self.miri_unleashed_features.lock().push((span, feature_gate)); @@ -596,6 +621,13 @@ impl Session { (&*self.target.staticlib_prefix, &*self.target.staticlib_suffix) } } + + pub fn lint_groups_iter(&self) -> Box<dyn Iterator<Item = LintGroup> + '_> { + match self.lint_store { + Some(ref lint_store) => lint_store.lint_groups_iter(), + None => Box::new(std::iter::empty()), + } + } } // JUSTIFICATION: defn of the suggested wrapper fns @@ -1368,6 +1400,12 @@ fn validate_commandline_args_with_session_available(sess: &Session) { } } + if sess.opts.unstable_opts.indirect_branch_cs_prefix { + if sess.target.arch != "x86" && sess.target.arch != "x86_64" { + sess.dcx().emit_err(errors::IndirectBranchCsPrefixRequiresX86OrX8664); + } + } + if let Some(regparm) = sess.opts.unstable_opts.regparm { if regparm > 3 { sess.dcx().emit_err(errors::UnsupportedRegparm { regparm }); diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs index e9ddd66b5e8..c64d9bc1efe 100644 --- a/compiler/rustc_session/src/utils.rs +++ b/compiler/rustc_session/src/utils.rs @@ -3,6 +3,7 @@ use std::sync::OnceLock; use rustc_data_structures::profiling::VerboseTimingGuard; use rustc_fs_util::try_canonicalize; +use rustc_hir::attrs::NativeLibKind; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use crate::session::Session; @@ -17,69 +18,6 @@ impl Session { } } -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] -#[derive(HashStable_Generic)] -pub enum NativeLibKind { - /// Static library (e.g. `libfoo.a` on Linux or `foo.lib` on Windows/MSVC) - Static { - /// Whether to bundle objects from static library into produced rlib - bundle: Option<bool>, - /// Whether to link static library without throwing any object files away - whole_archive: Option<bool>, - }, - /// Dynamic library (e.g. `libfoo.so` on Linux) - /// or an import library corresponding to a dynamic library (e.g. `foo.lib` on Windows/MSVC). - Dylib { - /// Whether the dynamic library will be linked only if it satisfies some undefined symbols - as_needed: Option<bool>, - }, - /// Dynamic library (e.g. `foo.dll` on Windows) without a corresponding import library. - /// On Linux, it refers to a generated shared library stub. - RawDylib, - /// A macOS-specific kind of dynamic libraries. - Framework { - /// Whether the framework will be linked only if it satisfies some undefined symbols - as_needed: Option<bool>, - }, - /// Argument which is passed to linker, relative order with libraries and other arguments - /// is preserved - LinkArg, - - /// Module imported from WebAssembly - WasmImportModule, - - /// The library kind wasn't specified, `Dylib` is currently used as a default. - Unspecified, -} - -impl NativeLibKind { - pub fn has_modifiers(&self) -> bool { - match self { - NativeLibKind::Static { bundle, whole_archive } => { - bundle.is_some() || whole_archive.is_some() - } - NativeLibKind::Dylib { as_needed } | NativeLibKind::Framework { as_needed } => { - as_needed.is_some() - } - NativeLibKind::RawDylib - | NativeLibKind::Unspecified - | NativeLibKind::LinkArg - | NativeLibKind::WasmImportModule => false, - } - } - - pub fn is_statically_included(&self) -> bool { - matches!(self, NativeLibKind::Static { .. }) - } - - pub fn is_dllimport(&self) -> bool { - matches!( - self, - NativeLibKind::Dylib { .. } | NativeLibKind::RawDylib | NativeLibKind::Unspecified - ) - } -} - #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] #[derive(HashStable_Generic)] pub struct NativeLib { | 
