Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove notion of predicates as types, move predicates back to signatures #6744

Merged
merged 15 commits into from
Feb 12, 2016
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
257 changes: 122 additions & 135 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,10 @@
"category": "Error",
"code": 1227
},
"A type predicate is only allowed in return type position for functions and methods.": {
"category": "Error",
"code": 1228
},
"A type predicate cannot reference a rest parameter.": {
"category": "Error",
"code": 1229
Expand Down
4 changes: 2 additions & 2 deletions src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1940,7 +1940,7 @@ namespace ts {
return finishNode(node);
}

function parseTypePredicate(lhs: Identifier | ThisTypeNode): TypePredicateNode {
function parseThisTypePredicate(lhs: ThisTypeNode): TypePredicateNode {
nextToken();
const node = createNode(SyntaxKind.TypePredicate, lhs.pos) as TypePredicateNode;
node.parameterName = lhs;
Expand Down Expand Up @@ -2399,7 +2399,7 @@ namespace ts {
case SyntaxKind.ThisKeyword: {
const thisKeyword = parseThisTypeNode();
if (token === SyntaxKind.IsKeyword && !scanner.hasPrecedingLineBreak()) {
return parseTypePredicate(thisKeyword);
return parseThisTypePredicate(thisKeyword);
}
else {
return thisKeyword;
Expand Down
21 changes: 10 additions & 11 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1778,7 +1778,8 @@ namespace ts {
buildSignatureDisplay(signatures: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): void;
buildParameterDisplay(parameter: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
buildTypeParameterDisplayFromSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaraiton?: Node, flags?: TypeFormatFlags): void;
buildTypePredicateDisplay(predicate: TypePredicate, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
buildTypeParameterDisplayFromSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
buildDisplayForParametersAndDelimiters(parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
buildDisplayForTypeParametersAndDelimiters(typeParameters: TypeParameter[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
buildReturnTypeDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
Expand Down Expand Up @@ -1843,22 +1844,24 @@ namespace ts {
Identifier
}

export interface TypePredicate {
export interface TypePredicateBase {
kind: TypePredicateKind;
type: Type;
}

// @kind (TypePredicateKind.This)
export interface ThisTypePredicate extends TypePredicate {
export interface ThisTypePredicate extends TypePredicateBase {
_thisTypePredicateBrand: any;
}

// @kind (TypePredicateKind.Identifier)
export interface IdentifierTypePredicate extends TypePredicate {
export interface IdentifierTypePredicate extends TypePredicateBase {
parameterName: string;
parameterIndex: number;
}

export type TypePredicate = IdentifierTypePredicate | ThisTypePredicate;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


/* @internal */
export type AnyImportSyntax = ImportDeclaration | ImportEqualsDeclaration;

Expand Down Expand Up @@ -2122,7 +2125,6 @@ namespace ts {
ESSymbol = 0x01000000, // Type of symbol primitive introduced in ES6
ThisType = 0x02000000, // This type
ObjectLiteralPatternWithComputedProperties = 0x04000000, // Object literal type implied by binding pattern has computed properties
PredicateType = 0x08000000, // Predicate types are also Boolean types, but should not be considered Intrinsics - there's no way to capture this with flags

/* @internal */
Intrinsic = Any | String | Number | Boolean | ESSymbol | Void | Undefined | Null,
Expand All @@ -2134,7 +2136,7 @@ namespace ts {
UnionOrIntersection = Union | Intersection,
StructuredType = ObjectType | Union | Intersection,
/* @internal */
RequiresWidening = ContainsUndefinedOrNull | ContainsObjectLiteral | PredicateType,
RequiresWidening = ContainsUndefinedOrNull | ContainsObjectLiteral,
/* @internal */
PropagatingFlags = ContainsUndefinedOrNull | ContainsObjectLiteral | ContainsAnyFunctionType
}
Expand All @@ -2155,11 +2157,6 @@ namespace ts {
intrinsicName: string; // Name of intrinsic type
}

// Predicate types (TypeFlags.Predicate)
export interface PredicateType extends Type {
predicate: ThisTypePredicate | IdentifierTypePredicate;
}

// String literal types (TypeFlags.StringLiteral)
export interface StringLiteralType extends Type {
text: string; // Text of string literal
Expand Down Expand Up @@ -2294,6 +2291,8 @@ namespace ts {
erasedSignatureCache?: Signature; // Erased version of signature (deferred)
/* @internal */
isolatedSignatureType?: ObjectType; // A manufactured type that just contains the signature for purposes of signature comparison
/* @internal */
typePredicate?: TypePredicate;
}

export const enum IndexKind {
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,10 @@ namespace ts {
return predicate && predicate.kind === TypePredicateKind.Identifier;
}

export function isThisTypePredicate(predicate: TypePredicate): predicate is ThisTypePredicate {
return predicate && predicate.kind === TypePredicateKind.This;
}

export function getContainingFunction(node: Node): FunctionLikeDeclaration {
while (true) {
node = node.parent;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ var obj: Object;
>Object : Object

if (ArrayBuffer.isView(obj)) {
>ArrayBuffer.isView(obj) : arg is ArrayBufferView
>ArrayBuffer.isView(obj) : boolean
>ArrayBuffer.isView : (arg: any) => arg is ArrayBufferView
>ArrayBuffer : ArrayBufferConstructor
>isView : (arg: any) => arg is ArrayBufferView
Expand Down
16 changes: 16 additions & 0 deletions tests/baselines/reference/declarationEmitIdentifierPredicates01.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//// [declarationEmitIdentifierPredicates01.ts]

export function f(x: any): x is number {
return typeof x === "number";
}

//// [declarationEmitIdentifierPredicates01.js]
"use strict";
function f(x) {
return typeof x === "number";
}
exports.f = f;


//// [declarationEmitIdentifierPredicates01.d.ts]
export declare function f(x: any): x is number;
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
=== tests/cases/conformance/declarationEmit/typePredicates/declarationEmitIdentifierPredicates01.ts ===

export function f(x: any): x is number {
>f : Symbol(f, Decl(declarationEmitIdentifierPredicates01.ts, 0, 0))
>x : Symbol(x, Decl(declarationEmitIdentifierPredicates01.ts, 1, 18))
>x : Symbol(x, Decl(declarationEmitIdentifierPredicates01.ts, 1, 18))

return typeof x === "number";
>x : Symbol(x, Decl(declarationEmitIdentifierPredicates01.ts, 1, 18))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
=== tests/cases/conformance/declarationEmit/typePredicates/declarationEmitIdentifierPredicates01.ts ===

export function f(x: any): x is number {
>f : (x: any) => x is number
>x : any
>x : any

return typeof x === "number";
>typeof x === "number" : boolean
>typeof x : string
>x : any
>"number" : string
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
tests/cases/conformance/declarationEmit/typePredicates/declarationEmitIdentifierPredicatesWithPrivateName01.ts(6,33): error TS4060: Return type of exported function has or is using private name 'I'.


==== tests/cases/conformance/declarationEmit/typePredicates/declarationEmitIdentifierPredicatesWithPrivateName01.ts (1 errors) ====

interface I {
a: number;
}

export function f(x: any): x is I {
~
!!! error TS4060: Return type of exported function has or is using private name 'I'.
return typeof x.a === "number";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//// [declarationEmitIdentifierPredicatesWithPrivateName01.ts]

interface I {
a: number;
}

export function f(x: any): x is I {
return typeof x.a === "number";
}

//// [declarationEmitIdentifierPredicatesWithPrivateName01.js]
"use strict";
function f(x) {
return typeof x.a === "number";
}
exports.f = f;
43 changes: 43 additions & 0 deletions tests/baselines/reference/declarationEmitThisPredicates01.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//// [declarationEmitThisPredicates01.ts]

export class C {
m(): this is D {
return this instanceof D;
}
}

export class D extends C {
}

//// [declarationEmitThisPredicates01.js]
"use strict";
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var C = (function () {
function C() {
}
C.prototype.m = function () {
return this instanceof D;
};
return C;
}());
exports.C = C;
var D = (function (_super) {
__extends(D, _super);
function D() {
_super.apply(this, arguments);
}
return D;
}(C));
exports.D = D;


//// [declarationEmitThisPredicates01.d.ts]
export declare class C {
m(): this is D;
}
export declare class D extends C {
}
19 changes: 19 additions & 0 deletions tests/baselines/reference/declarationEmitThisPredicates01.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
=== tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicates01.ts ===

export class C {
>C : Symbol(C, Decl(declarationEmitThisPredicates01.ts, 0, 0))

m(): this is D {
>m : Symbol(m, Decl(declarationEmitThisPredicates01.ts, 1, 16))
>D : Symbol(D, Decl(declarationEmitThisPredicates01.ts, 5, 1))

return this instanceof D;
>this : Symbol(C, Decl(declarationEmitThisPredicates01.ts, 0, 0))
>D : Symbol(D, Decl(declarationEmitThisPredicates01.ts, 5, 1))
}
}

export class D extends C {
>D : Symbol(D, Decl(declarationEmitThisPredicates01.ts, 5, 1))
>C : Symbol(C, Decl(declarationEmitThisPredicates01.ts, 0, 0))
}
20 changes: 20 additions & 0 deletions tests/baselines/reference/declarationEmitThisPredicates01.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
=== tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicates01.ts ===

export class C {
>C : C

m(): this is D {
>m : () => this is D
>D : D

return this instanceof D;
>this instanceof D : boolean
>this : this
>D : typeof D
}
}

export class D extends C {
>D : D
>C : C
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicates02.ts(9,10): error TS2526: A 'this' type is available only in a non-static member of a class or interface.


==== tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicates02.ts (1 errors) ====

export interface Foo {
a: string;
b: number;
c: boolean;
}

export const obj = {
m(): this is Foo {
~~~~
!!! error TS2526: A 'this' type is available only in a non-static member of a class or interface.
let dis = this as Foo;
return dis.a != null && dis.b != null && dis.c != null;
}
}
34 changes: 34 additions & 0 deletions tests/baselines/reference/declarationEmitThisPredicates02.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//// [declarationEmitThisPredicates02.ts]

export interface Foo {
a: string;
b: number;
c: boolean;
}

export const obj = {
m(): this is Foo {
let dis = this as Foo;
return dis.a != null && dis.b != null && dis.c != null;
}
}

//// [declarationEmitThisPredicates02.js]
"use strict";
exports.obj = {
m: function () {
var dis = this;
return dis.a != null && dis.b != null && dis.c != null;
}
};


//// [declarationEmitThisPredicates02.d.ts]
export interface Foo {
a: string;
b: number;
c: boolean;
}
export declare const obj: {
m(): this is Foo;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicatesWithPrivateName01.ts(3,18): error TS4055: Return type of public method from exported class has or is using private name 'D'.


==== tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicatesWithPrivateName01.ts (1 errors) ====

export class C {
m(): this is D {
~
!!! error TS4055: Return type of public method from exported class has or is using private name 'D'.
return this instanceof D;
}
}

class D extends C {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//// [declarationEmitThisPredicatesWithPrivateName01.ts]

export class C {
m(): this is D {
return this instanceof D;
}
}

class D extends C {
}

//// [declarationEmitThisPredicatesWithPrivateName01.js]
"use strict";
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var C = (function () {
function C() {
}
C.prototype.m = function () {
return this instanceof D;
};
return C;
}());
exports.C = C;
var D = (function (_super) {
__extends(D, _super);
function D() {
_super.apply(this, arguments);
}
return D;
}(C));
Loading