Fixed a few bugs in generics processing.

This commit is contained in:
Eric Traut 2019-03-14 17:33:46 -07:00
parent 4f270b62d7
commit 9f3b20bfc1
2 changed files with 53 additions and 14 deletions

View File

@ -1300,7 +1300,9 @@ export class TypeAnalyzer extends ParseTreeWalker {
node.entries.forEach(expr => {
this._getTypeOfExpression(expr);
});
exprType = TypeAnnotation.getBuiltInObject(this._currentScope, 'list');
// TODO - infer list type
exprType = TypeAnnotation.getBuiltInObject(
this._currentScope, 'list', []);
} else if (node instanceof SliceExpressionNode) {
// TODO - need to implement
if (node.startValue) {
@ -1312,7 +1314,9 @@ export class TypeAnalyzer extends ParseTreeWalker {
if (node.stepValue) {
this._getTypeOfExpression(node.stepValue);
}
exprType = TypeAnnotation.getBuiltInObject(this._currentScope, 'set');
// TODO - infer set type
exprType = TypeAnnotation.getBuiltInObject(
this._currentScope, 'set', []);
} else if (node instanceof AwaitExpressionNode) {
// TODO - need to implement
exprType = this._getTypeOfExpression(node.expression);
@ -1323,18 +1327,23 @@ export class TypeAnalyzer extends ParseTreeWalker {
let rightType = this._getTypeOfExpression(node.elseExpression);
exprType = TypeUtils.combineTypes(leftType, rightType);
} else if (node instanceof ListComprehensionNode) {
// TODO - need to implement
// TODO - infer list type
this._getTypeOfExpression(node.baseExpression);
exprType = TypeAnnotation.getBuiltInObject(this._currentScope, 'list');
exprType = TypeAnnotation.getBuiltInObject(
this._currentScope, 'list', []);
} else if (node instanceof DictionaryNode) {
exprType = TypeAnnotation.getBuiltInObject(this._currentScope, 'dict');
// TODO - infer dict type
exprType = TypeAnnotation.getBuiltInObject(
this._currentScope, 'dict', []);
} else if (node instanceof LambdaNode) {
exprType = AnalyzerNodeInfo.getExpressionType(node);
} else if (node instanceof SetNode) {
node.entries.forEach(expr => {
this._getTypeOfExpression(expr);
});
exprType = TypeAnnotation.getBuiltInObject(this._currentScope, 'set');
// TODO - infer set type
exprType = TypeAnnotation.getBuiltInObject(
this._currentScope, 'set', []);
} else if (node instanceof AssignmentNode) {
this._getTypeOfExpression(node.rightExpression);
exprType = this._getTypeOfExpression(node.leftExpression);

View File

@ -157,16 +157,19 @@ export class TypeAnnotation {
initType.setDeclaredReturnType(NoneType.create());
initType.addParameter(selfParameter);
let addGenericGetAttribute = false;
if (node.arguments.length < 2) {
diagSink.addErrorWithTextRange('Expected named tuple entry list as second parameter',
node.leftExpression);
addGenericGetAttribute = true;
} else {
const entriesArg = node.arguments[1];
if (entriesArg.argumentCategory !== ArgumentCategory.Simple ||
!(entriesArg.valueExpression instanceof ListNode)) {
diagSink.addErrorWithTextRange(
'Expected named tuple entry list as second parameter',
entriesArg.valueExpression);
// A dynamic expression was used, so we can't evaluate
// the named tuple statically.
addGenericGetAttribute = true;
} else {
const entryList = entriesArg.valueExpression;
let entryMap: { [name: string]: string } = {};
@ -237,7 +240,8 @@ export class TypeAnnotation {
classFields.set('__init__', new Symbol(initType, DefaultTypeSourceId));
let keysItemType = new FunctionType(FunctionTypeFlags.None);
keysItemType.setDeclaredReturnType(this.getBuiltInObject(currentScope, 'list'));
keysItemType.setDeclaredReturnType(this.getBuiltInObject(currentScope, 'list',
[this.getBuiltInObject(currentScope, 'str')]));
classFields.set('keys', new Symbol(keysItemType, DefaultTypeSourceId));
classFields.set('items', new Symbol(keysItemType, DefaultTypeSourceId));
@ -246,6 +250,18 @@ export class TypeAnnotation {
lenType.addParameter(selfParameter);
classFields.set('__len__', new Symbol(lenType, DefaultTypeSourceId));
if (addGenericGetAttribute) {
let getAttribType = new FunctionType(FunctionTypeFlags.InstanceMethod);
getAttribType.setDeclaredReturnType(AnyType.create());
getAttribType.addParameter(selfParameter);
getAttribType.addParameter({
category: ParameterCategory.Simple,
name: 'name',
type: this.getBuiltInObject(currentScope, 'str')
});
classFields.set('__getattribute__', new Symbol(getAttribType, DefaultTypeSourceId));
}
return classType;
}
@ -265,10 +281,17 @@ export class TypeAnnotation {
return UnknownType.create();
}
static getBuiltInObject(currentScope: Scope, className: string): Type {
static getBuiltInObject(currentScope: Scope, className: string,
typeArguments?: Type[]): Type {
let nameType = this.getBuiltInType(currentScope, className);
if (nameType instanceof ClassType) {
return new ObjectType(nameType);
let classType = nameType;
if (typeArguments) {
classType = classType.cloneForSpecialization();
classType.setTypeArguments(typeArguments);
}
return new ObjectType(classType);
}
return nameType;
@ -590,8 +613,15 @@ export class TypeAnnotation {
}
if (!type) {
type = this._createSpecializedClassType(baseTypeResult.type,
typeArgs, diagSink);
if (baseTypeResult.type === this.getBuiltInType(currentScope, 'type')) {
// The built-in 'type' class isn't defined as a generic class. It needs
// to be special-cased here.
type = this._createTypeType(node, typeArgs, diagSink);
isClassType = true;
} else {
type = this._createSpecializedClassType(baseTypeResult.type,
typeArgs, diagSink);
}
}
} else if (!baseTypeResult.type.isAny()) {
diagSink.addErrorWithTextRange(