Skip to content
This repository was archived by the owner on Jan 12, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/QsCompiler/Core/SyntaxGenerator.fs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ open Microsoft.Quantum.QsCompiler.Transformations.Core

type private StripPositionInfoFromType(parent: StripPositionInfo) =
inherit TypeTransformation(parent)

override this.OnTypeRange _ = TypeRange.Generated

override this.OnRangeInformation _ = Null

and private StripPositionInfoFromExpression(parent: StripPositionInfo) =
Expand Down
9 changes: 6 additions & 3 deletions src/QsCompiler/DataStructures/Diagnostics.fs
Original file line number Diff line number Diff line change
Expand Up @@ -461,9 +461,9 @@ type DiagnosticItem =
DiagnosticItem.ApplyArguments args
<< function
| ErrorCode.TypeMismatch ->
"The expected type {0} does not match the actual type {1}.\nExpected type: {2}\n Actual type: {3}"
"The type {1} does not match the type {0}.\nActual type: {3}\nExpected type: {2}"
| ErrorCode.MissingBaseType ->
"The type {3} cannot be used with the type {4}, because {1} does not {0} {2}."
"The type {1} does not {0} the type {2}.\nLeft-hand type: {3}\nRight-hand type: {4}"

| ErrorCode.ExcessBracketError -> "No matching opening bracket for this closing bracket."
| ErrorCode.MissingBracketError -> "An opening bracket has not been closed."
Expand Down Expand Up @@ -769,7 +769,10 @@ type DiagnosticItem =
"The type of the given argument does not match the expected type. Got an argument of type {0}, expecting one of type {1} instead."
| ErrorCode.UnexpectedTupleArgument -> "Unexpected argument tuple. Expecting an argument of type {0}."
| ErrorCode.AmbiguousTypeParameterResolution ->
"The type parameter resolution for the expression is ambiguous. Please provide explicit type arguments, e.g. Op<Int, Double>(arg)."
"The type parameter {0} is ambiguous. More type annotations or usage context may be necessary."
+ if Seq.item 1 args |> String.IsNullOrWhiteSpace
then ""
else " Note: {0} has constraints {1}."
| ErrorCode.ConstrainsTypeParameter -> "The given expression constrains the type parameter(s) {0}."
| ErrorCode.GlobalTypeAlreadyExists -> "A type with the name \"{0}\" already exists."
| ErrorCode.GlobalCallableAlreadyExists -> "A callable with the name \"{0}\" already exists."
Expand Down
21 changes: 21 additions & 0 deletions src/QsCompiler/SyntaxProcessor/TypeInference/Constraint.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ namespace Microsoft.Quantum.QsCompiler.SyntaxProcessing.TypeInference

open Microsoft.Quantum.QsCompiler.SyntaxTokens
open Microsoft.Quantum.QsCompiler.SyntaxTree
open Microsoft.Quantum.QsCompiler.Transformations.QsCodeOutput

type internal Constraint =
| Adjointable
Expand All @@ -21,6 +22,9 @@ type internal Constraint =
| Wrapped of item: ResolvedType

module internal Constraint =
/// Pretty prints a type.
let private prettyType: ResolvedType -> _ = SyntaxTreeToQsharp.Default.ToCode

let types =
function
| Adjointable -> []
Expand All @@ -35,3 +39,20 @@ module internal Constraint =
| Numeric -> []
| Semigroup -> []
| Wrapped item -> [ item ]

let pretty =
function
| Adjointable -> "Adjointable"
| Callable (input, output) -> sprintf "Callable(%s, %s)" (prettyType input) (prettyType output)
| CanGenerateFunctors functors ->
sprintf "CanGenerateFunctors(%s)" (functors |> Seq.map string |> String.concat ", ")
| Controllable controlled -> sprintf "Controllable(%s)" (prettyType controlled)
| Equatable -> "Equatable"
| HasPartialApplication (missing, result) ->
sprintf "HasPartialApplication(%s, %s)" (prettyType missing) (prettyType result)
| Indexed (index, item) -> sprintf "Indexed(%s, %s)" (prettyType index) (prettyType item)
| Integral -> "Integral"
| Iterable item -> sprintf "Iterable(%s)" (prettyType item)
| Numeric -> "Numeric"
| Semigroup -> "Semigroup"
| Wrapped item -> sprintf "Wrapped(%s)" (prettyType item)
3 changes: 3 additions & 0 deletions src/QsCompiler/SyntaxProcessor/TypeInference/Constraint.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,6 @@ type internal Constraint =
module internal Constraint =
/// The list of types contained in a constraint.
val types: Constraint -> ResolvedType list

/// Pretty prints a constraint.
val pretty: Constraint -> string
57 changes: 39 additions & 18 deletions src/QsCompiler/SyntaxProcessor/TypeInference/InferenceContext.fs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ open Microsoft.Quantum.QsCompiler.SyntaxProcessing
open Microsoft.Quantum.QsCompiler.SyntaxProcessing.VerificationTools
open Microsoft.Quantum.QsCompiler.SyntaxTokens
open Microsoft.Quantum.QsCompiler.SyntaxTree
open Microsoft.Quantum.QsCompiler.TextProcessing
open Microsoft.Quantum.QsCompiler.Transformations.Core
open Microsoft.Quantum.QsCompiler.Transformations.QsCodeOutput
open Microsoft.Quantum.QsCompiler.Utils
Expand Down Expand Up @@ -111,10 +110,6 @@ module private TypeContext =
OriginalRight = context.OriginalLeft
}

/// The list of types in the context, in order: left, right, original left, original right.
let toList context =
[ context.Left; context.Right; context.OriginalLeft; context.OriginalRight ]

/// Tools to help with type inference.
module private Inference =
/// <summary>
Expand Down Expand Up @@ -143,11 +138,29 @@ module private Inference =
/// Shows the type as a string.
let showType: ResolvedType -> _ = SyntaxTreeToQsharp.Default.ToCode

/// Shows the functor as a string.
let showFunctor =
function
| Adjoint -> Keywords.qsAdjointFunctor.id
| Controlled -> Keywords.qsControlledFunctor.id
/// <summary>
/// Describes a type with additional information.
/// </summary>
/// <remarks>
/// For most types, this is the same as <see cref="showType"/>. For type parameters, the origin is included in the
/// description.
/// </remarks>
let private describeType (resolvedType: ResolvedType) =
match resolvedType.Resolution with
| TypeParameter param -> sprintf "parameter %s (bound by %s)" (showType resolvedType) param.Origin.Name
| _ -> showType resolvedType

/// <summary>
/// The list of strings from applying <see cref="describeType"/> to the left and right types, and
/// <see cref="showType"/> to the original left and right types, in order.
/// </summary>
let describeTypeContext context =
[
describeType context.Left
describeType context.Right
showType context.OriginalLeft
showType context.OriginalRight
]

/// <summary>
/// Combines information from two callables such that the resulting callable information satisfies the given
Expand Down Expand Up @@ -191,7 +204,7 @@ module private Inference =

let error =
QsCompilerDiagnostic.Error
(ErrorCode.MissingBaseType, relation :: (TypeContext.toList types |> List.map showType))
(ErrorCode.MissingBaseType, relation :: describeTypeContext types)
(range |> QsNullable.defaultValue Range.Zero)

match types.Left.Resolution, types.Right.Resolution with
Expand Down Expand Up @@ -284,11 +297,19 @@ type InferenceContext(symbolTracker: SymbolTracker) =
diagnostics

member context.AmbiguousDiagnostics =
[
for variable in variables do
if not variable.Value.HasError && Option.isNone variable.Value.Substitution
then QsCompilerDiagnostic.Error (ErrorCode.AmbiguousTypeParameterResolution, []) variable.Value.Source
]
let diagnostic param variable =
let args =
[
TypeParameter param |> ResolvedType.New |> showType
variable.Constraints |> List.map Constraint.pretty |> String.concat ", "
]

QsCompilerDiagnostic.Error (ErrorCode.AmbiguousTypeParameterResolution, args) variable.Source

variables
|> Seq.filter (fun item -> not item.Value.HasError && Option.isNone item.Value.Substitution)
|> Seq.map (fun item -> diagnostic item.Key item.Value)
|> Seq.toList

member context.UseStatementPosition position = statementPosition <- position

Expand Down Expand Up @@ -369,7 +390,7 @@ type InferenceContext(symbolTracker: SymbolTracker) =
member private context.UnifyByOrdering(ordering, types) =
let error =
QsCompilerDiagnostic.Error
(ErrorCode.TypeMismatch, TypeContext.toList types |> List.map showType)
(ErrorCode.TypeMismatch, describeTypeContext types)
(TypeRange.tryRange types.Right.Range |> QsNullable.defaultValue Range.Zero)

match types.Left.Resolution, types.Right.Resolution with
Expand Down Expand Up @@ -447,7 +468,7 @@ type InferenceContext(symbolTracker: SymbolTracker) =
let missing = Set.difference functors (Set.ofSeq supported)

let error =
ErrorCode.MissingFunctorForAutoGeneration, [ missing |> Seq.map showFunctor |> String.concat "," ]
ErrorCode.MissingFunctorForAutoGeneration, [ missing |> Seq.map string |> String.concat "," ]

[
if not info.Characteristics.AreInvalid && Set.isEmpty missing |> not
Expand Down
5 changes: 5 additions & 0 deletions src/QsCompiler/Tests.Compiler/LocalVerificationTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ type LocalVerificationTests() =
this.Expect "TypeArgumentsInference40" []
this.Expect "TypeArgumentsInference41" [ Error ErrorCode.TypeMismatch ]
this.Expect "TypeArgumentsInference42" [ Error ErrorCode.TypeMismatch ]
this.Expect "TypeArgumentsInference43" []
this.Expect "TypeArgumentsInference44" [ Error ErrorCode.AmbiguousTypeParameterResolution ]
this.Expect "TypeArgumentsInference45" [ Error ErrorCode.AmbiguousTypeParameterResolution ]
this.Expect "TypeArgumentsInference46" [ Error ErrorCode.AmbiguousTypeParameterResolution ]
this.Expect "TypeArgumentsInference47" []


[<Fact>]
Expand Down
25 changes: 24 additions & 1 deletion src/QsCompiler/Tests.Compiler/TestCases/LocalVerification.qs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@

/// This namespace contains test cases for expression and statement verification
namespace Microsoft.Quantum.Testing.LocalVerification {

open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Testing.General;
open Microsoft.Quantum.Testing.TypeChecking;

function UnusedTypeParam<'a>() : Unit {}

operation Sequence<'a, 'b>(f : 'a => Unit, g : 'b => Unit) : ('a, 'b) => Unit {
fail "Not implemented.";
}

// type argument inference

Expand Down Expand Up @@ -222,6 +226,25 @@ namespace Microsoft.Quantum.Testing.LocalVerification {
TypeArgumentsInference23<'A, 'A>(a, b);
}

function TypeArgumentsInference43() : Unit {
Default();
}

function TypeArgumentsInference44() : Unit {
let _ = Default();
}

function TypeArgumentsInference45() : Unit {
UnusedTypeParam();
}

function TypeArgumentsInference46() : Unit {
let _ = GenericFunction(Default);
}

operation TypeArgumentsInference47() : Unit {
Sequence(GenericOperation, GenericOperation)("Foo", 3);
}

// variable declarations

Expand Down