File: Mathlib/CategoryTheory/Limits/Shapes/Pullback/Assoc.lean

full_name: CategoryTheory.Limits._aux_Mathlib_CategoryTheory_Limits_Shapes_Pullback_Assoc___unexpand_CategoryTheory_Limits_pullback_1
code: local notation "Z₁" => pullback f₁ f₂
goal: Lean.PrettyPrinter.Unexpander

full_name: CategoryTheory.Limits._aux_Mathlib_CategoryTheory_Limits_Shapes_Pullback_Assoc___macroRules_CategoryTheory_Limits_termZ₁_1
code: local notation "Z₁" => pullback f₁ f₂
goal: Lean.Macro

full_name: CategoryTheory.Limits._aux_Mathlib_CategoryTheory_Limits_Shapes_Pullback_Assoc___macroRules_CategoryTheory_Limits_termZ₂_1
code: local notation "Z₂" => pullback f₃ f₄
goal: Lean.Macro

full_name: CategoryTheory.Limits._aux_Mathlib_CategoryTheory_Limits_Shapes_Pullback_Assoc___unexpand_CategoryTheory_Limits_pullback_2
code: local notation "Z₂" => pullback f₃ f₄
goal: Lean.PrettyPrinter.Unexpander

full_name: CategoryTheory.Limits._aux_Mathlib_CategoryTheory_Limits_Shapes_Pullback_Assoc___macroRules_CategoryTheory_Limits_termG₁_1
code: local notation "g₁" => (pullback.fst _ _ : Z₁ ⟶ X₁)
goal: Lean.Macro

full_name: CategoryTheory.Limits._aux_Mathlib_CategoryTheory_Limits_Shapes_Pullback_Assoc___macroRules_CategoryTheory_Limits_termG₂_1
code: local notation "g₂" => (pullback.snd _ _ : Z₁ ⟶ X₂)
goal: Lean.Macro

full_name: CategoryTheory.Limits._aux_Mathlib_CategoryTheory_Limits_Shapes_Pullback_Assoc___macroRules_CategoryTheory_Limits_termG₃_1
code: local notation "g₃" => (pullback.fst _ _ : Z₂ ⟶ X₂)
goal: Lean.Macro

full_name: CategoryTheory.Limits._aux_Mathlib_CategoryTheory_Limits_Shapes_Pullback_Assoc___macroRules_CategoryTheory_Limits_termG₄_1
code: local notation "g₄" => (pullback.snd _ _ : Z₂ ⟶ X₃)
goal: Lean.Macro

full_name: CategoryTheory.Limits._aux_Mathlib_CategoryTheory_Limits_Shapes_Pullback_Assoc___macroRules_CategoryTheory_Limits_termW_1
code: local notation "W" => pullback (g₂ ≫ f₃) f₄
goal: Lean.Macro

full_name: CategoryTheory.Limits._aux_Mathlib_CategoryTheory_Limits_Shapes_Pullback_Assoc___unexpand_CategoryTheory_Limits_pullback_3
code: local notation "W" => pullback (g₂ ≫ f₃) f₄
goal: Lean.PrettyPrinter.Unexpander

full_name: CategoryTheory.Limits._aux_Mathlib_CategoryTheory_Limits_Shapes_Pullback_Assoc___macroRules_CategoryTheory_Limits_termW'_1
code: local notation "W'" => pullback f₁ (g₃ ≫ f₂)
goal: Lean.Macro

full_name: CategoryTheory.Limits._aux_Mathlib_CategoryTheory_Limits_Shapes_Pullback_Assoc___unexpand_CategoryTheory_Limits_pullback_4
code: local notation "W'" => pullback f₁ (g₃ ≫ f₂)
goal: Lean.PrettyPrinter.Unexpander

full_name: CategoryTheory.Limits._aux_Mathlib_CategoryTheory_Limits_Shapes_Pullback_Assoc___macroRules_CategoryTheory_Limits_termL₁_1
code: local notation "l₁" => (pullback.fst _ _ : W ⟶ Z₁)
goal: Lean.Macro

full_name: CategoryTheory.Limits._aux_Mathlib_CategoryTheory_Limits_Shapes_Pullback_Assoc___macroRules_CategoryTheory_Limits_termL₂_1
code: local notation "l₂" =>
  (pullback.lift (pullback.fst _ _ ≫ g₂) (pullback.snd _ _)
      (Eq.trans (Category.assoc _ _ _) pullback.condition) :
    W ⟶ Z₂)
goal: Lean.Macro

full_name: CategoryTheory.Limits._aux_Mathlib_CategoryTheory_Limits_Shapes_Pullback_Assoc___macroRules_CategoryTheory_Limits_termL₁'_1
code: local notation "l₁'" =>
  (pullback.lift (pullback.fst _ _) (pullback.snd _ _ ≫ g₃)
      (pullback.condition.trans (Eq.symm (Category.assoc _ _ _))) :
    W' ⟶ Z₁)
goal: Lean.Macro

full_name: CategoryTheory.Limits._aux_Mathlib_CategoryTheory_Limits_Shapes_Pullback_Assoc___macroRules_CategoryTheory_Limits_termL₂'_1
code: local notation "l₂'" => (pullback.snd f₁ (g₃ ≫ f₂))
goal: Lean.Macro

full_name: CategoryTheory.Limits.pullbackPullbackLeftIsPullback
code: /-- `(X₁ ×[Y₁] X₂) ×[Y₂] X₃` is the pullback `(X₁ ×[Y₁] X₂) ×[X₂] (X₂ ×[Y₂] X₃)`. -/
def pullbackPullbackLeftIsPullback [HasPullback (g₂ ≫ f₃) f₄] : IsLimit (PullbackCone.mk l₁ l₂
    (show l₁ ≫ g₂ = l₂ ≫ g₃ from (pullback.lift_fst _ _ _).symm)) 
goal: CategoryTheory.Limits.IsLimit
  (CategoryTheory.Limits.PullbackCone.mk
    (CategoryTheory.Limits.pullback.fst (CategoryTheory.Limits.pullback.snd f₁ f₂ ≫ f₃) f₄)
    (CategoryTheory.Limits.pullback.lift
      (CategoryTheory.Limits.pullback.fst (CategoryTheory.Limits.pullback.snd f₁ f₂ ≫ f₃) f₄ ≫
        CategoryTheory.Limits.pullback.snd f₁ f₂)
      (CategoryTheory.Limits.pullback.snd (CategoryTheory.Limits.pullback.snd f₁ f₂ ≫ f₃) f₄) ⋯)
    ⋯)

full_name: CategoryTheory.Limits.pullbackAssocIsPullback
code: /-- `(X₁ ×[Y₁] X₂) ×[Y₂] X₃` is the pullback `X₁ ×[Y₁] (X₂ ×[Y₂] X₃)`. -/
def pullbackAssocIsPullback [HasPullback (g₂ ≫ f₃) f₄] :
    IsLimit
      (PullbackCone.mk (l₁ ≫ g₁) l₂
        (show (l₁ ≫ g₁) ≫ f₁ = l₂ ≫ g₃ ≫ f₂ by
          rw [pullback.lift_fst_assoc, Category.assoc, Category.assoc, pullback.condition])) 
goal: CategoryTheory.Limits.IsLimit
  (CategoryTheory.Limits.PullbackCone.mk
    (CategoryTheory.Limits.pullback.fst (CategoryTheory.Limits.pullback.snd f₁ f₂ ≫ f₃) f₄ ≫
      CategoryTheory.Limits.pullback.fst f₁ f₂)
    (CategoryTheory.Limits.pullback.lift
      (CategoryTheory.Limits.pullback.fst (CategoryTheory.Limits.pullback.snd f₁ f₂ ≫ f₃) f₄ ≫
        CategoryTheory.Limits.pullback.snd f₁ f₂)
      (CategoryTheory.Limits.pullback.snd (CategoryTheory.Limits.pullback.snd f₁ f₂ ≫ f₃) f₄) ⋯)
    ⋯)

full_name: CategoryTheory.Limits.hasPullback_assoc
code: theorem hasPullback_assoc [HasPullback (g₂ ≫ f₃) f₄] : HasPullback f₁ (g₃ ≫ f₂) 
goal: CategoryTheory.Limits.HasPullback f₁ (CategoryTheory.Limits.pullback.fst f₃ f₄ ≫ f₂)

full_name: CategoryTheory.Limits.pullbackPullbackRightIsPullback
code: /-- `X₁ ×[Y₁] (X₂ ×[Y₂] X₃)` is the pullback `(X₁ ×[Y₁] X₂) ×[X₂] (X₂ ×[Y₂] X₃)`. -/
def pullbackPullbackRightIsPullback [HasPullback f₁ (g₃ ≫ f₂)] :
    IsLimit (PullbackCone.mk l₁' l₂' (show l₁' ≫ g₂ = l₂' ≫ g₃ from pullback.lift_snd _ _ _)) 
goal: CategoryTheory.Limits.IsLimit
  (CategoryTheory.Limits.PullbackCone.mk
    (CategoryTheory.Limits.pullback.lift
      (CategoryTheory.Limits.pullback.fst f₁ (CategoryTheory.Limits.pullback.fst f₃ f₄ ≫ f₂))
      (CategoryTheory.Limits.pullback.snd f₁ (CategoryTheory.Limits.pullback.fst f₃ f₄ ≫ f₂) ≫
        CategoryTheory.Limits.pullback.fst f₃ f₄)
      ⋯)
    (CategoryTheory.Limits.pullback.snd f₁ (CategoryTheory.Limits.pullback.fst f₃ f₄ ≫ f₂)) ⋯)

full_name: CategoryTheory.Limits.pullbackAssocSymmIsPullback
code: /-- `X₁ ×[Y₁] (X₂ ×[Y₂] X₃)` is the pullback `(X₁ ×[Y₁] X₂) ×[Y₂] X₃`. -/
def pullbackAssocSymmIsPullback [HasPullback f₁ (g₃ ≫ f₂)] :
    IsLimit
      (PullbackCone.mk l₁' (l₂' ≫ g₄)
        (show l₁' ≫ g₂ ≫ f₃ = (l₂' ≫ g₄) ≫ f₄ by
          rw [pullback.lift_snd_assoc, Category.assoc, Category.assoc, pullback.condition])) 
goal: CategoryTheory.Limits.IsLimit
  (CategoryTheory.Limits.PullbackCone.mk
    (CategoryTheory.Limits.pullback.lift
      (CategoryTheory.Limits.pullback.fst f₁ (CategoryTheory.Limits.pullback.fst f₃ f₄ ≫ f₂))
      (CategoryTheory.Limits.pullback.snd f₁ (CategoryTheory.Limits.pullback.fst f₃ f₄ ≫ f₂) ≫
        CategoryTheory.Limits.pullback.fst f₃ f₄)
      ⋯)
    (CategoryTheory.Limits.pullback.snd f₁ (CategoryTheory.Limits.pullback.fst f₃ f₄ ≫ f₂) ≫
      CategoryTheory.Limits.pullback.snd f₃ f₄)
    ⋯)

full_name: CategoryTheory.Limits.hasPullback_assoc_symm
code: theorem hasPullback_assoc_symm [HasPullback f₁ (g₃ ≫ f₂)] : HasPullback (g₂ ≫ f₃) f₄ 
goal: CategoryTheory.Limits.HasPullback (CategoryTheory.Limits.pullback.snd f₁ f₂ ≫ f₃) f₄

full_name: CategoryTheory.Limits.pullbackAssoc
code: /-- The canonical isomorphism `(X₁ ×[Y₁] X₂) ×[Y₂] X₃ ≅ X₁ ×[Y₁] (X₂ ×[Y₂] X₃)`. -/
noncomputable def pullbackAssoc [HasPullback ((pullback.snd _ _ : Z₁ ⟶ X₂) ≫ f₃) f₄]
    [HasPullback f₁ ((pullback.fst _ _ : Z₂ ⟶ X₂) ≫ f₂)] :
    pullback (pullback.snd _ _ ≫ f₃ : pullback f₁ f₂ ⟶ _) f₄ ≅
      pullback f₁ (pullback.fst _ _ ≫ f₂ : pullback f₃ f₄ ⟶ _) 
goal: CategoryTheory.Limits.pullback (CategoryTheory.Limits.pullback.snd f₁ f₂ ≫ f₃) f₄ ≅
  CategoryTheory.Limits.pullback f₁ (CategoryTheory.Limits.pullback.fst f₃ f₄ ≫ f₂)

full_name: CategoryTheory.Limits.pullbackAssoc_inv_fst_fst
code: @[reassoc (attr := simp)]
theorem pullbackAssoc_inv_fst_fst [HasPullback ((pullback.snd _ _ : Z₁ ⟶ X₂) ≫ f₃) f₄]
    [HasPullback f₁ ((pullback.fst _ _ : Z₂ ⟶ X₂) ≫ f₂)] :
    (pullbackAssoc f₁ f₂ f₃ f₄).inv ≫ pullback.fst _ _ ≫ pullback.fst _ _ = pullback.fst _ _ 
goal: (CategoryTheory.Limits.pullbackAssoc f₁ f₂ f₃ f₄).inv ≫
    CategoryTheory.Limits.pullback.fst (CategoryTheory.Limits.pullback.snd f₁ f₂ ≫ f₃) f₄ ≫
      CategoryTheory.Limits.pullback.fst f₁ f₂ =
  CategoryTheory.Limits.pullback.fst f₁ (CategoryTheory.Limits.pullback.fst f₃ f₄ ≫ f₂)

full_name: CategoryTheory.Limits.pullbackAssoc_hom_fst
code: @[reassoc (attr := simp)]
theorem pullbackAssoc_hom_fst [HasPullback ((pullback.snd _ _ : Z₁ ⟶ X₂) ≫ f₃) f₄]
    [HasPullback f₁ ((pullback.fst _ _ : Z₂ ⟶ X₂) ≫ f₂)] :
    (pullbackAssoc f₁ f₂ f₃ f₄).hom ≫ pullback.fst _ _ = pullback.fst _ _ ≫ pullback.fst _ _ 
goal: (CategoryTheory.Limits.pullbackAssoc f₁ f₂ f₃ f₄).hom ≫
    CategoryTheory.Limits.pullback.fst f₁ (CategoryTheory.Limits.pullback.fst f₃ f₄ ≫ f₂) =
  CategoryTheory.Limits.pullback.fst (CategoryTheory.Limits.pullback.snd f₁ f₂ ≫ f₃) f₄ ≫
    CategoryTheory.Limits.pullback.fst f₁ f₂

full_name: CategoryTheory.Limits.pullbackAssoc_hom_snd_fst
code: @[reassoc (attr := simp)]
theorem pullbackAssoc_hom_snd_fst [HasPullback ((pullback.snd _ _ : Z₁ ⟶ X₂) ≫ f₃) f₄]
    [HasPullback f₁ ((pullback.fst _ _ : Z₂ ⟶ X₂) ≫ f₂)] : (pullbackAssoc f₁ f₂ f₃ f₄).hom ≫
    pullback.snd _ _ ≫ pullback.fst _ _ = pullback.fst _ _ ≫ pullback.snd _ _ 
goal: (CategoryTheory.Limits.pullbackAssoc f₁ f₂ f₃ f₄).hom ≫
    CategoryTheory.Limits.pullback.snd f₁ (CategoryTheory.Limits.pullback.fst f₃ f₄ ≫ f₂) ≫
      CategoryTheory.Limits.pullback.fst f₃ f₄ =
  CategoryTheory.Limits.pullback.fst (CategoryTheory.Limits.pullback.snd f₁ f₂ ≫ f₃) f₄ ≫
    CategoryTheory.Limits.pullback.snd f₁ f₂

full_name: CategoryTheory.Limits.pullbackAssoc_hom_snd_snd
code: @[reassoc (attr := simp)]
theorem pullbackAssoc_hom_snd_snd [HasPullback ((pullback.snd _ _ : Z₁ ⟶ X₂) ≫ f₃) f₄]
    [HasPullback f₁ ((pullback.fst _ _ : Z₂ ⟶ X₂) ≫ f₂)] :
    (pullbackAssoc f₁ f₂ f₃ f₄).hom ≫ pullback.snd _ _ ≫ pullback.snd _ _ = pullback.snd _ _ 
goal: (CategoryTheory.Limits.pullbackAssoc f₁ f₂ f₃ f₄).hom ≫
    CategoryTheory.Limits.pullback.snd f₁ (CategoryTheory.Limits.pullback.fst f₃ f₄ ≫ f₂) ≫
      CategoryTheory.Limits.pullback.snd f₃ f₄ =
  CategoryTheory.Limits.pullback.snd (CategoryTheory.Limits.pullback.snd f₁ f₂ ≫ f₃) f₄

full_name: CategoryTheory.Limits.pullbackAssoc_inv_fst_snd
code: @[reassoc (attr := simp)]
theorem pullbackAssoc_inv_fst_snd [HasPullback ((pullback.snd _ _ : Z₁ ⟶ X₂) ≫ f₃) f₄]
    [HasPullback f₁ ((pullback.fst _ _ : Z₂ ⟶ X₂) ≫ f₂)] :
    (pullbackAssoc f₁ f₂ f₃ f₄).inv ≫ pullback.fst _ _ ≫ pullback.snd _ _ =
    pullback.snd _ _ ≫ pullback.fst _ _ 
goal: (CategoryTheory.Limits.pullbackAssoc f₁ f₂ f₃ f₄).inv ≫
    CategoryTheory.Limits.pullback.fst (CategoryTheory.Limits.pullback.snd f₁ f₂ ≫ f₃) f₄ ≫
      CategoryTheory.Limits.pullback.snd f₁ f₂ =
  CategoryTheory.Limits.pullback.snd f₁ (CategoryTheory.Limits.pullback.fst f₃ f₄ ≫ f₂) ≫
    CategoryTheory.Limits.pullback.fst f₃ f₄

full_name: CategoryTheory.Limits.pullbackAssoc_inv_snd
code: @[reassoc (attr := simp)]
theorem pullbackAssoc_inv_snd [HasPullback ((pullback.snd _ _ : Z₁ ⟶ X₂) ≫ f₃) f₄]
    [HasPullback f₁ ((pullback.fst _ _ : Z₂ ⟶ X₂) ≫ f₂)] :
    (pullbackAssoc f₁ f₂ f₃ f₄).inv ≫ pullback.snd _ _ = pullback.snd _ _ ≫ pullback.snd _ _ 
goal: (CategoryTheory.Limits.pullbackAssoc f₁ f₂ f₃ f₄).inv ≫
    CategoryTheory.Limits.pullback.snd (CategoryTheory.Limits.pullback.snd f₁ f₂ ≫ f₃) f₄ =
  CategoryTheory.Limits.pullback.snd f₁ (CategoryTheory.Limits.pullback.fst f₃ f₄ ≫ f₂) ≫
    CategoryTheory.Limits.pullback.snd f₃ f₄

full_name: CategoryTheory.Limits._aux_Mathlib_CategoryTheory_Limits_Shapes_Pullback_Assoc___unexpand_CategoryTheory_Limits_pushout_1
code: local notation "Y₁" => pushout g₁ g₂
goal: Lean.PrettyPrinter.Unexpander

full_name: CategoryTheory.Limits._aux_Mathlib_CategoryTheory_Limits_Shapes_Pullback_Assoc___macroRules_CategoryTheory_Limits_termY₁_1
code: local notation "Y₁" => pushout g₁ g₂
goal: Lean.Macro

full_name: CategoryTheory.Limits._aux_Mathlib_CategoryTheory_Limits_Shapes_Pullback_Assoc___macroRules_CategoryTheory_Limits_termY₂_1
code: local notation "Y₂" => pushout g₃ g₄
goal: Lean.Macro

full_name: CategoryTheory.Limits._aux_Mathlib_CategoryTheory_Limits_Shapes_Pullback_Assoc___unexpand_CategoryTheory_Limits_pushout_2
code: local notation "Y₂" => pushout g₃ g₄
goal: Lean.PrettyPrinter.Unexpander

full_name: CategoryTheory.Limits._aux_Mathlib_CategoryTheory_Limits_Shapes_Pullback_Assoc___macroRules_CategoryTheory_Limits_termF₁_1
code: local notation "f₁" => (pushout.inl _ _ : X₁ ⟶ Y₁)
goal: Lean.Macro

full_name: CategoryTheory.Limits._aux_Mathlib_CategoryTheory_Limits_Shapes_Pullback_Assoc___macroRules_CategoryTheory_Limits_termF₂_1
code: local notation "f₂" => (pushout.inr _ _ : X₂ ⟶ Y₁)
goal: Lean.Macro

full_name: CategoryTheory.Limits._aux_Mathlib_CategoryTheory_Limits_Shapes_Pullback_Assoc___macroRules_CategoryTheory_Limits_termF₃_1
code: local notation "f₃" => (pushout.inl _ _ : X₂ ⟶ Y₂)
goal: Lean.Macro

full_name: CategoryTheory.Limits._aux_Mathlib_CategoryTheory_Limits_Shapes_Pullback_Assoc___macroRules_CategoryTheory_Limits_termF₄_1
code: local notation "f₄" => (pushout.inr _ _ : X₃ ⟶ Y₂)
goal: Lean.Macro

full_name: CategoryTheory.Limits._aux_Mathlib_CategoryTheory_Limits_Shapes_Pullback_Assoc___macroRules_CategoryTheory_Limits_termW_2
code: local notation "W" => pushout g₁ (g₂ ≫ f₃)
goal: Lean.Macro

full_name: CategoryTheory.Limits._aux_Mathlib_CategoryTheory_Limits_Shapes_Pullback_Assoc___unexpand_CategoryTheory_Limits_pushout_3
code: local notation "W" => pushout g₁ (g₂ ≫ f₃)
goal: Lean.PrettyPrinter.Unexpander

full_name: CategoryTheory.Limits._aux_Mathlib_CategoryTheory_Limits_Shapes_Pullback_Assoc___unexpand_CategoryTheory_Limits_pushout_4
code: local notation "W'" => pushout (g₃ ≫ f₂) g₄
goal: Lean.PrettyPrinter.Unexpander

full_name: CategoryTheory.Limits._aux_Mathlib_CategoryTheory_Limits_Shapes_Pullback_Assoc___macroRules_CategoryTheory_Limits_termW'_2
code: local notation "W'" => pushout (g₃ ≫ f₂) g₄
goal: Lean.Macro

full_name: CategoryTheory.Limits._aux_Mathlib_CategoryTheory_Limits_Shapes_Pullback_Assoc___macroRules_CategoryTheory_Limits_termL₁_2
code: local notation "l₁" =>
  (pushout.desc (pushout.inl _ _) (f₃ ≫ pushout.inr _ _)
    (pushout.condition.trans (Category.assoc _ _ _)) : Y₁ ⟶ W)
goal: Lean.Macro

full_name: CategoryTheory.Limits._aux_Mathlib_CategoryTheory_Limits_Shapes_Pullback_Assoc___macroRules_CategoryTheory_Limits_termL₂_2
code: local notation "l₂" => (pushout.inr _ _ : Y₂ ⟶ W)
goal: Lean.Macro

full_name: CategoryTheory.Limits._aux_Mathlib_CategoryTheory_Limits_Shapes_Pullback_Assoc___macroRules_CategoryTheory_Limits_termL₁'_2
code: local notation "l₁'" => (pushout.inl _ _ : Y₁ ⟶ W')
goal: Lean.Macro

full_name: CategoryTheory.Limits._aux_Mathlib_CategoryTheory_Limits_Shapes_Pullback_Assoc___macroRules_CategoryTheory_Limits_termL₂'_2
code: local notation "l₂'" =>
  (pushout.desc (f₂ ≫ pushout.inl _ _) (pushout.inr _ _)
      (Eq.trans (Eq.symm (Category.assoc _ _ _)) pushout.condition) :
    Y₂ ⟶ W')
goal: Lean.Macro

full_name: CategoryTheory.Limits.pushoutPushoutLeftIsPushout
code: /-- `(X₁ ⨿[Z₁] X₂) ⨿[Z₂] X₃` is the pushout `(X₁ ⨿[Z₁] X₂) ×[X₂] (X₂ ⨿[Z₂] X₃)`. -/
def pushoutPushoutLeftIsPushout [HasPushout (g₃ ≫ f₂) g₄] :
    IsColimit
      (PushoutCocone.mk l₁' l₂' (show f₂ ≫ l₁' = f₃ ≫ l₂' from (pushout.inl_desc _ _ _).symm)) 
goal: CategoryTheory.Limits.IsColimit
  (CategoryTheory.Limits.PushoutCocone.mk
    (CategoryTheory.Limits.pushout.inl (g₃ ≫ CategoryTheory.Limits.pushout.inr g₁ g₂) g₄)
    (CategoryTheory.Limits.pushout.desc
      (CategoryTheory.Limits.pushout.inr g₁ g₂ ≫
        CategoryTheory.Limits.pushout.inl (g₃ ≫ CategoryTheory.Limits.pushout.inr g₁ g₂) g₄)
      (CategoryTheory.Limits.pushout.inr (g₃ ≫ CategoryTheory.Limits.pushout.inr g₁ g₂) g₄) ⋯)
    ⋯)

full_name: CategoryTheory.Limits.pushoutAssocIsPushout
code: /-- `(X₁ ⨿[Z₁] X₂) ⨿[Z₂] X₃` is the pushout `X₁ ⨿[Z₁] (X₂ ⨿[Z₂] X₃)`. -/
def pushoutAssocIsPushout [HasPushout (g₃ ≫ f₂) g₄] :
    IsColimit
      (PushoutCocone.mk (f₁ ≫ l₁') l₂'
        (show g₁ ≫ f₁ ≫ l₁' = (g₂ ≫ f₃) ≫ l₂' by
          rw [Category.assoc, pushout.inl_desc, pushout.condition_assoc])) 
goal: CategoryTheory.Limits.IsColimit
  (CategoryTheory.Limits.PushoutCocone.mk
    (CategoryTheory.Limits.pushout.inl g₁ g₂ ≫
      CategoryTheory.Limits.pushout.inl (g₃ ≫ CategoryTheory.Limits.pushout.inr g₁ g₂) g₄)
    (CategoryTheory.Limits.pushout.desc
      (CategoryTheory.Limits.pushout.inr g₁ g₂ ≫
        CategoryTheory.Limits.pushout.inl (g₃ ≫ CategoryTheory.Limits.pushout.inr g₁ g₂) g₄)
      (CategoryTheory.Limits.pushout.inr (g₃ ≫ CategoryTheory.Limits.pushout.inr g₁ g₂) g₄) ⋯)
    ⋯)

full_name: CategoryTheory.Limits.hasPushout_assoc
code: theorem hasPushout_assoc [HasPushout (g₃ ≫ f₂) g₄] : HasPushout g₁ (g₂ ≫ f₃) 
goal: CategoryTheory.Limits.HasPushout g₁ (g₂ ≫ CategoryTheory.Limits.pushout.inl g₃ g₄)

full_name: CategoryTheory.Limits.pushoutPushoutRightIsPushout
code: /-- `X₁ ⨿[Z₁] (X₂ ⨿[Z₂] X₃)` is the pushout `(X₁ ⨿[Z₁] X₂) ×[X₂] (X₂ ⨿[Z₂] X₃)`. -/
def pushoutPushoutRightIsPushout [HasPushout g₁ (g₂ ≫ f₃)] :
    IsColimit (PushoutCocone.mk l₁ l₂ (show f₂ ≫ l₁ = f₃ ≫ l₂ from pushout.inr_desc _ _ _)) 
goal: CategoryTheory.Limits.IsColimit
  (CategoryTheory.Limits.PushoutCocone.mk
    (CategoryTheory.Limits.pushout.desc
      (CategoryTheory.Limits.pushout.inl g₁ (g₂ ≫ CategoryTheory.Limits.pushout.inl g₃ g₄))
      (CategoryTheory.Limits.pushout.inl g₃ g₄ ≫
        CategoryTheory.Limits.pushout.inr g₁ (g₂ ≫ CategoryTheory.Limits.pushout.inl g₃ g₄))
      ⋯)
    (CategoryTheory.Limits.pushout.inr g₁ (g₂ ≫ CategoryTheory.Limits.pushout.inl g₃ g₄)) ⋯)

full_name: CategoryTheory.Limits.pushoutAssocSymmIsPushout
code: /-- `X₁ ⨿[Z₁] (X₂ ⨿[Z₂] X₃)` is the pushout `(X₁ ⨿[Z₁] X₂) ⨿[Z₂] X₃`. -/
def pushoutAssocSymmIsPushout [HasPushout g₁ (g₂ ≫ f₃)] :
    IsColimit
      (PushoutCocone.mk l₁ (f₄ ≫ l₂)
        (show (g₃ ≫ f₂) ≫ l₁ = g₄ ≫ f₄ ≫ l₂ by
          rw [Category.assoc, pushout.inr_desc, pushout.condition_assoc])) 
goal: CategoryTheory.Limits.IsColimit
  (CategoryTheory.Limits.PushoutCocone.mk
    (CategoryTheory.Limits.pushout.desc
      (CategoryTheory.Limits.pushout.inl g₁ (g₂ ≫ CategoryTheory.Limits.pushout.inl g₃ g₄))
      (CategoryTheory.Limits.pushout.inl g₃ g₄ ≫
        CategoryTheory.Limits.pushout.inr g₁ (g₂ ≫ CategoryTheory.Limits.pushout.inl g₃ g₄))
      ⋯)
    (CategoryTheory.Limits.pushout.inr g₃ g₄ ≫
      CategoryTheory.Limits.pushout.inr g₁ (g₂ ≫ CategoryTheory.Limits.pushout.inl g₃ g₄))
    ⋯)

full_name: CategoryTheory.Limits.hasPushout_assoc_symm
code: theorem hasPushout_assoc_symm [HasPushout g₁ (g₂ ≫ f₃)] : HasPushout (g₃ ≫ f₂) g₄ 
goal: CategoryTheory.Limits.HasPushout (g₃ ≫ CategoryTheory.Limits.pushout.inr g₁ g₂) g₄

full_name: CategoryTheory.Limits.pushoutAssoc
code: /-- The canonical isomorphism `(X₁ ⨿[Z₁] X₂) ⨿[Z₂] X₃ ≅ X₁ ⨿[Z₁] (X₂ ⨿[Z₂] X₃)`. -/
noncomputable def pushoutAssoc [HasPushout (g₃ ≫ (pushout.inr _ _ : X₂ ⟶ Y₁)) g₄]
    [HasPushout g₁ (g₂ ≫ (pushout.inl _ _ : X₂ ⟶ Y₂))] :
    pushout (g₃ ≫ pushout.inr _ _ : _ ⟶ pushout g₁ g₂) g₄ ≅
      pushout g₁ (g₂ ≫ pushout.inl _ _ : _ ⟶ pushout g₃ g₄) 
goal: CategoryTheory.Limits.pushout (g₃ ≫ CategoryTheory.Limits.pushout.inr g₁ g₂) g₄ ≅
  CategoryTheory.Limits.pushout g₁ (g₂ ≫ CategoryTheory.Limits.pushout.inl g₃ g₄)

full_name: CategoryTheory.Limits.inl_inl_pushoutAssoc_hom
code: @[reassoc (attr := simp)]
theorem inl_inl_pushoutAssoc_hom [HasPushout (g₃ ≫ (pushout.inr _ _ : X₂ ⟶ Y₁)) g₄]
    [HasPushout g₁ (g₂ ≫ (pushout.inl _ _ : X₂ ⟶ Y₂))] :
    pushout.inl _ _ ≫ pushout.inl _ _ ≫ (pushoutAssoc g₁ g₂ g₃ g₄).hom = pushout.inl _ _ 
goal: CategoryTheory.Limits.pushout.inl g₁ g₂ ≫
    CategoryTheory.Limits.pushout.inl (g₃ ≫ CategoryTheory.Limits.pushout.inr g₁ g₂) g₄ ≫
      (CategoryTheory.Limits.pushoutAssoc g₁ g₂ g₃ g₄).hom =
  CategoryTheory.Limits.pushout.inl g₁ (g₂ ≫ CategoryTheory.Limits.pushout.inl g₃ g₄)

full_name: CategoryTheory.Limits.inr_inl_pushoutAssoc_hom
code: @[reassoc (attr := simp)]
theorem inr_inl_pushoutAssoc_hom [HasPushout (g₃ ≫ (pushout.inr _ _ : X₂ ⟶ Y₁)) g₄]
    [HasPushout g₁ (g₂ ≫ (pushout.inl _ _ : X₂ ⟶ Y₂))] :
    pushout.inr _ _ ≫ pushout.inl _ _ ≫ (pushoutAssoc g₁ g₂ g₃ g₄).hom =
      pushout.inl _ _ ≫ pushout.inr _ _ 
goal: CategoryTheory.Limits.pushout.inr g₁ g₂ ≫
    CategoryTheory.Limits.pushout.inl (g₃ ≫ CategoryTheory.Limits.pushout.inr g₁ g₂) g₄ ≫
      (CategoryTheory.Limits.pushoutAssoc g₁ g₂ g₃ g₄).hom =
  CategoryTheory.Limits.pushout.inl g₃ g₄ ≫
    CategoryTheory.Limits.pushout.inr g₁ (g₂ ≫ CategoryTheory.Limits.pushout.inl g₃ g₄)

full_name: CategoryTheory.Limits.inr_inr_pushoutAssoc_inv
code: @[reassoc (attr := simp)]
theorem inr_inr_pushoutAssoc_inv [HasPushout (g₃ ≫ (pushout.inr _ _ : X₂ ⟶ Y₁)) g₄]
    [HasPushout g₁ (g₂ ≫ (pushout.inl _ _ : X₂ ⟶ Y₂))] :
    pushout.inr _ _ ≫ pushout.inr _ _ ≫ (pushoutAssoc g₁ g₂ g₃ g₄).inv = pushout.inr _ _ 
goal: CategoryTheory.Limits.pushout.inr g₃ g₄ ≫
    CategoryTheory.Limits.pushout.inr g₁ (g₂ ≫ CategoryTheory.Limits.pushout.inl g₃ g₄) ≫
      (CategoryTheory.Limits.pushoutAssoc g₁ g₂ g₃ g₄).inv =
  CategoryTheory.Limits.pushout.inr (g₃ ≫ CategoryTheory.Limits.pushout.inr g₁ g₂) g₄

full_name: CategoryTheory.Limits.inl_pushoutAssoc_inv
code: @[reassoc (attr := simp)]
theorem inl_pushoutAssoc_inv [HasPushout (g₃ ≫ (pushout.inr _ _ : X₂ ⟶ Y₁)) g₄]
    [HasPushout g₁ (g₂ ≫ (pushout.inl _ _ : X₂ ⟶ Y₂))] :
    pushout.inl _ _ ≫ (pushoutAssoc g₁ g₂ g₃ g₄).inv = pushout.inl _ _ ≫ pushout.inl _ _ 
goal: CategoryTheory.Limits.pushout.inl g₁ (g₂ ≫ CategoryTheory.Limits.pushout.inl g₃ g₄) ≫
    (CategoryTheory.Limits.pushoutAssoc g₁ g₂ g₃ g₄).inv =
  CategoryTheory.Limits.pushout.inl g₁ g₂ ≫
    CategoryTheory.Limits.pushout.inl (g₃ ≫ CategoryTheory.Limits.pushout.inr g₁ g₂) g₄

full_name: CategoryTheory.Limits.inl_inr_pushoutAssoc_inv
code: @[reassoc (attr := simp)]
theorem inl_inr_pushoutAssoc_inv [HasPushout (g₃ ≫ (pushout.inr _ _ : X₂ ⟶ Y₁)) g₄]
    [HasPushout g₁ (g₂ ≫ (pushout.inl _ _ : X₂ ⟶ Y₂))] :
    pushout.inl _ _ ≫ pushout.inr _ _ ≫ (pushoutAssoc g₁ g₂ g₃ g₄).inv =
      pushout.inr _ _ ≫ pushout.inl _ _ 
goal: CategoryTheory.Limits.pushout.inl g₃ g₄ ≫
    CategoryTheory.Limits.pushout.inr g₁ (g₂ ≫ CategoryTheory.Limits.pushout.inl g₃ g₄) ≫
      (CategoryTheory.Limits.pushoutAssoc g₁ g₂ g₃ g₄).inv =
  CategoryTheory.Limits.pushout.inr g₁ g₂ ≫
    CategoryTheory.Limits.pushout.inl (g₃ ≫ CategoryTheory.Limits.pushout.inr g₁ g₂) g₄

full_name: CategoryTheory.Limits.inr_pushoutAssoc_hom
code: @[reassoc (attr := simp)]
theorem inr_pushoutAssoc_hom [HasPushout (g₃ ≫ (pushout.inr _ _ : X₂ ⟶ Y₁)) g₄]
    [HasPushout g₁ (g₂ ≫ (pushout.inl _ _ : X₂ ⟶ Y₂))] :
    pushout.inr _ _ ≫ (pushoutAssoc g₁ g₂ g₃ g₄).hom = pushout.inr _ _ ≫ pushout.inr _ _ 
goal: CategoryTheory.Limits.pushout.inr (g₃ ≫ CategoryTheory.Limits.pushout.inr g₁ g₂) g₄ ≫
    (CategoryTheory.Limits.pushoutAssoc g₁ g₂ g₃ g₄).hom =
  CategoryTheory.Limits.pushout.inr g₃ g₄ ≫
    CategoryTheory.Limits.pushout.inr g₁ (g₂ ≫ CategoryTheory.Limits.pushout.inl g₃ g₄)