diff --git a/src/QsCompiler/BondSchemas/CompilerObjectTranslator.cs b/src/QsCompiler/BondSchemas/CompilerObjectTranslator.cs index 9622c3cfc9..2ba29c5809 100644 --- a/src/QsCompiler/BondSchemas/CompilerObjectTranslator.cs +++ b/src/QsCompiler/BondSchemas/CompilerObjectTranslator.cs @@ -250,6 +250,7 @@ private static SyntaxTree.QsDeclarationAttribute ToCompilerObject(this QsDeclara typeId: bondQsDeclarationAttribute.TypeId != null ? bondQsDeclarationAttribute.TypeId.ToCompilerObject().ToQsNullableGeneric() : QsNullable.Null, + typeIdRange: QsNullable.Null, argument: bondQsDeclarationAttribute.Argument.ToCompilerObject(), offset: bondQsDeclarationAttribute.Offset.ToCompilerObject(), comments: bondQsDeclarationAttribute.Comments.ToCompilerObject()); diff --git a/src/QsCompiler/CompilationManager/CompilationUnit.cs b/src/QsCompiler/CompilationManager/CompilationUnit.cs index 532223ac48..8866e2706e 100644 --- a/src/QsCompiler/CompilationManager/CompilationUnit.cs +++ b/src/QsCompiler/CompilationManager/CompilationUnit.cs @@ -105,15 +105,14 @@ private static Headers LoadTestNames(string source, Headers headers) static QsDeclarationAttribute Renamed(QsQualifiedName originalName, Position declLocation) { - var attName = new UserDefinedType( - GeneratedAttributes.Namespace, - GeneratedAttributes.LoadedViaTestNameInsteadOf, - QsNullable.Null); - var attArg = SyntaxGenerator.StringLiteral( - originalName.ToString(), - ImmutableArray.Empty); + var attName = + UserDefinedType.New(GeneratedAttributes.Namespace, GeneratedAttributes.LoadedViaTestNameInsteadOf); + var attArg = + SyntaxGenerator.StringLiteral(originalName.ToString(), ImmutableArray.Empty); + return new QsDeclarationAttribute( QsNullable.NewValue(attName), + QsNullable.Null, attArg, declLocation, QsComments.Empty); diff --git a/src/QsCompiler/Core/ConstructorExtensions.fs b/src/QsCompiler/Core/ConstructorExtensions.fs index 7b3a1c592d..bf359608db 100644 --- a/src/QsCompiler/Core/ConstructorExtensions.fs +++ b/src/QsCompiler/Core/ConstructorExtensions.fs @@ -19,13 +19,7 @@ type QsQualifiedName with static member New(nsName, cName) = { Namespace = nsName; Name = cName } type UserDefinedType with - static member New(ns, name) = - { - Namespace = ns - Name = name - Range = Null - } - + // TODO: RELEASE 2021-10: Remove member. [] static member New(nsName, tName, range) = { @@ -35,13 +29,7 @@ type UserDefinedType with } type QsTypeParameter with - static member New(origin, name) = - { - Origin = origin - TypeName = name - Range = Null - } - + // TODO: RELEASE 2021-10: Remove member. [] static member New(origin, tName, range) = { @@ -248,9 +236,12 @@ type QsCustomType with } type QsDeclarationAttribute with + // TODO: RELEASE 2021-10: Remove member. + [] static member New(typeId, arg, pos, comments) = { TypeId = typeId + TypeIdRange = Null Argument = arg Offset = pos Comments = comments diff --git a/src/QsCompiler/Core/SymbolResolution.fs b/src/QsCompiler/Core/SymbolResolution.fs index a8ca80941b..6d091f7f20 100644 --- a/src/QsCompiler/Core/SymbolResolution.fs +++ b/src/QsCompiler/Core/SymbolResolution.fs @@ -747,6 +747,7 @@ module SymbolResolution = let buildAttribute id = { TypeId = id + TypeIdRange = attribute.Id.Range Argument = resArg Offset = attribute.Position Comments = attribute.Comments diff --git a/src/QsCompiler/Core/SymbolTable/NamespaceManager.fs b/src/QsCompiler/Core/SymbolTable/NamespaceManager.fs index 6e3d4145e1..5b82aca45e 100644 --- a/src/QsCompiler/Core/SymbolTable/NamespaceManager.fs +++ b/src/QsCompiler/Core/SymbolTable/NamespaceManager.fs @@ -242,10 +242,9 @@ type NamespaceManager(syncRoot: IReaderWriterLock, /// /// contains a . let resolveType (parent: QsQualifiedName, tpNames, source) qsType checkUdt = - let processUDT = - tryResolveTypeName (parent.Namespace, source) - >> function - | Some (udt, _, access), errs -> UserDefinedType udt, Array.append errs (checkUdt (udt, access)) + let processUDT (name, range) = + match tryResolveTypeName (parent.Namespace, source) (name, range) with + | Some (udt, _, access), errs -> UserDefinedType udt, Array.append errs (checkUdt (udt, range, access)) | None, errs -> InvalidType, errs let processTP (symName, symRange) = @@ -274,10 +273,12 @@ type NamespaceManager(syncRoot: IReaderWriterLock, /// Compares the accessibility of the parent declaration with the accessibility of the UDT being referenced. If the /// accessibility of a referenced type is less than the accessibility of the parent, returns a diagnostic using the /// given error code. Otherwise, returns an empty array. - let checkUdtAccess code (parent, parentAccess) (udt: UserDefinedType, udtAccess) = + let checkUdtAccess code (parent, parentAccess) (udt: UserDefinedType, udtRange, udtAccess) = + let udtRange = udtRange |> QsNullable.defaultValue Range.Zero + [| if udtAccess < parentAccess - then yield QsCompilerDiagnostic.Error (code, [ udt.Name; parent ]) (udt.Range.ValueOr Range.Zero) + then yield QsCompilerDiagnostic.Error (code, [ udt.Name; parent ]) udtRange |] /// @@ -498,7 +499,7 @@ type NamespaceManager(syncRoot: IReaderWriterLock, // the attribute is a duplication of another attribute on this declaration if alreadyDefined.Contains attributeHash then (att.Offset, - tId.Range + att.TypeIdRange |> orDefault |> QsCompilerDiagnostic.Warning(WarningCode.DuplicateAttribute, [ tId.Name ])) |> Seq.singleton @@ -506,7 +507,7 @@ type NamespaceManager(syncRoot: IReaderWriterLock, // the attribute marks an entry point elif tId |> isBuiltIn BuiltIn.EntryPoint then - let register, msgs = validateEntryPoint parent (att.Offset, tId.Range) decl + let register, msgs = validateEntryPoint parent (att.Offset, att.TypeIdRange) decl errs.AddRange msgs if register @@ -550,7 +551,7 @@ type NamespaceManager(syncRoot: IReaderWriterLock, |> returnInvalid | _ -> (att.Offset, - tId.Range + att.TypeIdRange |> orDefault |> QsCompilerDiagnostic.Error(ErrorCode.InvalidTestAttributePlacement, [])) |> Seq.singleton @@ -563,7 +564,7 @@ type NamespaceManager(syncRoot: IReaderWriterLock, match box decl.Defined with | :? QsSpecializationGenerator -> (att.Offset, - tId.Range + att.TypeIdRange |> orDefault |> QsCompilerDiagnostic.Error(ErrorCode.AttributeInvalidOnSpecialization, [ tId.Name ])) |> Seq.singleton @@ -572,7 +573,7 @@ type NamespaceManager(syncRoot: IReaderWriterLock, attributeHash :: alreadyDefined, att :: resAttr | _ -> (att.Offset, - tId.Range + att.TypeIdRange |> orDefault |> QsCompilerDiagnostic.Error(ErrorCode.ExpectingFullNameAsAttributeArgument, [ tId.Name ])) |> Seq.singleton @@ -583,14 +584,14 @@ type NamespaceManager(syncRoot: IReaderWriterLock, match box decl.Defined with | :? CallableSignature -> (att.Offset, - tId.Range + att.TypeIdRange |> orDefault |> QsCompilerDiagnostic.Error(ErrorCode.AttributeInvalidOnCallable, [ tId.Name ])) |> Seq.singleton |> returnInvalid | :? QsSpecializationGenerator -> (att.Offset, - tId.Range + att.TypeIdRange |> orDefault |> QsCompilerDiagnostic.Error(ErrorCode.AttributeInvalidOnSpecialization, [ tId.Name ])) |> Seq.singleton @@ -602,7 +603,7 @@ type NamespaceManager(syncRoot: IReaderWriterLock, match box decl.Defined with | :? QsSpecializationGenerator -> (att.Offset, - tId.Range + att.TypeIdRange |> orDefault |> QsCompilerDiagnostic.Error(ErrorCode.AttributeInvalidOnSpecialization, [ tId.Name ])) |> Seq.singleton diff --git a/src/QsCompiler/Core/Transformations/TypeTransformation.fs b/src/QsCompiler/Core/Transformations/TypeTransformation.fs index 12ff800f6e..dca60e2d3b 100644 --- a/src/QsCompiler/Core/Transformations/TypeTransformation.fs +++ b/src/QsCompiler/Core/Transformations/TypeTransformation.fs @@ -126,7 +126,8 @@ type TypeTransformationBase(options: TransformationOptions) = // transformation root called on each node - member this.OnType(t: ResolvedType) = + abstract OnType: ResolvedType -> ResolvedType + default this.OnType(t: ResolvedType) = if not options.Enable then t else diff --git a/src/QsCompiler/DataStructures/SyntaxTree.fs b/src/QsCompiler/DataStructures/SyntaxTree.fs index d2601d7c47..91d356a6ae 100644 --- a/src/QsCompiler/DataStructures/SyntaxTree.fs +++ b/src/QsCompiler/DataStructures/SyntaxTree.fs @@ -151,9 +151,26 @@ type QsTypeParameter = override param.GetHashCode() = hash (param.Origin, param.TypeName) /// - /// Returns this type parameter with the given . + /// Returns a copy of this with updated fields. /// - member param.WithOrigin origin = { param with Origin = origin } + member param.With([] ?origin, + [] ?typeName, + [] ?range) = + { param with + Origin = defaultArg origin param.Origin + TypeName = defaultArg typeName param.TypeName + Range = defaultArg range param.Range + } + + /// + /// Creates a new . + /// + static member New(origin, name) = + { + Origin = origin + TypeName = name + Range = Null + } /// used to represent the use of a user defined type within a fully resolved Q# type [] @@ -189,6 +206,28 @@ type UserDefinedType = member this.GetFullName() = { Namespace = this.Namespace; Name = this.Name } + /// + /// Returns a copy of this with updated fields. + /// + member udt.With([] ?ns, + [] ?name, + [] ?range) = + { udt with + Namespace = defaultArg ns udt.Namespace + Name = defaultArg name udt.Name + Range = defaultArg range udt.Range + } + + /// + /// Creates a new . + /// + static member New(ns, name) = + { + Namespace = ns + Name = name + Range = Null + } + /// Fully resolved operation characteristics used to describe the properties of a Q# callable. /// A resolved characteristic expression by construction never contains an empty or invalid set as inner expressions, /// and necessarily contains the property "Adjointable" if it contains the property "SelfAdjoint". @@ -876,17 +915,35 @@ type QsLocalSymbol = type QsDeclarationAttribute = { /// Identifies the user defined type that the attribute instantiates. - /// The range information describes the range occupied by the attribute identifier relative to the attribute offset. /// Is Null only if the correct attribute could not be determined. Attributes set to Null should be ignored. TypeId: QsNullable + + /// + /// The range of relative to . + /// + TypeIdRange: QsNullable + /// Contains the argument with which the attribute is instantiated. Argument: TypedExpression + /// Represents the position in the source file where the attribute is used. Offset: Position + /// contains comments in the code associated with the attached attribute Comments: QsComments } + /// + /// Creates a new . + /// + static member New(typeId, typeIdRange, argument, offset, comments) = + { + TypeId = typeId + TypeIdRange = typeIdRange + Argument = argument + Offset = offset + Comments = comments + } /// Fully resolved Q# callable signature type ResolvedSignature = diff --git a/src/QsCompiler/Transformations/Attributes.cs b/src/QsCompiler/Transformations/Attributes.cs index d86fdc07d8..c15c9e41fa 100644 --- a/src/QsCompiler/Transformations/Attributes.cs +++ b/src/QsCompiler/Transformations/Attributes.cs @@ -32,7 +32,7 @@ private static AttributeId BuildId(QsQualifiedName name) => /// The attribute argument is set to an invalid expression if the given argument is null. /// public static QsDeclarationAttribute BuildAttribute(QsQualifiedName name, TypedExpression arg) => - new QsDeclarationAttribute(BuildId(name), arg ?? SyntaxGenerator.InvalidExpression, Position.Zero, QsComments.Empty); + new QsDeclarationAttribute(BuildId(name), QsNullable.Null, arg, Position.Zero, QsComments.Empty); /// /// Builds a string literal with the given content that can be used as argument to a Q# attribute. diff --git a/src/QsCompiler/Transformations/ContentLifting.cs b/src/QsCompiler/Transformations/ContentLifting.cs index 2814f90bf0..ee285da412 100644 --- a/src/QsCompiler/Transformations/ContentLifting.cs +++ b/src/QsCompiler/Transformations/ContentLifting.cs @@ -437,7 +437,7 @@ public TypeTransformation(SyntaxTreeTransformation parent) public override ResolvedTypeKind OnTypeParameter(QsTypeParameter tp) => // Reroute a type parameter's origin to the newly generated operation !this.SharedState.IsRecursiveIdentifier && this.SharedState.OldName.Equals(tp.Origin) - ? base.OnTypeParameter(tp.WithOrigin(this.SharedState.NewName)) + ? base.OnTypeParameter(tp.With(this.SharedState.NewName)) : base.OnTypeParameter(tp); } } diff --git a/src/QsCompiler/Transformations/SearchAndReplace.cs b/src/QsCompiler/Transformations/SearchAndReplace.cs index cfec1b55b7..9e577a353b 100644 --- a/src/QsCompiler/Transformations/SearchAndReplace.cs +++ b/src/QsCompiler/Transformations/SearchAndReplace.cs @@ -25,8 +25,7 @@ namespace Microsoft.Quantum.QsCompiler.Transformations.SearchAndReplace /// Class that allows to walk the syntax tree and find all locations where a certain identifier occurs. /// If a set of source file names is given on initialization, the search is limited to callables and specializations in those files. /// - public class IdentifierReferences - : SyntaxTreeTransformation + public class IdentifierReferences : SyntaxTreeTransformation { public class Location : IEquatable { @@ -171,7 +170,7 @@ internal void LogIdentifierLocation(TypedExpression ex) } public IdentifierReferences(TransformationState state) - : base(state, TransformationOptions.NoRebuild) + : base(state, TransformationOptions.NoRebuild) { this.Types = new TypeTransformation(this); this.Expressions = new TypedExpressionWalker(this.SharedState.LogIdentifierLocation, this); @@ -180,12 +179,12 @@ public IdentifierReferences(TransformationState state) } public IdentifierReferences(string idName, QsLocation? defaultOffset, IImmutableSet? limitToSourceFiles = null) - : this(new TransformationState(id => id is Identifier.LocalVariable varName && varName.Item == idName, defaultOffset, limitToSourceFiles)) + : this(new TransformationState(id => id is Identifier.LocalVariable varName && varName.Item == idName, defaultOffset, limitToSourceFiles)) { } public IdentifierReferences(QsQualifiedName idName, QsLocation? defaultOffset, IImmutableSet? limitToSourceFiles = null) - : this(new TransformationState(id => id is Identifier.GlobalCallable cName && cName.Item.Equals(idName), defaultOffset, limitToSourceFiles)) + : this(new TransformationState(id => id is Identifier.GlobalCallable cName && cName.Item.Equals(idName), defaultOffset, limitToSourceFiles)) { } @@ -219,39 +218,35 @@ public static ImmutableHashSet Find( // helper classes - private class TypeTransformation - : TypeTransformation + private class TypeTransformation : TypeTransformation { public TypeTransformation(SyntaxTreeTransformation parent) - : base(parent, TransformationOptions.NoRebuild) + : base(parent, TransformationOptions.NoRebuild) { } - public override QsTypeKind OnUserDefinedType(UserDefinedType udt) + public override ResolvedType OnType(ResolvedType type) { - var id = Identifier.NewGlobalCallable(new QsQualifiedName(udt.Namespace, udt.Name)); -#pragma warning disable 618 // UserDefinedType.Range is obsolete. - this.SharedState.LogIdentifierLocation(id, udt.Range); -#pragma warning restore 618 - return QsTypeKind.NewUserDefinedType(udt); - } + switch (type.Resolution) + { + case QsTypeKind.UserDefinedType { Item: var udt }: + var id = Identifier.NewGlobalCallable(new QsQualifiedName(udt.Namespace, udt.Name)); + this.SharedState.LogIdentifierLocation(id, TypeRangeModule.TryRange(type.Range)); + break; + case QsTypeKind.TypeParameter _: + id = Identifier.NewLocalVariable(SyntaxTreeToQsharp.Default.ToCode(type) ?? ""); + this.SharedState.LogIdentifierLocation(id, TypeRangeModule.TryRange(type.Range)); + break; + } - public override QsTypeKind OnTypeParameter(QsTypeParameter tp) - { - var resT = ResolvedType.New(QsTypeKind.NewTypeParameter(tp)); - var id = Identifier.NewLocalVariable(SyntaxTreeToQsharp.Default.ToCode(resT) ?? ""); -#pragma warning disable 618 // QsTypeParameter.Range is obsolete. - this.SharedState.LogIdentifierLocation(id, tp.Range); -#pragma warning restore 618 - return resT.Resolution; + return base.OnType(type); } } - private class StatementTransformation - : StatementTransformation + private class StatementTransformation : StatementTransformation { public StatementTransformation(SyntaxTreeTransformation parent) - : base(parent, TransformationOptions.NoRebuild) + : base(parent, TransformationOptions.NoRebuild) { } @@ -262,11 +257,10 @@ public override QsNullable OnLocation(QsNullable loc) } } - private class NamespaceTransformation - : NamespaceTransformation + private class NamespaceTransformation : NamespaceTransformation { public NamespaceTransformation(SyntaxTreeTransformation parent) - : base(parent, TransformationOptions.NoRebuild) + : base(parent, TransformationOptions.NoRebuild) { } @@ -337,8 +331,7 @@ public override Source OnSource(Source source) /// The location information is relative to the root node, i.e. the start position of the containing specialization /// declaration. /// - public class AccumulateIdentifiers - : SyntaxTreeTransformation + public class AccumulateIdentifiers : SyntaxTreeTransformation { public class TransformationState { @@ -375,7 +368,7 @@ private Action Add(List<(string, QsLocation?)> accumulate) => ( } public AccumulateIdentifiers() - : base(new TransformationState(), TransformationOptions.NoRebuild) + : base(new TransformationState(), TransformationOptions.NoRebuild) { this.Statements = new StatementTransformation(this); this.StatementKinds = new StatementKindTransformation(this); @@ -385,11 +378,10 @@ public AccumulateIdentifiers() // helper classes - private class StatementTransformation - : StatementTransformation + private class StatementTransformation : StatementTransformation { public StatementTransformation(SyntaxTreeTransformation parent) - : base(parent, TransformationOptions.NoRebuild) + : base(parent, TransformationOptions.NoRebuild) { } @@ -401,11 +393,10 @@ public override QsStatement OnStatement(QsStatement stm) } } - private class StatementKindTransformation - : StatementKindTransformation + private class StatementKindTransformation : StatementKindTransformation { public StatementKindTransformation(SyntaxTreeTransformation parent) - : base(parent, TransformationOptions.NoRebuild) + : base(parent, TransformationOptions.NoRebuild) { } @@ -494,8 +485,7 @@ public static QsQualifiedName OriginalNameFromMonomorphized(QsQualifiedName mang /// The original variable name can be recovered by using the static method StripUniqueName. /// This class is *not* threadsafe. /// - public class UniqueVariableNames - : SyntaxTreeTransformation + public class UniqueVariableNames : SyntaxTreeTransformation { public class TransformationState { @@ -522,7 +512,7 @@ internal string GenerateUniqueName(string varName) } public UniqueVariableNames() - : base(new TransformationState()) + : base(new TransformationState()) { this.Statements = new StatementTransformation(this); this.StatementKinds = new StatementKindTransformation(this); @@ -538,11 +528,10 @@ public UniqueVariableNames() // helper classes - private class StatementTransformation - : StatementTransformation + private class StatementTransformation : StatementTransformation { public StatementTransformation(SyntaxTreeTransformation parent) - : base(parent) + : base(parent) { } @@ -550,11 +539,10 @@ public override string OnVariableName(string name) => this.SharedState.TryGetUniqueName(name, out var unique) ? unique : name; } - private class StatementKindTransformation - : StatementKindTransformation + private class StatementKindTransformation : StatementKindTransformation { public StatementKindTransformation(SyntaxTreeTransformation parent) - : base(parent) + : base(parent) { } @@ -566,11 +554,10 @@ syms is SymbolTuple.VariableNameTuple tuple : syms; } - private class ExpressionKindTransformation - : ExpressionKindTransformation + private class ExpressionKindTransformation : ExpressionKindTransformation { public ExpressionKindTransformation(SyntaxTreeTransformation parent) - : base(parent) + : base(parent) { } @@ -609,9 +596,7 @@ internal TransformationState(IImmutableDictionary QsTypeKind.NewUserDefinedType(this.state.RenameUdt(udt)); public override QsTypeKind OnTypeParameter(QsTypeParameter tp) => -#pragma warning disable 618 // QsTypeParameter.Range is obsolete. - QsTypeKind.NewTypeParameter(new QsTypeParameter(this.state.GetNewName(tp.Origin), tp.TypeName, tp.Range)); -#pragma warning restore 618 + QsTypeKind.NewTypeParameter(tp.With(this.state.GetNewName(tp.Origin))); } private class ExpressionKindTransformation : Core.ExpressionKindTransformation @@ -745,7 +728,9 @@ public override QsDeclarationAttribute OnAttribute(QsDeclarationAttribute attrib var typeId = attribute.TypeId.IsValue ? QsNullable.NewValue(this.state.RenameUdt(attribute.TypeId.Item)) : attribute.TypeId; - return new QsDeclarationAttribute(typeId, argument, attribute.Offset, attribute.Comments); + + return new QsDeclarationAttribute( + typeId, attribute.TypeIdRange, argument, attribute.Offset, attribute.Comments); } public override QsCallable OnCallableDeclaration(QsCallable callable) => diff --git a/src/QsCompiler/Transformations/Transformations.csproj b/src/QsCompiler/Transformations/Transformations.csproj index 7325a08cbf..ef6a8be0a9 100644 --- a/src/QsCompiler/Transformations/Transformations.csproj +++ b/src/QsCompiler/Transformations/Transformations.csproj @@ -5,6 +5,7 @@ Library netstandard2.1 Microsoft.Quantum.QsTransformations + Microsoft.Quantum.QsCompiler.Transformations