Added configuration option "strictSetInference" which is analogous to "strictListInference" and "strictDictionaryInference" but specifically for set expressions.

This commit is contained in:
Eric Traut 2021-04-03 08:35:40 -07:00
parent 4d2c913ad9
commit 4f03ba88c0
6 changed files with 49 additions and 1 deletions

View File

@ -44,6 +44,8 @@ The following settings control pyrights diagnostic output (warnings or errors
**strictDictionaryInference** [boolean]: When inferring the type of a dictionarys keys and values, use strict type assumptions. For example, the expression `{'a': 1, 'b': 'a'}` could be inferred to be of type `Dict[str, Any]` or `Dict[str, Union[int, str]]`. If this setting is true, it will use the latter (stricter) type. The default value for this setting is 'false'.
**strictSetInference** [boolean]: When inferring the type of a set, use strict type assumptions. For example, the expression `{1, 'a', 3.4}` could be inferred to be of type `Set[Any]` or `Set[Union[int, str, float]]`. If this setting is true, it will use the latter (stricter) type. The default value for this setting is 'false'.
**strictParameterNoneValue** [boolean]: PEP 484 indicates that when a function parameter is assigned a default value of None, its type should implicitly be Optional even if the explicit type is not. When enabled, this rule requires that parameter type annotations use Optional explicitly in this case. The default value for this setting is 'false'.
**enableTypeIgnoreComments** [boolean]: PEP 484 defines support for "# type: ignore" comments. This switch enables or disables support for these comments. The default value for this setting is 'true'.

View File

@ -257,6 +257,29 @@ var4: List[float] = [1, 3.4] # Infer List[float]
```
### Set Expressions
When inferring the type of a set expression (in the absence of bidirectional inference hints), Pyright uses the following heuristics:
1. If the set contains at least one element and all elements are the same type T, infer the type `Set[T]`.
2. If the set contains multiple elements that are of different types, the behavior depends on the `strictSetInference` configuration setting. By default this setting is off.
* If `strictSetInference` is off, infer `Set[Unknown]`.
* Otherwise use the union of all element types and infer `Set[Union[(elements)]]`.
These heuristics can be overridden through the use of bidirectional inference hints (e.g. by providing a declared type for the target of the assignment expression).
```python
var1 = {1, 2} # Infer Set[int]
# Type depends on strictSetInference config setting
var2 = {1, 3.4} # Infer Set[Unknown] (off)
var2 = {1, 3.4} # Infer Set[Union[int, float]] (on)
var3: Set[float] = {1, 3.4} # Infer Set[float]
```
### Dictionary Expressions
When inferring the type of a dictionary expression (in the absence of bidirectional inference hints), Pyright uses the following heuristics:

View File

@ -10083,10 +10083,12 @@ export function createTypeEvaluator(
let inferredEntryType: Type = expectedType ? AnyType.create() : UnknownType.create();
if (entryTypes.length > 0) {
const fileInfo = getFileInfo(node);
// If there was an expected type or we're using strict list inference,
// combine the types into a union.
if (
(builtInClassName === 'list' && getFileInfo(node).diagnosticRuleSet.strictListInference) ||
(builtInClassName === 'list' && fileInfo.diagnosticRuleSet.strictListInference) ||
(builtInClassName === 'set' && fileInfo.diagnosticRuleSet.strictSetInference) ||
!!expectedType
) {
inferredEntryType = combineTypes(entryTypes, maxSubtypesForInferredType);

View File

@ -84,6 +84,9 @@ export interface DiagnosticRuleSet {
// Use strict inference rules for list expressions?
strictListInference: boolean;
// Use strict inference rules for set expressions?
strictSetInference: boolean;
// Use strict inference rules for dictionary expressions?
strictDictionaryInference: boolean;
@ -260,6 +263,7 @@ export function cloneDiagnosticRuleSet(diagSettings: DiagnosticRuleSet): Diagnos
export function getBooleanDiagnosticRules() {
return [
DiagnosticRule.strictListInference,
DiagnosticRule.strictSetInference,
DiagnosticRule.strictDictionaryInference,
DiagnosticRule.strictParameterNoneValue,
@ -337,6 +341,7 @@ export function getOffDiagnosticRuleSet(): DiagnosticRuleSet {
omitUnannotatedParamType: true,
pep604Printing: true,
strictListInference: false,
strictSetInference: false,
strictDictionaryInference: false,
strictParameterNoneValue: false,
enableTypeIgnoreComments: true,
@ -401,6 +406,7 @@ export function getBasicDiagnosticRuleSet(): DiagnosticRuleSet {
omitUnannotatedParamType: true,
pep604Printing: true,
strictListInference: false,
strictSetInference: false,
strictDictionaryInference: false,
strictParameterNoneValue: false,
enableTypeIgnoreComments: true,
@ -465,6 +471,7 @@ export function getStrictDiagnosticRuleSet(): DiagnosticRuleSet {
omitUnannotatedParamType: false,
pep604Printing: true,
strictListInference: true,
strictSetInference: true,
strictDictionaryInference: true,
strictParameterNoneValue: true,
enableTypeIgnoreComments: true, // Not overridden by strict mode
@ -813,6 +820,13 @@ export class ConfigOptions {
defaultSettings.strictListInference
),
// Use strict inference rules for set expressions?
strictSetInference: this._convertBoolean(
configObj.strictSetInference,
DiagnosticRule.strictSetInference,
defaultSettings.strictSetInference
),
// Use strict inference rules for dictionary expressions?
strictDictionaryInference: this._convertBoolean(
configObj.strictDictionaryInference,

View File

@ -12,6 +12,7 @@
// to match declaration of user-visible settings in package.json
export enum DiagnosticRule {
strictListInference = 'strictListInference',
strictSetInference = 'strictSetInference',
strictDictionaryInference = 'strictDictionaryInference',
strictParameterNoneValue = 'strictParameterNoneValue',
enableTypeIgnoreComments = 'enableTypeIgnoreComments',

View File

@ -107,6 +107,12 @@
"title": "Infer strict types for list expressions",
"default": false
},
"strictSetInference": {
"$id": "#/properties/strictSetInference",
"type": "boolean",
"title": "Infer strict types for set expressions",
"default": false
},
"strictDictionaryInference": {
"$id": "#/properties/strictDictionaryInference",
"type": "boolean",