Simon Jakobi pushed to branch wip/sjakobi/multi-caret at Glasgow Haskell Compiler / GHC

Commits:

11 changed files:

Changes:

  • compiler/GHC/Driver/Errors.hs
    ... ... @@ -15,7 +15,7 @@ import GHC.Utils.Json
    15 15
     import GHC.Utils.Error
    
    16 16
     import GHC.Utils.Outputable
    
    17 17
     import GHC.Utils.Logger
    
    18
    -import Data.List.NonEmpty (NonEmpty(..))
    
    18
    +import Data.List.NonEmpty (NonEmpty(..), nub)
    
    19 19
     
    
    20 20
     reportError :: Logger -> NamePprCtx -> DiagOpts -> SrcSpan -> SDoc -> IO ()
    
    21 21
     reportError logger nameContext opts span doc = do
    
    ... ... @@ -85,7 +85,7 @@ printMessage logger msg_opts opts message
    85 85
         relatedSpans = diagnosticRelatedLocations diagnostic
    
    86 86
     
    
    87 87
         sourceSpans :: NonEmpty SrcSpan
    
    88
    -    sourceSpans = location :| relatedSpans
    
    88
    +    sourceSpans = nub (location :| relatedSpans)
    
    89 89
     
    
    90 90
         severity :: Severity
    
    91 91
         severity = errMsgSeverity message
    

  • compiler/GHC/Tc/Errors/Ppr.hs
    ... ... @@ -3470,8 +3470,305 @@ instance Diagnostic TcRnMessage where
    3470 3470
           -> [getLocA lie2]
    
    3471 3471
         TcRnDuplicateNamedDefaultExport _ _lie1 lie2
    
    3472 3472
           -> [getLocA lie2]
    
    3473
    -    _ ->
    
    3474
    -      []
    
    3473
    +    -- The remaining constructors have no related locations (yet). They are listed
    
    3474
    +    -- explicitly (rather than matched with a wildcard) so that adding a new
    
    3475
    +    -- constructor produces an incomplete-patterns warning here, prompting
    
    3476
    +    -- whoever adds it to consider whether it has related locations.
    
    3477
    +    TcRnInterfaceError{} -> []
    
    3478
    +    TcRnSolverReport{} -> []
    
    3479
    +    TcRnSolverDepthError{} -> []
    
    3480
    +    TcRnRedundantConstraints{} -> []
    
    3481
    +    TcRnInaccessibleCode{} -> []
    
    3482
    +    TcRnInaccessibleCoAxBranch{} -> []
    
    3483
    +    TcRnTypeDoesNotHaveFixedRuntimeRep{} -> []
    
    3484
    +    TcRnImplicitLift{} -> []
    
    3485
    +    TcRnUnusedPatternBinds{} -> []
    
    3486
    +    TcRnUnusedQuantifiedTypeVar{} -> []
    
    3487
    +    TcRnDodgyImports{} -> []
    
    3488
    +    TcRnDodgyExports{} -> []
    
    3489
    +    TcRnMissingImportList{} -> []
    
    3490
    +    TcRnUnsafeDueToPlugin{} -> []
    
    3491
    +    TcRnModMissingRealSrcSpan{} -> []
    
    3492
    +    TcRnIdNotExportedFromModuleSig{} -> []
    
    3493
    +    TcRnIdNotExportedFromLocalSig{} -> []
    
    3494
    +    TcRnShadowedName{} -> []
    
    3495
    +    TcRnInvalidWarningCategory{} -> []
    
    3496
    +    TcRnDuplicateWarningDecls{} -> []
    
    3497
    +    TcRnSimplifierTooManyIterations{} -> []
    
    3498
    +    TcRnIllegalPatSynDecl{} -> []
    
    3499
    +    TcRnLinearPatSyn{} -> []
    
    3500
    +    TcRnEmptyRecordUpdate{} -> []
    
    3501
    +    TcRnIllegalFieldPunning{} -> []
    
    3502
    +    TcRnIllegalWildcardsInRecord{} -> []
    
    3503
    +    TcRnIllegalWildcardInType{} -> []
    
    3504
    +    TcRnIllegalNamedWildcardInTypeArgument{} -> []
    
    3505
    +    TcRnIllegalImplicitTyVarInTypeArgument{} -> []
    
    3506
    +    TcRnIllegalPunnedVarOccInTypeArgument{} -> []
    
    3507
    +    TcRnDuplicateFieldName{} -> []
    
    3508
    +    TcRnIllegalViewPattern{} -> []
    
    3509
    +    TcRnCharLiteralOutOfRange{} -> []
    
    3510
    +    TcRnNegativeNumTypeLiteral{} -> []
    
    3511
    +    TcRnIllegalWildcardsInConstructor{} -> []
    
    3512
    +    TcRnIgnoringAnnotations{} -> []
    
    3513
    +    TcRnAnnotationInSafeHaskell{} -> []
    
    3514
    +    TcRnInvalidTypeApplication{} -> []
    
    3515
    +    TcRnTagToEnumMissingValArg{} -> []
    
    3516
    +    TcRnTagToEnumUnspecifiedResTy{} -> []
    
    3517
    +    TcRnTagToEnumResTyNotAnEnum{} -> []
    
    3518
    +    TcRnTagToEnumResTyTypeData{} -> []
    
    3519
    +    TcRnArrowIfThenElsePredDependsOnResultTy{} -> []
    
    3520
    +    TcRnIllegalHsBootOrSigDecl{} -> []
    
    3521
    +    TcRnBootMismatch{} -> []
    
    3522
    +    TcRnRecursivePatternSynonym{} -> []
    
    3523
    +    TcRnPartialTypeSigTyVarMismatch{} -> []
    
    3524
    +    TcRnPartialTypeSigBadQuantifier{} -> []
    
    3525
    +    TcRnMissingSignature{} -> []
    
    3526
    +    TcRnPolymorphicBinderMissingSig{} -> []
    
    3527
    +    TcRnOverloadedSig{} -> []
    
    3528
    +    TcRnTupleConstraintInst{} -> []
    
    3529
    +    TcRnUserTypeError{} -> []
    
    3530
    +    TcRnConstraintInKind{} -> []
    
    3531
    +    TcRnUnboxedTupleOrSumTypeFuncArg{} -> []
    
    3532
    +    TcRnLinearFuncInKind{} -> []
    
    3533
    +    TcRnForAllEscapeError{} -> []
    
    3534
    +    TcRnVDQInTermType{} -> []
    
    3535
    +    TcRnBadQuantPredHead{} -> []
    
    3536
    +    TcRnIllegalTupleConstraint{} -> []
    
    3537
    +    TcRnNonTypeVarArgInConstraint{} -> []
    
    3538
    +    TcRnIllegalImplicitParam{} -> []
    
    3539
    +    TcRnIllegalConstraintSynonymOfKind{} -> []
    
    3540
    +    TcRnOversaturatedVisibleKindArg{} -> []
    
    3541
    +    TcRnForAllRankErr{} -> []
    
    3542
    +    TcRnSimplifiableConstraint{} -> []
    
    3543
    +    TcRnArityMismatch{} -> []
    
    3544
    +    TcRnIllegalInstance{} -> []
    
    3545
    +    TcRnMonomorphicBindings{} -> []
    
    3546
    +    TcRnOrphanInstance{} -> []
    
    3547
    +    TcRnFunDepConflict{} -> []
    
    3548
    +    TcRnDupInstanceDecls{} -> []
    
    3549
    +    TcRnConflictingFamInstDecls{} -> []
    
    3550
    +    TcRnFamInstNotInjective{} -> []
    
    3551
    +    TcRnBangOnUnliftedType{} -> []
    
    3552
    +    TcRnLazyBangOnUnliftedType{} -> []
    
    3553
    +    TcRnMultipleDefaultDeclarations{} -> []
    
    3554
    +    TcRnWarnClashingDefaultImports{} -> []
    
    3555
    +    TcRnBadDefaultType{} -> []
    
    3556
    +    TcRnPatSynBundledWithNonDataCon{} -> []
    
    3557
    +    TcRnPatSynBundledWithWrongType{} -> []
    
    3558
    +    TcRnDupeModuleExport{} -> []
    
    3559
    +    TcRnDupeWildcardExport{} -> []
    
    3560
    +    TcRnExportedModNotImported{} -> []
    
    3561
    +    TcRnMissingExportList{} -> []
    
    3562
    +    TcRnExportHiddenDefault{} -> []
    
    3563
    +    TcRnExportedParentChildMismatch{} -> []
    
    3564
    +    TcRnExportedSubordinateNotFound{} -> []
    
    3565
    +    TcRnConflictingExports{} -> []
    
    3566
    +    TcRnDuplicateFieldExport{} -> []
    
    3567
    +    TcRnAmbiguousRecordUpdate{} -> []
    
    3568
    +    TcRnMissingFields{} -> []
    
    3569
    +    TcRnFieldUpdateInvalidType{} -> []
    
    3570
    +    TcRnMissingStrictFields{} -> []
    
    3571
    +    TcRnAmbiguousFieldInUpdate{} -> []
    
    3572
    +    TcRnBadRecordUpdate{} -> []
    
    3573
    +    TcRnStaticFormNotClosed{} -> []
    
    3574
    +    TcRnUselessTypeable{} -> []
    
    3575
    +    TcRnDerivingDefaults{} -> []
    
    3576
    +    TcRnNonUnaryTypeclassConstraint{} -> []
    
    3577
    +    TcRnPartialTypeSignatures{} -> []
    
    3578
    +    TcRnCannotDeriveInstance{} -> []
    
    3579
    +    TcRnLazyGADTPattern{} -> []
    
    3580
    +    TcRnArrowProcGADTPattern{} -> []
    
    3581
    +    TcRnCapturedTermName{} -> []
    
    3582
    +    TcRnTypeEqualityOutOfScope{} -> []
    
    3583
    +    TcRnTypeEqualityRequiresOperators{} -> []
    
    3584
    +    TcRnIllegalTypeOperator{} -> []
    
    3585
    +    TcRnIllegalTypeOperatorDecl{} -> []
    
    3586
    +    TcRnGADTMonoLocalBinds{} -> []
    
    3587
    +    TcRnNotInScope{} -> []
    
    3588
    +    TcRnTermNameInType{} -> []
    
    3589
    +    TcRnUntickedPromotedThing{} -> []
    
    3590
    +    TcRnIllegalBuiltinSyntax{} -> []
    
    3591
    +    TcRnWarnDefaulting{} -> []
    
    3592
    +    TcRnIncorrectNameSpace{} -> []
    
    3593
    +    TcRnForeignImportPrimExtNotSet{} -> []
    
    3594
    +    TcRnForeignImportPrimSafeAnn{} -> []
    
    3595
    +    TcRnForeignFunctionImportAsValue{} -> []
    
    3596
    +    TcRnFunPtrImportWithoutAmpersand{} -> []
    
    3597
    +    TcRnIllegalForeignDeclBackend{} -> []
    
    3598
    +    TcRnUnsupportedCallConv{} -> []
    
    3599
    +    TcRnIllegalForeignType{} -> []
    
    3600
    +    TcRnInvalidCIdentifier{} -> []
    
    3601
    +    TcRnExpectedValueId{} -> []
    
    3602
    +    TcRnRecSelectorEscapedTyVar{} -> []
    
    3603
    +    TcRnPatSynNotBidirectional{} -> []
    
    3604
    +    TcRnIllegalDerivingItem{} -> []
    
    3605
    +    TcRnIllegalDefaultClass{} -> []
    
    3606
    +    TcRnIllegalNamedDefault{} -> []
    
    3607
    +    TcRnUnexpectedAnnotation{} -> []
    
    3608
    +    TcRnIllegalRecordSyntax{} -> []
    
    3609
    +    TcRnInvalidVisibleKindArgument{} -> []
    
    3610
    +    TcRnTooManyBinders{} -> []
    
    3611
    +    TcRnDifferentNamesForTyVar{} -> []
    
    3612
    +    TcRnDisconnectedTyVar{} -> []
    
    3613
    +    TcRnInvalidReturnKind{} -> []
    
    3614
    +    TcRnUnexpectedKindVar{} -> []
    
    3615
    +    TcRnIllegalKind{} -> []
    
    3616
    +    TcRnClassKindNotConstraint{} -> []
    
    3617
    +    TcRnUnpromotableThing{} -> []
    
    3618
    +    TcRnUnpromotableLit{} -> []
    
    3619
    +    TcRnIllegalTermLevelUse{} -> []
    
    3620
    +    TcRnMatchesHaveDiffNumArgs{} -> []
    
    3621
    +    TcRnUnexpectedPatSigType{} -> []
    
    3622
    +    TcRnDataKindsError{} -> []
    
    3623
    +    TcRnCannotBindScopedTyVarInPatSig{} -> []
    
    3624
    +    TcRnCannotBindTyVarsInPatBind{} -> []
    
    3625
    +    TcRnMultipleInlinePragmas{} -> []
    
    3626
    +    TcRnUnexpectedPragmas{} -> []
    
    3627
    +    TcRnNonOverloadedSpecialisePragma{} -> []
    
    3628
    +    TcRnSpecialiseNotVisible{} -> []
    
    3629
    +    TcRnPragmaWarning{} -> []
    
    3630
    +    TcRnDifferentExportWarnings{} -> []
    
    3631
    +    TcRnIncompleteExportWarnings{} -> []
    
    3632
    +    TcRnIllegalHsigDefaultMethods{} -> []
    
    3633
    +    TcRnHsigFixityMismatch{} -> []
    
    3634
    +    TcRnHsigShapeMismatch{} -> []
    
    3635
    +    TcRnHsigMissingModuleExport{} -> []
    
    3636
    +    TcRnBadGenericMethod{} -> []
    
    3637
    +    TcRnWarningMinimalDefIncomplete{} -> []
    
    3638
    +    TcRnIllegalQuasiQuotes{} -> []
    
    3639
    +    TcRnTHError{} -> []
    
    3640
    +    TcRnDefaultMethodForPragmaLacksBinding{} -> []
    
    3641
    +    TcRnIgnoreSpecialisePragmaOnDefMethod{} -> []
    
    3642
    +    TcRnBadMethodErr{} -> []
    
    3643
    +    TcRnIllegalNewtype{} -> []
    
    3644
    +    TcRnIllegalTypeData{} -> []
    
    3645
    +    TcRnTypeDataForbids{} -> []
    
    3646
    +    TcRnOrPatBindsVariables{} -> []
    
    3647
    +    TcRnUnsatisfiedMinimalDef{} -> []
    
    3648
    +    TcRnMisplacedInstSig{} -> []
    
    3649
    +    TcRnNoRebindableSyntaxRecordDot{} -> []
    
    3650
    +    TcRnNoFieldPunsRecordDot{} -> []
    
    3651
    +    TcRnIllegalStaticExpression{} -> []
    
    3652
    +    TcRnListComprehensionDuplicateBinding{} -> []
    
    3653
    +    TcRnEmptyStmtsGroup{} -> []
    
    3654
    +    TcRnLastStmtNotExpr{} -> []
    
    3655
    +    TcRnUnexpectedStatementInContext{} -> []
    
    3656
    +    TcRnIllegalTupleSection{} -> []
    
    3657
    +    TcRnIllegalImplicitParameterBindings{} -> []
    
    3658
    +    TcRnSectionWithoutParentheses{} -> []
    
    3659
    +    TcRnBindingOfExistingName{} -> []
    
    3660
    +    TcRnMultipleFixityDecls{} -> []
    
    3661
    +    TcRnIllegalPatternSynonymDecl{} -> []
    
    3662
    +    TcRnIllegalClassBinding{} -> []
    
    3663
    +    TcRnOrphanCompletePragma{} -> []
    
    3664
    +    TcRnEmptyCase{} -> []
    
    3665
    +    TcRnNonStdGuards{} -> []
    
    3666
    +    TcRnDuplicateSigDecl{} -> []
    
    3667
    +    TcRnMisplacedSigDecl{} -> []
    
    3668
    +    TcRnUnexpectedDefaultSig{} -> []
    
    3669
    +    TcRnDuplicateMinimalSig{} -> []
    
    3670
    +    TcRnSpecSigShape{} -> []
    
    3671
    +    TcRnIllegalInvisTyVarBndr{} -> []
    
    3672
    +    TcRnIllegalWildcardTyVarBndr{} -> []
    
    3673
    +    TcRnInvalidInvisTyVarBndr{} -> []
    
    3674
    +    TcRnInvisBndrWithoutSig{} -> []
    
    3675
    +    TcRnUnexpectedStandaloneDerivingDecl{} -> []
    
    3676
    +    TcRnUnusedVariableInRuleDecl{} -> []
    
    3677
    +    TcRnUnexpectedStandaloneKindSig{} -> []
    
    3678
    +    TcRnIllegalRuleLhs{} -> []
    
    3679
    +    TcRnRuleLhsEqualities{} -> []
    
    3680
    +    TcRnDuplicateRoleAnnot{} -> []
    
    3681
    +    TcRnDuplicateKindSig{} -> []
    
    3682
    +    TcRnIllegalDerivStrategy{} -> []
    
    3683
    +    TcRnIllegalMultipleDerivClauses{} -> []
    
    3684
    +    TcRnNoDerivStratSpecified{} -> []
    
    3685
    +    TcRnStupidThetaInGadt{} -> []
    
    3686
    +    TcRnShadowedTyVarNameInFamResult{} -> []
    
    3687
    +    TcRnIncorrectTyVarOnLhsOfInjCond{} -> []
    
    3688
    +    TcRnUnknownTyVarsOnRhsOfInjCond{} -> []
    
    3689
    +    TcRnLookupInstance{} -> []
    
    3690
    +    TcRnBadlyLevelled{} -> []
    
    3691
    +    TcRnBadlyLevelledType{} -> []
    
    3692
    +    TcRnTyThingUsedWrong{} -> []
    
    3693
    +    TcRnCannotDefaultKindVar{} -> []
    
    3694
    +    TcRnUninferrableTyVar{} -> []
    
    3695
    +    TcRnSkolemEscape{} -> []
    
    3696
    +    TcRnPatSynEscapedCoercion{} -> []
    
    3697
    +    TcRnPatSynExistentialInResult{} -> []
    
    3698
    +    TcRnPatSynArityMismatch{} -> []
    
    3699
    +    TcRnPatSynInvalidRhs{} -> []
    
    3700
    +    TcRnZonkerMessage{} -> []
    
    3701
    +    TcRnTyFamDepsDisabled{} -> []
    
    3702
    +    TcRnAbstractClosedTyFamDecl{} -> []
    
    3703
    +    TcRnPartialFieldSelector{} -> []
    
    3704
    +    TcRnHasFieldResolvedIncomplete{} -> []
    
    3705
    +    TcRnBadFieldAnnotation{} -> []
    
    3706
    +    TcRnSuperclassCycle{} -> []
    
    3707
    +    TcRnDefaultSigMismatch{} -> []
    
    3708
    +    TcRnTyFamsDisabled{} -> []
    
    3709
    +    TcRnBadTyConTelescope{} -> []
    
    3710
    +    TcRnTyFamResultDisabled{} -> []
    
    3711
    +    TcRnRoleValidationFailed{} -> []
    
    3712
    +    TcRnCommonFieldResultTypeMismatch{} -> []
    
    3713
    +    TcRnCommonFieldTypeMismatch{} -> []
    
    3714
    +    TcRnClassExtensionDisabled{} -> []
    
    3715
    +    TcRnDataConParentTypeMismatch{} -> []
    
    3716
    +    TcRnGADTsDisabled{} -> []
    
    3717
    +    TcRnExistentialQuantificationDisabled{} -> []
    
    3718
    +    TcRnGADTDataContext{} -> []
    
    3719
    +    TcRnMultipleConForNewtype{} -> []
    
    3720
    +    TcRnKindSignaturesDisabled{} -> []
    
    3721
    +    TcRnEmptyDataDeclsDisabled{} -> []
    
    3722
    +    TcRnRoleMismatch{} -> []
    
    3723
    +    TcRnRoleCountMismatch{} -> []
    
    3724
    +    TcRnIllegalRoleAnnotation{} -> []
    
    3725
    +    TcRnRoleAnnotationsDisabled{} -> []
    
    3726
    +    TcRnIncoherentRoles{} -> []
    
    3727
    +    TcRnPrecedenceParsingError{} -> []
    
    3728
    +    TcRnSectionPrecedenceError{} -> []
    
    3729
    +    TcRnTypeSynonymCycle{} -> []
    
    3730
    +    TcRnSelfImport{} -> []
    
    3731
    +    TcRnNoExplicitImportList{} -> []
    
    3732
    +    TcRnSafeImportsDisabled{} -> []
    
    3733
    +    TcRnDeprecatedModule{} -> []
    
    3734
    +    TcRnRedundantSourceImport{} -> []
    
    3735
    +    TcRnImportLookup{} -> []
    
    3736
    +    TcRnUnusedImport{} -> []
    
    3737
    +    TcRnPackageImportsDisabled{} -> []
    
    3738
    +    TcRnIllegalDataCon{} -> []
    
    3739
    +    TcRnNestedForallsContexts{} -> []
    
    3740
    +    TcRnRedundantRecordWildcard{} -> []
    
    3741
    +    TcRnUnusedRecordWildcard{} -> []
    
    3742
    +    TcRnUnusedName{} -> []
    
    3743
    +    TcRnQualifiedBinder{} -> []
    
    3744
    +    TcRnTypeApplicationsDisabled{} -> []
    
    3745
    +    TcRnInvalidRecordField{} -> []
    
    3746
    +    TcRnTupleTooLarge{} -> []
    
    3747
    +    TcRnCTupleTooLarge{} -> []
    
    3748
    +    TcRnIllegalInferredTyVars{} -> []
    
    3749
    +    TcRnAmbiguousName{} -> []
    
    3750
    +    TcRnNonCanonicalDefinition{} -> []
    
    3751
    +    TcRnImplicitImportOfPrelude{} -> []
    
    3752
    +    TcRnMissingMain{} -> []
    
    3753
    +    TcRnGhciUnliftedBind{} -> []
    
    3754
    +    TcRnGhciMonadLookupFail{} -> []
    
    3755
    +    TcRnMissingRoleAnnotation{} -> []
    
    3756
    +    TcRnPatersonCondFailure{} -> []
    
    3757
    +    TcRnImplicitRhsQuantification{} -> []
    
    3758
    +    TcRnIllformedTypePattern{} -> []
    
    3759
    +    TcRnIllegalTypePattern{} -> []
    
    3760
    +    TcRnIllformedTypeArgument{} -> []
    
    3761
    +    TcRnIllegalTypeExpr{} -> []
    
    3762
    +    TcRnInvalidDefaultedTyVar{} -> []
    
    3763
    +    TcRnNamespacedWarningPragmaWithoutFlag{} -> []
    
    3764
    +    TcRnIllegalInvisibleTypePattern{} -> []
    
    3765
    +    TcRnNamespacedFixitySigWithoutFlag{} -> []
    
    3766
    +    TcRnDefaultedExceptionContext{} -> []
    
    3767
    +    TcRnOutOfArityTyVar{} -> []
    
    3768
    +    TcRnUnexpectedTypeSyntaxInTerms{} -> []
    
    3769
    +    TcRnUnrecognisedModifier{} -> []
    
    3770
    +    TcRnUnknownModifierKind{} -> []
    
    3771
    +    TcRnTooManyMultiplicities{} -> []
    
    3475 3772
     
    
    3476 3773
     pprTcRnBadlyLevelled :: LevelCheckReason -> Set.Set ThLevelIndex -> ThLevelIndex -> Maybe ErrorItem -> DecoratedSDoc
    
    3477 3774
     pprTcRnBadlyLevelled reason bind_lvls use_lvl lift_attempt = mkDecorated $
    

  • compiler/GHC/Types/Error.hs
    ... ... @@ -234,6 +234,51 @@ defaultDiagnosticOpts :: forall opts . HasDefaultDiagnosticOpts (DiagnosticOpts
    234 234
     defaultDiagnosticOpts = defaultOpts @(DiagnosticOpts opts)
    
    235 235
     
    
    236 236
     
    
    237
    +{- Note [The source span model for diagnostics]
    
    238
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    239
    +Every diagnostic is associated with source locations on two levels:
    
    240
    +
    
    241
    +  * One /primary/ span: the 'errMsgSpan' of the 'MsgEnvelope'. This is the
    
    242
    +    single location that identifies "where" the diagnostic is reported. It
    
    243
    +    drives the @file:line:col:@ message prefix, the order in which messages are
    
    244
    +    sorted, and the squiggle an editor draws for the diagnostic. The primary
    
    245
    +    span is always rendered with a caret ('^').
    
    246
    +
    
    247
    +  * Zero or more /related/ spans: 'diagnosticRelatedLocations'. These are
    
    248
    +    /additional/ locations that help explain the diagnostic — for a
    
    249
    +    duplicate-binding error, say, the other binding sites. They are rendered as
    
    250
    +    further carets alongside the primary span, and are exposed to tooling (e.g.
    
    251
    +    via -fdiagnostics-as-json, and onwards to HLS/LSP).
    
    252
    +
    
    253
    +This is close to the diagnostic model of the Language Server Protocol (LSP), to
    
    254
    +which GHC's diagnostics are forwarded by HLS. An LSP diagnostic carries a single
    
    255
    +@range@ plus a list of @relatedInformation@ entries, each a location with its
    
    256
    +own message; GHC's 'errMsgSpan' corresponds to the @range@ and
    
    257
    +'diagnosticRelatedLocations' to @relatedInformation@. See the @Diagnostic@ and
    
    258
    +@DiagnosticRelatedInformation@ interfaces under "Basic JSON Structures":
    
    259
    +
    
    260
    +  https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#diagnostic
    
    261
    +
    
    262
    +A couple of points follow from this:
    
    263
    +
    
    264
    +  * Related spans are additional to the primary span, not replacements for it.
    
    265
    +    The spans that receive a caret are @primary :| relatedLocations@ (see
    
    266
    +    'GHC.Driver.Errors.printMessage' and 'defaultLogActionWithHandles'), with
    
    267
    +    duplicates removed so that a related span coinciding with the primary is not
    
    268
    +    caretted twice.
    
    269
    +
    
    270
    +  * The primary span need not be the leftmost or smallest of the locations
    
    271
    +    involved, and need not be a synthetic span combining all of them. When
    
    272
    +    several real locations are in play, it is usually better to pick one as the
    
    273
    +    primary and list the rest as related locations than to report a single
    
    274
    +    combined span, which gives a less precise prefix and a larger caret.
    
    275
    +
    
    276
    +Note that GHC's related locations are currently bare 'SrcSpan's with no per-span
    
    277
    +label, whereas an LSP @relatedInformation@ entry pairs each location with a
    
    278
    +message (as do rustc's span labels). Carrying such a message per related span is
    
    279
    +a natural future extension; see #23414.
    
    280
    +-}
    
    281
    +
    
    237 282
     -- | A class identifying a diagnostic.
    
    238 283
     -- Dictionary.com defines a diagnostic as:
    
    239 284
     --
    
    ... ... @@ -281,7 +326,7 @@ class (Outputable (DiagnosticHint a), HasDefaultDiagnosticOpts (DiagnosticOpts a
    281 326
       -- | Additional locations related to this diagnostic.
    
    282 327
       --
    
    283 328
       -- When rendering caret diagnostics, these locations are shown alongside the
    
    284
    -  -- message's primary location.
    
    329
    +  -- message's primary location. See Note [The source span model for diagnostics].
    
    285 330
       diagnosticRelatedLocations :: a -> [SrcSpan]
    
    286 331
       diagnosticRelatedLocations _ = []
    
    287 332
     
    
    ... ... @@ -567,8 +612,8 @@ instance ToJson MessageClass where
    567 612
       json MCInteractive = JSString "MCInteractive"
    
    568 613
       json MCDump = JSString "MCDump"
    
    569 614
       json MCInfo = JSString "MCInfo"
    
    570
    -  json (MCDiagnostic sev reason code _) =
    
    571
    -    JSString $ renderWithContext defaultSDocContext (ppr $ text "MCDiagnostic" <+> ppr sev <+> ppr reason <+> ppr code)
    
    615
    +  json (MCDiagnostic sev reason code relatedSpans) =
    
    616
    +    JSString $ renderWithContext defaultSDocContext (ppr $ text "MCDiagnostic" <+> ppr sev <+> ppr reason <+> ppr code <+> ppr relatedSpans)
    
    572 617
     
    
    573 618
     instance ToJson DiagnosticCode where
    
    574 619
       json c = JSInt (fromIntegral (diagnosticCodeNumber c))
    
    ... ... @@ -576,7 +621,7 @@ instance ToJson DiagnosticCode where
    576 621
     {- Note [Diagnostic Message JSON Schema]
    
    577 622
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    578 623
     The below instance of ToJson must conform to the JSON schema
    
    579
    -specified in docs/users_guide/diagnostics-as-json-schema-1_2.json.
    
    624
    +specified in docs/users_guide/diagnostics-as-json-schema-1_3.json.
    
    580 625
     When the schema is altered, please bump the version.
    
    581 626
     If the content is altered in a backwards compatible way,
    
    582 627
     update the minor version (e.g. 1.3 ~> 1.4).
    
    ... ... @@ -589,7 +634,7 @@ https://json-schema.org
    589 634
     -}
    
    590 635
     
    
    591 636
     schemaVersion :: String
    
    592
    -schemaVersion = "1.2"
    
    637
    +schemaVersion = "1.3"
    
    593 638
     
    
    594 639
     -- See Note [Diagnostic Message JSON Schema] before editing!
    
    595 640
     jsonDiagnostic :: forall e. Diagnostic e => String -> MsgEnvelope e -> JsonDoc
    
    ... ... @@ -597,6 +642,7 @@ jsonDiagnostic rendered m = JSObject $ [
    597 642
         ("version", JSString schemaVersion),
    
    598 643
         ("ghcVersion", JSString $ "ghc-" ++ cProjectVersion),
    
    599 644
         ("span", json $ errMsgSpan m),
    
    645
    +    ("relatedSpans", JSArray $ map json (diagnosticRelatedLocations diag)),
    
    600 646
         ("severity", json $ errMsgSeverity m),
    
    601 647
         ("code", maybe JSNull json (diagnosticCode diag)),
    
    602 648
         ("rendered", JSString rendered),
    

  • compiler/GHC/Utils/Logger.hs
    ... ... @@ -102,7 +102,7 @@ import System.FilePath ( takeDirectory, (</>) )
    102 102
     import qualified Data.Map.Strict as Map
    
    103 103
     import Data.Map.Strict (Map)
    
    104 104
     import Data.List (stripPrefix)
    
    105
    -import Data.List.NonEmpty (NonEmpty(..))
    
    105
    +import Data.List.NonEmpty (NonEmpty(..), nub)
    
    106 106
     import Data.Time
    
    107 107
     import System.IO
    
    108 108
     import Control.Monad
    
    ... ... @@ -425,7 +425,7 @@ defaultLogActionWithHandles out err logflags msg_class srcSpan msg
    425 425
           MCFatal                      -> printErrs msg
    
    426 426
           MCDiagnostic SevIgnore _ _ _ -> pure () -- suppress the message
    
    427 427
           MCDiagnostic _sev _rea _code relatedSpans ->
    
    428
    -        decorateDiagnostic logflags msg_class srcSpan (srcSpan :| relatedSpans) msg >>= printErrs
    
    428
    +        decorateDiagnostic logflags msg_class srcSpan (nub (srcSpan :| relatedSpans)) msg >>= printErrs
    
    429 429
         where
    
    430 430
           printOut   = defaultLogActionHPrintDoc  logflags False out
    
    431 431
           printErrs  = defaultLogActionHPrintDoc  logflags False err
    

  • docs/users_guide/diagnostics-as-json-schema-1_3.json
    1
    +{
    
    2
    +  "$schema": "https://json-schema.org/draft/2020-12/schema",
    
    3
    +  "title": "JSON Diagnostic Schema",
    
    4
    +  "description": "A Schema for specifying GHC diagnostics output as JSON",
    
    5
    +  "type": "object",
    
    6
    +  "properties": {
    
    7
    +    "version": {
    
    8
    +      "description": "The current JSON schema version this object conforms to",
    
    9
    +      "type": "string"
    
    10
    +    },
    
    11
    +    "ghcVersion": {
    
    12
    +      "description": "The GHC version",
    
    13
    +      "type": "string"
    
    14
    +    },
    
    15
    +    "span": {
    
    16
    +      "oneOf": [
    
    17
    +        { "$ref": "#/$defs/span" },
    
    18
    +        { "type": "null" }
    
    19
    +      ]
    
    20
    +    },
    
    21
    +    "relatedSpans": {
    
    22
    +      "description": "Additional source spans related to the diagnostic, beyond the primary span",
    
    23
    +      "type": "array",
    
    24
    +      "items": {
    
    25
    +        "oneOf": [
    
    26
    +          { "$ref": "#/$defs/span" },
    
    27
    +          { "type": "null" }
    
    28
    +        ]
    
    29
    +      }
    
    30
    +    },
    
    31
    +    "severity": {
    
    32
    +      "description": "The diagnostic severity",
    
    33
    +      "type": "string",
    
    34
    +      "enum": [
    
    35
    +        "Warning",
    
    36
    +        "Error"
    
    37
    +      ]
    
    38
    +    },
    
    39
    +    "code": {
    
    40
    +      "description": "The diagnostic code (if it exists)",
    
    41
    +      "type": [
    
    42
    +        "integer",
    
    43
    +        "null"
    
    44
    +      ]
    
    45
    +    },
    
    46
    +    "rendered": {
    
    47
    +      "description": "The rendered diagnostics message, in the exact same format as what GHC would have produced without -fdiagnostics-as-json (including ANSI escape sequences)",
    
    48
    +      "type": "string"
    
    49
    +    },
    
    50
    +    "message": {
    
    51
    +      "description": "The string output of the diagnostic message by GHC",
    
    52
    +      "type": "array",
    
    53
    +      "items": {
    
    54
    +        "type": "string"
    
    55
    +      }
    
    56
    +    },
    
    57
    +    "hints": {
    
    58
    +      "description": "The suggested fixes",
    
    59
    +      "type": "array",
    
    60
    +      "items": {
    
    61
    +        "type": "string"
    
    62
    +      }
    
    63
    +    },
    
    64
    +    "reason" : {
    
    65
    +      "description": "The GHC flag that was responsible for the emission of the diagnostic message",
    
    66
    +      "oneOf": [
    
    67
    +        {
    
    68
    +          "type": "object",
    
    69
    +          "description": "The diagnostic message was controlled by one or more GHC flags",
    
    70
    +          "properties": {
    
    71
    +            "flags": {
    
    72
    +              "type": "array",
    
    73
    +              "items": {
    
    74
    +                "description": "The name of a GHC flag controlling the diagnostic message",
    
    75
    +                "type": "string"
    
    76
    +              },
    
    77
    +              "minItems": 1
    
    78
    +            }
    
    79
    +          },
    
    80
    +          "required": ["flags"]
    
    81
    +        },
    
    82
    +        {
    
    83
    +          "type": "object",
    
    84
    +          "description": "The diagnostic message was controlled by a GHC diagnostic message category",
    
    85
    +          "properties": {
    
    86
    +            "category": {
    
    87
    +              "description": "The name of the GHC diagnostic message category controlling the diagnostic message",
    
    88
    +              "type": "string"
    
    89
    +            }
    
    90
    +          },
    
    91
    +          "required": ["category"]
    
    92
    +        }
    
    93
    +      ]
    
    94
    +    }
    
    95
    +  },
    
    96
    +
    
    97
    +  "$comment": "NOTE: \"rendered\" and \"relatedSpans\" are not required fields so that the schema is backward compatible with versions 1.1 and 1.2 respectively. If you bump the schema version to 2.0 then please also add \"rendered\" to the \"required\" fields.",
    
    98
    +  "required": [
    
    99
    +    "version",
    
    100
    +    "ghcVersion",
    
    101
    +    "span",
    
    102
    +    "severity",
    
    103
    +    "code",
    
    104
    +    "message",
    
    105
    +    "hints"
    
    106
    +  ],
    
    107
    +
    
    108
    +  "additionalProperties": false,
    
    109
    +  "$defs": {
    
    110
    +    "span": {
    
    111
    +      "description": "The span of the diagnostic",
    
    112
    +      "type": "object",
    
    113
    +      "properties": {
    
    114
    +        "file": {
    
    115
    +          "description": "The file in which the diagnostic occurs",
    
    116
    +          "type": "string"
    
    117
    +        },
    
    118
    +        "start": {
    
    119
    +          "description": "The start location of the diagnostic",
    
    120
    +          "$ref": "#/$defs/location"
    
    121
    +        },
    
    122
    +        "end": {
    
    123
    +          "description": "The end location of the diagnostic",
    
    124
    +          "$ref": "#/$defs/location"
    
    125
    +        }
    
    126
    +      },
    
    127
    +      "required": [
    
    128
    +        "file",
    
    129
    +        "start",
    
    130
    +        "end"
    
    131
    +      ],
    
    132
    +      "additionalProperties": false
    
    133
    +    },
    
    134
    +    "location": {
    
    135
    +      "description": "A location in a text file",
    
    136
    +      "type": "object",
    
    137
    +      "properties": {
    
    138
    +        "line": {
    
    139
    +          "description": "The line number",
    
    140
    +          "type": "integer"
    
    141
    +        },
    
    142
    +        "column": {
    
    143
    +          "description": "The column number",
    
    144
    +          "type": "integer"
    
    145
    +        }
    
    146
    +      },
    
    147
    +      "required": [
    
    148
    +        "line",
    
    149
    +        "column"
    
    150
    +      ],
    
    151
    +      "additionalProperties": false
    
    152
    +    }
    
    153
    +  }
    
    154
    +}

  • docs/users_guide/using.rst
    ... ... @@ -1437,7 +1437,7 @@ messages and in GHCi:
    1437 1437
         a new line.
    
    1438 1438
     
    
    1439 1439
         The structure of the output is described by a `JSON Schema <https://json-schema.org/>`_.
    
    1440
    -    The schema can be downloaded :download:`here <diagnostics-as-json-schema-1_2.json>`.
    
    1440
    +    The schema can be downloaded :download:`here <diagnostics-as-json-schema-1_3.json>`.
    
    1441 1441
     
    
    1442 1442
     .. ghc-flag:: -fdiagnostics-color=⟨always|auto|never⟩
    
    1443 1443
         :shortdesc: Use colors in error messages
    

  • testsuite/tests/driver/T16167.stdout
    1
    -{"span":null,"doc":"-ddump-json is deprecated: Use `-fdiagnostics-as-json` instead","messageClass":"MCDiagnostic SevWarning WarningWithFlags Opt_WarnDeprecatedFlags :| [] Just GHC-53692"}
    
    2
    -{"span":{"file":"T16167.hs","startLine":1,"startCol":8,"endLine":1,"endCol":9},"doc":"parse error on input \u2018f\u2019","messageClass":"MCDiagnostic SevError ErrorWithoutFlag Just GHC-58481"}
    1
    +{"span":null,"doc":"-ddump-json is deprecated: Use `-fdiagnostics-as-json` instead","messageClass":"MCDiagnostic SevWarning WarningWithFlags Opt_WarnDeprecatedFlags :| [] Just GHC-53692 []"}
    
    2
    +{"span":{"file":"T16167.hs","startLine":1,"startCol":8,"endLine":1,"endCol":9},"doc":"parse error on input \u2018f\u2019","messageClass":"MCDiagnostic SevError ErrorWithoutFlag Just GHC-58481 []"}

  • testsuite/tests/driver/json.stderr
    1
    -{"version":"1.2","ghcVersion":"ghc-9.13.20250627","span":{"file":"json.hs","start":{"line":9,"column":11},"end":{"line":9,"column":21}},"severity":"Error","code":48010,"rendered":"json.hs:9:11: error: [GHC-48010]\n    Empty list of alternatives in case expression\n    Suggested fix:\n      Perhaps you intended to use the \u2018EmptyCase\u2019 extension\n","message":["Empty list of alternatives in case expression"],"hints":["Perhaps you intended to use the \u2018EmptyCase\u2019 extension"]}
    1
    +{"version":"1.3","ghcVersion":"ghc-9.13.20250627","span":{"file":"json.hs","start":{"line":9,"column":11},"end":{"line":9,"column":21}},"relatedSpans":[],"severity":"Error","code":48010,"rendered":"json.hs:9:11: error: [GHC-48010]\n    Empty list of alternatives in case expression\n    Suggested fix:\n      Perhaps you intended to use the \u2018EmptyCase\u2019 extension\n","message":["Empty list of alternatives in case expression"],"hints":["Perhaps you intended to use the \u2018EmptyCase\u2019 extension"]}

  • testsuite/tests/driver/json2.stderr
    1
    -{"span":null,"doc":"-ddump-json is deprecated: Use `-fdiagnostics-as-json` instead","messageClass":"MCDiagnostic SevWarning WarningWithFlags Opt_WarnDeprecatedFlags :| [] Just GHC-53692"}
    
    1
    +{"span":null,"doc":"-ddump-json is deprecated: Use `-fdiagnostics-as-json` instead","messageClass":"MCDiagnostic SevWarning WarningWithFlags Opt_WarnDeprecatedFlags :| [] Just GHC-53692 []"}
    
    2 2
     {"span":null,"doc":"TYPE SIGNATURES\n  foo :: forall a. a -> a\nDependent modules: []\nDependent packages: [(normal, base-4.21.0.0)]","messageClass":"MCOutput"}

  • testsuite/tests/driver/json_dump.stderr
    1
    -{"span":null,"doc":"-ddump-json is deprecated: Use `-fdiagnostics-as-json` instead","messageClass":"MCDiagnostic SevWarning WarningWithFlags Opt_WarnDeprecatedFlags :| [] Just GHC-53692"}
    
    2
    -{"span":{"file":"json_dump.hs","startLine":6,"startCol":7,"endLine":6,"endCol":8},"doc":"\u2022 No instance for \u2018Num (a -> a)\u2019 arising from the literal \u20185\u2019\n    (maybe you haven't applied a function to enough arguments?)\n\u2022 In the expression: 5\n  In an equation for \u2018id1\u2019: id1 = 5","messageClass":"MCDiagnostic SevError ErrorWithoutFlag Just GHC-39999"}
    1
    +{"span":null,"doc":"-ddump-json is deprecated: Use `-fdiagnostics-as-json` instead","messageClass":"MCDiagnostic SevWarning WarningWithFlags Opt_WarnDeprecatedFlags :| [] Just GHC-53692 []"}
    
    2
    +{"span":{"file":"json_dump.hs","startLine":6,"startCol":7,"endLine":6,"endCol":8},"doc":"\u2022 No instance for \u2018Num (a -> a)\u2019 arising from the literal \u20185\u2019\n    (maybe you haven't applied a function to enough arguments?)\n\u2022 In the expression: 5\n  In an equation for \u2018id1\u2019: id1 = 5","messageClass":"MCDiagnostic SevError ErrorWithoutFlag Just GHC-39999 []"}

  • testsuite/tests/driver/json_warn.stderr
    1
    -{"version":"1.2","ghcVersion":"ghc-9.13.20250627","span":{"file":"json_warn.hs","start":{"line":4,"column":3},"end":{"line":4,"column":4}},"severity":"Warning","code":40910,"rendered":"json_warn.hs:4:3: warning: [GHC-40910] [-Wunused-matches (in -Wextra)]\n    Defined but not used: \u2018x\u2019\n","message":["Defined but not used: \u2018x\u2019"],"hints":[],"reason":{"flags":["unused-matches"]}}
    
    2
    -{"version":"1.2","ghcVersion":"ghc-9.13.20250627","span":{"file":"json_warn.hs","start":{"line":7,"column":5},"end":{"line":7,"column":9}},"severity":"Warning","code":63394,"rendered":"json_warn.hs:7:5: warning: [GHC-63394] [-Wx-partial (in -Wextended-warnings)]\n    In the use of \u2018head\u2019\n    (imported from Prelude, but defined in GHC.Internal.List):\n    \"This is a partial function, it throws an error on empty lists. Use pattern matching, 'Data.List.uncons' or 'Data.Maybe.listToMaybe' instead. Consider refactoring to use \"Data.List.NonEmpty\".\"\n","message":["In the use of \u2018head\u2019\n(imported from Prelude, but defined in GHC.Internal.List):\n\"This is a partial function, it throws an error on empty lists. Use pattern matching, 'Data.List.uncons' or 'Data.Maybe.listToMaybe' instead. Consider refactoring to use \"Data.List.NonEmpty\".\""],"hints":[],"reason":{"category":"x-partial"}}
    1
    +{"version":"1.3","ghcVersion":"ghc-9.13.20250627","span":{"file":"json_warn.hs","start":{"line":4,"column":3},"end":{"line":4,"column":4}},"relatedSpans":[],"severity":"Warning","code":40910,"rendered":"json_warn.hs:4:3: warning: [GHC-40910] [-Wunused-matches (in -Wextra)]\n    Defined but not used: \u2018x\u2019\n","message":["Defined but not used: \u2018x\u2019"],"hints":[],"reason":{"flags":["unused-matches"]}}
    
    2
    +{"version":"1.3","ghcVersion":"ghc-9.13.20250627","span":{"file":"json_warn.hs","start":{"line":7,"column":5},"end":{"line":7,"column":9}},"relatedSpans":[],"severity":"Warning","code":63394,"rendered":"json_warn.hs:7:5: warning: [GHC-63394] [-Wx-partial (in -Wextended-warnings)]\n    In the use of \u2018head\u2019\n    (imported from Prelude, but defined in GHC.Internal.List):\n    \"This is a partial function, it throws an error on empty lists. Use pattern matching, 'Data.List.uncons' or 'Data.Maybe.listToMaybe' instead. Consider refactoring to use \"Data.List.NonEmpty\".\"\n","message":["In the use of \u2018head\u2019\n(imported from Prelude, but defined in GHC.Internal.List):\n\"This is a partial function, it throws an error on empty lists. Use pattern matching, 'Data.List.uncons' or 'Data.Maybe.listToMaybe' instead. Consider refactoring to use \"Data.List.NonEmpty\".\""],"hints":[],"reason":{"category":"x-partial"}}