Skip to content

fix(parser): "unless they're mana abilities" exemption dropped for U+2019 apostrophe, wrongly blocking mana abilities (Pithing Needle, Bound by Moonsilver) #4999

Description

@ultrahighsuper

Summary

The CR 605.1a mana-ability exemption suffix "unless they're mana abilities" is parsed with the straight ASCII apostrophe only. Since MTGJSON oracle text uses the typographic apostrophe (U+2019), a permanent whose text carries the U+2019 form silently loses the exemption: the static is built with ActivationExemption::None, and the runtime then wrongly blocks the permanent's mana abilities — a rules violation, not just a coverage miss.

Affected cards (a class)

Every card templated …activated abilities can't be activated unless they're mana abilities. with the U+2019 apostrophe, e.g.:

  • Pithing NeedleActivated abilities of sources with the chosen name can't be activated unless they're mana abilities.
  • Bound by MoonsilverEnchanted permanent can't attack or block, and its activated abilities can't be activated unless they're mana abilities.
  • Faith's Fetters / Kenrith's Transformation–shaped auras…and its activated abilities can't be activated unless they're mana abilities.

Root cause

The asymmetry is internal and self-evident. The predicate half of the clause already accepts both apostrophes:

  • crates/engine/src/parser/oracle_static/shared.rs:693-694alt((tag("activated abilities can't be activated"), tag("activated abilities can\u{2019}t be activated")))
  • crates/engine/src/parser/oracle_static/evasion.rs:1204-1205 — same dual-apostrophe pair.

But the exemption suffix half is straight-apostrophe only:

  • crates/engine/src/parser/oracle_static/restriction.rs:292tag(" unless they're ")
  • crates/engine/src/parser/oracle_static/shared.rs:696opt((tag(" unless they're "), tag("mana abilities")))

There is no global apostrophe normalization in the pipeline (only /-), which is exactly why the predicate carries dual-apostrophe branches. So a U+2019 printing parses the predicate but drops the suffix.

Trace: parse_cant_be_activated_exemption_in_textparse_activation_exemption_suffix tries tag(" unless they're ") against unless they\u{2019}re mana abilities, the tag fails, opt yields None, unwrap_or_default() returns ActivationExemption::None. The runtime gate then blocks mana abilities that CR 605.1a requires to remain activatable.

Expected behavior (CR 605.1a)

Mana abilities remain activatable under a "can't be activated" static that carves them out with "unless they're mana abilities", regardless of which apostrophe glyph the oracle text uses.

Proposed fix

Add the U+2019 branch to both exemption-suffix parse sites, mirroring the dual-apostrophe pattern already used for the adjacent predicate:

alt((tag(" unless they're "), tag(" unless they\u{2019}re ")))

Parser-only, no new enum variant, zero blast radius — both sites map to the existing ActivationExemption::ManaAbilities.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions