{"record":{"id":"4e84288faf5af3cf","repo":"swc-project/swc","slug":"unsafeid-to-id-is-not-allowed-because-it-is-very","errorCode":null,"errorMessage":"UnsafeId.to_id() is not allowed because it is very likely to be unsafe","messagePattern":"UnsafeId\\.to_id\\(\\) is not allowed because it is very likely to be unsafe","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/swc_ecma_utils/src/ident.rs","lineNumber":79,"sourceCode":"\n    #[inline]\n    fn to_id(&self) -> Id {\n        (self.sym.clone(), self.ctxt)\n    }\n\n    #[inline]\n    fn into_id(self) -> Id {\n        (self.sym, self.ctxt)\n    }\n}\n\nimpl IdentLike for UnsafeId {\n    fn from_ident(i: &Ident) -> Self {\n        unsafe { unsafe_id_from_ident(i) }\n    }\n\n    fn to_id(&self) -> Id {\n        unreachable!(\"UnsafeId.to_id() is not allowed because it is very likely to be unsafe\")\n    }\n\n    fn into_id(self) -> Id {\n        unreachable!(\"UnsafeId.into_id() is not allowed because it is very likely to be unsafe\")\n    }\n}\n","sourceCodeStart":61,"sourceCodeEnd":86,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc_ecma_utils/src/ident.rs#L61-L86","documentation":"UnsafeId (swc_ecma_ast) is a performance-oriented IdentLike implementation created through the unsafe unsafe_id_from_ident path; converting it back to an Id via IdentLike::to_id()/into_id() is deliberately blocked with unreachable! because such a conversion would be 'very likely to be unsafe' given how UnsafeId instances are constructed. The panic is an intentional guard against misusing the fast identifier type in generic code.","triggerScenarios":"Instantiating generic utilities bound by IdentLike (scopes, ident-usage collectors, caches in swc_ecma_utils etc.) with UnsafeId and letting them call .to_id() or .into_id() on their keys/values — typically when someone swaps Id for UnsafeId for speed and forgets a downstream conversion.","commonSituations":"Contributors optimizing hot passes by keying maps with UnsafeId; copying Id-based code and only changing the type parameter; using APIs whose default type parameter is UnsafeId on a version where that became opt-in.","solutions":["Key your maps/scopes by Id (or (Atom, SyntaxContext)) wherever downstream code needs to_id/into_id; keep UnsafeId only in leaf passes that never convert back.","Extract the Id at the boundary before switching to UnsafeId: store `(sym.clone(), ctxt)` while you still have the Ident.","Audit call sites with `rg '\\.to_id\\(\\)|\\.into_id\\(\\)'` in code generic over `I: IdentLike`.","If a public swc API forces the conversion, report it as a bug against that API."],"exampleFix":"// before: UnsafeId flows into code that converts keys back to Id\nlet mut usage: IdentUsageFinder<UnsafeId> = ...; // later calls .to_id()\n\n// after: convert while the Ident is still around, key by Id\nlet key: Id = (ident.sym.clone(), ident.ctxt);\nlet mut usage: IdentUsageFinder<Id> = ...;","handlingStrategy":"type-guard","validationCode":"// Extract the Id while a real Ident is available, before switching to UnsafeId\nuse swc_ecma_ast::Ident; use swc_ecma_utils::IdentLike;\nfn id_of(i: &Ident) -> Id { (i.sym.clone(), i.ctxt) }\n// store id_of(&ident) as the map key; pass UnsafeId only through code that never converts","typeGuard":"// Compile-time discipline: any API that will call to_id/into_id must be\n// instantiated with Id (or (Atom, SyntaxContext)), never UnsafeId.\nfn takes_convertible_key<I: IdentLike>(k: &I) -> Id where I: Clone { k.to_id() } // OK for Id, PANICS for UnsafeId — keep UnsafeId out of these call paths","tryCatchPattern":null,"preventionTips":["Grep for `.to_id()` / `.into_id()` in code generic over `I: IdentLike` before swapping Id for UnsafeId.","Convert identifiers to Id at the boundary where the Ident still exists.","Reserve UnsafeId for leaf hot paths proven never to convert back."],"tags":["swc","identifiers","unsafid","identlike","api-misuse","panic"],"backgroundTag":"forbidden-unsafe-api","analyzedSha":"5176682b65416c6b5de6b47379ae1588ea3ecb3f","analyzedAt":"2026-08-17T16:16:52.067Z","contentChangedAt":"2026-08-17T16:16:52.067Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}