Skip to content

[DiagnosticsQoI] Fully Qualify the Parent Type When Diagnosing Missing Member Types #34648

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

Merged
merged 2 commits into from
Nov 10, 2020

Conversation

CodaFi
Copy link
Contributor

@CodaFi CodaFi commented Nov 9, 2020

Teach the diagnostic engine about a new wrapper type FullyQualified<T>. The intent is to clarify which parameters will be printed with additional qualification in diagnostic text. For now, this is only useful for types, so there's a bit of SFINAE guarding against misuse of the abstraction.

rdar://63199963

Teach the diagnostic engine about a new wrapper type `FullyQualified<T>`. The intent is to clarify which parameters will be printed with additional qualification in diagnostic text. For now, this is only useful for types, so there's a bit of SFINAE guarding against misuse of the abstraction.

 rdar://63199963
@CodaFi
Copy link
Contributor Author

CodaFi commented Nov 9, 2020

@swift-ci smoke test

Copy link
Contributor

@beccadax beccadax left a comment

Choose a reason for hiding this comment

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

Nice!

case DiagnosticArgumentKind::Type: {
assert(Modifier.empty() && "Improper modifier for Type argument");

// Strip extraneous parentheses; they add no value.
auto type = Arg.getAsType()->getWithoutParens();
Type type;
bool needsQualification = false;
Copy link
Contributor

Choose a reason for hiding this comment

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

While you are here, what do you think about enabling this by default for generic parameters? It's very common to name generic parameters like T or U which results in diagnostics that say something like "T is not convertible to T" and it would be much better to always qualify it to avoid confusion.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think something like a DescriptiveTypeKind would help out there too.

T is not convertible to generic parameter T

Copy link
Contributor

Choose a reason for hiding this comment

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

The problem is in most cases we don't know what type we'd get in conversion diagnostics so it'd be better to always qualify generic parameters...

Copy link
Contributor

Choose a reason for hiding this comment

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

e.g.

protocol P {}
func foo<T: P>(_: T) {}
func bar<T>(t: T) {
  foo(t)
}

This would produce a note which says where 'T' = 'T'

Copy link
Contributor

Choose a reason for hiding this comment

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

I think it would have been better if it did say where 'T' = generic parameter bar.T or something similar.

Copy link
Contributor

Choose a reason for hiding this comment

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

Another example with shadowing:

protocol MyProtocol {}

struct Generic<M: MyProtocol> {
    var values: [M] = []

    func valueAt<M>(_ index: Int) -> M? {
        if values.indices.contains(index) {
            return values[index]
        } else {
            return nil
        }
    }
}

Currently results in cannot convert return expression of type 'M' to return type 'M?'

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point. I'll build the abstractions for this in a follow-up.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sounds great, thank you!

Use the FullyQualified<Type> abstraction from the prior commit plus DescriptiveDeclKind to give a bit more information when issuing a missing member type diagnostic during type resolution.
@CodaFi CodaFi force-pushed the a-fully-qualified-success branch from 4bdf90d to 363b66a Compare November 10, 2020 01:10
@CodaFi
Copy link
Contributor Author

CodaFi commented Nov 10, 2020

@swift-ci smoke test

@CodaFi CodaFi merged commit 4dab4c2 into swiftlang:main Nov 10, 2020
@CodaFi CodaFi deleted the a-fully-qualified-success branch November 10, 2020 05:32
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.

3 participants