diff --git a/changelog.d/student-loan-interest-claimed-spouse.fixed.md b/changelog.d/student-loan-interest-claimed-spouse.fixed.md new file mode 100644 index 00000000000..5790737c6cc --- /dev/null +++ b/changelog.d/student-loan-interest-claimed-spouse.fixed.md @@ -0,0 +1 @@ +Let the unclaimed spouse on a joint return deduct their own student loan interest when the other spouse is claimed as a dependent elsewhere (26 U.S.C. 221(c)), and count both spouses in joint MAGI. diff --git a/policyengine_us/tests/core/test_ald_determinism.py b/policyengine_us/tests/core/test_ald_determinism.py index 4dd95f6dd2c..4196b389ea8 100644 --- a/policyengine_us/tests/core/test_ald_determinism.py +++ b/policyengine_us/tests/core/test_ald_determinism.py @@ -38,6 +38,7 @@ "alimony_expense_ald": 1, "health_savings_account_ald": 1, "student_loan_interest_ald_eligible": True, + "is_tax_unit_head_or_spouse": True, "is_tax_unit_dependent": False, "is_tax_unit_head": True, "is_tax_unit_spouse": False, diff --git a/policyengine_us/tests/core/test_student_loan_interest_claimed_spouse_invariants.py b/policyengine_us/tests/core/test_student_loan_interest_claimed_spouse_invariants.py new file mode 100644 index 00000000000..46300826ea6 --- /dev/null +++ b/policyengine_us/tests/core/test_student_loan_interest_claimed_spouse_invariants.py @@ -0,0 +1,193 @@ +"""Student loan interest deduction on a joint return with a claimed spouse. + +IRC 221(c) denies the deduction "to an individual" for whom another taxpayer +is allowed a dependency deduction. The bar reaches that individual only: on a +joint return the unclaimed spouse keeps the deduction for their own interest, +under the single return-level cap of IRC 221(b)(1) and the joint phase-out of +IRC 221(b)(2), whose MAGI includes both spouses. + +Hypothesis draws batches of joint couples with one unclaimed filer and one +filer who may be claimed. Each couple draws whether the claimable filer is the +head or the spouse, so the checks hold for either claimed filer. Each couple +runs in one vectorized simulation in four variants: + +- A: the claimable filer is claimed and has the drawn interest; +- B: the claimable filer is claimed and has no interest; +- C: the claimable filer is not claimed and has no interest; +- D: the claimable filer is not claimed and has the drawn interest. + +The checks: + +1. The unclaimed filer's deduction is the same in A, B and C: it never + depends on the claimed filer's own interest, or on whether a filer with no + interest is claimed. +2. A claimed filer's own interest is never deducted: their deduction is zero + and the return's total in A is no more than the unclaimed filer's own + interest. +3. The return's deduction never exceeds the cap, in every variant. + +Explicit examples put a claimed filer's income inside the joint phase-out in +both years, with the claimed filer as head and as spouse, so a joint MAGI that +dropped the claimed filer would break check 1 by hundreds of dollars. +""" + +import numpy as np +from hypothesis import HealthCheck, example, given, settings +from hypothesis import strategies as st + +from policyengine_us import Simulation + +TOLERANCE = 0.01 +VARIANTS = { + "A": dict(claimed=True, spouse_interest=True), + "B": dict(claimed=True, spouse_interest=False), + "C": dict(claimed=False, spouse_interest=False), + "D": dict(claimed=False, spouse_interest=True), +} + +money = st.integers(0, 200_000).map(float) +interest = st.one_of(st.just(0.0), st.integers(1, 4_000).map(float)) + + +@st.composite +def couples(draw): + return { + "claimed_role": draw(st.sampled_from(["spouse", "head"])), + "unclaimed_income": draw(money), + "claimed_income": draw(st.one_of(st.just(0.0), money)), + "unclaimed_interest": draw(interest), + "claimed_interest": draw(interest), + } + + +def couple( + claimed_role, + unclaimed_income, + claimed_income, + unclaimed_interest, + claimed_interest, +): + return dict( + claimed_role=claimed_role, + unclaimed_income=float(unclaimed_income), + claimed_income=float(claimed_income), + unclaimed_interest=float(unclaimed_interest), + claimed_interest=float(claimed_interest), + ) + + +# Couples whose claimed filer's income moves the joint phase-out. 2025: start +# $170,000, range $30,000; 2019: start $140,000, range $30,000. +PHASE_OUT_2025 = [ + # Joint MAGI 150,000 + 30,000 = 180,000: 2,500 x (1 - 10/30) = 1,666.67, + # against 2,500 if the claimed spouse's 30,000 were dropped. + couple("spouse", 150_000, 30_000, 2_500, 1_000), + # The same with the head claimed. + couple("head", 150_000, 30_000, 2_500, 1_000), + # Joint MAGI 165,000 + 20,000 = 185,000: 2,000 x (1 - 15/30) = 1,000, + # against 2,000 x (1 - 0) = 2,000 at 165,000. + couple("spouse", 165_000, 20_000, 2_000, 3_000), + couple("spouse", 2_000, 0, 1_000, 700), +] +PHASE_OUT_2019 = [ + # Joint MAGI 130,000 + 20,000 = 150,000: 2,000 x (1 - 10/30) = 1,333.33, + # against 2,000 at 130,000. + couple("spouse", 130_000, 20_000, 2_000, 500), + couple("head", 130_000, 20_000, 2_000, 500), + couple("head", 0, 0, 0, 0), +] + + +def _situation(units, year): + people, tax_units, households = {}, {}, {} + for i, unit in enumerate(units): + claimed_is_head = unit["claimed_role"] == "head" + for key, variant in VARIANTS.items(): + unclaimed, claimed = f"unclaimed_{i}_{key}", f"claimed_{i}_{key}" + people[unclaimed] = { + "age": {year: 30}, + "employment_income": {year: unit["unclaimed_income"]}, + "student_loan_interest": {year: unit["unclaimed_interest"]}, + "claimed_as_dependent_on_another_return": {year: False}, + "is_tax_unit_head": {year: not claimed_is_head}, + "is_tax_unit_spouse": {year: claimed_is_head}, + } + claimed_interest = ( + unit["claimed_interest"] if variant["spouse_interest"] else 0.0 + ) + people[claimed] = { + "age": {year: 22}, + "employment_income": {year: unit["claimed_income"]}, + "student_loan_interest": {year: claimed_interest}, + "claimed_as_dependent_on_another_return": {year: variant["claimed"]}, + "is_tax_unit_head": {year: claimed_is_head}, + "is_tax_unit_spouse": {year: not claimed_is_head}, + } + members = [unclaimed, claimed] + tax_units[f"tu_{i}_{key}"] = { + "members": members, + "filing_status": {year: "JOINT"}, + } + households[f"hh_{i}_{key}"] = { + "members": members, + "state_code": {year: "TX"}, + } + return {"people": people, "tax_units": tax_units, "households": households} + + +def _check(units, year): + sim = Simulation(situation=_situation(units, year)) + ald = sim.calculate("student_loan_interest_ald", year) + own = sim.calculate("student_loan_interest", year) + cap = sim.tax_benefit_system.parameters( + f"{year}-01-01" + ).gov.irs.ald.student_loan_interest.cap.JOINT + n_variants = len(VARIANTS) + # People are ordered unit by unit, variant by variant, unclaimed filer + # then claimable filer, whichever of them is the head. + ald = ald.reshape(len(units), n_variants, 2) + own = own.reshape(len(units), n_variants, 2) + a, b, c, d = range(n_variants) + unclaimed_ald = ald[:, :, 0] + + # 1. The unclaimed filer's deduction ignores the claimed filer. + np.testing.assert_allclose(unclaimed_ald[:, a], unclaimed_ald[:, b], atol=TOLERANCE) + np.testing.assert_allclose(unclaimed_ald[:, a], unclaimed_ald[:, c], atol=TOLERANCE) + + # 2. The claimed filer's own interest is never deducted. + assert (ald[:, [a, b], 1] == 0).all() + assert (ald[:, a].sum(axis=1) <= own[:, a, 0] + TOLERANCE).all() + + # 3. The return's deduction never exceeds the cap. + assert (ald.sum(axis=2) <= cap + TOLERANCE).all() + assert (ald >= 0).all() + # The claimed filer doesn't change the unclaimed filer's deduction + # through the shared cap: with the claimable filer's interest, the + # unclaimed filer's share in D is never above their deduction in A. + assert (unclaimed_ald[:, d] <= unclaimed_ald[:, a] + TOLERANCE).all() + + +SETTINGS = dict( + max_examples=4, + deadline=None, + derandomize=True, + suppress_health_check=[HealthCheck.too_slow, HealthCheck.data_too_large], +) + + +@settings(**SETTINGS) +@example(PHASE_OUT_2025, 2025) +@example(PHASE_OUT_2019, 2019) +@given(st.lists(couples(), min_size=10, max_size=30), st.sampled_from([2019, 2025])) +def test_claimed_spouse_invariants(units, year): + _check(units, year) + + +def test_crafted_witnesses(): + # A claimed spouse with interest beside an unclaimed head below and in + # the 2025 joint phase-out ($170,000 start, $30,000 range). + units = [ + couple("spouse", 2_000, 0, 1_000, 700), + couple("spouse", 150_000, 30_000, 4_000, 3_000), + ] + _check(units, 2025) diff --git a/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/deductions/student_loan_interest/student_loan_interest_ald.yaml b/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/deductions/student_loan_interest/student_loan_interest_ald.yaml index 717160aaf00..dc624c3781b 100644 --- a/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/deductions/student_loan_interest/student_loan_interest_ald.yaml +++ b/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/deductions/student_loan_interest/student_loan_interest_ald.yaml @@ -259,3 +259,107 @@ output: # MAGI 70,000 + 15,000 = 85,000; reduced by (85,000 - 80,000) / 15,000. student_loan_interest_ald: 1_666.67 + +# IRC 221(c) denies the deduction "to an individual" whom another taxpayer +# claims. On a joint return filed only to claim a refund (IRC 152(c)(1)(E)), +# the unclaimed spouse keeps the deduction for their own interest. +- name: Unclaimed spouse retains own loan-interest deduction on a refund-only joint return + period: 2025 + input: + people: + unclaimed: + age: 30 + is_tax_unit_head: true + is_tax_unit_spouse: false + employment_income: 2_000 + student_loan_interest: 1_000 + claimed_student: + age: 22 + is_full_time_student: true + is_tax_unit_head: false + is_tax_unit_spouse: true + claimable_as_dependent_on_another_return: true + claimed_as_dependent_on_another_return: true + student_loan_interest: 700 + tax_units: + joint: + members: [unclaimed, claimed_student] + filing_status: JOINT + households: + household: + members: [unclaimed, claimed_student] + state_code: TX + output: + # Eligible interest 1,000 + 0; the 2,500 cap and the 170,000 phase-out + # start don't bind. AGI = 2,000 - 1,000. + student_loan_interest_ald_eligible: [true, false] + student_loan_interest_ald: [1_000, 0] + adjusted_gross_income: 1_000 + +- name: Claimed head does not bar the unclaimed spouse or drop out of joint MAGI + period: 2025 + input: + people: + claimed_student: + age: 22 + is_full_time_student: true + is_tax_unit_head: true + is_tax_unit_spouse: false + claimable_as_dependent_on_another_return: true + claimed_as_dependent_on_another_return: true + employment_income: 1_000 + student_loan_interest: 700 + unclaimed: + age: 30 + is_tax_unit_head: false + is_tax_unit_spouse: true + employment_income: 4_000 + student_loan_interest: 4_000 + tax_units: + joint: + members: [claimed_student, unclaimed] + filing_status: JOINT + households: + household: + members: [claimed_student, unclaimed] + state_code: TX + output: + # Eligible interest 4,000, capped once at 2,500. Joint MAGI + # 1,000 + 4,000 = 5,000. AGI = 5,000 - 2,500. + student_loan_interest_ald_eligible: [false, true] + student_loan_interest_ald_magi: [1_000, 4_000] + student_loan_interest_ald: [0, 2_500] + adjusted_gross_income: 2_500 + +# Mechanics only: the claim is set as an input. The joint phase-out reads +# both spouses' MAGI (IRC 221(b)(2)(B)), including a claimed spouse's. +- name: Joint phase-out counts the claimed spouse's MAGI + period: 2025 + absolute_error_margin: 0.01 + input: + people: + unclaimed: + age: 30 + is_tax_unit_head: true + is_tax_unit_spouse: false + employment_income: 150_000 + student_loan_interest: 2_500 + claimed_spouse: + age: 22 + is_tax_unit_head: false + is_tax_unit_spouse: true + claimed_as_dependent_on_another_return: true + employment_income: 30_000 + tax_units: + joint: + members: [unclaimed, claimed_spouse] + filing_status: JOINT + households: + household: + members: [unclaimed, claimed_spouse] + state_code: TX + output: + # Joint MAGI 180,000; reduced by (180,000 - 170,000) / 30,000: + # 2,500 x (1 - 1/3) = 1,666.67. + student_loan_interest_ald_magi: [150_000, 30_000] + student_loan_interest_ald: [1_666.67, 0] diff --git a/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/deductions/student_loan_interest/student_loan_interest_ald_eligible.yaml b/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/deductions/student_loan_interest/student_loan_interest_ald_eligible.yaml index e161077097f..4241b0edb0c 100644 --- a/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/deductions/student_loan_interest/student_loan_interest_ald_eligible.yaml +++ b/policyengine_us/tests/policy/baseline/gov/irs/income/taxable_income/deductions/student_loan_interest/student_loan_interest_ald_eligible.yaml @@ -56,7 +56,7 @@ # IRC 221(c). student_loan_interest_ald_eligible: false -- name: 2024 joint return with one spouse claimed elsewhere cannot deduct student loan interest (the claimable spouse is the head) +- name: 2024 joint return with the head claimed elsewhere; only the claimed head is barred period: 2024 input: people: @@ -78,11 +78,11 @@ members: [person_a, person_b] state_code: TX output: - # Form 1040 instructions: "you, or your spouse if filing jointly, aren't - # claimed as a dependent". - student_loan_interest_ald_eligible: [false, false] + # IRC 221(c) bars the claimed individual only; the statute governs the + # Form 1040 instructions, which bar the whole joint return. + student_loan_interest_ald_eligible: [false, true] -- name: 2024 joint return with one spouse claimed elsewhere cannot deduct student loan interest (the claimable spouse is the spouse) +- name: 2024 joint return with the spouse claimed elsewhere; only the claimed spouse is barred period: 2024 input: people: @@ -104,7 +104,7 @@ members: [person_b, person_a] state_code: TX output: - student_loan_interest_ald_eligible: [false, false] + student_loan_interest_ald_eligible: [true, false] # IRC 221(c): the bar applies to an individual who is claimed. - name: 2024 single filer who can be claimed but is not claimed can deduct student loan interest diff --git a/policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/hi_student_loan_interest_adjustment.yaml b/policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/hi_student_loan_interest_adjustment.yaml index a40d25ee3fd..682cd09349e 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/hi_student_loan_interest_adjustment.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/hi/tax/income/hi_student_loan_interest_adjustment.yaml @@ -273,3 +273,44 @@ hi_subtractions: 5_000 # $62,500 + $1,666.67 addition - $5,000 pension subtraction. hi_agi: 59_166.67 + +- name: Hawaii deduction keeps the unclaimed head's interest on a joint return with a claimed spouse + period: 2025 + absolute_error_margin: 0.01 + input: + people: + head: + age: 30 + employment_income: 2_000 + student_loan_interest: 1_000 + is_tax_unit_head: true + spouse: + age: 22 + is_full_time_student: true + is_tax_unit_spouse: true + claimable_as_dependent_on_another_return: true + claimed_as_dependent_on_another_return: true + student_loan_interest: 700 + tax_units: + tax_unit: + members: [head, spouse] + filing_status: JOINT + spm_units: + spm_unit: + members: [head, spouse] + households: + household: + members: [head, spouse] + state_code: HI + output: + # IRC 221(c) bars only the claimed spouse, so Hawaii counts the head's + # interest only: min(1,000, 2,500 cap) = 1,000. Federal AGI is + # 2,000 - 1,000 = 1,000; Hawaii MAGI adds back the 1,000 federal + # deduction, giving 2,000, below the 100,000 joint phase-out start. + student_loan_interest_ald_eligible: [true, false] + hi_modified_agi: 2_000 + hi_student_loan_interest_deduction: 1_000 + # Hawaii deduction 1,000 - federal deduction 1,000 = 0, so Hawaii AGI + # equals federal AGI. + hi_student_loan_interest_adjustment: 0 + hi_agi: 1_000 diff --git a/policyengine_us/tests/policy/baseline/gov/states/ky/tax/income/ky_federal_agi.yaml b/policyengine_us/tests/policy/baseline/gov/states/ky/tax/income/ky_federal_agi.yaml index faebdf8b0fd..24d98364314 100644 --- a/policyengine_us/tests/policy/baseline/gov/states/ky/tax/income/ky_federal_agi.yaml +++ b/policyengine_us/tests/policy/baseline/gov/states/ky/tax/income/ky_federal_agi.yaml @@ -361,3 +361,41 @@ output: adjusted_gross_income: 40_000 ky_federal_agi: [0, 40_000] + +# IRC 221(c) bars only the claimed spouse from the student loan interest +# deduction; Kentucky starts each column from the filer's own federal AGI. +# Mechanics only: the claim is set as an input on a return that couldn't be +# refund-only at this income. +- name: Unclaimed head's student loan interest deduction lowers Kentucky AGI on a joint return with a claimed spouse + period: 2025 + input: + people: + head: + age: 30 + employment_income: 50_000 + student_loan_interest: 2_000 + is_tax_unit_head: true + spouse: + age: 22 + is_tax_unit_spouse: true + claimed_as_dependent_on_another_return: true + student_loan_interest: 1_000 + tax_units: + tax_unit: + members: [head, spouse] + filing_status: JOINT + households: + household: + members: [head, spouse] + state_code: KY + output: + # Federal: only the head's 2,000 is eligible; joint MAGI 50,000 is below + # the 170,000 phase-out start. Head AGI 50,000 - 2,000 = 48,000. + student_loan_interest_ald: [2_000, 0] + ky_federal_agi: [48_000, 0] + ky_agi: [48_000, 0] + # Joint: (48,000 - 3,270 standard deduction) x 4% = 1,789.20. The + # separate path gives the same (the spouse's column is 0), so the joint + # path stands. Family size credit: Kentucky modified AGI 48,000 is above + # its range for two; no personal or refundable credits apply. + ky_income_tax: 1_789.20 diff --git a/policyengine_us/variables/gov/irs/income/taxable_income/adjusted_gross_income/above_the_line_deductions/student_loan_interest/student_loan_interest_ald_eligible.py b/policyengine_us/variables/gov/irs/income/taxable_income/adjusted_gross_income/above_the_line_deductions/student_loan_interest/student_loan_interest_ald_eligible.py index fd1bcc2bab0..ae5de35368c 100644 --- a/policyengine_us/variables/gov/irs/income/taxable_income/adjusted_gross_income/above_the_line_deductions/student_loan_interest/student_loan_interest_ald_eligible.py +++ b/policyengine_us/variables/gov/irs/income/taxable_income/adjusted_gross_income/above_the_line_deductions/student_loan_interest/student_loan_interest_ald_eligible.py @@ -6,11 +6,16 @@ class student_loan_interest_ald_eligible(Variable): entity = Person label = "Eligible for the Student loan interest ALD" definition_period = YEAR - reference = "https://www.law.cornell.edu/uscode/text/26/221" + reference = ( + "https://www.law.cornell.edu/uscode/text/26/221#c", + "https://www.law.cornell.edu/uscode/text/26/221#e_2", + ) documentation = ( "Eligibility for the student loan interest above-the-line deduction. " "Per IRC § 221, the taxpayer must not file as Married Filing Separately " - "(§ 221(e)(2)) and cannot be claimed as a dependent (§ 221(c)). " + "(§ 221(e)(2)) and must not be an individual whom another taxpayer " + "claims as a dependent (§ 221(c)); on a joint return that bar " + "applies to the claimed spouse only. " "The MAGI phase-out is handled separately in the deduction calculation. " "Note: While § 221(d)(3) references § 25A(b)(3) for the definition of " "'eligible student', this refers to the student's status when the loan " @@ -20,15 +25,14 @@ class student_loan_interest_ald_eligible(Variable): def formula(person, period, parameters): head_or_spouse = person("is_tax_unit_head_or_spouse", period) - # Per IRC § 221(c), no deduction for an individual for whom a section - # 151 deduction "is allowed to another taxpayer"; the Form 1040 - # instructions require that "you, or your spouse if filing jointly, - # aren't claimed as a dependent", so either filer being claimed bars - # the return. This turns on an actual claim, so it reads the claimed - # input rather than a claimability helper. + # Per IRC § 221(c), no deduction "to an individual" for whom a + # section 151 deduction "is allowed to another taxpayer". The bar + # reaches that individual only: on a joint return the other spouse + # keeps the deduction for their own interest, although the Form 1040 + # instructions bar the whole return. This turns on an actual claim, + # so it reads the claimed input rather than a claimability helper. claimed = person("claimed_as_dependent_on_another_return", period) - filer_claimed = person.tax_unit.any(head_or_spouse & claimed) # Per IRC § 221(e)(2), taxpayer cannot file as Married Filing Separately filing_status = person.tax_unit("filing_status", period) separate = filing_status == filing_status.possible_values.SEPARATE - return head_or_spouse & ~separate & ~filer_claimed + return head_or_spouse & ~separate & ~claimed diff --git a/policyengine_us/variables/gov/irs/income/taxable_income/adjusted_gross_income/above_the_line_deductions/student_loan_interest/student_loan_interest_ald_magi.py b/policyengine_us/variables/gov/irs/income/taxable_income/adjusted_gross_income/above_the_line_deductions/student_loan_interest/student_loan_interest_ald_magi.py index 5fa8a8768cc..e5717748c10 100644 --- a/policyengine_us/variables/gov/irs/income/taxable_income/adjusted_gross_income/above_the_line_deductions/student_loan_interest/student_loan_interest_ald_magi.py +++ b/policyengine_us/variables/gov/irs/income/taxable_income/adjusted_gross_income/above_the_line_deductions/student_loan_interest/student_loan_interest_ald_magi.py @@ -14,13 +14,15 @@ class student_loan_interest_ald_magi(Variable): "222), and after application of sections 86, 135, 137, 219 and 469. " "Built from gross income sources rather than adjusted gross income, " "which includes this deduction. On a joint return each spouse " - "carries half of the tax unit's deductions and exclusions." + "carries half of the tax unit's deductions and exclusions. Joint " + "MAGI includes both spouses, including one claimed as a dependent " + "elsewhere who cannot take the deduction." ) reference = ( "https://www.law.cornell.edu/uscode/text/26/221#b_2_C", "https://www.irs.gov/pub/irs-prior/p970--2024.pdf#page=36", ) - defined_for = "student_loan_interest_ald_eligible" + defined_for = "is_tax_unit_head_or_spouse" def formula(person, period, parameters): p_irs = parameters(period).gov.irs diff --git a/source_conflicts/candidates.yaml b/source_conflicts/candidates.yaml index 025bb5dd42b..3af4376ef07 100644 --- a/source_conflicts/candidates.yaml +++ b/source_conflicts/candidates.yaml @@ -10252,30 +10252,29 @@ candidates: years: from: 2018 type: tax - question: Does claiming one spouse as a dependent bar only that spouse's education credits and student loan interest - deduction, or the whole joint return? + question: Does claiming one spouse as a dependent bar only that spouse's education credits, or the whole joint + return? sources: - kind: statute - citation: 26 U.S.C. 25A(g)(3); 26 U.S.C. 221(c) + citation: 26 U.S.C. 25A(g)(3) url: https://www.law.cornell.edu/uscode/text/26/25A#g_3 - kind: instructions - citation: Form 1040 instructions (education credits and student loan interest) + citation: Form 1040 instructions (education credits) url: https://www.irs.gov/pub/irs-prior/i1040gi--2025.pdf#page=98 readings: - statute: The claimed spouse loses the benefit; the other spouse keeps their own credit or deduction. + statute: The claimed spouse loses the credit; the other spouse keeps their own credit. other: The whole joint return is barred. pe_us: follows: conflicting-source code: - policyengine_us/variables/gov/irs/credits/education/is_barred_from_education_credits_by_dependency.py - - policyengine_us/variables/gov/irs/income/taxable_income/adjusted_gross_income/above_the_line_deductions/student_loan_interest/student_loan_interest_ald_eligible.py prs: - https://github.com/PolicyEngine/policyengine-us/pull/10087 state: ruled note: 'PE-US follows the Form 1040 instructions: a claimed head or spouse bars the whole joint return from the - education credits and the student loan interest deduction (is_barred_from_education_credits_by_dependency.py, - student_loan_interest_ald_eligible.py). Ruled October 2026; the statute-first rule now requires changing the - whole-return bar; verify the education-credit page anchor because the supplied URL is for student loan interest.' + education credits (is_barred_from_education_credits_by_dependency.py). Ruled October 2026; the statute-first + rule now requires changing the whole-return bar; verify the education-credit page anchor because the supplied + URL is for student loan interest.' - id: us:eitc-trust-royalties-investment-income program: income-tax years: @@ -10760,6 +10759,36 @@ candidates: state: unreviewed note: 'The open PR follows POMS rather than the broader regulatory reading; no statutory comparison or specific ruling is supplied. Code not yet on main: ssi_spousal_deeming_child_allocations, ssi_ineligible_child_allocation.' +- id: us:student-loan-interest-joint-claimed-spouse + program: income-tax + years: + from: 2018 + type: tax + question: Does claiming one spouse as a dependent bar only that spouse's student loan interest deduction, or the + whole joint return? + sources: + - kind: statute + citation: 26 U.S.C. 221(c) + url: https://www.law.cornell.edu/uscode/text/26/221#c + - kind: instructions + citation: 2025 Form 1040 instructions, Schedule 1 line 21 (student loan interest deduction) + url: https://www.irs.gov/pub/irs-prior/i1040gi--2025.pdf#page=98 + readings: + statute: Section 221(c) bars only the individual whom another taxpayer claims; the other spouse keeps the deduction + for their own interest. + other: The instructions bar the return if the filer, or the spouse on a joint return, is claimed as a dependent. + example: On a 2025 refund-only joint return, a head with $2,000 wages and $1,000 interest, beside a spouse claimed + elsewhere with $700 interest, deducts $1,000 under the statute and nothing under the instructions. + pe_us: + follows: statute + code: + - policyengine_us/variables/gov/irs/income/taxable_income/adjusted_gross_income/above_the_line_deductions/student_loan_interest/student_loan_interest_ald_eligible.py + prs: + - https://github.com/PolicyEngine/policyengine-us/pull/10577 + state: ruled + note: 'Ruled 2026-10-20 for the statute by the project lead. PE-US bars only the claimed head or spouse + (student_loan_interest_ald_eligible.py); joint MAGI for the section 221(b)(2) phase-out still counts both spouses. + Split from us:education-benefits-joint-claimed-spouse, which keeps the education credits.' - id: us:surviving-spouse-child-gross-income-test program: income-tax years: