Repository navigation
Question: is there a way to detect an unsound assignment via public compiler API? #3523
Description
Activity
- addedQuestionAn issue which isn't directly actionable in codeAn issue which isn't directly actionable in codeDomain: APIRelates to the public API for TypeScriptRelates to the public API for TypeScript
on Jun 17, 2015 No. That is too deep in the stack at this point and not surfeced. Jason Freeman (@JsonFreeman) any ideas?
DanielRosenwasser commented
on Jun 18, 2015 MemberMore actionsI believe you'd have to extract relations that you're interested from the compiler/create your own relations and test whether types in certain positions pass those relations.
the relationship check might not be sufficient, if the relation was used in overload resolution, it would be too late at this point.
DanielRosenwasser commented
on Jun 18, 2015 MemberMore actionsif the relation was used in overload resolution, it would be too late at this point.
True. This and type argument inference might complicate things.
JsonFreeman commented
on Jun 18, 2015 ContributorMore actionsYou'd have to do a couple of things:
- Augment checkTypeAssignableTo to take a flag indicating that you only want to allow sound assignments.
- Add the checks that you want to fail on, guarded by this flag.
- Add a relation cache that stores results for sound checks, so it doesn't mix with the existing cache.
- Expose this function on the type checker interface.
looks like the original issue has been answered. closing.
zpdDG4gta8XKpMCd commented
on Dec 13, 2015 AuthorMore actionsgentlemen, can this be considered a pull request: https://github.com/aleksey-bykov/TypeScript/commit/8a8b2a46fddc0e55494c7a009f077bf499b077a7 ?
zpdDG4gta8XKpMCd commented
on Dec 13, 2015 AuthorMore actionsworks:
const enum AsNonEmpty {} let xx : <a, r>( values: a[] & AsNonEmpty, toResult: (value: a, index: number) => r, folding: (result: r, value: a, index: number) => r ) => r; let yy: <a, r>( values: a[], toResult: (value: a, index: number) => r, folding: (result: r, value: a, index: number) => r ) => r; xx = yy;
src/array.ts (38,1): Type '<a, r>(values: a[], toResult: (value: a, index: number) => r, folding: (result: r, value: a, inde...' is not assignable to type '<a, r>(values: a[] & AsNonEmpty, toResult: (value: a, index: number) => r, folding: (result: r, v...'. Type 'any[]' is not assignable to type 'any[] & AsNonEmpty'. Type 'any[]' is not assignable to type 'AsNonEmpty'.DanielRosenwasser commented
on Dec 13, 2015 MemberMore actionsThat's not actually correct, since parameters are contravariant when relating functions types.
yyshould be assignable toxxsinceyyexpects less of itsvaluesparameter, so it's permissible to pass in more. The fix for this is to swapsandtin each call toisRelatedTo.Another problem is that you're not elaborating the error that was previously checked (
Types_of_parameters_0_and_1_are_incompatible).Rather than completely failing, you should let the function continue the same logic, but additionally report an error (with the
errorfunction, notreportError) when encountering failure relatingttos, but notstot. The error should be"Parameter of type {0} was related to type {1} through covariance."Given that there are other issues with respect to soundness, I would consider calling this
warnOnParameterCovariance.I wouldn't be opposed to introducing this change, but we'd need to discuss it at a design meeting.
zpdDG4gta8XKpMCd commented
on Dec 14, 2015 AuthorMore actionsyy should be assignable to xx since yy expects less of its values parameter, so it's permissible to pass in more
I am afraid the whole point is that
yyshould not be assignable toxx. It's what I am trying the compiler to get me protected from. I agree that passing more should be permitted, but more is what whatxxis, because it's onxxside where intersection ofa[] & AsNonEmptyis and such intersection means a more elaborate type.Another problem is that you're not elaborating the error that was previously checked.
The thing is that the original code (very convoluted in my opinion) does not do it either. All it does is finds the first incompatible pair of parameters and returns, albeit with a customized error message rather than one set by the
isRelatedTofunction. Speaking of which:The error should be "Parameter of type {0} was related to type {1} through covariance."
You might be right, but I don't see a reason for why we should try covariance at all. The flag I am suggesting is about doing it right which is through contravariance. In my opinion we should keep the existing error message:
Types_of_parameters_0_and_1_are_incompatible. Ideally peppered by the information thatisRelatedToprovides:Type 'any[]' is not assignable to type 'any[] & AsNonEmpty'. Type 'any[]' is not assignable to type 'AsNonEmpty'.But I am not sure how to get a piece of one error message chain and attach it to another.
Given that there are other issues with respect to soundness, I would consider calling this
warnOnParameterCovariance.How about
noParameterCovariance?I am sure if design team votes for this feature you guys will make it right. For now I will stick with my version which already makes my life so much easier. All in all, thanks for considering this change. Here is the last change that separates the original parameter matching logic from the one enabled by the flag: https://github.com/aleksey-bykov/TypeScript/commit/34b8f9b5a937cb7bb471771d5c9b9c4d4f629fc8
PS
You don't use automatic code formatting do you? Out of curiosity what IDE and its settings should be to avoid the mess with whitespaces?JsonFreeman commented
on Dec 15, 2015 ContributorMore actionsAleksey-Bykov The "more elaborate type" in your description actually corresponds to "being able to pass less" in Daniel Rosenwasser (@DanielRosenwasser)'s description. So Daniel Rosenwasser (@DanielRosenwasser) is correct that the two signatures should be assignable with respect to the first parameter at least (assuming contravariance).
zpdDG4gta8XKpMCd commented
on Dec 15, 2015 AuthorMore actionsbeen giving it an extra though, you both are right, ugh, let me figure out
what I am fighting withAleksey-Bykov https://github.com/aleksey-bykov The "more elaborate type"
in your description actually corresponds to "being able to pass less" in
Daniel Rosenwasser (@DanielRosenwasser) https://github.com/DanielRosenwasser's description. So
Daniel Rosenwasser (@DanielRosenwasser) https://github.com/DanielRosenwasser is correct that
the two signatures should be assignable with respect to the first parameter
at least (assuming contravariance).—
Reply to this email directly or view it on GitHub
#3523 (comment)
.- locked and limited conversation to collaborators
on Jun 19, 2018
My situation (#3067):
I've managed to get an AST and a type checker. I am holding a reference to the argument (copyB from above) object.
Can anyone outline the steps that need to be taken to determine that the assignment from the example is unsound using the public compiler API?