use crate::attrs::AttributeKind;

#[derive(PartialEq)]
pub enum EncodeCrossCrate {
    Yes,
    No,
}

impl AttributeKind {
    /// Whether this attribute should be encoded in metadata files.
    ///
    /// If this is "Yes", then another crate can do `tcx.get_all_attrs(did)` for a did in this crate, and get the attribute.
    /// When this is No, the attribute is filtered out while encoding and other crate won't be able to observe it.
    /// This can be unexpectedly good for performance, so unless necessary for cross-crate compilation, prefer No.
    pub fn encode_cross_crate(&self) -> EncodeCrossCrate {
        use AttributeKind::*;
        use EncodeCrossCrate::*;

        match self {
            // tidy-alphabetical-start
            AllowInternalUnsafe(..) => Yes,
            AllowInternalUnstable(..) => Yes,
            AutomaticallyDerived => Yes,
            CfgAttrTrace => Yes,
            CfgTrace(..) => Yes,
            CfiEncoding { .. } => Yes,
            Cold => No,
            CollapseDebugInfo(..) => Yes,
            CompilerBuiltins => No,
            ConstContinue(..) => No,
            Coroutine => No,
            Coverage(..) => No,
            CrateName { .. } => No,
            CrateType(_) => No,
            CustomMir(_, _) => Yes,
            DebuggerVisualizer(..) => No,
            DefaultLibAllocator => No,
            Deprecated { .. } => Yes,
            DoNotRecommend => Yes,
            Doc(_) => Yes,
            DocComment { .. } => Yes,
            EiiDeclaration(_) => Yes,
            EiiImpls(..) => No,
            ExportName { .. } => Yes,
            ExportStable => No,
            Feature(..) => No,
            FfiConst => No,
            FfiPure(..) => No,
            Fundamental { .. } => Yes,
            Ignore { .. } => No,
            Inline(..) => No,
            InstructionSet(..) => No,
            InstrumentFn(..) => No,
            Lang(..) => Yes,
            Link(..) => No,
            LinkName { .. } => Yes, // Needed for rustdoc
            LinkOrdinal { .. } => No,
            LinkSection { .. } => Yes, // Needed for rustdoc
            Linkage(..) => No,
            LoopMatch(..) => No,
            MacroEscape => No,
            MacroExport { .. } => Yes,
            MacroUse { .. } => No,
            Marker => No,
            MayDangle(..) => No,
            MoveSizeLimit { .. } => No,
            MustNotSupend { .. } => Yes,
            MustUse { .. } => Yes,
            Naked(..) => No,
            NeedsAllocator => No,
            NeedsPanicRuntime => No,
            NoBuiltins => Yes,
            NoCore => No,
            NoImplicitPrelude => No,
            NoLink => No,
            NoMain => No,
            NoMangle(..) => Yes, // Needed for rustdoc
            NoStd => No,
            NonExhaustive(..) => Yes, // Needed for rustdoc
            OnConst { .. } => Yes,
            OnMove { .. } => Yes,
            OnTypeError { .. } => Yes,
            OnUnimplemented { .. } => Yes,
            OnUnknown { .. } => Yes,
            OnUnmatchedArgs { .. } => Yes,
            Optimize(..) => No,
            PanicRuntime => No,
            PatchableFunctionEntry { .. } => Yes,
            Path(..) => No,
            PatternComplexityLimit { .. } => No,
            PinV2(..) => Yes,
            PreludeImport => No,
            ProcMacro => No,
            ProcMacroAttribute => No,
            ProcMacroDerive { .. } => No,
            ProfilerRuntime => No,
            RecursionLimit { .. } => No,
            ReexportTestHarnessMain(..) => No,
            RegisterTool(..) => No,
            Repr { .. } => No,
            RustcAbi { .. } => No,
            RustcAlign { .. } => No,
            RustcAllocator => No,
            RustcAllocatorZeroed => No,
            RustcAllocatorZeroedVariant { .. } => Yes,
            RustcAllowConstFnUnstable(..) => No,
            RustcAllowIncoherentImpl(..) => No,
            RustcAsPtr => Yes,
            RustcAutodiff(..) => Yes,
            RustcBodyStability { .. } => No,
            RustcBuiltinMacro { .. } => Yes,
            RustcCaptureAnalysis => No,
            RustcCguTestAttr { .. } => No,
            RustcClean { .. } => No,
            RustcCoherenceIsCore => No,
            RustcCoinductive => No,
            RustcComptime(..) => No, // Encoded directly in signature
            RustcConfusables { .. } => Yes,
            RustcConstStability { .. } => Yes,
            RustcConstStableIndirect => No,
            RustcConversionSuggestion => Yes,
            RustcDeallocator => No,
            RustcDelayedBugFromInsideQuery => No,
            RustcDenyExplicitImpl => No,
            RustcDeprecatedSafe2024 { .. } => Yes,
            RustcDiagnosticItem(..) => Yes,
            RustcDoNotConstCheck => Yes,
            RustcDocPrimitive(..) => Yes,
            RustcDummy => No,
            RustcDumpDefParents => No,
            RustcDumpDefPath(..) => No,
            RustcDumpGenerics => No,
            RustcDumpHiddenTypeOfOpaques => No,
            RustcDumpInferredOutlives => No,
            RustcDumpItemBounds => No,
            RustcDumpLayout(..) => No,
            RustcDumpObjectLifetimeDefaults => No,
            RustcDumpPredicates => No,
            RustcDumpSymbolName(..) => Yes,
            RustcDumpUserArgs => No,
            RustcDumpVariances => No,
            RustcDumpVariancesOfOpaques => No,
            RustcDumpVtable(..) => No,
            RustcDynIncompatibleTrait(..) => No,
            RustcEffectiveVisibility => Yes,
            RustcEiiForeignItem => No,
            RustcEvaluateWhereClauses => Yes,
            RustcHasIncoherentInherentImpls => Yes,
            RustcIfThisChanged(..) => No,
            RustcInheritOverflowChecks => No,
            RustcInsignificantDtor => Yes,
            RustcIntrinsic => Yes,
            RustcIntrinsicConstStableIndirect => No,
            RustcLegacyConstGenerics { .. } => Yes,
            RustcLintOptDenyFieldAccess { .. } => Yes,
            RustcLintOptTy => Yes,
            RustcLintQueryInstability => Yes,
            RustcLintUntrackedQueryInformation => Yes,
            RustcMacroTransparency(..) => Yes,
            RustcMain => No,
            RustcMir(..) => Yes,
            RustcMustImplementOneOf { .. } => No,
            RustcMustMatchExhaustively(..) => Yes,
            RustcNeverReturnsNullPtr => Yes,
            RustcNeverTypeOptions { .. } => No,
            RustcNoImplicitAutorefs => Yes,
            RustcNoImplicitBounds => No,
            RustcNoMirInline => Yes,
            RustcNoWritable => Yes,
            RustcNonConstTraitMethod => No, // should be reported via other queries like `constness`
            RustcNonnullOptimizationGuaranteed => Yes,
            RustcNounwind => No,
            RustcObjcClass { .. } => No,
            RustcObjcSelector { .. } => No,
            RustcOffloadKernel => Yes,
            RustcParenSugar => No,
            RustcPassByValue => Yes,
            RustcPassIndirectlyInNonRusticAbis(..) => No,
            RustcPreserveUbChecks => No,
            RustcProcMacroDecls => No,
            RustcPubTransparent(..) => Yes,
            RustcReallocator => No,
            RustcRegions => No,
            RustcReservationImpl(..) => Yes,
            RustcScalableVector { .. } => Yes,
            RustcShouldNotBeCalledOnConstItems => Yes,
            RustcSimdMonomorphizeLaneLimit(..) => Yes, // Affects layout computation, which needs to work cross-crate
            RustcSkipDuringMethodDispatch { .. } => No,
            RustcSpecializationTrait => No,
            RustcStdInternalSymbol => No,
            RustcStrictCoherence(..) => Yes,
            RustcTestMarker(..) => No,
            RustcThenThisWouldNeed(..) => No,
            RustcTrivialFieldReads => Yes,
            RustcUnsafeSpecializationMarker => No,
            Sanitize { .. } => No,
            ShouldPanic { .. } => No,
            Splat(..) => Yes,
            Stability { .. } => Yes,
            TargetFeature { .. } => No,
            TestRunner(..) => Yes,
            ThreadLocal => No,
            TrackCaller(..) => Yes,
            TypeLengthLimit { .. } => No,
            Unroll(..) => No,
            UnstableFeatureBound(..) => No,
            UnstableRemoved(..) => Yes,
            Used { .. } => No,
            WindowsSubsystem(..) => No,
            // tidy-alphabetical-end
        }
    }
}
