typoland
(Łukasz Dziedzic)
1
Sorry for a title, but I couldn't invent a better one. And I have no good experience in asking for help.
I try to exchange data between two different models. (I know code is bit ugly)
....
let advanceWidthVertices = glyphLayers.map { flLayer in
HyperVertex (value: flLayer.advanceWidth,
at: layersCoordinates[flLayer.name!] ?? [],
strength: hyperMaster.masterLocations.keys.contains(where: { n in n == flLayer.name})
? 0 : 1)
}
self.advanceWidth = HyperValue(vertices: advanceWidthVertices, axes: axes)
....
It works pretty well, but because I have a lot of properties to exchange I would like to have a one function like this:
func getVerticesFor<T:SpaceIntepolatableProtocol>(masters:[String],
layers: [FontLabLayer],
layersCoordinates: [String:[Coordinate]],
path: PartialKeyPath<FontLabLayer>)
-> [HyperVertex<T, Coordinate>] {
return layers.map { flLayer in
HyperVertex (value: flLayer[keyPath: path] as! T,
at: layersCoordinates[flLayer.name!] ?? [],
strength: masters.contains(where: { n in n == flLayer.name})
? 0 : 1)
}
}
and call it:
....
self.advanceWidth = HyperValue(vertices: getVerticesFor(masters: hyperMaster.masterLocations.keys,
layers: glyphLayers,
layersCoordinates: layersCoordinates,
path: \.advanceWidth),
axes: axes)
//repeat many times for each property
...
But calling this function always give me an error "Type of expression is ambiguous without more context". Even in simplest possible form, with parameters taken from scope.
let vertices:[HyperVertex<Double, Coordinate>] = getVertices(path: \.advanceWidth)
How to solve this?
cukr
2
You've shown us the code with the problem, and the specific error message that you're getting. That's a good start!
Next step would be to make it self-contained, which means to include all the code that is needed to reproduce the bug in a single snippet. That way we can easily copy-paste it to a playground or something, and check if we also are getting the same error
protocol SpaceIntepolatableProtocol {}
struct FontLabLayer {
var advanceWidth: Int
}
struct Coordinate {}
struct HyperVertex<A, B> {}
extension Double: SpaceIntepolatableProtocol {}
func getVerticesFor<T:SpaceIntepolatableProtocol>(
masters:[String],
layers: [FontLabLayer],
layersCoordinates: [String:[Coordinate]],
path: PartialKeyPath<FontLabLayer>)
-> [HyperVertex<T, Coordinate>] {
return []
}
let vertices: [HyperVertex<Double, Coordinate>] = getVerticesFor( // Type of expression is ambiguous without more context
masters: [],
layers: [],
layersCoordinates: [:],
path: \.advanceWidth
)
Next step would be to make the sample minimal. How much can you cut out while still triggering that error?
func getVerticesFor(path: PartialKeyPath<Int>) {}
getVerticesFor(path: \.magnitude) // Type of expression is ambiguous without more context
This example is much simpler. It has no protocols, no arrays, no dictionaries, no generics, no return types, no custom types, and only a single parameter. It's much easier to see what's going on.
It looks like a bug to me, can you post it to bugs.swift.org ?
1 Like
typoland
(Łukasz Dziedzic)
3
Yes, of course. May I use your code as an example?
1 Like
typoland
(Łukasz Dziedzic)
6
cukr
7
You were supposed to use the short example not the long one 
The example you used is good, but is not great. It shows the bug, but 90% of it is useless code that can be removed and is just confusing the person trying to find out what the bug is.
You should also write when that bug happens. Does it happen for all function calls? When the parameter is any variant of a keypath? When the parameter is specifically a PartialKeyPath? When it's thursday? Spoiler: It's when parameter is a PartialKeyPath, and you pass in a key path literal to the function
That info would be useful to a person trying to solve this problem
2 Likes
We have seen that before on SR-5667, SR-12390, and in a few other duplicated issues. But in short is indeed a compiler issue while inferring the root type for the key path literal. There were some discussions some time ago about that in SR-12390 jira link so you can check there for more details :)