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
[SR-12672] Misleading diagnostic "type 'Any' has no member" #55116
Comments
@swift-ci create |
I just realized my mistake; I've had the wrong mental model for the past 9 months! We don't infer base types, we only check them. So it's not really possible to provide a diagnostic like "// note: the types 'E1' and 'E2' both have a member 'e' " because we don't have that information available; figuring that out would require going through all the types in scope (I had guessed that we were already doing that to infer base types, but apparently not). Instead, we should be saying something like error: cannot infer contextual base in reference to member 'e' which is what would happen if the code had something like `.some(.e)` instead of `[.e]`. Maybe I'm missing something on why we don't provide that error and talk about `Any` here. |
theindigamer (JIRA User) I was looking into this, seems that because of the Array literal initializer and the constraint where ArrayLiteralElement can default to Any the solver is attempting a binding for the array type Array<Any> which leads to .e := Any and recording a define missing member fix. And I think because of the rules around score and impact that end up the solution being diagnosed instead of many ambiguous fixes produced and diagnose it on DefineMemberBasedOnUse::diagnoseForAmbiguity where the unresolved_member_no_inference is produced. |
Thanks for looking into it Luciano! You mention > constraint where ArrayLiteralElement can default to Any That seems surprising to me. I'm looking at the test cases in the compiler and it seems like when we are doing inference for array literals, we don't really return `Array<Any>` as the type of an array literal – is that correct? We only assign the type `Array<Any>` to a literal in checking mode. We even have an error for this: heterogeneous collection literal could only be inferred to '[Any]'; add explicit type annotation if this is intentional If my understanding is correct, could we make it so that:
What do you think? (To be clear, I'm describing things in terms of my mental model of how the type-checker works, which may not match how it actually works.) |
Hey theindigamer (JIRA User) : ) $T4 conv $T0 [[locator@0x11c372758 [Assign@/Users/lucianoalmeida/Documents/Programming/swift-lang/swift/test/expr/test.swift:6:3]]];
($T4 literal=1 involves_type_vars bindings={(subtypes of) (default from ExpressibleByArrayLiteral) Array})
Initial bindings: $T4 := Array
(attempting type variable $T4 := Array
($T0 involves_type_vars bindings={(supertypes of) [$T6]})
($T6 potentially_incomplete involves_type_vars #defaultable_bindings=1 bindings={Any})
Initial bindings: $T0 := [$T6]
(attempting type variable $T0 := [$T6]
($T6 potentially_incomplete involves_type_vars #defaultable_bindings=1 bindings={Any})
Initial bindings: $T6 := Any
(attempting type variable $T6 := Any
($T3 subtype_of_existential involves_type_vars bindings={(subtypes of) Any})
Initial bindings: $T3 := Any
(attempting type variable $T3 := Any
(failed constraint $T1.Type[(implicit) .e: value] == $T2 [[locator@0x11c372288 [UnresolvedMember@/Users/lucianoalmeida/Documents/Programming/swift-lang/swift/test/expr/test.swift:6:7 -> unresolved member]]];)
)
)
)
) > During inference, we don't use `Any` at all and infer the type of the array. Also, in this case, the Any binding always fails(because Any don't satisfy the member constraint) and records the define missing member fix. The problem is that for some reason that is the solution that ends up being diagnosed. I think we have to find the reason why this solution (score or fix impact or some other reason I don't know?) instead of diagnosing the contextual ambiguity. I've ping @xedin and @hborla to see if that makes sense or if it may be some other problem 🙂 |
@LucianoPAlmeida I think the fix is correct we just need to add some special handling for situations like this to the `MissingMemberFailure` diagnostic (`cannot infer contextual base ...` is a pretty good suggestion IMHO). There is a way to identify that member was used as an element to an array literal and whether element type has been defaulted to `Any`. |
Makes sense, thank you @xedin 🙂 |
Here a PR #31366 |
cc theindigamer (JIRA User) |
Additional Detail from JIRA
md5: 166b2b63257c728a511b480a2a2e5a0b
Issue Description:
If one has code like
This is a compiler from GitHub master on Apr 23 0bbf378.
The diagnostic isn't helpful IMO; the user didn't write `Any` in the source code so it shouldn't be shown in the message unless absolutely necessary. Instead, it should be saying something like
The text was updated successfully, but these errors were encountered: