Skip to content

[NFC] Change diagnostic text mentioning 'undeclared type'/'unresolved identifier' #31315

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

Conversation

varungandhi-apple
Copy link
Contributor

@varungandhi-apple varungandhi-apple commented Apr 25, 2020

TL;DR: I changed "use of undeclared type %0" -> "couldn't find definition of type %0", and "use of unresolved identifier" -> "couldn't find definition of"

Undeclared type diagnostic

The current diagnostic seems unclear from a user-perspective as to what "undeclared type" means, especially if you have not written C/ObjC/C++ before, which do have a distinct notion of declaring types in the surface language, as opposed to only being able to define types. It also potentially nudges the reader familiar with C/ObjC/C++ but new to Swift in an incorrect direction: "ok, this type is undeclared, can I declare it somehow and get rid of this error?" (The answer is you can't; you need to define it or import it.)

While the newer diagnostic is not technically as accurate (e.g. you can have a declaration of a type in a swiftinterface without a definition), that's not really something people write in Swift code (unless this is a part of the language that I don't know about?). So I think the newer diagnostic matches the user model better.

For comparison, Rust says:

cannot find type `T` in this scope

which also seems like a reasonable alternative (although it mentions 'scope' which seems a bit unnecessary perhaps, even though it is technically correct).

Elm is a bit more verbose: (e.g. type X = MakeX { x : Foo })

I cannot find a `Foo` type:
[..]
Hint: Read <https://elm-lang.org/0.19.1/imports> to see how `import`
declarations work in Elm.

Unresolved identifier diagnostic

The basic reasoning is the same as before: "unresolved identifier" is compiler jargon which a user does not necessarily need to care about. Instead we can simply say that we could not find the definition. We could also do something like Rust where we say "cannot find $thing in scope".

Misc Notes

  1. I don't particularly care about the tense. If you think it should be cannot instead of couldn't, I'll change that, nbd.

  2. I read through docs/Diagnostics.md and I don't think the recommendation of "phrase diagnostics as rules rather than reporting that the compiler failed to do something" is a good one. If we follow that recommendation, the diagnostic would look like:

    definition of $thing cannot be found in scope
    

    That seems overly aggressive IMO. Moreover, the point of the diagnostic here is not to describe a fundamental language rule (one about scoping and define-before-use), but to gently point out what went wrong. Of course, nothing's perfect, but I think it makes sense to not follow that recommendation here.

@varungandhi-apple
Copy link
Contributor Author

@swift-ci please test

@varungandhi-apple varungandhi-apple changed the title [NFC] Change diagnostic text mentioning 'undeclared type' [NFC] Change diagnostic text mentioning 'undeclared type'/'unresolved identifier' Apr 25, 2020
@varungandhi-apple
Copy link
Contributor Author

@swift-ci please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - f335438c4e23a7980816f9beb9b9874cac8bf345

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - f335438c4e23a7980816f9beb9b9874cac8bf345

@varungandhi-apple
Copy link
Contributor Author

Tracking rdar://problem/62375243.

@hborla
Copy link
Member

hborla commented Apr 27, 2020

While the newer diagnostic is not technically as accurate (e.g. you can have a declaration of a type in a swiftinterface without a definition), that's not really something people write in Swift code (unless this is a part of the language that I don't know about?)

Could this be misleading in the context of protocol requirements? This is the one place I can think of where you're declaring things without providing a definition, and I'm wondering if that might cause confusion.

I read through docs/Diagnostics.md and I don't think the recommendation of "phrase diagnostics as rules rather than reporting that the compiler failed to do something" is a good one.

I think at some point we should re-evaluate the rules laid out in Diagnostics.md. This particular rule does seem to encourage more clinical language, which is not very friendly to the user and often leads to these really jargony messages.

@varungandhi-apple
Copy link
Contributor Author

Could this be misleading in the context of protocol requirements? This is the one place I can think of where you're declaring things without providing a definition, and I'm wondering if that might cause confusion.

Like in a function signature f<T : P>(_ t : T) -> ()? Or something else?

@hborla
Copy link
Member

hborla commented Apr 27, 2020

I just mean in general. Say a user is trying to call a function that is a protocol requirement, and they make a typo. Now, they will get the error message couldn't find definition of X. This could be really misleading because the user might think the error has to do with the conformance to that protocol. The error message isn't telling them that X doesn't exist.

protocol P {
  func somethingEasyToMisspell()
}



class C: P {
  func somethingEasyToMisspell() {
    // do something
  }

  func test() {
    somethingEasyToMispell() // error: couldn't find definition of `somethingEasyToMispell`
  }
}

@varungandhi-apple
Copy link
Contributor Author

I see what you mean, that makes sense. How about cannot find type X in scope/cannot find X in scope? That doesn't seem to have this problem. Any other ideas?

@varungandhi-apple
Copy link
Contributor Author

[Note to self: The test failures were due to LLDB -- it also needs to be updated since it is matching on the diagnostics.]

@hborla
Copy link
Member

hborla commented Apr 27, 2020

I agree that dropping definition and being specific about the kind of entity (if we can) avoids this problem. I like cannot find type X in scope/cannot find X in scope (and I haven't come up with anything better).

FWIW I don't think the word scope is jargon - this is a fundamental concept that programmers either will already know, or they will learn. This might be a good concept to explain in an educational note for this diagnostic (later, not in this PR 🙂).

@varungandhi-apple varungandhi-apple force-pushed the vg-improve-undeclared-type-diagnostic branch from 5dead8a to e2336c3 Compare April 27, 2020 21:04
@varungandhi-apple
Copy link
Contributor Author

Updated code to use cannot find X in scope/cannot find type X in scope.

Matching LLDB PR: swiftlang/llvm-project#1128

@swift-ci please test

@varungandhi-apple

This comment has been minimized.

@swift-ci

This comment has been minimized.

@swift-ci

This comment has been minimized.

@varungandhi-apple
Copy link
Contributor Author

swiftlang/llvm-project#1128

@swift-ci please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 4a48c02

Copy link
Member

@hborla hborla left a comment

Choose a reason for hiding this comment

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

The more I look at the test cases, the more I like cannot find [type/label/etc] X in scope. The previous message always seemed to indicate that the thing doesn't exist, but in scope adds another angle – I've definitely hit this error before when the type I'm trying to use isn't in scope

@varungandhi-apple
Copy link
Contributor Author

An LLDB test seems to be randomly failing. 😐

swiftlang/llvm-project#1128

@swift-ci please test

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants