diff --git a/Sources/FrontEnd/DiagnosticSet.swift b/Sources/FrontEnd/DiagnosticSet.swift index d08ce0625..d02d01df2 100644 --- a/Sources/FrontEnd/DiagnosticSet.swift +++ b/Sources/FrontEnd/DiagnosticSet.swift @@ -33,6 +33,11 @@ public struct DiagnosticSet: Error { containsError = containsError || other.containsError } + /// Removes from `self` the elements that are not also contained in `other`. + public mutating func formIntersection(_ other: Self) { + self = .init(elements.filter(other.elements.contains(_:))) + } + /// Throws `self` if any errors were reported. public func throwOnError() throws { if containsError { throw self } diff --git a/Sources/FrontEnd/TypeChecking/ConstraintSystem.swift b/Sources/FrontEnd/TypeChecking/ConstraintSystem.swift index 9d520da28..fefdab245 100644 --- a/Sources/FrontEnd/TypeChecking/ConstraintSystem.swift +++ b/Sources/FrontEnd/TypeChecking/ConstraintSystem.swift @@ -192,11 +192,17 @@ struct ConstraintSystem { penalties: penalties, diagnostics: d, stale: stale.map({ goals[$0] })) } - /// Creates an ambiguous solution. + /// Creates an ambiguous solution, reporting the ambiguity with `d`. + /// + /// The return value is the intersection of the choices and diagnostics that are identical in + /// each result along with an additional diagnostic describing the ambiguity. + /// + /// - Requires: `result` contains at least two elements. private func formAmbiguousSolution( _ results: Explorations, diagnosedBy d: Diagnostic ) -> Solution { - var s = results.elements.reduce(into: Solution(), { (s, r) in s.formIntersection(r.solution) }) + let (first, others) = results.elements.headAndTail! + var s = others.reduce(into: first.solution, { (s, r) in s.formIntersection(r.solution) }) s.incorporate(d) return s } diff --git a/Sources/FrontEnd/TypeChecking/Solution.swift b/Sources/FrontEnd/TypeChecking/Solution.swift index 2a5febeaa..970c6a173 100644 --- a/Sources/FrontEnd/TypeChecking/Solution.swift +++ b/Sources/FrontEnd/TypeChecking/Solution.swift @@ -83,6 +83,7 @@ struct Solution { mutating func formIntersection(_ other: Self) { typeAssumptions.formIntersection(other.typeAssumptions) bindingAssumptions.formIntersection(other.bindingAssumptions) + diagnostics.formIntersection(other.diagnostics) penalties = max(penalties, other.penalties) } diff --git a/Tests/HyloTests/TestCases/TypeChecking/Overloading.hylo b/Tests/HyloTests/TestCases/TypeChecking/Overloading.hylo index be45f81ed..1a5a0f705 100644 --- a/Tests/HyloTests/TestCases/TypeChecking/Overloading.hylo +++ b/Tests/HyloTests/TestCases/TypeChecking/Overloading.hylo @@ -39,5 +39,5 @@ public fun main() { check(x6) let a = 1 - fn(a, a) //! diagnostic ambiguous use of 'fn' + _ = fn(a, a) //! diagnostic ambiguous use of 'fn' }