/-- If a finset has cardinality larger than `finrank + 1`,
then there is a nontrivial linear relation amongst its elements,
such that the coefficients of the relation sum to zero.
-/
-- TODO: golf this
theorem Module.exists_nontrivial_relation_sum_zero_of_finrank_succ_lt_card [Module.Finite R V]
    {t : Finset V} (h : finrank R V + 1 < t.card) :
    ∃ f : V → R, ∑ e in t, f e • e = 0 ∧ ∑ e in t, f e = 0 ∧ ∃ x ∈ t, f x ≠ 0 := by
  classical
  -- Pick an element x₀ ∈ t,
  have card_pos : 0 < t.card := lt_trans (Nat.succ_pos _) h
  obtain ⟨x₀, m⟩ := (Finset.card_pos.1 card_pos).bex
  -- and apply the previous lemma to the {xᵢ - x₀}
  let shift : V ↪ V := ⟨fun x => x - x₀, sub_left_injective⟩
  let t' := (t.erase x₀).map shift
  have h' : finrank R V < t'.card := by
    simp only [card_map, Finset.card_erase_of_mem m]
    exact Nat.lt_pred_iff.mpr h
  -- to obtain a function `g`.
  obtain ⟨g, gsum, x₁, x₁_mem, nz⟩ := exists_nontrivial_relation_of_finrank_lt_card h'
  -- Then obtain `f` by translating back by `x₀`,
  -- and setting the value of `f` at `x₀` to ensure `∑ e in t, f e = 0`.
  let f : V → R := fun z => if z = x₀ then -∑ z in t.erase x₀, g (z - x₀) else g (z - x₀)
  refine' ⟨f, _, _, _⟩
  -- After this, it's a matter of verifying the properties,
  -- based on the corresponding properties for `g`.
  · show (∑ e : V in t, f e • e) = 0
    -- We prove this by splitting off the `x₀` term of the sum,
    -- which is itself a sum over `t.erase x₀`,
    -- combining the two sums, and
    -- observing that after reindexing we have exactly
    -- ∑ (x : V) in t', g x • x = 0.
    simp only
    conv_lhs =>
      apply_congr
      rfl
      rw [ite_smul]
    rw [Finset.sum_ite]
    conv =>
      congr
      congr
      apply_congr
      -- Porting note: the next two steps used to work by `simp [filter_eq', m]`
      erw [filter_eq']
      simp [m]
    conv =>
      congr
      congr
      rfl
      apply_congr
      simp [filter_ne']
    rw [sum_singleton, neg_smul, add_comm, ← sub_eq_add_neg, sum_smul, ← sum_sub_distrib]
    simp only [← smul_sub]
    -- At the end we have to reindex the sum, so we use `change` to
    -- express the summand using `shift`.
    change (∑ x : V in t.erase x₀, (fun e => g e • e) (shift x)) = 0
    -- porting note: last argument can't be inferred
    rw [← sum_map _ shift (fun e => g e • e)]
    exact gsum
  · show (∑ e : V in t, f e) = 0
    -- Again we split off the `x₀` term,
    -- observing that it exactly cancels the other terms.
    rw [← insert_erase m, sum_insert (not_mem_erase x₀ t)]
    dsimp
    rw [if_pos rfl]
    conv_lhs =>
      congr
      rfl
      apply_congr
      

Proof state:
case a.h
R : Type u
M : Type v
N : Type w
V : Type v
inst✝⁶ : AddCommGroup V
V₂ : Type v'
inst✝⁵ : AddCommGroup V₂
inst✝⁴ : Ring R
inst✝³ : StrongRankCondition R
inst✝² : Module R V
inst✝¹ : Free R V
K : ?m.334640
inst✝ : Finite R V
t : Finset V
h : finrank R V + 1 < Finset.card t
card_pos : 0 < Finset.card t
x₀ : V
m : x₀ ∈ t
shift : V ↪ V := { toFun := fun x => x - x₀, inj' := (_ : Injective fun a => a - x₀) }
t' : Finset V := Finset.map shift (erase t x₀)
h' : finrank R V < Finset.card t'
g : V → R
gsum : ∑ e in t', g e • e = 0
x₁ : V
x₁_mem : x₁ ∈ t'
nz : g x₁ ≠ 0
f : V → R := fun z => if z = x₀ then -∑ z in erase t x₀, g (z - x₀) else g (z - x₀)
⊢ erase t x₀ = ?a.s₂
case a.a
R : Type u
M : Type v
N : Type w
V : Type v
inst✝⁶ : AddCommGroup V
V₂ : Type v'
inst✝⁵ : AddCommGroup V₂
inst✝⁴ : Ring R
inst✝³ : StrongRankCondition R
inst✝² : Module R V
inst✝¹ : Free R V
K : ?m.334640
inst✝ : Finite R V
t : Finset V
h : finrank R V + 1 < Finset.card t
card_pos : 0 < Finset.card t
x₀ : V
m : x₀ ∈ t
shift : V ↪ V := { toFun := fun x => x - x₀, inj' := (_ : Injective fun a => a - x₀) }
t' : Finset V := Finset.map shift (erase t x₀)
h' : finrank R V < Finset.card t'
g : V → R
gsum : ∑ e in t', g e • e = 0
x₁ : V
x₁_mem : x₁ ∈ t'
nz : g x₁ ≠ 0
f : V → R := fun z => if z = x₀ then -∑ z in erase t x₀, g (z - x₀) else g (z - x₀)
x✝ : V
a✝ : x✝ ∈ ?a.s₂
⊢ (if x✝ = x₀ then -∑ z in erase t x₀, g (z - x₀) else g (x✝ - x₀)) = ?a.g x✝

Next tactic:
rfl