{"record":{"id":"76d7660fc6d9b541","repo":"antlr/antlr4","slug":"the-precedencedfa-field-cannot-change-after-a-dfa","errorCode":null,"errorMessage":"The precedenceDfa field cannot change after a DFA is constructed.","messagePattern":"The precedenceDfa field cannot change after a DFA is constructed\\.","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"warning","filePath":"runtime/Java/src/org/antlr/v4/runtime/dfa/DFA.java","lineNumber":153,"sourceCode":"\t\t\ts0.edges[precedence] = startState;\n\t\t}\n\t}\n\n\t/**\n\t * Sets whether this is a precedence DFA.\n\t *\n\t * @param precedenceDfa {@code true} if this is a precedence DFA; otherwise,\n\t * {@code false}\n\t *\n\t * @throws UnsupportedOperationException if {@code precedenceDfa} does not\n\t * match the value of {@link #isPrecedenceDfa} for the current DFA.\n\t *\n\t * @deprecated This method no longer performs any action.\n\t */\n\t@Deprecated\n\tpublic final void setPrecedenceDfa(boolean precedenceDfa) {\n\t\tif (precedenceDfa != isPrecedenceDfa()) {\n\t\t\tthrow new UnsupportedOperationException(\"The precedenceDfa field cannot change after a DFA is constructed.\");\n\t\t}\n\t}\n\n\t/**\n\t * Return a list of all states in this DFA, ordered by state number.\n\t */\n\n\tpublic List<DFAState> getStates() {\n\t\tList<DFAState> result = new ArrayList<DFAState>(states.keySet());\n\t\tCollections.sort(result, new Comparator<DFAState>() {\n\t\t\t@Override\n\t\t\tpublic int compare(DFAState o1, DFAState o2) {\n\t\t\t\treturn o1.stateNumber - o2.stateNumber;\n\t\t\t}\n\t\t});\n\n\t\treturn result;\n\t}","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/antlr/antlr4/blob/7d5770395bb7b02eb56e7c62662cb1d7c08f42a3/runtime/Java/src/org/antlr/v4/runtime/dfa/DFA.java#L135-L171","documentation":"DFA.setPrecedenceDfa(boolean) is deprecated and intentionally performs nothing except a consistency check: the precedence-ness of a DFA is fixed at construction. Passing a value different from the DFA's current isPrecedenceDfa() throws UnsupportedOperationException. The method exists only so old code that toggled this flag fails loudly instead of silently misbehaving.","triggerScenarios":"Calling dfa.setPrecedenceDfa(true) on a DFA constructed as a normal DFA, or setPrecedenceDfa(false) on a precedence DFA (created via new DFA(atnStart, -1)/precedence form or flagged during left-recursive rule simulation). Copy-pasted pre-4.6 code that 'converted' a DFA into a precedence DFA at runtime.","commonSituations":"Upgrading from ANTLR < 4.6 (where the field was mutable) to 4.6+: old workarounds that called setPrecedenceDfa now throw. Custom parser subclasses that mimic the old ParserATNSimulator init sequence.","solutions":["Delete the setPrecedenceDfa call; pass precedence at construction: new DFA(atnStart, precedence) (precedence >= 0 marks a precedence DFA)","If the call was a no-op consistency check in your code, replace it with an assertion on dfa.isPrecedenceDfa()","Regenerate nothing here; fix runtime-side code only and re-run your parser tests"],"exampleFix":"// before (pre-4.6 style)\nDFA dfa = new DFA(atnStart);\ndfa.setPrecedenceDfa(true); // throws in 4.6+\n// after\nDFA dfa = new DFA(atnStart, 0); // precedence DFA from construction\nassert dfa.isPrecedenceDfa();","handlingStrategy":"type-guard","validationCode":"// replace the call with a construction-time choice\nDFA dfa = wantPrecedence ? new DFA(atnStart, 0) : new DFA(atnStart);","typeGuard":"static boolean precedenceFlagMatches(DFA dfa, boolean want) { return dfa.isPrecedenceDfa() == want; }","tryCatchPattern":null,"preventionTips":["Delete setPrecedenceDfa calls when upgrading past ANTLR 4.6","Pass precedence to the DFA constructor instead","Grep for setPrecedenceDfa during version upgrades"],"tags":["antlr","java","dfa","precedence","deprecated","migration"],"backgroundTag":null,"analyzedSha":"7d5770395bb7b02eb56e7c62662cb1d7c08f42a3","analyzedAt":"2026-08-14T14:47:56.354Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}