diff --git a/packages/pyright-internal/src/analyzer/typeEvaluator.ts b/packages/pyright-internal/src/analyzer/typeEvaluator.ts index 360390c7993c..ba18d1f00cd6 100644 --- a/packages/pyright-internal/src/analyzer/typeEvaluator.ts +++ b/packages/pyright-internal/src/analyzer/typeEvaluator.ts @@ -5389,6 +5389,8 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions assertNever(baseType); } + // If type is undefined, emit a general error message indicating that the + // member could not be accessed. if (!type) { const isFunctionRule = isFunction(baseType) || @@ -5847,6 +5849,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions bindToClass, classType ); + if (specializedBoundType) { if ( isFunction(specializedBoundType) || @@ -5906,6 +5909,13 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions Localizer.Diagnostic.noOverload().format({ name: accessMethodName }) ); } + } else { + diag?.addMessage( + Localizer.DiagnosticAddendum.descriptorAccessCallFailed().format({ + name: accessMethodName, + className: printType(convertToInstance(accessMethod.classType)), + }) + ); } isTypeValid = false; @@ -5918,6 +5928,13 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions : AnyType.create(); } + diag?.addMessage( + Localizer.DiagnosticAddendum.descriptorAccessBindingFailed().format({ + name: accessMethodName, + className: printType(convertToInstance(accessMethod.classType)), + }) + ); + isTypeValid = false; return undefined; }); diff --git a/packages/pyright-internal/src/localization/localize.ts b/packages/pyright-internal/src/localization/localize.ts index e8bfc6ada081..cd9c19241832 100644 --- a/packages/pyright-internal/src/localization/localize.ts +++ b/packages/pyright-internal/src/localization/localize.ts @@ -1165,6 +1165,14 @@ export namespace Localizer { export const dataClassFrozen = () => new ParameterizedString<{ name: string }>(getRawString('DiagnosticAddendum.dataClassFrozen')); export const dataClassFieldLocation = () => getRawString('DiagnosticAddendum.dataClassFieldLocation'); + export const descriptorAccessBindingFailed = () => + new ParameterizedString<{ name: string; className: string }>( + getRawString('DiagnosticAddendum.descriptorAccessBindingFailed') + ); + export const descriptorAccessCallFailed = () => + new ParameterizedString<{ name: string; className: string }>( + getRawString('DiagnosticAddendum.descriptorAccessCallFailed') + ); export const finalMethod = () => getRawString('DiagnosticAddendum.finalMethod'); export const functionParamDefaultMissing = () => new ParameterizedString<{ name: string }>(getRawString('DiagnosticAddendum.functionParamDefaultMissing')); diff --git a/packages/pyright-internal/src/localization/package.nls.en-us.json b/packages/pyright-internal/src/localization/package.nls.en-us.json index eb93dce2c809..6bf241661f88 100644 --- a/packages/pyright-internal/src/localization/package.nls.en-us.json +++ b/packages/pyright-internal/src/localization/package.nls.en-us.json @@ -593,6 +593,8 @@ "bytesTypePromotions": "Set disableBytesTypePromotions to false to enable type promotion behavior for \"bytearray\" and \"memoryview\"", "conditionalRequiresBool": "Method __bool__ for type \"{operandType}\" returns type \"{boolReturnType}\" rather than \"bool\"", "dataClassFieldLocation": "Field declaration", + "descriptorAccessBindingFailed": "Failed to bind method \"{name}\" for class \"{className}\"", + "descriptorAccessCallFailed": "Failed to call method \"{name}\" for class \"{className}\"", "dataClassFrozen": "\"{name}\" is frozen", "finalMethod": "Final method", "keyNotRequired": "\"{name}\" is not a required key in \"{type}\", so access may result in runtime exception",