Appearance
| 1 | namespace Syntax.Process is | |
| 2 | use Logging | |
| 3 | use Source | |
| 4 | ||
| 5 | use Semantic.Types.Type | |
| 6 | ||
| 7 | use IR.Values | |
| 8 | ||
| 9 | use Ghul.Pipes | |
| 10 | ||
| 11 | // Compiles calls and constructor invocations: the `_(args)` | |
| 12 | // contextually-typed construction, function / method / closure / | |
| 13 | // indexer calls, and the shared constructor-resolution path. Split | |
| 14 | // out of COMPILE_EXPRESSIONS, which delegates visit(construct) and | |
| 15 | // the enclosed logic of visit(call) here. The try/catch wrapper of | |
| 16 | // visit(call) — with | |
| 17 | // its speculation bracket around the argument walk — stays on the | |
| 18 | // visitor; visit_call is the enclosed logic. | |
| 19 | class COMPILE_CALLS is | |
| 20 | _logger: Logger | |
| 21 | _symbol_table: Semantic.SYMBOL_TABLE | |
| 22 | _symbol_use_locations: Semantic.SYMBOL_USE_LOCATIONS | |
| 23 | _innate_symbol_lookup: Semantic.Lookups.InnateSymbolLookup | |
| 24 | _overload_resolver: Semantic.OVERLOAD_RESOLVER | |
| 25 | _function_caller: Semantic.FUNCTION_CALLER | |
| 26 | _owner_constraint_specializer: Semantic.OWNER_CONSTRAINT_SPECIALIZER | |
| 27 | _owner_type_arg_specializer: Semantic.OWNER_TYPE_ARG_SPECIALIZER | |
| 28 | _constructor_constraint_retry: Semantic.CONSTRUCTOR_CONSTRAINT_RETRY | |
| 29 | _under_determination_detector: Semantic.UNDER_DETERMINATION_DETECTOR | |
| 30 | _type_arg_placeholder_registry: Semantic.TYPE_ARG_PLACEHOLDER_REGISTRY | |
| 31 | _access: COMPILE_ACCESS | |
| 32 | _visitor: COMPILE_EXPRESSIONS | |
| 33 | _named_argument_binder: NAMED_ARGUMENT_BINDER | |
| 34 | _flow: NARROWING_FLOW | |
| 35 | _delegate_shape: Semantic.DELEGATE_SHAPE | |
| 36 | _delegate_push_candidates: Semantic.DELEGATE_PUSH_CANDIDATES | |
| 37 | _async_literal_candidates: Semantic.ASYNC_LITERAL_CANDIDATES | |
| 38 | _symbol_loader: Semantic.SYMBOL_LOADER | |
| 39 | _function_reference_adapter: FUNCTION_REFERENCE_ADAPTER | |
| 40 | _pack_wrap_builder: PACK_WRAP_BUILDER | |
| 41 | ||
| 42 | init( | |
| 43 | logger: Logger, | |
| 44 | symbol_table: Semantic.SYMBOL_TABLE, | |
| 45 | symbol_use_locations: Semantic.SYMBOL_USE_LOCATIONS, | |
| 46 | innate_symbol_lookup: Semantic.Lookups.InnateSymbolLookup, | |
| 47 | overload_resolver: Semantic.OVERLOAD_RESOLVER, | |
| 48 | function_caller: Semantic.FUNCTION_CALLER, | |
| 49 | owner_constraint_specializer: Semantic.OWNER_CONSTRAINT_SPECIALIZER, | |
| 50 | owner_type_arg_specializer: Semantic.OWNER_TYPE_ARG_SPECIALIZER, | |
| 51 | under_determination_detector: Semantic.UNDER_DETERMINATION_DETECTOR, | |
| 52 | type_arg_placeholder_registry: Semantic.TYPE_ARG_PLACEHOLDER_REGISTRY, | |
| 53 | access: COMPILE_ACCESS, | |
| 54 | visitor: COMPILE_EXPRESSIONS, | |
| 55 | flow: NARROWING_FLOW, | |
| 56 | symbol_loader: Semantic.SYMBOL_LOADER, | |
| 57 | function_reference_adapter: FUNCTION_REFERENCE_ADAPTER | |
| 58 | ) is | |
| 59 | super.init() | |
| 60 | ||
| 61 | _logger = logger | |
| 62 | _symbol_table = symbol_table | |
| 63 | _symbol_use_locations = symbol_use_locations | |
| 64 | _innate_symbol_lookup = innate_symbol_lookup | |
| 65 | _overload_resolver = overload_resolver | |
| 66 | _function_caller = function_caller | |
| 67 | _owner_constraint_specializer = owner_constraint_specializer | |
| 68 | _owner_type_arg_specializer = owner_type_arg_specializer | |
| 69 | _constructor_constraint_retry = Semantic.CONSTRUCTOR_CONSTRAINT_RETRY(owner_constraint_specializer) | |
| 70 | _under_determination_detector = under_determination_detector | |
| 71 | _type_arg_placeholder_registry = type_arg_placeholder_registry | |
| 72 | _access = access | |
| 73 | _visitor = visitor | |
| 74 | _named_argument_binder = NAMED_ARGUMENT_BINDER(logger) | |
| 75 | _flow = flow | |
| 76 | _delegate_shape = Semantic.DELEGATE_SHAPE() | |
| 77 | _delegate_push_candidates = Semantic.DELEGATE_PUSH_CANDIDATES(_delegate_shape, innate_symbol_lookup) | |
| 78 | _async_literal_candidates = Semantic.ASYNC_LITERAL_CANDIDATES(innate_symbol_lookup, Semantic.TASK_LIKE_RESOLVER(logger)) | |
| 79 | _symbol_loader = symbol_loader | |
| 80 | _function_reference_adapter = function_reference_adapter | |
| 81 | _pack_wrap_builder = PACK_WRAP_BUILDER(symbol_table, symbol_loader, innate_symbol_lookup) | |
| 82 | si | |
| 83 | ||
| 84 | // Rebuild a named call's already-collected argument lists - the | |
| 85 | // AST expressions and the parallel value / type lists - into | |
| 86 | // the resolved overload's parameter order. `permutation` is | |
| 87 | // indexed by formal parameter; a negative entry marks a | |
| 88 | // parameter the call omitted, which is filled with a `default` | |
| 89 | // value of that parameter's type (taken from `target`). | |
| 90 | _apply_named_permutation( | |
| 91 | argument_expressions: Trees.Expressions.LIST, | |
| 92 | arguments: Collections.LIST[Value], | |
| 93 | argument_types: Collections.LIST[Type], | |
| 94 | permutation: Collections.List[int], | |
| 95 | target: Semantic.Symbols.Function | |
| 96 | ) is | |
| 97 | let source_expressions = Collections.LIST[Trees.Expressions.Expression](argument_expressions) | |
| 98 | let source_arguments = Collections.LIST[Value](arguments) | |
| 99 | let source_argument_types = Collections.LIST[Type](argument_types) | |
| 100 | ||
| 101 | argument_expressions.expressions.clear() | |
| 102 | arguments.clear() | |
| 103 | argument_types.clear() | |
| 104 | ||
| 105 | for formal_index in 0..permutation.count do | |
| 106 | let source_index = permutation[formal_index] | |
| 107 | ||
| 108 | if source_index >= 0 then | |
| 109 | argument_expressions.expressions.add(source_expressions[source_index]) | |
| 110 | arguments.add(source_arguments[source_index]) | |
| 111 | argument_types.add(source_argument_types[source_index]) | |
| 112 | else | |
| 113 | let formal_type = target.arguments[formal_index] | |
| 114 | let stored = target.argument_defaults[formal_index] | |
| 115 | let default_value = DEFAULT_ARGUMENT_VALUES.build(stored, formal_type, _innate_symbol_lookup) | |
| 116 | ||
| 117 | let default_expression = Trees.Expressions.DEFAULT(argument_expressions.location, null) | |
| 118 | default_expression.set_expected_type(formal_type, "") | |
| 119 | default_expression.compile_expressions_state.value = default_value | |
| 120 | ||
| 121 | argument_expressions.expressions.add(default_expression) | |
| 122 | arguments.add(default_value) | |
| 123 | argument_types.add(formal_type) | |
| 124 | fi | |
| 125 | od | |
| 126 | si | |
| 127 | ||
| 128 | // `_(args)`: the type is never written, so it comes from the | |
| 129 | // constraint the parent pushed in. An optional constraint is | |
| 130 | // peeled - a constructor produces the underlying instance, and | |
| 131 | // the widening to the optional happens at the assignment site, | |
| 132 | // so the value carries the non-optional class type rather than | |
| 133 | // masquerading as `BOX?`. | |
| 134 | visit_construct(construct: Trees.Expressions.CONSTRUCT) is | |
| 135 | construct.compile_expressions_state.value = null | |
| 136 | ||
| 137 | let type: Type? mut | |
| 138 | ||
| 139 | if let construct.expected_type? then | |
| 140 | // The type comes from a local's later uses that have not | |
| 141 | // settled it yet. | |
| 142 | if expected_type.is_inferred then | |
| 143 | Semantic.OBLIGATIONS.defer("construct", expected_type, construct.location) | |
| 144 | construct.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), construct.location) | |
| 145 | return | |
| 146 | fi | |
| 147 | ||
| 148 | type = expected_type.as_non_optional() | |
| 149 | else | |
| 150 | _logger.error(construct.location, "cannot infer the type to construct here") | |
| 151 | construct.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), construct.location) | |
| 152 | return | |
| 153 | fi | |
| 154 | ||
| 155 | if !isa Semantic.Types.NAMED(type) then | |
| 156 | _logger.error(construct.location, "cannot instantiate {type}") | |
| 157 | construct.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), construct.location) | |
| 158 | return | |
| 159 | fi | |
| 160 | ||
| 161 | let named_type = type | |
| 162 | let type_symbol mut = named_type.symbol | |
| 163 | ||
| 164 | if let abstract_class: Semantic.Symbols.CLASS = type_symbol then | |
| 165 | if abstract_class.is_abstract then | |
| 166 | _logger.error(construct.location, "cannot instantiate abstract class {abstract_class.name}", abstract_class.location, "class declared abstract here") | |
| 167 | fi | |
| 168 | fi | |
| 169 | ||
| 170 | let symbol = named_type.scope.find_direct("init") | |
| 171 | ||
| 172 | let function_group = cast Semantic.Symbols.FUNCTION_GROUP?(symbol) | |
| 173 | ||
| 174 | let arguments = Collections.LIST[Value]() | |
| 175 | let argument_types = Collections.LIST[Type]() | |
| 176 | ||
| 177 | for a in construct.arguments do | |
| 178 | let value = a.value | |
| 179 | ||
| 180 | if value? /\ value.type? /\ value.check_is_consumable(_logger, a.location) then | |
| 181 | arguments.add(value) | |
| 182 | argument_types.add(value.type!) | |
| 183 | else | |
| 184 | let t = Semantic.Types.ERROR() | |
| 185 | ||
| 186 | arguments.add(DUMMY(t, a.location)) | |
| 187 | ||
| 188 | argument_types.add(t) | |
| 189 | fi | |
| 190 | od | |
| 191 | ||
| 192 | if !function_group? then | |
| 193 | construct.compile_expressions_state.value = DUMMY(type, construct.location) | |
| 194 | ||
| 195 | _logger.error(construct.location, "no constructor found init({argument_types |> join(", ")})") | |
| 196 | ||
| 197 | return | |
| 198 | fi | |
| 199 | ||
| 200 | let overload_result = _overload_resolver.resolve(construct.location, function_group, argument_types, false, true, true) | |
| 201 | ||
| 202 | if overload_result == null then | |
| 203 | construct.compile_expressions_state.value = DUMMY(type, construct.location) | |
| 204 | ||
| 205 | return | |
| 206 | fi | |
| 207 | ||
| 208 | let function mut = overload_result.function | |
| 209 | ||
| 210 | function = _owner_constraint_specializer.specialize_from_constraint(construct.location, function, construct.expected_type) | |
| 211 | ||
| 212 | if isa Semantic.Symbols.GENERIC(function.owner) then | |
| 213 | type_symbol = cast Semantic.Symbols.Symbol(function.owner) | |
| 214 | // The GENERIC owner of a resolved constructor always carries | |
| 215 | // a concrete type (the specialized class) by this point. | |
| 216 | type = function.owner.type | |
| 217 | fi | |
| 218 | ||
| 219 | let is_directly_owned mut = false | |
| 220 | ||
| 221 | if isa Semantic.Symbols.GENERIC(type_symbol) /\ isa Semantic.Symbols.Symbol(function.owner) then | |
| 222 | is_directly_owned = type_symbol =~ cast Semantic.Symbols.Symbol(function.owner) | |
| 223 | else | |
| 224 | is_directly_owned = type_symbol == function.owner | |
| 225 | fi | |
| 226 | ||
| 227 | if !is_directly_owned then | |
| 228 | _logger.error(construct.location, "cannot call superclass constructor {function}", function.location, "constructor declared here") | |
| 229 | fi | |
| 230 | ||
| 231 | construct.compile_expressions_state.value = | |
| 232 | NEW( | |
| 233 | // every branch above either sets type or early-returns | |
| 234 | type, | |
| 235 | function, | |
| 236 | arguments | |
| 237 | ) | |
| 238 | si | |
| 239 | ||
| 240 | // Sibling-arg specialisation entry: produce the phantom- | |
| 241 | // origin list for unbound slots from the per-AST cache, then | |
| 242 | // delegate to `OWNER_TYPE_ARG_SPECIALIZER` for the binding | |
| 243 | // and specialisation logic. Phantom origins live on the | |
| 244 | // placeholder registry so match propagation across body-retry | |
| 245 | // iterations lands on the same Variables; the specialiser | |
| 246 | // itself is stateless, which lets the binding contract be | |
| 247 | // unit-tested in isolation. | |
| 248 | _specialise_candidate_from_concrete_siblings( | |
| 249 | candidate: Semantic.Symbols.Function, | |
| 250 | argument_types: Collections.List[Semantic.Types.Type], | |
| 251 | cache_key: Trees.Node, | |
| 252 | location: LOCATION | |
| 253 | ) -> Semantic.Symbols.Function? is | |
| 254 | if isa Semantic.Symbols.GENERIC(candidate.owner) then | |
| 255 | return candidate | |
| 256 | fi | |
| 257 | ||
| 258 | let owner_classy = cast Semantic.Symbols.Classy?(candidate.owner) | |
| 259 | ||
| 260 | if !owner_classy? \/ !owner_classy.is_generic then | |
| 261 | return candidate | |
| 262 | fi | |
| 263 | ||
| 264 | let origins = _type_arg_placeholder_registry.get_or_create(cache_key, location, owner_classy) | |
| 265 | ||
| 266 | return _owner_type_arg_specializer.specialize_from_concrete_siblings(candidate, argument_types, origins, location) | |
| 267 | si | |
| 268 | ||
| 269 | // Find the single arity- and instance-matching candidate in a | |
| 270 | // function group, or null if there are zero or multiple. Used | |
| 271 | // by `visit_call`'s constraint-push retry: when the first | |
| 272 | // overload resolution fails, having exactly one candidate to | |
| 273 | // push formal arg types from disambiguates the constraint | |
| 274 | // direction. Multi-candidate disambiguation under constraint | |
| 275 | // push is bigger work tracked under #1174. | |
| 276 | _try_find_single_arity_candidate( | |
| 277 | group: Semantic.Symbols.FUNCTION_GROUP, | |
| 278 | arg_count: int, | |
| 279 | want_instance: bool | |
| 280 | ) -> Semantic.Symbols.Function? is | |
| 281 | let result: Semantic.Symbols.Function? mut = null | |
| 282 | let count mut = 0 | |
| 283 | ||
| 284 | for f in group.functions do | |
| 285 | if !want_instance /\ f.is_instance then | |
| 286 | continue | |
| 287 | fi | |
| 288 | ||
| 289 | if !f.are_arguments_declared then | |
| 290 | continue | |
| 291 | fi | |
| 292 | ||
| 293 | if f.arguments.count != arg_count then | |
| 294 | continue | |
| 295 | fi | |
| 296 | ||
| 297 | result = f | |
| 298 | count = count + 1 | |
| 299 | od | |
| 300 | ||
| 301 | if count == 1 then | |
| 302 | return result | |
| 303 | fi | |
| 304 | ||
| 305 | return null | |
| 306 | si | |
| 307 | ||
| 308 | // should be called with logger speculating | |
| 309 | _compile_call_arguments( | |
| 310 | argument_expressions: Trees.Expressions.LIST, | |
| 311 | arguments: Collections.LIST[Value], | |
| 312 | argument_types: Collections.LIST[Type] | |
| 313 | ) is | |
| 314 | for a in argument_expressions do | |
| 315 | _compile_one_argument(a, arguments, argument_types) | |
| 316 | od | |
| 317 | si | |
| 318 | ||
| 319 | // True for an argument that takes its type from the context - | |
| 320 | // a bare `_`, or a `cast(v)` with the target elided - and | |
| 321 | // failed to infer one on the first walk, because before the | |
| 322 | // callee was resolved nothing had pushed it an expected type. | |
| 323 | is_argument_awaiting_context_type(a: Trees.Expressions.Expression) -> bool static is | |
| 324 | if !a.awaits_context_type then | |
| 325 | return false | |
| 326 | fi | |
| 327 | ||
| 328 | if let value: Value = a.value then | |
| 329 | if let type: Type = value.type then | |
| 330 | return type.is_error | |
| 331 | fi | |
| 332 | ||
| 333 | return true | |
| 334 | fi | |
| 335 | ||
| 336 | return true | |
| 337 | si | |
| 338 | ||
| 339 | // True when the call carries at least one argument still | |
| 340 | // awaiting a type from its context. | |
| 341 | has_argument_awaiting_context_type(argument_expressions: Collections.List[Trees.Expressions.Expression]) -> bool static => | |
| 342 | argument_expressions |> any(a => COMPILE_CALLS.is_argument_awaiting_context_type(a)) | |
| 343 | ||
| 344 | // True for an argument that is a bare reference to an | |
| 345 | // overloaded function or method group and stayed a | |
| 346 | // non-consumable group load on the first walk. An overloaded | |
| 347 | // group only becomes a delegate once a target call shape is | |
| 348 | // pushed onto it, and before the callee was resolved nothing | |
| 349 | // had one to push. A single-overload group resolves on the | |
| 350 | // first walk and never looks like this. | |
| 351 | is_unresolved_group_argument(a: Trees.Expressions.Expression) -> bool static is | |
| 352 | if let value: Value = a.value then | |
| 353 | if let load: Load.SYMBOL = value then | |
| 354 | return load.symbol.is_function_group | |
| 355 | fi | |
| 356 | fi | |
| 357 | ||
| 358 | return false | |
| 359 | si | |
| 360 | ||
| 361 | // True when the call carries at least one unresolved group | |
| 362 | // reference among its arguments. | |
| 363 | has_unresolved_group_argument(argument_expressions: Collections.List[Trees.Expressions.Expression]) -> bool static => | |
| 364 | argument_expressions |> any(a => COMPILE_CALLS.is_unresolved_group_argument(a)) | |
| 365 | ||
| 366 | // Once overload resolution has settled on a single, unambiguous | |
| 367 | // `function`, retry any argument that had no type to infer | |
| 368 | // against on the first walk - the resolved callee's formal | |
| 369 | // types are available now. Re-walks every argument under a | |
| 370 | // fresh speculation level, since the roll-back below discards | |
| 371 | // whatever the first walk logged for the whole call, not just | |
| 372 | // the waiting arguments. | |
| 373 | // | |
| 374 | // Two argument shapes need this. A context-typed one - a bare | |
| 375 | // `_`, or a `cast(v)` with the target elided - infers its type | |
| 376 | // from the formal. A bare reference to an overloaded function | |
| 377 | // or method group turns into a delegate only once the formal's | |
| 378 | // call shape is pushed onto it, so the group picks its member | |
| 379 | // the same way an explicit annotation would pick it. | |
| 380 | // | |
| 381 | // Such an argument is only ever pushed a type when the resolved | |
| 382 | // formal at that position is itself concrete: a generic | |
| 383 | // candidate whose type variable is pinned by a sibling | |
| 384 | // argument or an enclosing constraint is already specialized | |
| 385 | // by this point, so the formal there is concrete too, but a | |
| 386 | // type variable free only in the waiting slot leaves the formal | |
| 387 | // wild and the argument is left to re-report its original | |
| 388 | // error - neither a `_` nor a `cast(v)` ever itself contributes | |
| 389 | // to binding a type variable. A group reference is additionally | |
| 390 | // gated on the formal being callable - a function type or a | |
| 391 | // named .NET delegate - since nothing else gives the group a | |
| 392 | // shape to resolve against. | |
| 393 | // | |
| 394 | // A resolved formal with a declared .NET default value (an | |
| 395 | // optional CLR parameter) takes that value rather than the | |
| 396 | // type's zero value, so a positionally-written `_` behaves | |
| 397 | // exactly like omitting the same parameter by name. That | |
| 398 | // applies to `_` alone: `cast(v)` asks for a conversion of `v`, | |
| 399 | // so a declared default has nothing to do with it. | |
| 400 | // Returns true when a bare group argument resolved to a | |
| 401 | // delegate under the pushed formal - the caller then | |
| 402 | // re-resolves the call so the callee's own type variables | |
| 403 | // bind from the delegate's shape rather than staying open. | |
| 404 | _resolve_deferred_defaults( | |
| 405 | function: Semantic.Symbols.Function, | |
| 406 | argument_expressions: Collections.List[Trees.Expressions.Expression], | |
| 407 | arguments: Collections.LIST[Value], | |
| 408 | argument_types: Collections.LIST[Type] | |
| 409 | ) -> bool is | |
| 410 | if | |
| 411 | !has_argument_awaiting_context_type(argument_expressions) /\ | |
| 412 | !COMPILE_CALLS.has_unresolved_group_argument(argument_expressions) | |
| 413 | then | |
| 414 | return false | |
| 415 | fi | |
| 416 | ||
| 417 | let use retry_site = RETRY_SITE_STATS.enter("calls.resolve_deferred_defaults", RetrySiteKind.REWALK_WITH_INFORMATION) | |
| 418 | _logger.roll_back() | |
| 419 | _logger.speculate() | |
| 420 | _flow.restore() | |
| 421 | ||
| 422 | let resolved_group mut = false | |
| 423 | ||
| 424 | for (index, a) in argument_expressions |> index() do | |
| 425 | if | |
| 426 | COMPILE_CALLS.is_unresolved_group_argument(a) /\ | |
| 427 | index < function.arguments.count /\ | |
| 428 | ( | |
| 429 | function.arguments[index].is_function \/ | |
| 430 | _delegate_shape.is_named_delegate(function.arguments[index], _innate_symbol_lookup) | |
| 431 | ) | |
| 432 | then | |
| 433 | a.set_expected_type(function.arguments[index], "{{0}} is not assignable to {{1}}") | |
| 434 | _visitor.rewalk(a) | |
| 435 | ||
| 436 | if !COMPILE_CALLS.is_unresolved_group_argument(a) then | |
| 437 | resolved_group = true | |
| 438 | fi | |
| 439 | elif | |
| 440 | COMPILE_CALLS.is_argument_awaiting_context_type(a) /\ | |
| 441 | index < function.arguments.count /\ | |
| 442 | !function.arguments[index].is_wild | |
| 443 | then | |
| 444 | let formal_type = function.arguments[index] | |
| 445 | ||
| 446 | let stored = | |
| 447 | if | |
| 448 | isa Trees.Expressions.DEFAULT(a) /\ | |
| 449 | index < function.argument_defaults.count | |
| 450 | then | |
| 451 | function.argument_defaults[index] | |
| 452 | else | |
| 453 | null | |
| 454 | fi | |
| 455 | ||
| 456 | if stored? then | |
| 457 | a.compile_expressions_state.value = DEFAULT_ARGUMENT_VALUES.build(stored, formal_type, _innate_symbol_lookup) | |
| 458 | else | |
| 459 | a.set_expected_type(formal_type, "") | |
| 460 | _visitor.rewalk(a) | |
| 461 | fi | |
| 462 | elif isa Trees.Expressions.DEFAULT(a) then | |
| 463 | // A `_[T]` argument, or a `DEFAULT` node | |
| 464 | // `_apply_named_permutation` synthesised to fill an | |
| 465 | // omitted named argument with the callee's own | |
| 466 | // declared default value, already carries its | |
| 467 | // final value. Re-walking either through | |
| 468 | // `visit_default` would overwrite that value with | |
| 469 | // the type's zero value - visit_default has no way | |
| 470 | // to tell "already resolved to the right thing" | |
| 471 | // from "resolved once, resolve again" - so leave | |
| 472 | // it untouched. A still-unresolved `_` whose | |
| 473 | // formal is wild has no value to protect and is | |
| 474 | // walked below to re-report its own error under | |
| 475 | // this fresh speculation level. | |
| 476 | if COMPILE_CALLS.is_argument_awaiting_context_type(a) then | |
| 477 | _visitor.rewalk(a) | |
| 478 | fi | |
| 479 | else | |
| 480 | // ensure any error messages are committed | |
| 481 | _visitor.rewalk(a) | |
| 482 | fi | |
| 483 | ||
| 484 | if let value: Value = a.value /\ value.type? then | |
| 485 | arguments[index] = value | |
| 486 | argument_types[index] = value.type! | |
| 487 | fi | |
| 488 | od | |
| 489 | ||
| 490 | return resolved_group | |
| 491 | si | |
| 492 | ||
| 493 | _compile_one_argument( | |
| 494 | a: Trees.Expressions.Expression, | |
| 495 | arguments: Collections.LIST[Value], | |
| 496 | argument_types: Collections.LIST[Type] | |
| 497 | ) is | |
| 498 | let value = a.value | |
| 499 | ||
| 500 | if value? /\ value.type? /\ value.check_is_consumable(_logger, a.location) then | |
| 501 | arguments.add(value) | |
| 502 | argument_types.add(value.type!) | |
| 503 | else | |
| 504 | let t = Semantic.Types.ERROR() | |
| 505 | ||
| 506 | arguments.add(DUMMY(t, a.location)) | |
| 507 | ||
| 508 | argument_types.add(t) | |
| 509 | fi | |
| 510 | si | |
| 511 | ||
| 512 | // Find the delegate type's own compiler-synthesized | |
| 513 | // constructor - `.ctor(object, native int)`, the only one a | |
| 514 | // real .NET delegate type ever declares. | |
| 515 | _find_delegate_constructor(type: Semantic.Types.Type) -> Semantic.Symbols.Function? is | |
| 516 | let named = cast Semantic.Types.NAMED?(type) | |
| 517 | ||
| 518 | if !named? then | |
| 519 | return null | |
| 520 | fi | |
| 521 | ||
| 522 | let symbol = named.scope.find_direct("init") | |
| 523 | ||
| 524 | if let group: Semantic.Symbols.FUNCTION_GROUP = symbol then | |
| 525 | if group.count == 1 then | |
| 526 | return group.functions[0] | |
| 527 | fi | |
| 528 | ||
| 529 | return null | |
| 530 | fi | |
| 531 | ||
| 532 | return cast Semantic.Symbols.Function?(symbol) | |
| 533 | si | |
| 534 | ||
| 535 | // Resolve a member that is either a bare Function or a | |
| 536 | // single-member FUNCTION_GROUP - the shape `find_member` | |
| 537 | // returns for a non-overloaded method (mirrors | |
| 538 | // DELEGATE_SHAPE._find_invoke). | |
| 539 | _find_single_function_member(type: Semantic.Types.Type, name: string) -> Semantic.Symbols.Function? is | |
| 540 | let symbol = type.find_member(name) | |
| 541 | ||
| 542 | if let group: Semantic.Symbols.FUNCTION_GROUP = symbol then | |
| 543 | if group.count == 1 then | |
| 544 | return group.functions[0] | |
| 545 | fi | |
| 546 | ||
| 547 | return null | |
| 548 | fi | |
| 549 | ||
| 550 | return cast Semantic.Symbols.Function?(symbol) | |
| 551 | si | |
| 552 | ||
| 553 | // A real .NET delegate type's sole constructor is the | |
| 554 | // compiler-synthesized `.ctor(object, native int)`, which no | |
| 555 | // ghūl call site can satisfy (nothing produces a usable | |
| 556 | // `native int`), so a single-argument constructor call | |
| 557 | // against a named delegate type is free to mean explicit | |
| 558 | // conversion: `TargetDelegate(functionValue)`. | |
| 559 | // | |
| 560 | // A literal written directly as the argument is pushed the | |
| 561 | // delegate type as its expected type, the same way an | |
| 562 | // assignment or argument-formal context does (see | |
| 563 | // COMPILE_LAMBDAS.visit_function), and constructs the | |
| 564 | // delegate directly via ldftn/newobj. An existing | |
| 565 | // function/delegate-typed value has no compile-time method | |
| 566 | // token to `ldftn` - its method is only known at runtime, via | |
| 567 | // its own `Method` property - so it is reconstructed over | |
| 568 | // (Target, MethodHandle function pointer) via the target | |
| 569 | // delegate's own constructor instead. | |
| 570 | _resolve_delegate_value_construction( | |
| 571 | location: LOCATION, | |
| 572 | type: Semantic.Types.Type, | |
| 573 | argument_expression: Trees.Expressions.Expression | |
| 574 | ) -> (Value, Value) is | |
| 575 | if isa Trees.Expressions.FUNCTION(argument_expression) then | |
| 576 | let use retry_site = RETRY_SITE_STATS.enter("calls.delegate_value_construction", RetrySiteKind.REWALK_WITH_INFORMATION) | |
| 577 | _logger.roll_back() | |
| 578 | _logger.speculate() | |
| 579 | _flow.restore() | |
| 580 | ||
| 581 | argument_expression.set_expected_type(type, "{{0}} is not assignable to {{1}}") | |
| 582 | _visitor.rewalk(argument_expression) | |
| 583 | ||
| 584 | let value = argument_expression.value | |
| 585 | ||
| 586 | if !value? \/ !value.type? \/ !value.check_is_consumable(_logger, argument_expression.location) then | |
| 587 | return (cast Value(DUMMY(type, location)), cast Value(DUMMY(type, location))) | |
| 588 | fi | |
| 589 | ||
| 590 | return (cast Value(DUMMY(type, location)), value) | |
| 591 | fi | |
| 592 | ||
| 593 | let value = argument_expression.value | |
| 594 | ||
| 595 | if !value? \/ !value.type? \/ !value.check_is_consumable(_logger, argument_expression.location) then | |
| 596 | return (cast Value(DUMMY(type, location)), cast Value(DUMMY(type, location))) | |
| 597 | fi | |
| 598 | ||
| 599 | let source_type = value.type! | |
| 600 | ||
| 601 | if !source_type.is_function /\ !_delegate_shape.is_named_delegate(source_type, _innate_symbol_lookup) then | |
| 602 | _logger.error(argument_expression.location, "no constructor found init({source_type})") | |
| 603 | return (cast Value(DUMMY(type, location)), cast Value(DUMMY(type, location))) | |
| 604 | fi | |
| 605 | ||
| 606 | // Compile-time shape check: the two call shapes must | |
| 607 | // actually agree. `Delegate.CreateDelegate` would have | |
| 608 | // caught a mismatch for us at construction time, but | |
| 609 | // going straight to a raw function pointer below bypasses | |
| 610 | // that check entirely, so it has to happen here instead. | |
| 611 | let source_shape = | |
| 612 | if source_type.is_function then | |
| 613 | source_type | |
| 614 | else | |
| 615 | _delegate_shape.try_get_function_type(source_type, _innate_symbol_lookup) | |
| 616 | fi | |
| 617 | ||
| 618 | let target_shape = _delegate_shape.try_get_function_type(type, _innate_symbol_lookup) | |
| 619 | ||
| 620 | if !source_shape? \/ !target_shape? \/ !target_shape.is_assignable_from(source_shape) then | |
| 621 | _logger.error(argument_expression.location, "{source_type} is not assignable to {type}") | |
| 622 | return (cast Value(DUMMY(type, location)), cast Value(DUMMY(type, location))) | |
| 623 | fi | |
| 624 | ||
| 625 | // `Target`/`Method` report only the last entry of a | |
| 626 | // combined (multicast) delegate's invocation list, so a | |
| 627 | // source built via `Delegate.Combine` would silently lose | |
| 628 | // every earlier target. Not guarded against: ghūl has no | |
| 629 | // syntax to combine delegates, so no ghūl-produced value | |
| 630 | // reaching here is ever multicast. | |
| 631 | let target_property = cast Semantic.Symbols.Property?(source_type.find_member("target")) | |
| 632 | let method_property = cast Semantic.Symbols.Property?(source_type.find_member("method")) | |
| 633 | ||
| 634 | if !target_property? \/ !method_property? then | |
| 635 | _logger.error(argument_expression.location, "cannot convert {source_type} to {type}") | |
| 636 | return (cast Value(DUMMY(type, location)), cast Value(DUMMY(type, location))) | |
| 637 | fi | |
| 638 | ||
| 639 | let target_value = target_property.load(location, value, _symbol_loader) | |
| 640 | let method_value = method_property.load(location, value, _symbol_loader) | |
| 641 | let method_type = method_value.type! | |
| 642 | ||
| 643 | let handle_property = cast Semantic.Symbols.Property?(method_type.find_member("method_handle")) | |
| 644 | ||
| 645 | if !handle_property? then | |
| 646 | _logger.error(argument_expression.location, "cannot convert {source_type} to {type}") | |
| 647 | return (cast Value(DUMMY(type, location)), cast Value(DUMMY(type, location))) | |
| 648 | fi | |
| 649 | ||
| 650 | let handle_value = handle_property.load(location, method_value, _symbol_loader) | |
| 651 | let handle_type = handle_value.type! | |
| 652 | ||
| 653 | let get_function_pointer_function = _find_single_function_member(handle_type, "get_function_pointer") | |
| 654 | ||
| 655 | if !get_function_pointer_function? then | |
| 656 | _logger.error(argument_expression.location, "cannot convert {source_type} to {type}") | |
| 657 | return (cast Value(DUMMY(type, location)), cast Value(DUMMY(type, location))) | |
| 658 | fi | |
| 659 | ||
| 660 | let pointer_value = get_function_pointer_function.call(location, handle_value, Collections.LIST[Value](), null, _function_caller) | |
| 661 | ||
| 662 | let ctor = _find_delegate_constructor(type) | |
| 663 | ||
| 664 | if !ctor? then | |
| 665 | _logger.error(argument_expression.location, "cannot convert {source_type} to {type}") | |
| 666 | return (cast Value(DUMMY(type, location)), cast Value(DUMMY(type, location))) | |
| 667 | fi | |
| 668 | ||
| 669 | let ctor_arguments = Collections.LIST[Value]() | |
| 670 | ctor_arguments.add(target_value) | |
| 671 | ctor_arguments.add(pointer_value) | |
| 672 | ||
| 673 | let constructed = _function_caller.call_constructor(ctor, ctor_arguments, type) | |
| 674 | ||
| 675 | return (cast Value(DUMMY(type, location)), constructed) | |
| 676 | si | |
| 677 | ||
| 678 | resolve_constructor( | |
| 679 | location: LOCATION, | |
| 680 | right_location: LOCATION, | |
| 681 | type: Semantic.Types.Type mut, | |
| 682 | argument_expressions: Trees.Expressions.LIST, | |
| 683 | argument_names: Collections.List[Trees.Identifiers.Identifier]?, | |
| 684 | constraint: Semantic.Types.Type?, | |
| 685 | cache_key: Trees.Node | |
| 686 | ) -> (Value, Value) is | |
| 687 | let result: Value mut | |
| 688 | ||
| 689 | // An explicit `Foo[...]` callee enters already specialized | |
| 690 | // and was constraint-checked by `specialize_type`; an | |
| 691 | // inferred `Foo(...)` callee is specialized below by | |
| 692 | // overload resolution and is checked post-resolution. | |
| 693 | let was_generic_on_entry = isa Semantic.Types.GENERIC(type) | |
| 694 | ||
| 695 | let named_or_null = cast Semantic.Types.NAMED?(type) | |
| 696 | ||
| 697 | // A callee whose type could not be settled was reported where | |
| 698 | // it went wrong, so only an error value comes out of here. | |
| 699 | if !named_or_null? \/ type.is_value_tuple \/ isa Semantic.Types.TUPLE(type) then | |
| 700 | if !type.is_error then | |
| 701 | _logger.error(location, "cannot construct {type}") | |
| 702 | fi | |
| 703 | ||
| 704 | return (DUMMY(Semantic.Types.ERROR(), location), DUMMY(Semantic.Types.ERROR(), location)) | |
| 705 | fi | |
| 706 | ||
| 707 | let named_type = named_or_null | |
| 708 | let type_symbol mut = named_type.symbol | |
| 709 | ||
| 710 | if | |
| 711 | !argument_names? /\ | |
| 712 | argument_expressions.expressions.count == 1 /\ | |
| 713 | _delegate_shape.is_named_delegate(type, _innate_symbol_lookup) | |
| 714 | then | |
| 715 | return _resolve_delegate_value_construction(location, type, argument_expressions.expressions[0]) | |
| 716 | fi | |
| 717 | ||
| 718 | if let abstract_class: Semantic.Symbols.CLASS = type_symbol then | |
| 719 | if abstract_class.is_abstract then | |
| 720 | _logger.error(location, "cannot instantiate abstract class {abstract_class.name}", abstract_class.location, "class declared abstract here") | |
| 721 | fi | |
| 722 | fi | |
| 723 | ||
| 724 | let symbol = named_type.scope.find_direct("init") | |
| 725 | ||
| 726 | let function_group = cast Semantic.Symbols.FUNCTION_GROUP?(symbol) | |
| 727 | ||
| 728 | let arguments = Collections.LIST[Value]() | |
| 729 | let argument_types = Collections.LIST[Type]() | |
| 730 | ||
| 731 | _compile_call_arguments(argument_expressions, arguments, argument_types) | |
| 732 | ||
| 733 | if !function_group? then | |
| 734 | _logger.error(location, "no constructor found init({argument_types |> join(", ")})") | |
| 735 | ||
| 736 | return (cast Value(DUMMY(type, location)), cast Value(DUMMY(type, location))) | |
| 737 | fi | |
| 738 | ||
| 739 | let named_restrict: Collections.List[Semantic.Symbols.Function]? mut = null | |
| 740 | ||
| 741 | if argument_names? then | |
| 742 | let binding = _named_argument_binder.bind(location, function_group, argument_names, true) | |
| 743 | ||
| 744 | if !binding? then | |
| 745 | return (cast Value(Load.SYMBOL(null, function_group)), cast Value(DUMMY(type, location))) | |
| 746 | fi | |
| 747 | ||
| 748 | _apply_named_permutation(argument_expressions, arguments, argument_types, binding.permutation, binding.targets[0]) | |
| 749 | ||
| 750 | named_restrict = binding.targets | |
| 751 | fi | |
| 752 | ||
| 753 | let overload_result mut = _overload_resolver.resolve(location, function_group, argument_types, false, true, true, named_restrict) | |
| 754 | ||
| 755 | // Sibling-arg fall-back: first resolve returned null AND | |
| 756 | // there's at least one FUNCTION-literal arg in the call. | |
| 757 | // The lambda's body walked under no parameter-type | |
| 758 | // constraint and likely errored, leaving an actual type | |
| 759 | // that doesn't reflect the real signature; binding fails; | |
| 760 | // resolver returns null. Try tentatively binding the | |
| 761 | // candidate's owner-generic args from the *resolvable* | |
| 762 | // sibling actuals (skipping the failing lambda), fill the | |
| 763 | // remaining slots with cached phantoms, then push the | |
| 764 | // substituted formals as constraints to each arg and | |
| 765 | // re-walk. The second resolve sees the lambda's now- | |
| 766 | // resolved actual type and binds T from it. | |
| 767 | // | |
| 768 | // The lambda guard matters: if no arg is a lambda, the | |
| 769 | // original null result reflects a genuine type mismatch | |
| 770 | // (e.g. `Pair([1,2,3], LIST[int]([4,5,6]))` — int[] and | |
| 771 | // LIST[int] don't unify for T) and the user-facing | |
| 772 | // diagnostic is correct as-is. | |
| 773 | if overload_result == null /\ argument_types |> any(a => a.is_function_with_any_implicit_argument_types) then | |
| 774 | let candidate = _try_find_single_arity_candidate(function_group, argument_types.count, true) | |
| 775 | ||
| 776 | if candidate? then | |
| 777 | let specialized_candidate = _specialise_candidate_from_concrete_siblings(candidate, argument_types, cache_key, location) | |
| 778 | ||
| 779 | if specialized_candidate? /\ specialized_candidate != candidate then | |
| 780 | let use retry_site = RETRY_SITE_STATS.enter("calls.constructor_sibling_specialisation", RetrySiteKind.REWALK_WITH_INFORMATION) | |
| 781 | _logger.roll_back() | |
| 782 | _logger.speculate() | |
| 783 | _flow.restore() | |
| 784 | ||
| 785 | for (index, a) in argument_expressions |> index() do | |
| 786 | let f = specialized_candidate.arguments[index] | |
| 787 | ||
| 788 | a.set_expected_type(f, "{{0}} is not assignable to {{1}}") | |
| 789 | ||
| 790 | _visitor.rewalk(a) | |
| 791 | ||
| 792 | if let a.value? /\ value.type? /\ value.check_is_consumable(_logger, a.location) then | |
| 793 | arguments[index] = value | |
| 794 | argument_types[index] = value.type! | |
| 795 | else | |
| 796 | let t = Semantic.Types.ERROR() | |
| 797 | arguments[index] = DUMMY(t, a.location) | |
| 798 | argument_types[index] = t | |
| 799 | fi | |
| 800 | od | |
| 801 | ||
| 802 | overload_result = _overload_resolver.resolve(location, function_group, argument_types, false, true, true, named_restrict) | |
| 803 | fi | |
| 804 | fi | |
| 805 | fi | |
| 806 | ||
| 807 | // An empty literal takes `object` as its element type with | |
| 808 | // nothing around it to say otherwise, so it resolves either no | |
| 809 | // constructor of the written type or one of the wrong | |
| 810 | // instantiation. The candidate this call is for - specialised | |
| 811 | // from the constraint where there is one - is pushed as the | |
| 812 | // formals and the arguments walked again, the same recovery an | |
| 813 | // ordinary call makes. | |
| 814 | if | |
| 815 | COMPILE_CALLS.has_empty_array_literal_argument(argument_expressions.expressions) /\ | |
| 816 | (overload_result == null \/ constraint?) | |
| 817 | then | |
| 818 | let specialised = | |
| 819 | if constraint? then | |
| 820 | _constructor_constraint_retry.try_specialise_candidates( | |
| 821 | location, | |
| 822 | if named_restrict? then named_restrict else function_group.functions fi, | |
| 823 | constraint) | |
| 824 | else | |
| 825 | null | |
| 826 | fi | |
| 827 | ||
| 828 | let candidate = | |
| 829 | if specialised? /\ specialised.count == 1 then | |
| 830 | specialised[0] | |
| 831 | else | |
| 832 | _try_find_single_arity_candidate(function_group, argument_types.count, true) | |
| 833 | fi | |
| 834 | ||
| 835 | if candidate? /\ candidate.arguments.count == argument_expressions.expressions.count then | |
| 836 | let use retry_site = RETRY_SITE_STATS.enter("calls.constructor_empty_literal", RetrySiteKind.REWALK_WITH_INFORMATION) | |
| 837 | _logger.roll_back() | |
| 838 | _logger.speculate() | |
| 839 | _flow.restore() | |
| 840 | ||
| 841 | for (index, a) in argument_expressions |> index() do | |
| 842 | a.set_expected_type(candidate.arguments[index], "{{0}} is not assignable to {{1}}") | |
| 843 | ||
| 844 | _visitor.rewalk(a) | |
| 845 | ||
| 846 | if let a.value? /\ value.type? /\ value.check_is_consumable(_logger, a.location) then | |
| 847 | arguments[index] = value | |
| 848 | argument_types[index] = value.type! | |
| 849 | else | |
| 850 | let t = Semantic.Types.ERROR() | |
| 851 | arguments[index] = DUMMY(t, a.location) | |
| 852 | argument_types[index] = t | |
| 853 | fi | |
| 854 | od | |
| 855 | ||
| 856 | overload_result = | |
| 857 | _overload_resolver.resolve( | |
| 858 | location, | |
| 859 | function_group, | |
| 860 | argument_types, | |
| 861 | false, | |
| 862 | true, | |
| 863 | true, | |
| 864 | specialised ?? named_restrict) | |
| 865 | fi | |
| 866 | fi | |
| 867 | ||
| 868 | // Return-type-constraint fall-back: first resolve returned | |
| 869 | // null AND we have a constraint pushed in by an enclosing | |
| 870 | // return / let-init / assignment. The candidate's owner- | |
| 871 | // generic args may include slots no actual arg can bind | |
| 872 | // (e.g. `RESULT.OK(42)` against `RESULT[int, string]` — | |
| 873 | // OK's arg binds T, the constraint contributes S; without | |
| 874 | // a contribution from the constraint, binding fails and | |
| 875 | // the resolver returns null). Pre-specialise each candidate | |
| 876 | // from the constraint via CONSTRUCTOR_CONSTRAINT_RETRY, | |
| 877 | // then re-resolve with the specialised list. Now formals | |
| 878 | // are no-longer-wild concrete types and arg binding | |
| 879 | // becomes verification. | |
| 880 | if overload_result == null /\ constraint? then | |
| 881 | let search = if named_restrict? then named_restrict else function_group.functions fi | |
| 882 | let pre_specialised = _constructor_constraint_retry.try_specialise_candidates(location, search, constraint) | |
| 883 | ||
| 884 | if pre_specialised? then | |
| 885 | let use retry_site = RETRY_SITE_STATS.enter("calls.constructor_constraint_retry", RetrySiteKind.REWALK_WITH_INFORMATION) | |
| 886 | _logger.roll_back() | |
| 887 | _logger.speculate() | |
| 888 | ||
| 889 | overload_result = _overload_resolver.resolve(location, function_group, argument_types, false, true, true, pre_specialised) | |
| 890 | fi | |
| 891 | fi | |
| 892 | ||
| 893 | if overload_result == null then | |
| 894 | return (cast Value(Load.SYMBOL(null, function_group)), cast Value(DUMMY(type, location))) | |
| 895 | fi | |
| 896 | ||
| 897 | if overload_result.needs_retry then | |
| 898 | let use retry_site = RETRY_SITE_STATS.enter("calls.constructor_needs_retry", RetrySiteKind.REWALK_WITH_INFORMATION) | |
| 899 | _logger.roll_back() | |
| 900 | _logger.speculate() | |
| 901 | _flow.restore() | |
| 902 | ||
| 903 | for (index, a) in argument_expressions |> index() do | |
| 904 | // let use debug_despose = debug_enter(); | |
| 905 | if a.value? /\ isa Trees.Expressions.FUNCTION(a) then | |
| 906 | let f = overload_result.function.arguments[index] | |
| 907 | ||
| 908 | a.set_expected_type(f, "{{0}} is not assignable to {{1}}") | |
| 909 | _visitor.rewalk(a) | |
| 910 | ||
| 911 | argument_types[index] = a.value!.type! | |
| 912 | else | |
| 913 | // ensure any error messages are committed | |
| 914 | _visitor.rewalk(a) | |
| 915 | fi | |
| 916 | ||
| 917 | if a.value? then | |
| 918 | arguments[index] = a.value | |
| 919 | fi | |
| 920 | od | |
| 921 | ||
| 922 | overload_result = _overload_resolver.resolve(location, function_group, argument_types, false, true, true, named_restrict) | |
| 923 | ||
| 924 | if !overload_result? then | |
| 925 | return (cast Value(Load.SYMBOL(null, function_group)), cast Value(DUMMY(type, location))) | |
| 926 | fi | |
| 927 | fi | |
| 928 | ||
| 929 | let function mut = overload_result.function | |
| 930 | ||
| 931 | function = _owner_constraint_specializer.specialize_from_constraint(location, function, constraint) | |
| 932 | function = _type_arg_placeholder_registry.specialize_with_placeholders(location, function, cache_key) | |
| 933 | ||
| 934 | let _ = _resolve_deferred_defaults(function, argument_expressions.expressions, arguments, argument_types) | |
| 935 | ||
| 936 | if isa Semantic.Symbols.GENERIC(function.owner) then | |
| 937 | type_symbol = cast Semantic.Symbols.Symbol(function.owner) | |
| 938 | // The GENERIC owner of a resolved constructor always carries | |
| 939 | // a concrete type (the specialized class) by this point. | |
| 940 | type = function.owner.type | |
| 941 | fi | |
| 942 | ||
| 943 | let is_directly_owned mut = false | |
| 944 | ||
| 945 | if isa Semantic.Symbols.GENERIC(type_symbol) /\ isa Semantic.Symbols.Symbol(function.owner) then | |
| 946 | is_directly_owned = type_symbol =~ cast Semantic.Symbols.Symbol(function.owner) | |
| 947 | else | |
| 948 | is_directly_owned = type_symbol == function.owner | |
| 949 | fi | |
| 950 | ||
| 951 | if !is_directly_owned then | |
| 952 | _logger.error(location, "cannot call superclass constructor {function}", function.location, "constructor declared here") | |
| 953 | fi | |
| 954 | ||
| 955 | _symbol_use_locations.add_symbol_use(right_location, function) | |
| 956 | _symbol_use_locations.add_symbol_use(right_location, type_symbol.root_unspecialized_symbol) | |
| 957 | ||
| 958 | ||
| 959 | if !was_generic_on_entry then | |
| 960 | if let constructed: Semantic.Types.GENERIC = type then | |
| 961 | if let generic_symbol: Semantic.Symbols.GENERIC = constructed.symbol then | |
| 962 | generic_symbol.symbol.check_argument_constraints(location, _logger, constructed.arguments) | |
| 963 | fi | |
| 964 | fi | |
| 965 | fi | |
| 966 | ||
| 967 | return (cast Value(Load.SYMBOL(null, function_group)), _function_caller.call_constructor(function, arguments, type)) | |
| 968 | si | |
| 969 | ||
| 970 | // True iff any formal arg in the resolver's PARTIAL function | |
| 971 | // is itself ERROR or contains an ERROR. Signal that the | |
| 972 | // partial binding was driven from a tainted lambda actual | |
| 973 | // (a typical free-function-with-lambda inference scenario) | |
| 974 | // and the PARTIAL formals shouldn't be pushed as constraints | |
| 975 | // unchanged. | |
| 976 | _partial_arguments_contain_error(function: Semantic.Symbols.Function) -> bool is | |
| 977 | if !function.are_arguments_declared then | |
| 978 | return false | |
| 979 | fi | |
| 980 | ||
| 981 | let found = Ghul.BOX(false) | |
| 982 | ||
| 983 | for arg in function.arguments do | |
| 984 | arg.walk((t: Type) is | |
| 985 | if t.is_error then | |
| 986 | found.value = true | |
| 987 | fi | |
| 988 | si) | |
| 989 | ||
| 990 | if found.value then | |
| 991 | return true | |
| 992 | fi | |
| 993 | od | |
| 994 | ||
| 995 | return false | |
| 996 | si | |
| 997 | ||
| 998 | // True iff any formal arg in the resolver's PARTIAL function | |
| 999 | // still references one of the function's own generic | |
| 1000 | // type-variables (i.e. the resolver couldn't bind that slot | |
| 1001 | // from any sibling actual). Same shape problem as | |
| 1002 | // `_partial_arguments_contain_error`: pushing the formal as-is | |
| 1003 | // burdens the lambda's re-walk with a constraint | |
| 1004 | // (`int -> STEP[T]`) that can't be satisfied by anything | |
| 1005 | // concrete the body produces. Re-specialise with phantoms in | |
| 1006 | // those slots so the constraint pushed becomes | |
| 1007 | // (`int -> STEP[<phantom>]`) — actually informative, and | |
| 1008 | // open to match propagation from inside the body. | |
| 1009 | _partial_arguments_contain_unbound_function_type_variable(function: Semantic.Symbols.Function) -> bool is | |
| 1010 | let found = Ghul.BOX(false) | |
| 1011 | ||
| 1012 | for arg in function.arguments do | |
| 1013 | arg.walk((t: Type) is | |
| 1014 | if t.is_function_generic_argument then | |
| 1015 | found.value = true | |
| 1016 | fi | |
| 1017 | si) | |
| 1018 | ||
| 1019 | if found.value then | |
| 1020 | return true | |
| 1021 | fi | |
| 1022 | od | |
| 1023 | ||
| 1024 | return false | |
| 1025 | si | |
| 1026 | ||
| 1027 | // True if any of the actual argument expressions is a | |
| 1028 | // Trees.Expressions.FUNCTION literal. Used to gate the | |
| 1029 | // constraint-push retry on the recoverable case where a | |
| 1030 | // not-yet-constrained lambda body walked with placeholder | |
| 1031 | // args and produced an ERROR-tainted type that the under- | |
| 1032 | // determination detector wouldn't otherwise recognise as | |
| 1033 | // recoverable. | |
| 1034 | // | |
| 1035 | // Static so it can be exercised by unit tests with hand-built | |
| 1036 | // expression lists, without spinning up COMPILE_CALLS's full | |
| 1037 | // dependency graph. | |
| 1038 | // A caller may hand over a partially built argument list, whose | |
| 1039 | // unfilled slots have no expression yet. | |
| 1040 | has_function_literal_argument(argument_expressions: Collections.List[Trees.Expressions.Expression?]?) -> bool static is | |
| 1041 | if !argument_expressions? then | |
| 1042 | return false | |
| 1043 | fi | |
| 1044 | ||
| 1045 | for a in argument_expressions do | |
| 1046 | if isa Trees.Expressions.FUNCTION(a) then | |
| 1047 | return true | |
| 1048 | fi | |
| 1049 | od | |
| 1050 | ||
| 1051 | return false | |
| 1052 | si | |
| 1053 | ||
| 1054 | // An empty array literal argument has no elements to infer its | |
| 1055 | // element type from, so it walks to object[] and fails to match a | |
| 1056 | // more specific array parameter. Like a function literal, it can be | |
| 1057 | // re-walked under a pushed formal type, so it is a signal that a | |
| 1058 | // null overload result might be recoverable. | |
| 1059 | // As above: an unfilled slot in a partially built list has no | |
| 1060 | // expression yet. | |
| 1061 | has_empty_array_literal_argument(argument_expressions: Collections.List[Trees.Expressions.Expression?]?) -> bool static is | |
| 1062 | if !argument_expressions? then | |
| 1063 | return false | |
| 1064 | fi | |
| 1065 | ||
| 1066 | for a in argument_expressions do | |
| 1067 | if let sequence: Trees.Expressions.SEQUENCE = a then | |
| 1068 | if sequence.elements.expressions.count == 0 then | |
| 1069 | return true | |
| 1070 | fi | |
| 1071 | fi | |
| 1072 | od | |
| 1073 | ||
| 1074 | return false | |
| 1075 | si | |
| 1076 | ||
| 1077 | // An actual whose type still carries a type parameter of the | |
| 1078 | // function that produced it: a call to a generic function | |
| 1079 | // nothing in its own arguments could bind, such as | |
| 1080 | // `zero_of[T](n: int) -> T` called as `takes(zero_of(1))`. | |
| 1081 | // The formal it is being matched against is the only thing | |
| 1082 | // that can settle the parameter, so pushing it as the | |
| 1083 | // argument's expected type and re-walking is what turns the | |
| 1084 | // call into a resolvable one. A parameter of `caller` itself, | |
| 1085 | // or of a function `caller` is nested in, is in scope where | |
| 1086 | // the call is written and needs nothing pushed. | |
| 1087 | // | |
| 1088 | // Static, and taking the caller rather than reading it off the | |
| 1089 | // symbol table, so it can be exercised with hand-built types. | |
| 1090 | // A caller may hand over a partially built argument list, whose | |
| 1091 | // unfilled slots have no type yet. | |
| 1092 | has_unbound_type_argument( | |
| 1093 | argument_types: Collections.List[Type?]?, | |
| 1094 | caller: Semantic.Scope? | |
| 1095 | ) -> bool static is | |
| 1096 | if !argument_types? then | |
| 1097 | return false | |
| 1098 | fi | |
| 1099 | ||
| 1100 | for t in argument_types do | |
| 1101 | if t? /\ t.has_function_generic_argument_foreign_to(caller) then | |
| 1102 | return true | |
| 1103 | fi | |
| 1104 | od | |
| 1105 | ||
| 1106 | return false | |
| 1107 | si | |
| 1108 | ||
| 1109 | // Walk the scope stack from current_function outward to find | |
| 1110 | // the recursive closure a `rec` reference here would bind to. | |
| 1111 | // Mirrors the lookup in `visit(RECURSE)`. | |
| 1112 | _find_recursive_target() -> Semantic.Symbols.Closure? is | |
| 1113 | let function = _symbol_table.current_function | |
| 1114 | ||
| 1115 | if !function? \/ !function.is_closure then | |
| 1116 | return null | |
| 1117 | fi | |
| 1118 | ||
| 1119 | let closure = cast Semantic.Symbols.Closure?(function)! | |
| 1120 | ||
| 1121 | if closure.is_recursive then | |
| 1122 | return closure | |
| 1123 | fi | |
| 1124 | ||
| 1125 | let stack = _symbol_table.stack | |
| 1126 | let index mut = stack.count - 1 | |
| 1127 | let seen_self mut = false | |
| 1128 | ||
| 1129 | while index >= 0 do | |
| 1130 | let scope = stack[index] | |
| 1131 | ||
| 1132 | if scope.is_closure then | |
| 1133 | let c = cast Semantic.Symbols.Closure?(scope)! | |
| 1134 | ||
| 1135 | if seen_self then | |
| 1136 | if c.is_recursive then | |
| 1137 | return c | |
| 1138 | fi | |
| 1139 | elif c == closure then | |
| 1140 | seen_self = true | |
| 1141 | fi | |
| 1142 | fi | |
| 1143 | ||
| 1144 | index = index - 1 | |
| 1145 | od | |
| 1146 | ||
| 1147 | return null | |
| 1148 | si | |
| 1149 | ||
| 1150 | // Push each actual argument of a `rec(actual...)` call onto | |
| 1151 | // the recursive closure's parameter Variables as a LUB | |
| 1152 | // candidate. When the actual isn't assignable to the | |
| 1153 | // parameter's current type, reset that type back to an | |
| 1154 | // INFERRED_VARIABLE_TYPE placeholder so the next outer-body | |
| 1155 | // retry iteration's closure_arg_resolver re-derives the | |
| 1156 | // parameter type from the widened LUB. Handles both self-rec | |
| 1157 | // and nested-rec (rec referring to an outer recursive | |
| 1158 | // ancestor) — the target is determined by walking the | |
| 1159 | // closure stack mirroring `visit(RECURSE)`. | |
| 1160 | try_propagate_recursive_call_args(call: Trees.Expressions.CALL) is | |
| 1161 | if !isa Trees.Expressions.RECURSE(call.function) then | |
| 1162 | return | |
| 1163 | fi | |
| 1164 | ||
| 1165 | let closure = _find_recursive_target() | |
| 1166 | ||
| 1167 | if !closure? then | |
| 1168 | return | |
| 1169 | fi | |
| 1170 | ||
| 1171 | let param_count = closure.argument_names.count | |
| 1172 | let args = call.arguments.expressions | |
| 1173 | let arg_count = args.count | |
| 1174 | ||
| 1175 | let n = if param_count < arg_count then param_count else arg_count fi | |
| 1176 | ||
| 1177 | let i mut = 0 | |
| 1178 | while i < n do | |
| 1179 | let name = closure.argument_names[i] | |
| 1180 | let param = cast Semantic.Symbols.Variable?(closure.find_direct(name)) | |
| 1181 | let arg_expr = args[i] | |
| 1182 | ||
| 1183 | // Prefer arg_expr.value.type, but fall back to the | |
| 1184 | // resolved symbol's type when the value's snapshot | |
| 1185 | // is null — happens for outer-scope locals captured | |
| 1186 | // into a nested closure before being typed. | |
| 1187 | let actual: Semantic.Types.Type? mut = null | |
| 1188 | if let arg_expr?.value? /\ value.type? then | |
| 1189 | actual = value.type | |
| 1190 | elif isa Trees.Expressions.IDENTIFIER(arg_expr) then | |
| 1191 | let id_expr = arg_expr | |
| 1192 | let sym = _visitor.find(id_expr.identifier) | |
| 1193 | if sym? then | |
| 1194 | actual = sym.type | |
| 1195 | fi | |
| 1196 | fi | |
| 1197 | ||
| 1198 | if param? /\ actual? then | |
| 1199 | if actual.is_settled then | |
| 1200 | _logger.mark_consumed_any_if(Semantic.INFERENCE_TRACE.add_lower_bound("calls.recursive_call_argument", param, actual)) | |
| 1201 | ||
| 1202 | // Reset the param's type if currently | |
| 1203 | // resolved to something narrower than the | |
| 1204 | // actual — leaves it concrete when the | |
| 1205 | // actual fits. The comparison is against the | |
| 1206 | // declared type: inside an `if let` on the | |
| 1207 | // parameter, `param.type` is the narrowed | |
| 1208 | // variant, which the recursive call's argument | |
| 1209 | // legitimately widens. | |
| 1210 | let declared = _flow.declared_type_of(param) ?? param.type | |
| 1211 | ||
| 1212 | if | |
| 1213 | declared? /\ | |
| 1214 | !declared.is_sentinel /\ | |
| 1215 | !declared.is_assignable_from(actual) | |
| 1216 | then | |
| 1217 | param.set_type(Semantic.Types.INFERRED_VARIABLE_TYPE(param)) | |
| 1218 | _logger.mark_consumed_any() | |
| 1219 | fi | |
| 1220 | fi | |
| 1221 | fi | |
| 1222 | ||
| 1223 | i = i + 1 | |
| 1224 | od | |
| 1225 | si | |
| 1226 | ||
| 1227 | // A call returning a pack slot still to be inferred, written where | |
| 1228 | // the context already names an N-ary function - `let g: (int, int) | |
| 1229 | // -> int = once(...)` - takes the pack from the context: the | |
| 1230 | // parameters of the function the context expects are the tuple | |
| 1231 | // the pack binds to, and its return bounds the result slot. | |
| 1232 | feed_pack_from_expected(function: Semantic.Symbols.Function, expected: Semantic.Types.Type?) => | |
| 1233 | _feed_pack_from_expected(function, expected) | |
| 1234 | ||
| 1235 | _feed_pack_from_expected(function: Semantic.Symbols.Function, expected: Semantic.Types.Type?) is | |
| 1236 | if !expected? \/ !expected.is_function \/ expected.is_action then | |
| 1237 | return | |
| 1238 | fi | |
| 1239 | ||
| 1240 | let returned = function.return_type | |
| 1241 | ||
| 1242 | if !returned? \/ !Semantic.ARGUMENT_PACK.is_pack_slot(returned) then | |
| 1243 | return | |
| 1244 | fi | |
| 1245 | ||
| 1246 | let arity = Semantic.ARGUMENT_PACK.parameter_count(expected) | |
| 1247 | ||
| 1248 | if arity < 2 \/ arity > Semantic.ARGUMENT_PACK.MAXIMUM_ARITY then | |
| 1249 | return | |
| 1250 | fi | |
| 1251 | ||
| 1252 | if let placeholder: Semantic.Types.INFERRED_VARIABLE_TYPE = returned.arguments[0] then | |
| 1253 | if let origin: Semantic.Symbols.INFERRED_TYPE_ARG_ORIGIN = placeholder.origin /\ origin.is_argument_pack then | |
| 1254 | let elements = Collections.LIST[Semantic.Types.Type]() | |
| 1255 | ||
| 1256 | for i in 0..arity do | |
| 1257 | elements.add(expected.arguments[i]) | |
| 1258 | od | |
| 1259 | ||
| 1260 | let tuple = _innate_symbol_lookup.get_tuple_type(elements, null) | |
| 1261 | ||
| 1262 | _logger.mark_consumed_any_if(Semantic.INFERENCE_TRACE.add_lower_bound("calls.pack_expected_type", origin, tuple)) | |
| 1263 | fi | |
| 1264 | fi | |
| 1265 | ||
| 1266 | if let result: Semantic.Types.INFERRED_VARIABLE_TYPE = returned.arguments[returned.arguments.count - 1] then | |
| 1267 | _logger.mark_consumed_any_if(Semantic.INFERENCE_TRACE.add_upper_bound("calls.pack_expected_return", result.origin, expected.arguments[expected.arguments.count - 1])) | |
| 1268 | fi | |
| 1269 | si | |
| 1270 | ||
| 1271 | // Resolution against the group binds a type argument only from | |
| 1272 | // what the arguments say. One nothing binds - a pack whose element | |
| 1273 | // types only a later call supplies - comes back as the callee's own | |
| 1274 | // bare parameter, which no variable can take as its type. Where | |
| 1275 | // the retry specialised the same candidate over the call's | |
| 1276 | // phantoms, that specialisation carries the slot instead: the | |
| 1277 | // phantom is what a later use constrains, and the re-walk that | |
| 1278 | // follows resolves the call again over what it learned. | |
| 1279 | _prefer_phantom_specialised( | |
| 1280 | result: Semantic.OVERLOAD_RESOLVE_RESULT?, | |
| 1281 | push: Semantic.Symbols.Function? | |
| 1282 | ) -> Semantic.OVERLOAD_RESOLVE_RESULT? is | |
| 1283 | if | |
| 1284 | result? /\ | |
| 1285 | push? /\ | |
| 1286 | push != result.function /\ | |
| 1287 | push.root_specialized_from == result.function.root_specialized_from /\ | |
| 1288 | COMPILE_CALLS.has_unbound_type_argument([result.function.return_type!], _symbol_table.current_function) | |
| 1289 | then | |
| 1290 | _logger.mark_consumed_any() | |
| 1291 | ||
| 1292 | return Semantic.OVERLOAD_RESOLVE_RESULT(push, result.score, false) | |
| 1293 | fi | |
| 1294 | ||
| 1295 | return result | |
| 1296 | si | |
| 1297 | ||
| 1298 | // An array literal argument can hold an element whose type is still | |
| 1299 | // being inferred - an untyped local initialized with `[]`, say. Its | |
| 1300 | // join then waits on that element, so the literal carries no element | |
| 1301 | // type and nothing would tell the element what it has to be. The | |
| 1302 | // resolved formal does: each such element is bounded above by the | |
| 1303 | // formal's element type, which a later walk settles it from. | |
| 1304 | _bound_awaiting_sequence_elements( | |
| 1305 | candidate: Semantic.Symbols.Function, | |
| 1306 | argument_expressions: Collections.List[Trees.Expressions.Expression] | |
| 1307 | ) is | |
| 1308 | if candidate.arguments.count != argument_expressions.count then | |
| 1309 | return | |
| 1310 | fi | |
| 1311 | ||
| 1312 | for index in 0..argument_expressions.count do | |
| 1313 | _bound_sequence_elements(argument_expressions[index], candidate.arguments[index]) | |
| 1314 | od | |
| 1315 | si | |
| 1316 | ||
| 1317 | _bound_sequence_elements(argument: Trees.Expressions.Expression, formal: Type?) is | |
| 1318 | let sequence = cast Trees.Expressions.SEQUENCE?(argument) | |
| 1319 | ||
| 1320 | if !sequence? \/ !formal? then | |
| 1321 | return | |
| 1322 | fi | |
| 1323 | ||
| 1324 | let element_type = Semantic.SEQUENCE_ELEMENT_BOUND.for_element_type(formal.get_element_type()) | |
| 1325 | ||
| 1326 | if !element_type? then | |
| 1327 | return | |
| 1328 | fi | |
| 1329 | ||
| 1330 | for element in sequence.elements do | |
| 1331 | if let value = element.value, placeholder: Semantic.Types.INFERRED_VARIABLE_TYPE = value.type then | |
| 1332 | _logger.mark_consumed_any_if( | |
| 1333 | Semantic.INFERENCE_TRACE.add_upper_bound("calls.sequence_element", placeholder.origin, element_type) | |
| 1334 | ) | |
| 1335 | elif isa Trees.Expressions.SEQUENCE(element) then | |
| 1336 | _bound_sequence_elements(element, element_type) | |
| 1337 | fi | |
| 1338 | od | |
| 1339 | si | |
| 1340 | ||
| 1341 | // Constraint-push retry: when the first resolve fails AND | |
| 1342 | // there's exactly one arity-matching candidate AND at least | |
| 1343 | // one argument's first-walk type is under-determined for | |
| 1344 | // its corresponding formal type, push that candidate's | |
| 1345 | // formal arg types as constraints to each call argument | |
| 1346 | // and re-walk. This catches `apply(Box())` cases where a | |
| 1347 | // constructor argument's owner generic args were | |
| 1348 | // under-determined the first time round but become | |
| 1349 | // resolvable from the formal argument's type. The | |
| 1350 | // candidate's signature is the only signal we have for | |
| 1351 | // what the under-determined arg should resolve to — | |
| 1352 | // multi-candidate disambiguation under constraint push | |
| 1353 | // is left to a more general overload-as-constraint | |
| 1354 | // pass under #1174. | |
| 1355 | // Constraint-push retry for when the initial overload resolution | |
| 1356 | // returned null. Generalised over the source of the argument | |
| 1357 | // expressions: calls pass `call.arguments.expressions` / | |
| 1358 | // `call.arguments.location` / `call` as the cache key; binary | |
| 1359 | // operators pass `[left, right]`, `binary.location`, the BINARY | |
| 1360 | // node; unary operators pass `[right]`, `unary.location`, the | |
| 1361 | // UNARY node. Assumes the caller is inside a `_logger.speculate()` | |
| 1362 | // level: this method does `_logger.roll_back(); _logger.speculate();` | |
| 1363 | // to re-enter before re-walking, mirroring the visit_call wrapper. | |
| 1364 | try_overload_after_null( | |
| 1365 | function_group: Semantic.Symbols.FUNCTION_GROUP, | |
| 1366 | arguments: Collections.LIST[Value], | |
| 1367 | argument_types: Collections.LIST[Type], | |
| 1368 | want_instance: bool, | |
| 1369 | named_restrict: Collections.List[Semantic.Symbols.Function]?, | |
| 1370 | argument_expressions: Collections.List[Trees.Expressions.Expression], | |
| 1371 | argument_location: LOCATION, | |
| 1372 | cache_key: Trees.Node | |
| 1373 | ) -> Semantic.OVERLOAD_RESOLVE_RESULT? is | |
| 1374 | let candidate = | |
| 1375 | _try_find_single_arity_candidate(function_group, argument_types.count, want_instance) ?? | |
| 1376 | _async_literal_candidates.find(function_group, argument_expressions, want_instance) | |
| 1377 | let effective_candidate = candidate ?? _delegate_push_candidates.find_single_pushable_candidate(function_group, argument_types, want_instance) | |
| 1378 | ||
| 1379 | // Trigger the retry when at least one actual | |
| 1380 | // is a FUNCTION literal even if its first-walk | |
| 1381 | // type has been ERROR-tainted by a body that | |
| 1382 | // walked without a constraint. The lambda can | |
| 1383 | // be re-walked under a pushed formal, so a | |
| 1384 | // FUNCTION arg is the natural signal that the | |
| 1385 | // null overload result might be recoverable. | |
| 1386 | // The pre-existing `any_arg_under_determined` | |
| 1387 | // path still covers the constructor-arg shape | |
| 1388 | // (e.g. `apply(Box())`). A named-delegate formal | |
| 1389 | // mismatched against a bare function-shaped actual | |
| 1390 | // (a named function reference, or a lambda that | |
| 1391 | // resolved to its own native shape) is the same kind | |
| 1392 | // of recoverable gap. | |
| 1393 | ||
| 1394 | if effective_candidate? /\ ( | |
| 1395 | _under_determination_detector.any_arg_under_determined(effective_candidate, argument_types) \/ | |
| 1396 | COMPILE_CALLS.has_function_literal_argument(argument_expressions) \/ | |
| 1397 | COMPILE_CALLS.has_empty_array_literal_argument(argument_expressions) \/ | |
| 1398 | _delegate_push_candidates.has_push_mismatch(effective_candidate, argument_types) \/ | |
| 1399 | COMPILE_CALLS.has_unresolved_group_argument(argument_expressions) \/ | |
| 1400 | _has_carrier_mismatch_reference(effective_candidate, argument_types, argument_expressions) \/ | |
| 1401 | _has_pack_mismatch_argument(effective_candidate, argument_types, argument_expressions) \/ | |
| 1402 | COMPILE_CALLS.has_unbound_type_argument(argument_types, _symbol_table.current_function) | |
| 1403 | ) then | |
| 1404 | // Sibling-arg specialisation, symmetric to | |
| 1405 | // the path in `resolve_constructor`: when | |
| 1406 | // one actual is a not-yet-resolved FUNCTION | |
| 1407 | // literal AND the candidate has a generic | |
| 1408 | // owner, push specialised formals (bound | |
| 1409 | // from concrete sibling actuals) rather | |
| 1410 | // than unsubstituted formals containing | |
| 1411 | // free type variables that the lambda's | |
| 1412 | // argument-setup would reject as "type | |
| 1413 | // variable" anyway. Owners that aren't | |
| 1414 | // generic short-circuit inside | |
| 1415 | // OWNER_TYPE_ARG_SPECIALIZER and the | |
| 1416 | // pre-existing behaviour is preserved. | |
| 1417 | let push_candidate: Semantic.Symbols.Function? mut = effective_candidate | |
| 1418 | ||
| 1419 | // Two-step specialisation: try | |
| 1420 | // owner-class generic args first (for | |
| 1421 | // method calls whose receiver class is | |
| 1422 | // generic), then if push_candidate is | |
| 1423 | // still the unsubstituted candidate and | |
| 1424 | // the candidate has its own generic | |
| 1425 | // args, try binding those from concrete | |
| 1426 | // siblings. The function-own path is | |
| 1427 | // what catches free-function HOFs like | |
| 1428 | // `generate[T,S]((0,1), state => ...)` — | |
| 1429 | // S binds from the (0,1) actual, T fills | |
| 1430 | // from a phantom, and the substituted | |
| 1431 | // formal-arg-type can then constrain the | |
| 1432 | // lambda's body re-walk. | |
| 1433 | push_candidate = _specialise_candidate_from_concrete_siblings(effective_candidate, argument_types, cache_key, argument_location) | |
| 1434 | ||
| 1435 | if push_candidate == effective_candidate /\ effective_candidate.is_generic then | |
| 1436 | let phantom_origins = _type_arg_placeholder_registry.get_or_create_for_function(cache_key, argument_location, effective_candidate) | |
| 1437 | push_candidate = _owner_type_arg_specializer.specialize_function_own_args_from_concrete_siblings(effective_candidate, argument_types, phantom_origins, argument_location) | |
| 1438 | fi | |
| 1439 | ||
| 1440 | let use retry_site = RETRY_SITE_STATS.enter("calls.try_overload_after_null", RetrySiteKind.REWALK_WITH_INFORMATION) | |
| 1441 | _logger.roll_back() | |
| 1442 | _logger.speculate() | |
| 1443 | _flow.restore() | |
| 1444 | ||
| 1445 | // Indexed rather than iterated: an argument may be | |
| 1446 | // replaced in place below, and the list being walked is | |
| 1447 | // the call's own. | |
| 1448 | for index in 0..argument_expressions.count do | |
| 1449 | let original = argument_expressions[index] | |
| 1450 | let f = push_candidate!.arguments[index] | |
| 1451 | ||
| 1452 | // A named function reference whose shape differs | |
| 1453 | // from the formal only in an optional position's | |
| 1454 | // carrier has no delegate to load; it is | |
| 1455 | // eta-expanded here, and the literal that replaces | |
| 1456 | // it walks under the formal in its place. | |
| 1457 | let a mut = original | |
| 1458 | ||
| 1459 | _bound_value_parameters_from_pack(push_candidate!, index, argument_types[index]) | |
| 1460 | ||
| 1461 | _take_spread_reading(push_candidate!, index, original, arguments, argument_types) | |
| 1462 | ||
| 1463 | if let outer_arity = _nested_pack_adaptation_arity(push_candidate!, index, original, argument_types[index]) then | |
| 1464 | if | |
| 1465 | let literal = _function_reference_adapter.try_adapt(original, outer_arity) /\ | |
| 1466 | _splice(cache_key, original, index, literal) | |
| 1467 | then | |
| 1468 | a = literal | |
| 1469 | fi | |
| 1470 | elif _is_packable_literal(push_candidate!, index, original, argument_types[index], cache_key) then | |
| 1471 | // compiled taking the tuple, under the formal pushed below | |
| 1472 | elif let presented = _presented_pack_type(cache_key, push_candidate!, index, original, argument_types[index]) then | |
| 1473 | // A function value of the pack's elements is judged as | |
| 1474 | // the function of their tuple it will be presented as. | |
| 1475 | // The value itself is wrapped once a candidate has won. | |
| 1476 | argument_types[index] = presented | |
| 1477 | ||
| 1478 | continue | |
| 1479 | elif let shape = _carrier_mismatch_shape(original, argument_types[index], f) then | |
| 1480 | if | |
| 1481 | let literal = | |
| 1482 | _function_reference_adapter.try_adapt( | |
| 1483 | original, | |
| 1484 | shape.arguments.count - 1 | |
| 1485 | ) /\ | |
| 1486 | _splice(cache_key, original, index, literal) | |
| 1487 | then | |
| 1488 | a = literal | |
| 1489 | fi | |
| 1490 | fi | |
| 1491 | ||
| 1492 | a.set_expected_type(f, "{{0}} is not assignable to {{1}}") | |
| 1493 | _mark_packed_literal(push_candidate!, index, a) | |
| 1494 | ||
| 1495 | _visitor.rewalk(a) | |
| 1496 | ||
| 1497 | if let a.value? /\ value.type? /\ value.check_is_consumable(_logger, a.location) then | |
| 1498 | arguments[index] = value | |
| 1499 | argument_types[index] = value.type! | |
| 1500 | else | |
| 1501 | let t = Semantic.Types.ERROR() | |
| 1502 | ||
| 1503 | arguments[index] = DUMMY(t, a.location) | |
| 1504 | argument_types[index] = t | |
| 1505 | fi | |
| 1506 | od | |
| 1507 | ||
| 1508 | return _prefer_phantom_specialised( | |
| 1509 | _overload_resolver.resolve(argument_location, function_group, argument_types, true, want_instance, false, named_restrict), | |
| 1510 | push_candidate) | |
| 1511 | fi | |
| 1512 | ||
| 1513 | return null | |
| 1514 | si | |
| 1515 | ||
| 1516 | // Puts `literal` where `original` stood, so the walk below | |
| 1517 | // reaches it and generate-il emits the closure's body from it. | |
| 1518 | // A call holds its arguments in a list addressed by index; an | |
| 1519 | // operator holds each operand in a slot of its own. Any other | |
| 1520 | // node declines rather than being spliced blind: a literal that | |
| 1521 | // does not land in the tree is never emitted, and the delegate | |
| 1522 | // built over it would name a method with no body. | |
| 1523 | _splice( | |
| 1524 | cache_key: Trees.Node, | |
| 1525 | original: Trees.Expressions.Expression, | |
| 1526 | index: int, | |
| 1527 | literal: Trees.Expressions.FUNCTION | |
| 1528 | ) -> bool is | |
| 1529 | if let call: Trees.Expressions.CALL = cache_key then | |
| 1530 | call.arguments.replace_element(index, literal) | |
| 1531 | return true | |
| 1532 | fi | |
| 1533 | ||
| 1534 | if let binary: Trees.Expressions.BINARY = cache_key then | |
| 1535 | binary.replace_child(original, literal) | |
| 1536 | return binary.left == literal \/ binary.right == literal | |
| 1537 | fi | |
| 1538 | ||
| 1539 | return false | |
| 1540 | si | |
| 1541 | ||
| 1542 | // Whether the pack tuple the formal at `index` takes is decided | |
| 1543 | // by another of the candidate's formals and that formal has not | |
| 1544 | // settled it yet - the element type of a pipe whose source is | |
| 1545 | // still being inferred, say. An operand going into the formal | |
| 1546 | // then waits for that walk rather than deciding the tuple itself. | |
| 1547 | _pack_tuple_waits_for_sibling(candidate: Semantic.Symbols.Function, index: int) -> bool is | |
| 1548 | let formal = if index < candidate.arguments.count then candidate.arguments[index] else null fi | |
| 1549 | ||
| 1550 | let shape = _target_shape_of(formal) | |
| 1551 | ||
| 1552 | return | |
| 1553 | shape? /\ | |
| 1554 | Semantic.ARGUMENT_PACK.is_pack_slot(shape) /\ | |
| 1555 | !shape.arguments[Semantic.ARGUMENT_PACK.fixed_count(shape)].is_settled /\ | |
| 1556 | Semantic.PACK_TUPLE_SOURCE().is_decided_by_another_formal(candidate.arguments, index, shape.arguments[Semantic.ARGUMENT_PACK.fixed_count(shape)]) | |
| 1557 | si | |
| 1558 | ||
| 1559 | // A function value whose own parameter types are still | |
| 1560 | // placeholders - a literal stored in a local that nothing has typed | |
| 1561 | // yet - going into a spread formal whose pack the other arguments | |
| 1562 | // have already pinned takes its parameter types from the pack's | |
| 1563 | // tuple, as a literal written in the same slot does. | |
| 1564 | _bound_value_parameters_from_pack(candidate: Semantic.Symbols.Function, index: int, argument_type: Type?) is | |
| 1565 | if | |
| 1566 | !candidate.get_argument_is_pack(index) \/ | |
| 1567 | candidate.get_argument_pack_depth(index) != 0 \/ | |
| 1568 | index >= candidate.arguments.count \/ | |
| 1569 | !argument_type? \/ | |
| 1570 | !argument_type.is_function | |
| 1571 | then | |
| 1572 | return | |
| 1573 | fi | |
| 1574 | ||
| 1575 | let shape = _target_shape_of(candidate.arguments[index]) | |
| 1576 | ||
| 1577 | if !shape? \/ !Semantic.ARGUMENT_PACK.is_pack_slot(shape) then | |
| 1578 | return | |
| 1579 | fi | |
| 1580 | ||
| 1581 | let fixed = Semantic.ARGUMENT_PACK.fixed_count(shape) | |
| 1582 | ||
| 1583 | let tuple = shape.arguments[fixed] | |
| 1584 | ||
| 1585 | // A tuple still carrying the candidate's own unbound type | |
| 1586 | // parameters names no type the value's parameters could take. | |
| 1587 | if !tuple.is_settled \/ COMPILE_CALLS.has_unbound_type_argument([tuple], _symbol_table.current_function) then | |
| 1588 | return | |
| 1589 | fi | |
| 1590 | ||
| 1591 | let arity = Semantic.ARGUMENT_PACK.parameter_count(argument_type) - fixed | |
| 1592 | ||
| 1593 | if arity < 2 \/ tuple.arguments.count != arity then | |
| 1594 | return | |
| 1595 | fi | |
| 1596 | ||
| 1597 | for i in 0..arity do | |
| 1598 | if let placeholder: Semantic.Types.INFERRED_VARIABLE_TYPE = argument_type.arguments[fixed + i] then | |
| 1599 | _logger.mark_consumed_any_if( | |
| 1600 | Semantic.INFERENCE_TRACE.add_lower_bound("calls.pack_value_parameters", placeholder.origin, tuple.arguments[i]) | |
| 1601 | ) | |
| 1602 | fi | |
| 1603 | od | |
| 1604 | si | |
| 1605 | ||
| 1606 | // The function-type shape a formal presents: the formal itself | |
| 1607 | // when it is a ghul function type, the call shape of a named | |
| 1608 | // delegate's `invoke` when it is one, and null otherwise. | |
| 1609 | _target_shape_of(formal: Type?) -> Type? is | |
| 1610 | if !formal? then | |
| 1611 | return null | |
| 1612 | fi | |
| 1613 | ||
| 1614 | if formal.is_function then | |
| 1615 | return formal | |
| 1616 | fi | |
| 1617 | ||
| 1618 | return _delegate_shape.try_get_function_type(formal, _innate_symbol_lookup) | |
| 1619 | si | |
| 1620 | ||
| 1621 | // The formal's call shape, when this argument is a named | |
| 1622 | // function reference the eta-expansion applies to: it loaded as | |
| 1623 | // a delegate over a named function with no receiver to | |
| 1624 | // re-evaluate, and its own shape differs from the formal's only | |
| 1625 | // in which carrier an optional position uses. Null otherwise. | |
| 1626 | _carrier_mismatch_shape( | |
| 1627 | argument: Trees.Expressions.Expression, | |
| 1628 | argument_type: Type?, | |
| 1629 | formal: Type? | |
| 1630 | ) -> Type? is | |
| 1631 | if isa Trees.Expressions.FUNCTION(argument) then | |
| 1632 | return null | |
| 1633 | fi | |
| 1634 | ||
| 1635 | if let delegate: Load.DELEGATE = argument.value then | |
| 1636 | if !delegate.referenced_function? \/ !isa NULL(delegate.frame) then | |
| 1637 | return null | |
| 1638 | fi | |
| 1639 | else | |
| 1640 | return null | |
| 1641 | fi | |
| 1642 | ||
| 1643 | let shape = _target_shape_of(formal) | |
| 1644 | ||
| 1645 | if !FUNCTION_REFERENCE_ADAPTER.is_carrier_only_mismatch(argument_type, shape) then | |
| 1646 | return null | |
| 1647 | fi | |
| 1648 | ||
| 1649 | return shape | |
| 1650 | si | |
| 1651 | ||
| 1652 | // A literal that cannot be compiled taking the pack's tuple - one | |
| 1653 | // that calls itself, say - is presented through a thunk like any | |
| 1654 | // other function value. Where the formal has settled the tuple, | |
| 1655 | // the literal is first walked under the other reading of the same | |
| 1656 | // pack, a function of the tuple's elements, so that parameters it | |
| 1657 | // left untyped take their types from them. Returns the type the | |
| 1658 | // literal then has, or the one it had. | |
| 1659 | // How many parameters the formal at `index` takes of its own | |
| 1660 | // before the pack. | |
| 1661 | _fixed_count_of(candidate: Semantic.Symbols.Function, index: int) -> int is | |
| 1662 | if index < candidate.arguments.count then | |
| 1663 | if let shape = _target_shape_of(candidate.arguments[index]) /\ Semantic.ARGUMENT_PACK.is_pack_slot(shape) then | |
| 1664 | return Semantic.ARGUMENT_PACK.fixed_count(shape) | |
| 1665 | fi | |
| 1666 | fi | |
| 1667 | ||
| 1668 | return 0 | |
| 1669 | si | |
| 1670 | ||
| 1671 | _walk_under_spread_reading( | |
| 1672 | candidate: Semantic.Symbols.Function, | |
| 1673 | index: int, | |
| 1674 | argument: Trees.Expressions.Expression, | |
| 1675 | argument_type: Type? | |
| 1676 | ) -> Type? is | |
| 1677 | let literal = parenthesised_literal(argument) | |
| 1678 | ||
| 1679 | if | |
| 1680 | !literal? \/ | |
| 1681 | PACKED_LITERAL.is_eligible(literal, _fixed_count_of(candidate, index)) \/ | |
| 1682 | !candidate.get_argument_is_pack(index) \/ | |
| 1683 | candidate.get_argument_pack_depth(index) != 0 \/ | |
| 1684 | index >= candidate.arguments.count | |
| 1685 | then | |
| 1686 | return argument_type | |
| 1687 | fi | |
| 1688 | ||
| 1689 | let shape = _target_shape_of(candidate.arguments[index]) | |
| 1690 | ||
| 1691 | if !Semantic.ARGUMENT_PACK.is_pack_slot(shape) then | |
| 1692 | return argument_type | |
| 1693 | fi | |
| 1694 | ||
| 1695 | let fixed = Semantic.ARGUMENT_PACK.fixed_count(shape!) | |
| 1696 | ||
| 1697 | let arity = literal.arguments.expressions.count - fixed | |
| 1698 | ||
| 1699 | // One parameter in the pack's place is the tuple itself, not | |
| 1700 | // the pack spread out, whatever the tuple destructures into. | |
| 1701 | if arity < 2 \/ arity > Semantic.ARGUMENT_PACK.MAXIMUM_ARITY then | |
| 1702 | return argument_type | |
| 1703 | fi | |
| 1704 | ||
| 1705 | let tuple = Semantic.SETTLED_PLACEHOLDER_RESOLVER.instance.resolve(shape.arguments[fixed]) | |
| 1706 | ||
| 1707 | if !tuple.is_settled then | |
| 1708 | return argument_type | |
| 1709 | fi | |
| 1710 | ||
| 1711 | let strategy = DESTRUCTURE_RESOLVER.resolve_strategy(tuple, arity) | |
| 1712 | ||
| 1713 | let types = Collections.LIST[Type]() | |
| 1714 | ||
| 1715 | for i in 0..fixed do | |
| 1716 | types.add(shape.arguments[i]) | |
| 1717 | od | |
| 1718 | ||
| 1719 | for i in 0..arity do | |
| 1720 | if strategy.is_deconstruct then | |
| 1721 | if let element = strategy.deconstruct_function!.arguments[i].get_element_type() then | |
| 1722 | types.add(element) | |
| 1723 | fi | |
| 1724 | elif i < strategy.members.count then | |
| 1725 | if let member = strategy.members[i], member_type = member.type then | |
| 1726 | types.add(member_type) | |
| 1727 | fi | |
| 1728 | fi | |
| 1729 | od | |
| 1730 | ||
| 1731 | if types.count != fixed + arity then | |
| 1732 | return argument_type | |
| 1733 | fi | |
| 1734 | ||
| 1735 | types.add( | |
| 1736 | if shape.is_action then | |
| 1737 | _innate_symbol_lookup.get_void_type() | |
| 1738 | else | |
| 1739 | shape.arguments[shape.arguments.count - 1] | |
| 1740 | fi | |
| 1741 | ) | |
| 1742 | ||
| 1743 | literal.set_expected_type( | |
| 1744 | _innate_symbol_lookup.get_function_type(types, shape.is_pure_function), | |
| 1745 | "{{0}} is not assignable to {{1}}" | |
| 1746 | ) | |
| 1747 | ||
| 1748 | _visitor.rewalk(literal) | |
| 1749 | ||
| 1750 | return literal.value?.type ?? argument_type | |
| 1751 | si | |
| 1752 | ||
| 1753 | // The value of `expression`, a function of an argument pack's | |
| 1754 | // elements, presented as a function of their tuple. Absent where | |
| 1755 | // the value is not such a function. | |
| 1756 | present_function_value(expression: Trees.Expressions.Expression) -> Value? is | |
| 1757 | let value = expression.value | |
| 1758 | ||
| 1759 | if !value? \/ !value.type? \/ isa IR.Values.PACK_WRAP(value) then | |
| 1760 | return null | |
| 1761 | fi | |
| 1762 | ||
| 1763 | return _pack_wrap_builder.unpack(expression, 0, expression.location, value, 0) | |
| 1764 | si | |
| 1765 | ||
| 1766 | ||
| 1767 | _take_spread_reading( | |
| 1768 | candidate: Semantic.Symbols.Function, | |
| 1769 | index: int, | |
| 1770 | argument: Trees.Expressions.Expression, | |
| 1771 | arguments: Collections.LIST[Value], | |
| 1772 | argument_types: Collections.LIST[Type] | |
| 1773 | ) is | |
| 1774 | let walked = _walk_under_spread_reading(candidate, index, argument, argument_types[index]) | |
| 1775 | ||
| 1776 | if walked? /\ walked != argument_types[index] then | |
| 1777 | argument_types[index] = walked | |
| 1778 | ||
| 1779 | if let value = argument.value then | |
| 1780 | arguments[index] = value | |
| 1781 | fi | |
| 1782 | fi | |
| 1783 | si | |
| 1784 | ||
| 1785 | ||
| 1786 | // The type a function value of the pack's elements is presented at | |
| 1787 | // in the formal at `index`, where that formal takes the pack as | |
| 1788 | // one tuple and the value is settled enough to say what the tuple | |
| 1789 | // is. Absent otherwise. | |
| 1790 | _presented_pack_type( | |
| 1791 | owner: Trees.Node?, | |
| 1792 | candidate: Semantic.Symbols.Function, | |
| 1793 | index: int, | |
| 1794 | argument: Trees.Expressions.Expression, | |
| 1795 | argument_type: Type? | |
| 1796 | ) -> Type? is | |
| 1797 | // Only a call and an operator have the step, after a candidate | |
| 1798 | // has won, that wraps the value. | |
| 1799 | if !isa Trees.Expressions.CALL(owner) /\ !isa Trees.Expressions.BINARY(owner) then | |
| 1800 | return null | |
| 1801 | fi | |
| 1802 | ||
| 1803 | if let literal = parenthesised_literal(argument) then | |
| 1804 | if PACKED_LITERAL.is_eligible(literal, _fixed_count_of(candidate, index)) then | |
| 1805 | return null | |
| 1806 | fi | |
| 1807 | fi | |
| 1808 | ||
| 1809 | if !_pack_adaptation_value_arity(candidate, index, argument, argument_type)? then | |
| 1810 | return null | |
| 1811 | fi | |
| 1812 | ||
| 1813 | let fixed = _fixed_count_of(candidate, index) | |
| 1814 | ||
| 1815 | if let settled = _pack_wrap_builder.packed_type(argument_type, fixed) then | |
| 1816 | return settled | |
| 1817 | fi | |
| 1818 | ||
| 1819 | // A value whose parameter types are still being inferred is | |
| 1820 | // judged over them all the same, unless another argument is | |
| 1821 | // what decides the tuple: the pack binds to the tuple of | |
| 1822 | // placeholders, and the call resolves provisionally, so that a | |
| 1823 | // later use of its result has a pack to settle. What it is | |
| 1824 | // judged as is the formal's own shape, whose tuple is the pack | |
| 1825 | // that use will bind; each placeholder is an obligation of | |
| 1826 | // this walk. | |
| 1827 | if parenthesised_literal(argument)? \/ _pack_tuple_waits_for_sibling(candidate, index) then | |
| 1828 | return null | |
| 1829 | fi | |
| 1830 | ||
| 1831 | let provisional = _pack_wrap_builder.packed_type(argument_type, fixed, true) | |
| 1832 | ||
| 1833 | if provisional? /\ argument_type? then | |
| 1834 | for i in 0..Semantic.ARGUMENT_PACK.parameter_count(argument_type) do | |
| 1835 | if argument_type.arguments[i].contains_inferred then | |
| 1836 | Semantic.OBLIGATIONS.defer("pack_value", argument_type.arguments[i], argument.location) | |
| 1837 | fi | |
| 1838 | od | |
| 1839 | fi | |
| 1840 | ||
| 1841 | if !provisional? then | |
| 1842 | return null | |
| 1843 | fi | |
| 1844 | ||
| 1845 | return _target_shape_of(candidate.arguments[index]) | |
| 1846 | si | |
| 1847 | ||
| 1848 | // Wraps each argument of a resolved call that is a function of | |
| 1849 | // the pack's elements going into a formal that takes their tuple. | |
| 1850 | present_pack_arguments( | |
| 1851 | key: Trees.Node, | |
| 1852 | expressions: Collections.List[Trees.Expressions.Expression], | |
| 1853 | function: Semantic.Symbols.Function, | |
| 1854 | arguments: Collections.LIST[Value] | |
| 1855 | ) is | |
| 1856 | for index in 0..arguments.count do | |
| 1857 | if !function.get_argument_is_pack(index) \/ function.get_argument_pack_depth(index) != 0 then | |
| 1858 | continue | |
| 1859 | fi | |
| 1860 | ||
| 1861 | let expression = expressions[index] | |
| 1862 | ||
| 1863 | if !Semantic.ARGUMENT_PACK.adaptation_arity(_target_shape_of(function.arguments[index]), arguments[index].type)? then | |
| 1864 | continue | |
| 1865 | fi | |
| 1866 | ||
| 1867 | if let wrapped = _pack_wrap_builder.unpack(key, index, expression.location, arguments[index], _fixed_count_of(function, index)) then | |
| 1868 | arguments[index] = wrapped | |
| 1869 | ||
| 1870 | // Whatever reads the argument.s value afterwards - a fused | |
| 1871 | // pipe stage takes its callback from there - has to see the | |
| 1872 | // function the formal was given. | |
| 1873 | expression.compile_expressions_state.value = wrapped | |
| 1874 | fi | |
| 1875 | od | |
| 1876 | si | |
| 1877 | ||
| 1878 | // Whether this argument is a literal written with the pack spread | |
| 1879 | // out that is compiled taking the pack's tuple directly. | |
| 1880 | _is_packable_literal( | |
| 1881 | candidate: Semantic.Symbols.Function, | |
| 1882 | index: int, | |
| 1883 | argument: Trees.Expressions.Expression, | |
| 1884 | argument_type: Type?, | |
| 1885 | owner: Trees.Node? | |
| 1886 | ) -> bool is | |
| 1887 | if let literal = parenthesised_literal(argument) then | |
| 1888 | return | |
| 1889 | PACKED_LITERAL.is_eligible(literal, _fixed_count_of(candidate, index)) /\ | |
| 1890 | _pack_adaptation_arity(candidate, index, argument, argument_type, owner)? | |
| 1891 | fi | |
| 1892 | ||
| 1893 | return false | |
| 1894 | si | |
| 1895 | ||
| 1896 | // Says, beside the expected type just pushed, that the formal is | |
| 1897 | // one declared to take an argument pack spread out. | |
| 1898 | _mark_packed_literal( | |
| 1899 | candidate: Semantic.Symbols.Function, | |
| 1900 | index: int, | |
| 1901 | argument: Trees.Expressions.Expression | |
| 1902 | ) is | |
| 1903 | if !candidate.get_argument_is_pack(index) then | |
| 1904 | return | |
| 1905 | fi | |
| 1906 | ||
| 1907 | let depth = candidate.get_argument_pack_depth(index) | |
| 1908 | ||
| 1909 | // Where another argument decides the tuple and has not yet, the | |
| 1910 | // literal stays as written until a walk on which it has. | |
| 1911 | if depth == 0 /\ _pack_tuple_waits_for_sibling(candidate, index) then | |
| 1912 | return | |
| 1913 | fi | |
| 1914 | ||
| 1915 | if parenthesised_literal(argument)? then | |
| 1916 | argument.set_expects_pack(depth) | |
| 1917 | fi | |
| 1918 | si | |
| 1919 | ||
| 1920 | // How many of this argument's parameters the pack stands for, when | |
| 1921 | // the formal it is going into was declared to take an argument | |
| 1922 | // pack spread out - `f: T.. -> U` - and absent otherwise. | |
| 1923 | // | |
| 1924 | // Such a formal takes a function whose last parameter is the | |
| 1925 | // tuple the pack binds to. An actual with two or more parameters | |
| 1926 | // in its place describes the same call with the pack spread out, | |
| 1927 | // and is presented in the shape the formal asks for. One | |
| 1928 | // parameter there needs no presenting, and anything past the | |
| 1929 | // tuple limit has no tuple to bind to. | |
| 1930 | _pack_adaptation_arity( | |
| 1931 | candidate: Semantic.Symbols.Function, | |
| 1932 | index: int, | |
| 1933 | argument: Trees.Expressions.Expression, | |
| 1934 | argument_type: Type?, | |
| 1935 | owner: Trees.Node? | |
| 1936 | ) -> int? is | |
| 1937 | if !candidate.get_argument_is_pack(index) then | |
| 1938 | return null | |
| 1939 | fi | |
| 1940 | ||
| 1941 | // A marker written past the formal's own function type is | |
| 1942 | // about the function the actual returns, not the actual, so | |
| 1943 | // there is nothing to present here. | |
| 1944 | if candidate.get_argument_pack_depth(index) != 0 then | |
| 1945 | return null | |
| 1946 | fi | |
| 1947 | ||
| 1948 | let formal = if index < candidate.arguments.count then candidate.arguments[index] else null fi | |
| 1949 | ||
| 1950 | let shape = _target_shape_of(formal) | |
| 1951 | ||
| 1952 | let arity = Semantic.ARGUMENT_PACK.adaptation_arity(shape, argument_type) | |
| 1953 | ||
| 1954 | if !arity? then | |
| 1955 | return null | |
| 1956 | fi | |
| 1957 | ||
| 1958 | // Where another argument decides the tuple - the element type | |
| 1959 | // of a pipe whose source has not yet been inferred - settling | |
| 1960 | // it from this one would pin a literal's parameters to a | |
| 1961 | // placeholder, so it waits for a walk on which that argument | |
| 1962 | // has settled it. Where only this argument can decide it, | |
| 1963 | // presenting it is how it gets decided. | |
| 1964 | if _pack_tuple_waits_for_sibling(candidate, index) then | |
| 1965 | return null | |
| 1966 | fi | |
| 1967 | ||
| 1968 | // A literal is compiled where it stands; anything else has to | |
| 1969 | // name a function. | |
| 1970 | // A call argument in parentheses - the subject of a `|>` has to | |
| 1971 | // be written that way - is still one, and so is an operator | |
| 1972 | // operand, which is always parenthesised. Either way a context | |
| 1973 | // that pins the pack reaches it through the expected type the | |
| 1974 | // call or operator carries. | |
| 1975 | let looks_through = | |
| 1976 | isa Trees.Expressions.CALL(owner) \/ | |
| 1977 | isa Trees.Expressions.BINARY(owner) | |
| 1978 | ||
| 1979 | let literal = | |
| 1980 | if looks_through then | |
| 1981 | parenthesised_literal(argument) | |
| 1982 | else | |
| 1983 | cast Trees.Expressions.FUNCTION?(argument) | |
| 1984 | fi | |
| 1985 | ||
| 1986 | if literal? then | |
| 1987 | return arity | |
| 1988 | fi | |
| 1989 | ||
| 1990 | // A method named on an instance is included: the delegate | |
| 1991 | // over it carries its receiver. | |
| 1992 | if let delegate: Load.DELEGATE = argument.value then | |
| 1993 | if delegate.referenced_function? then | |
| 1994 | return arity | |
| 1995 | fi | |
| 1996 | fi | |
| 1997 | ||
| 1998 | return null | |
| 1999 | si | |
| 2000 | ||
| 2001 | // The function literal an argument is, looking through the | |
| 2002 | // parentheses a single-element group puts around it. | |
| 2003 | parenthesised_literal(argument: Trees.Expressions.Expression?) -> Trees.Expressions.FUNCTION? static is | |
| 2004 | if let literal: Trees.Expressions.FUNCTION = argument then | |
| 2005 | return literal | |
| 2006 | fi | |
| 2007 | ||
| 2008 | if let group: Trees.Expressions.TUPLE = argument /\ group.elements.expressions.count == 1 then | |
| 2009 | return parenthesised_literal(group.elements.expressions[0]) | |
| 2010 | fi | |
| 2011 | ||
| 2012 | return null | |
| 2013 | si | |
| 2014 | ||
| 2015 | // How many of a function-valued operand's parameters the pack | |
| 2016 | // stands for, when the formal it is going into was declared to | |
| 2017 | // take an argument pack spread out. The operand is evaluated once | |
| 2018 | // where it stands and presented through a thunk that captures the | |
| 2019 | // value. Absent when the formal is not a pack formal or the | |
| 2020 | // operand is not a function value with two or more parameters in | |
| 2021 | // the pack's place. | |
| 2022 | _pack_adaptation_value_arity( | |
| 2023 | candidate: Semantic.Symbols.Function, | |
| 2024 | index: int, | |
| 2025 | argument: Trees.Expressions.Expression, | |
| 2026 | argument_type: Type? | |
| 2027 | ) -> int? is | |
| 2028 | if !candidate.get_argument_is_pack(index) then | |
| 2029 | return null | |
| 2030 | fi | |
| 2031 | ||
| 2032 | // A marker written past the formal's own function type is | |
| 2033 | // about the function the actual returns, not the actual, so | |
| 2034 | // there is nothing to adapt here. | |
| 2035 | if candidate.get_argument_pack_depth(index) != 0 then | |
| 2036 | return null | |
| 2037 | fi | |
| 2038 | ||
| 2039 | let formal = if index < candidate.arguments.count then candidate.arguments[index] else null fi | |
| 2040 | ||
| 2041 | return Semantic.ARGUMENT_PACK.adaptation_arity(_target_shape_of(formal), argument_type) | |
| 2042 | si | |
| 2043 | ||
| 2044 | // A call whose callee's declared return type carries the pack | |
| 2045 | // marker - `retry[T.., U](f: T.. -> U, n: int) -> T.. -> U` - | |
| 2046 | // resolves to the tuple-in function type the declaration names. | |
| 2047 | // Where this call binds the pack to a concrete tuple, the | |
| 2048 | // result is presented as the corresponding N-ary function. Depth past the outermost return | |
| 2049 | // is left as the tuple-in shape; the marker there names a | |
| 2050 | // function the result itself returns, one the caller reaches | |
| 2051 | // through its own call. | |
| 2052 | _try_wrap_return_pack( | |
| 2053 | call: Trees.Expressions.CALL, | |
| 2054 | function: Semantic.Symbols.Function, | |
| 2055 | call_receiver: IR.Values.Value?, | |
| 2056 | arguments: Collections.LIST[IR.Values.Value] | |
| 2057 | ) -> bool is | |
| 2058 | let wrapped = wrap_return_pack(call, function, call.location, call_receiver, arguments) | |
| 2059 | ||
| 2060 | if !wrapped? then | |
| 2061 | return false | |
| 2062 | fi | |
| 2063 | ||
| 2064 | call.compile_expressions_state.value = wrapped | |
| 2065 | ||
| 2066 | return true | |
| 2067 | si | |
| 2068 | ||
| 2069 | // The call-boundary presentation a pack-marked declared return | |
| 2070 | // type asks for: `retry[T.., U](f: T.. -> U, n: int) -> T.. -> U` | |
| 2071 | // resolves to the tuple-in function type the declaration names. | |
| 2072 | // Where this call binds the pack to a concrete tuple, the result | |
| 2073 | // is presented as the corresponding N-ary function: the call's | |
| 2074 | // own value is computed once, where the call stands, and a thunk | |
| 2075 | // taking the elements packs them and calls it. `key` is the node | |
| 2076 | // the call is compiled for. Null when this call is not one the | |
| 2077 | // presentation applies to. | |
| 2078 | wrap_return_pack( | |
| 2079 | key: Trees.Node, | |
| 2080 | function: Semantic.Symbols.Function, | |
| 2081 | location: Source.LOCATION, | |
| 2082 | call_receiver: IR.Values.Value?, | |
| 2083 | arguments: Collections.LIST[IR.Values.Value] | |
| 2084 | ) -> IR.Values.Value? is | |
| 2085 | if function.return_pack_depth != 0 then | |
| 2086 | return null | |
| 2087 | fi | |
| 2088 | ||
| 2089 | // The pack may have bound to a tuple of placeholders that have | |
| 2090 | // since settled; the stored composite is not rewritten when | |
| 2091 | // they do, so it is read through the resolver here. | |
| 2092 | let declared = if let rt = function.return_type then Semantic.SETTLED_PLACEHOLDER_RESOLVER.instance.resolve(rt) else null fi | |
| 2093 | ||
| 2094 | if !declared? \/ !Semantic.ARGUMENT_PACK.is_pack_slot(declared) then | |
| 2095 | return null | |
| 2096 | fi | |
| 2097 | ||
| 2098 | let fixed = Semantic.ARGUMENT_PACK.fixed_count(declared) | |
| 2099 | ||
| 2100 | if !_pack_wrap_builder.spread_type(declared, fixed)? then | |
| 2101 | return null | |
| 2102 | fi | |
| 2103 | ||
| 2104 | return | |
| 2105 | _pack_wrap_builder.pack( | |
| 2106 | key, | |
| 2107 | -1, | |
| 2108 | location, | |
| 2109 | function.call(location, call_receiver, arguments, null, _function_caller), | |
| 2110 | declared, | |
| 2111 | fixed | |
| 2112 | ) | |
| 2113 | si | |
| 2114 | ||
| 2115 | // The tuple the pack formal at `index` binds to. The formal's own | |
| 2116 | // element type is the answer where the call has already settled | |
| 2117 | // it; the actual's parameter types are the fallback, which is what | |
| 2118 | // lets the type argument be inferred when nothing else pins it. | |
| 2119 | _packed_group_type( | |
| 2120 | candidate: Semantic.Symbols.Function, | |
| 2121 | index: int, | |
| 2122 | argument_type: Type? | |
| 2123 | ) -> Type? is | |
| 2124 | let formal = if index < candidate.arguments.count then candidate.arguments[index] else null fi | |
| 2125 | let shape = _target_shape_of(formal) | |
| 2126 | ||
| 2127 | if let s: Type = shape then | |
| 2128 | if Semantic.ARGUMENT_PACK.is_pack_slot(s) then | |
| 2129 | let element = s.arguments[Semantic.ARGUMENT_PACK.fixed_count(s)] | |
| 2130 | ||
| 2131 | if !element.is_error /\ !element.contains_inferred /\ !element.is_wild then | |
| 2132 | return element | |
| 2133 | fi | |
| 2134 | fi | |
| 2135 | fi | |
| 2136 | ||
| 2137 | return Semantic.ARGUMENT_PACK.packed_parameters(argument_type, _fixed_count_of(candidate, index)) | |
| 2138 | si | |
| 2139 | ||
| 2140 | // A literal compiled taking the pack's tuple was typed before the | |
| 2141 | // call settled the pack, so element names that only its own | |
| 2142 | // result gives the pack reach the settled formal but not the | |
| 2143 | // literal. Where the two differ in nothing but those names, the | |
| 2144 | // literal's one physical parameter takes the formal's, as it | |
| 2145 | // would have had the call been written with its type arguments. | |
| 2146 | _settle_packed_literal_names(function: Semantic.Symbols.Function, argument_expressions: Collections.List[Trees.Expressions.Expression]) is | |
| 2147 | for index in 0..argument_expressions.count do | |
| 2148 | if let literal = parenthesised_literal(argument_expressions[index]) then | |
| 2149 | if | |
| 2150 | let closure: Semantic.Symbols.Closure = _symbol_table.scope_for(literal) /\ | |
| 2151 | closure.packed_parameters? /\ | |
| 2152 | closure.arguments.count >= 1 | |
| 2153 | then | |
| 2154 | let settled = _packed_group_type(function, index, null) | |
| 2155 | ||
| 2156 | let last = closure.arguments.count - 1 | |
| 2157 | ||
| 2158 | if | |
| 2159 | settled? /\ | |
| 2160 | closure.arguments[last] != settled /\ | |
| 2161 | closure.arguments[last].is_equivalent_to(settled) /\ | |
| 2162 | settled.is_equivalent_to(closure.arguments[last]) | |
| 2163 | then | |
| 2164 | let physical = Collections.LIST[Type](closure.arguments) | |
| 2165 | ||
| 2166 | physical[last] = settled | |
| 2167 | ||
| 2168 | closure.pack_group?.set_type(settled) | |
| 2169 | closure.arguments = physical | |
| 2170 | fi | |
| 2171 | fi | |
| 2172 | fi | |
| 2173 | od | |
| 2174 | si | |
| 2175 | ||
| 2176 | // A call written with the pack spread out - `apply(f, "a", "b")` | |
| 2177 | // - describes the same call as the written-out tuple form the | |
| 2178 | // formal takes. The trailing actuals are collected into a tuple | |
| 2179 | // literal here, so that everything downstream sees the form it | |
| 2180 | // already resolves. | |
| 2181 | _try_normalise_spread( | |
| 2182 | function_group: Semantic.Symbols.FUNCTION_GROUP, | |
| 2183 | arguments: Collections.LIST[Value], | |
| 2184 | argument_types: Collections.LIST[Type], | |
| 2185 | argument_expressions: Trees.Expressions.LIST, | |
| 2186 | want_instance: bool | |
| 2187 | ) -> bool is | |
| 2188 | let candidate: Semantic.Symbols.Function? mut = null | |
| 2189 | let count mut = 0 | |
| 2190 | ||
| 2191 | for f in function_group.functions do | |
| 2192 | if !want_instance /\ f.is_instance then | |
| 2193 | continue | |
| 2194 | fi | |
| 2195 | ||
| 2196 | if !f.are_arguments_declared \/ !f.has_spread_argument then | |
| 2197 | continue | |
| 2198 | fi | |
| 2199 | ||
| 2200 | candidate = f | |
| 2201 | count = count + 1 | |
| 2202 | od | |
| 2203 | ||
| 2204 | if count != 1 then | |
| 2205 | return false | |
| 2206 | fi | |
| 2207 | ||
| 2208 | let first = candidate!.spread_argument_index | |
| 2209 | ||
| 2210 | if !Semantic.ARGUMENT_PACK.spread_arity(first, argument_expressions.expressions.count)? then | |
| 2211 | return false | |
| 2212 | fi | |
| 2213 | ||
| 2214 | let elements = Collections.LIST[Trees.Expressions.Expression]() | |
| 2215 | ||
| 2216 | for i in first..argument_expressions.expressions.count do | |
| 2217 | elements.add(argument_expressions.expressions[i]) | |
| 2218 | od | |
| 2219 | ||
| 2220 | let span = argument_expressions.location | |
| 2221 | let tuple = Trees.Expressions.TUPLE(span, Trees.Expressions.LIST(span, elements), false) | |
| 2222 | ||
| 2223 | // The trailing actuals are walked a second time below, so | |
| 2224 | // the failed resolve's diagnostics and the flow state it | |
| 2225 | // left behind are both dropped first - the same contract | |
| 2226 | // every other retry in this file walks under. | |
| 2227 | let use retry_site = RETRY_SITE_STATS.enter("calls.normalise_spread", RetrySiteKind.ALTERNATIVE) | |
| 2228 | _logger.roll_back() | |
| 2229 | _logger.speculate() | |
| 2230 | _flow.restore() | |
| 2231 | ||
| 2232 | // The leading actuals were walked under the speculation the | |
| 2233 | // roll back just discarded, and nothing below walks them | |
| 2234 | // again: walked once more here, so that what they reported | |
| 2235 | // is not lost with the failed resolve's diagnostics. | |
| 2236 | for i in 0..first do | |
| 2237 | let a = argument_expressions.expressions[i] | |
| 2238 | ||
| 2239 | _visitor.rewalk(a) | |
| 2240 | ||
| 2241 | if let a.value? /\ value.type? then | |
| 2242 | arguments[i] = value | |
| 2243 | argument_types[i] = value.type! | |
| 2244 | else | |
| 2245 | let t = Semantic.Types.ERROR() | |
| 2246 | ||
| 2247 | arguments[i] = DUMMY(t, a.location) | |
| 2248 | argument_types[i] = t | |
| 2249 | fi | |
| 2250 | od | |
| 2251 | ||
| 2252 | while argument_expressions.expressions.count > first do | |
| 2253 | argument_expressions.expressions.remove_at(argument_expressions.expressions.count - 1) | |
| 2254 | arguments.remove_at(arguments.count - 1) | |
| 2255 | argument_types.remove_at(argument_types.count - 1) | |
| 2256 | od | |
| 2257 | ||
| 2258 | _visitor.rewalk(tuple) | |
| 2259 | ||
| 2260 | argument_expressions.expressions.add(tuple) | |
| 2261 | ||
| 2262 | if let tuple.value? /\ value.type? then | |
| 2263 | arguments.add(value) | |
| 2264 | argument_types.add(value.type!) | |
| 2265 | else | |
| 2266 | let t = Semantic.Types.ERROR() | |
| 2267 | ||
| 2268 | arguments.add(DUMMY(t, span)) | |
| 2269 | argument_types.add(t) | |
| 2270 | fi | |
| 2271 | ||
| 2272 | return true | |
| 2273 | si | |
| 2274 | ||
| 2275 | // True when at least one argument is one the pack adaptation | |
| 2276 | // applies to - the signal that a failed resolve is recoverable | |
| 2277 | // by wrapping it under the candidate's formal. | |
| 2278 | _has_pack_mismatch_argument( | |
| 2279 | candidate: Semantic.Symbols.Function, | |
| 2280 | argument_types: Collections.LIST[Type], | |
| 2281 | argument_expressions: Collections.List[Trees.Expressions.Expression] | |
| 2282 | ) -> bool is | |
| 2283 | if candidate.arguments.count != argument_expressions.count then | |
| 2284 | return false | |
| 2285 | fi | |
| 2286 | ||
| 2287 | for i in 0..argument_expressions.count do | |
| 2288 | if _pack_adaptation_arity(candidate, i, argument_expressions[i], argument_types[i], null)? then | |
| 2289 | return true | |
| 2290 | fi | |
| 2291 | ||
| 2292 | if _pack_adaptation_value_arity(candidate, i, argument_expressions[i], argument_types[i])? then | |
| 2293 | return true | |
| 2294 | fi | |
| 2295 | ||
| 2296 | if _nested_pack_adaptation_arity(candidate, i, argument_expressions[i], argument_types[i])? then | |
| 2297 | return true | |
| 2298 | fi | |
| 2299 | od | |
| 2300 | ||
| 2301 | return false | |
| 2302 | si | |
| 2303 | ||
| 2304 | // The arity to eta-expand an argument with when its formal wrote | |
| 2305 | // the pack marker past its own function type - `make: (int) -> T.. | |
| 2306 | // -> U` - and the argument is a function, not a literal, that | |
| 2307 | // returns an N-ary function at that depth. The expansion is a | |
| 2308 | // literal over the formal's own parameters calling the argument, | |
| 2309 | // so the N-ary function becomes a literal's body, which the | |
| 2310 | // return-spine carry fits to the tuple the pack binds to. Absent | |
| 2311 | // otherwise. | |
| 2312 | _nested_pack_adaptation_arity( | |
| 2313 | candidate: Semantic.Symbols.Function, | |
| 2314 | index: int, | |
| 2315 | argument: Trees.Expressions.Expression, | |
| 2316 | argument_type: Type? | |
| 2317 | ) -> int? is | |
| 2318 | if !candidate.get_argument_is_pack(index) then | |
| 2319 | return null | |
| 2320 | fi | |
| 2321 | ||
| 2322 | let depth = candidate.get_argument_pack_depth(index) | |
| 2323 | ||
| 2324 | if depth <= 0 \/ parenthesised_literal(argument)? then | |
| 2325 | return null | |
| 2326 | fi | |
| 2327 | ||
| 2328 | if !argument_type? \/ !argument_type.is_function then | |
| 2329 | return null | |
| 2330 | fi | |
| 2331 | ||
| 2332 | let returned mut = argument_type | |
| 2333 | ||
| 2334 | for _ in 0..depth do | |
| 2335 | if !returned.is_function \/ returned.is_action \/ returned.arguments.count == 0 then | |
| 2336 | return null | |
| 2337 | fi | |
| 2338 | ||
| 2339 | returned = returned.arguments[returned.arguments.count - 1] | |
| 2340 | od | |
| 2341 | ||
| 2342 | if !returned.is_function then | |
| 2343 | return null | |
| 2344 | fi | |
| 2345 | ||
| 2346 | let arity = Semantic.ARGUMENT_PACK.parameter_count(returned) | |
| 2347 | ||
| 2348 | if arity < 2 \/ arity > Semantic.ARGUMENT_PACK.MAXIMUM_ARITY then | |
| 2349 | return null | |
| 2350 | fi | |
| 2351 | ||
| 2352 | return Semantic.ARGUMENT_PACK.parameter_count(argument_type) | |
| 2353 | si | |
| 2354 | ||
| 2355 | // True when at least one argument is such a reference - the | |
| 2356 | // signal that a failed resolve is recoverable by eta-expanding | |
| 2357 | // it under the candidate's formal. | |
| 2358 | _has_carrier_mismatch_reference( | |
| 2359 | candidate: Semantic.Symbols.Function, | |
| 2360 | argument_types: Collections.LIST[Type], | |
| 2361 | argument_expressions: Collections.List[Trees.Expressions.Expression] | |
| 2362 | ) -> bool is | |
| 2363 | if candidate.arguments.count != argument_expressions.count then | |
| 2364 | return false | |
| 2365 | fi | |
| 2366 | ||
| 2367 | for i in 0..argument_expressions.count do | |
| 2368 | if _carrier_mismatch_shape(argument_expressions[i], argument_types[i], candidate.arguments[i])? then | |
| 2369 | return true | |
| 2370 | fi | |
| 2371 | od | |
| 2372 | ||
| 2373 | return false | |
| 2374 | si | |
| 2375 | ||
| 2376 | // PARTIAL re-specialisation: the resolver may | |
| 2377 | // have driven its type-arg binding from a | |
| 2378 | // tainted lambda actual whose body errored on | |
| 2379 | // the first walk (the free-function lambda- | |
| 2380 | // inference gap). Pushing those ERROR-bearing | |
| 2381 | // formals as constraints to the lambda would | |
| 2382 | // taint its re-walk too. Detect the case and | |
| 2383 | // re-specialise from CLEAN siblings via the | |
| 2384 | // function-own-args specialiser (which skips | |
| 2385 | // ERROR / placeholder-bearing actuals); push | |
| 2386 | // that cleaner form. | |
| 2387 | // | |
| 2388 | // Same shape for unbound function-own type | |
| 2389 | // variables: when the resolver couldn't bind a | |
| 2390 | // slot, the formal still contains the | |
| 2391 | // candidate's literal `T` / `S` /…, which is | |
| 2392 | // useless as a constraint downstream | |
| 2393 | // (literal `T` matches nothing concrete the | |
| 2394 | // body could produce). Re-specialise so those | |
| 2395 | // slots become phantoms — open to match propagation | |
| 2396 | // from inside the lambda body. | |
| 2397 | // PARTIAL-result retry. Generalised over the source of the | |
| 2398 | // argument expressions in the same way as `try_overload_after_null`. | |
| 2399 | // Assumes the caller is inside a `_logger.speculate()` level. | |
| 2400 | try_overload_on_partial( | |
| 2401 | overload_result: Semantic.OVERLOAD_RESOLVE_RESULT, | |
| 2402 | function_group: Semantic.Symbols.FUNCTION_GROUP, | |
| 2403 | arguments: Collections.LIST[Value], | |
| 2404 | argument_types: Collections.LIST[Type], | |
| 2405 | want_instance: bool, | |
| 2406 | named_restrict: Collections.List[Semantic.Symbols.Function]?, | |
| 2407 | argument_expressions: Collections.List[Trees.Expressions.Expression], | |
| 2408 | argument_location: LOCATION, | |
| 2409 | cache_key: Trees.Node | |
| 2410 | ) -> Semantic.OVERLOAD_RESOLVE_RESULT? is | |
| 2411 | let push_function mut = overload_result.function | |
| 2412 | ||
| 2413 | // An asynchronous literal with no declared return type | |
| 2414 | // settles between same-arity candidates by whether its body | |
| 2415 | // produces a value. The resolver picked before the literal's | |
| 2416 | // return type could say, so its pick may be the other one. | |
| 2417 | if let agreed = _async_literal_candidates.find(function_group, argument_expressions, want_instance) then | |
| 2418 | if agreed != push_function then | |
| 2419 | push_function = agreed | |
| 2420 | ||
| 2421 | if agreed.is_generic then | |
| 2422 | let phantom_origins = _type_arg_placeholder_registry.get_or_create_for_function(cache_key, argument_location, agreed) | |
| 2423 | let respecialized = _owner_type_arg_specializer.specialize_function_own_args_from_concrete_siblings(agreed, argument_types, phantom_origins, argument_location) | |
| 2424 | ||
| 2425 | if respecialized != agreed then | |
| 2426 | push_function = respecialized | |
| 2427 | fi | |
| 2428 | fi | |
| 2429 | fi | |
| 2430 | fi | |
| 2431 | ||
| 2432 | if | |
| 2433 | _partial_arguments_contain_error(push_function) \/ | |
| 2434 | _partial_arguments_contain_unbound_function_type_variable(push_function) | |
| 2435 | then | |
| 2436 | let candidate = _try_find_single_arity_candidate(function_group, argument_types.count, want_instance) | |
| 2437 | ||
| 2438 | if candidate? /\ candidate.is_generic then | |
| 2439 | let phantom_origins = _type_arg_placeholder_registry.get_or_create_for_function(cache_key, argument_location, candidate) | |
| 2440 | let respecialized = _owner_type_arg_specializer.specialize_function_own_args_from_concrete_siblings(candidate, argument_types, phantom_origins, argument_location) | |
| 2441 | ||
| 2442 | if respecialized != candidate then | |
| 2443 | push_function = respecialized | |
| 2444 | fi | |
| 2445 | fi | |
| 2446 | fi | |
| 2447 | ||
| 2448 | let use retry_site = RETRY_SITE_STATS.enter("calls.try_overload_on_partial", RetrySiteKind.REWALK_WITH_INFORMATION) | |
| 2449 | _logger.roll_back() | |
| 2450 | _logger.speculate() | |
| 2451 | _flow.restore() | |
| 2452 | ||
| 2453 | // Indexed rather than iterated: an argument may be replaced | |
| 2454 | // in place below, and the list being walked is the call's own. | |
| 2455 | for index in 0..argument_expressions.count do | |
| 2456 | let a mut = argument_expressions[index] | |
| 2457 | ||
| 2458 | // A splice from the after-null retry may have replaced | |
| 2459 | // the original operand in the tree while this list still | |
| 2460 | // names the original (the operator path snapshots its | |
| 2461 | // operands once, before the retries). Read the tree's | |
| 2462 | // current child so the re-walk and the commit of | |
| 2463 | // arguments[index] target what stands there. | |
| 2464 | if let binary: Trees.Expressions.BINARY = cache_key then | |
| 2465 | // Two operands name the free-function path's | |
| 2466 | // [left, right]; one names the member path's | |
| 2467 | // [right], the left being the receiver. | |
| 2468 | let tree_arg = | |
| 2469 | if argument_expressions.count == 2 /\ index == 0 then binary.left else binary.right fi | |
| 2470 | ||
| 2471 | if tree_arg != a then | |
| 2472 | a = tree_arg | |
| 2473 | fi | |
| 2474 | fi | |
| 2475 | ||
| 2476 | // A delegate formal is pushed onto any argument, not only | |
| 2477 | // a literal: an expression that merely contains literals | |
| 2478 | // (an `if` over two of them, say) forwards the constraint | |
| 2479 | // to them and joins at the delegate type. One that cannot | |
| 2480 | // act on it re-walks unchanged and is caught by the | |
| 2481 | // delegate check below. | |
| 2482 | let argument mut = a | |
| 2483 | let is_packed mut = false | |
| 2484 | ||
| 2485 | _bound_value_parameters_from_pack(push_function, index, argument_types[index]) | |
| 2486 | ||
| 2487 | _take_spread_reading(push_function, index, a, arguments, argument_types) | |
| 2488 | ||
| 2489 | if let presented = _presented_pack_type(cache_key, push_function, index, a, argument_types[index]) then | |
| 2490 | argument_types[index] = presented | |
| 2491 | ||
| 2492 | continue | |
| 2493 | fi | |
| 2494 | ||
| 2495 | if _is_packable_literal(push_function, index, a, argument_types[index], cache_key) then | |
| 2496 | is_packed = true | |
| 2497 | fi | |
| 2498 | ||
| 2499 | if | |
| 2500 | is_packed \/ | |
| 2501 | ( | |
| 2502 | argument.value? /\ | |
| 2503 | ( | |
| 2504 | parenthesised_literal(argument)? \/ | |
| 2505 | _delegate_shape.is_named_delegate(push_function.arguments[index], _innate_symbol_lookup) | |
| 2506 | ) | |
| 2507 | ) | |
| 2508 | then | |
| 2509 | let f = push_function.arguments[index] | |
| 2510 | ||
| 2511 | argument.set_expected_type(f, "{{0}} is not assignable to {{1}}") | |
| 2512 | _mark_packed_literal(push_function, index, argument) | |
| 2513 | _visitor.rewalk(argument) | |
| 2514 | ||
| 2515 | if let argument.value? /\ value.type? then | |
| 2516 | argument_types[index] = value.type! | |
| 2517 | fi | |
| 2518 | else | |
| 2519 | // ensure any error messages are committed | |
| 2520 | _visitor.rewalk(argument) | |
| 2521 | fi | |
| 2522 | ||
| 2523 | if argument.value? then | |
| 2524 | arguments[index] = argument.value | |
| 2525 | fi | |
| 2526 | od | |
| 2527 | ||
| 2528 | // A delegate formal was matched partially on the strength of | |
| 2529 | // the actual being some function type, which only a literal | |
| 2530 | // can make good on - the re-walk above compiles a literal to | |
| 2531 | // the delegate and leaves anything else at its own type. | |
| 2532 | // Reject those here: letting one through would emit a value | |
| 2533 | // of one delegate type into a slot of another, which the CLR | |
| 2534 | // does not convert. | |
| 2535 | for (index, formal) in push_function.arguments |> index() do | |
| 2536 | if _delegate_shape.is_named_delegate(formal, _innate_symbol_lookup) /\ !formal.is_assignable_from(argument_types[index]) then | |
| 2537 | _logger.error( | |
| 2538 | argument_expressions[index].location, | |
| 2539 | "{argument_types[index]} is not assignable to {formal}") | |
| 2540 | ||
| 2541 | return null | |
| 2542 | fi | |
| 2543 | od | |
| 2544 | ||
| 2545 | return _prefer_phantom_specialised( | |
| 2546 | _overload_resolver.resolve(argument_location, function_group, argument_types, false, want_instance, false, named_restrict), | |
| 2547 | push_function) | |
| 2548 | si | |
| 2549 | ||
| 2550 | visit_call(call: Trees.Expressions.CALL) is | |
| 2551 | // The stand-in call a `|>` leaves behind when its right side is | |
| 2552 | // not a call: the parser has already reported that, and there | |
| 2553 | // is nothing here to resolve. Anything this pass said about it | |
| 2554 | // would describe the placeholder rather than the code. | |
| 2555 | if call.is_poisoned then | |
| 2556 | call.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), call.location) | |
| 2557 | return | |
| 2558 | fi | |
| 2559 | ||
| 2560 | // Recursive-call match propagation for self-recursive lambdas | |
| 2561 | // (`let f = x rec => ... rec(actual) ...`). The | |
| 2562 | // call-site match propagation below only widens a closure's | |
| 2563 | // argument type when the formal is still an | |
| 2564 | // INFERRED_VARIABLE_TYPE placeholder. For a rec call the | |
| 2565 | // formal is the closure's own parameter Variable, which | |
| 2566 | // by iter N is already resolved to (often the narrow) | |
| 2567 | // outer call-site type. Without further widening, a rec | |
| 2568 | // call with a wider actual fails type-check. | |
| 2569 | // | |
| 2570 | // Widen here: push each actual as a candidate on the | |
| 2571 | // closure parameter's LUB. When the actual isn't | |
| 2572 | // assignable to the current parameter type, reset the | |
| 2573 | // parameter's type back to a placeholder so the next | |
| 2574 | // outer-body-retry iteration's closure_arg_resolver pass | |
| 2575 | // re-derives from the now-wider LUB. | |
| 2576 | try_propagate_recursive_call_args(call) | |
| 2577 | ||
| 2578 | // Arity-aware refinement of MEMBER_CONSTRAINT for the | |
| 2579 | // `<placeholder>.<name>(args...)` shape. MEMBER.visit | |
| 2580 | // already emitted MEMBER_CONSTRAINT(name); pin the | |
| 2581 | // arity here so the resolved type must have `name` | |
| 2582 | // callable at this arg count, not merely present. The | |
| 2583 | // receiver may already have been ERROR-typed by | |
| 2584 | // MEMBER.visit's placeholder branch — read the *member's | |
| 2585 | // left*'s type to find the placeholder regardless. | |
| 2586 | if let member: Trees.Expressions.MEMBER = call.function then | |
| 2587 | if let member.left?, left.value? /\ value.type? then | |
| 2588 | if let placeholder: Semantic.Types.INFERRED_VARIABLE_TYPE = value.type then | |
| 2589 | let arity = call.arguments.count | |
| 2590 | ||
| 2591 | _logger.mark_consumed_any_if(Semantic.INFERENCE_TRACE.add_constraint("calls.member_call_arity", placeholder.origin, | |
| 2592 | Semantic.MEMBER_CONSTRAINT(member.identifier.name, arity) | |
| 2593 | )) | |
| 2594 | fi | |
| 2595 | fi | |
| 2596 | fi | |
| 2597 | ||
| 2598 | let function_value = call.function.value | |
| 2599 | ||
| 2600 | if !function_value? \/ !function_value.type? then | |
| 2601 | call.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), call.location) | |
| 2602 | return | |
| 2603 | fi | |
| 2604 | ||
| 2605 | // `|>` threads its subject in as the first argument, which is | |
| 2606 | // positional; it is spliced into the argument list but not into | |
| 2607 | // argument_names, so combining it with named written arguments | |
| 2608 | // is rejected rather than silently misaligned. Checked before | |
| 2609 | // the constructor dispatch below so it covers constructor calls | |
| 2610 | // too. | |
| 2611 | if call.is_thread_first /\ call.argument_names? then | |
| 2612 | _logger.error(call.location, "named arguments cannot be combined with |>") | |
| 2613 | call.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), call.location) | |
| 2614 | return | |
| 2615 | fi | |
| 2616 | ||
| 2617 | // Bare unit-variant accesses (`COLOR.RED`, `Option.NONE[int]`) | |
| 2618 | // already lowered to a NEW pointing at the singleton. Empty | |
| 2619 | // parens on top of that — `COLOR.RED()` — pass the value | |
| 2620 | // through; supplying any argument is an error because a unit | |
| 2621 | // variant carries no fields. Generic unit variants with the | |
| 2622 | // type arguments inferred from context still arrive as a | |
| 2623 | // TYPE_EXPRESSION (the lower step needs a constraint that | |
| 2624 | // only the parent has) and fall through to resolve_constructor. | |
| 2625 | if isa NEW(function_value) then | |
| 2626 | let new_value = cast NEW(function_value) | |
| 2627 | ||
| 2628 | if new_value.constructor.owner!.is_unit_variant then | |
| 2629 | if call.arguments.count == 0 then | |
| 2630 | call.compile_expressions_state.value = new_value | |
| 2631 | return | |
| 2632 | fi | |
| 2633 | ||
| 2634 | _logger.error( | |
| 2635 | call.location, | |
| 2636 | "unit variant {new_value.type} takes no arguments" | |
| 2637 | ) | |
| 2638 | ||
| 2639 | call.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), call.location) | |
| 2640 | return | |
| 2641 | fi | |
| 2642 | fi | |
| 2643 | ||
| 2644 | if function_value.is_type_expression then | |
| 2645 | (call.function.compile_expressions_state.value, call.compile_expressions_state.value) = resolve_constructor(call.location, call.right_location, function_value.type, call.arguments, call.argument_names, call.expected_type, call) | |
| 2646 | ||
| 2647 | return | |
| 2648 | fi | |
| 2649 | ||
| 2650 | let arguments = Collections.LIST[Value]() | |
| 2651 | let argument_types = Collections.LIST[Type]() | |
| 2652 | ||
| 2653 | // Snapshot the presence-narrowed type before the argument | |
| 2654 | // walk crosses the fact it was read through. | |
| 2655 | let function_value_type = function_value.type | |
| 2656 | ||
| 2657 | _compile_call_arguments(call.arguments, arguments, argument_types) | |
| 2658 | ||
| 2659 | // A `~>` call's subject arrives as `T?`, but the callee | |
| 2660 | // takes `T`: the propagation unwraps it before the call, | |
| 2661 | // so the candidate match sees the unwrapped type. The | |
| 2662 | // presence test and the extract happen at the wrap, not | |
| 2663 | // here. | |
| 2664 | if call.propagates_absence /\ argument_types.count > 0 then | |
| 2665 | let subject_type = argument_types[0] | |
| 2666 | ||
| 2667 | if subject_type.is_optional then | |
| 2668 | let inner = | |
| 2669 | if subject_type.is_value_type then | |
| 2670 | subject_type.optional_inner_type | |
| 2671 | else | |
| 2672 | subject_type.as_non_optional() | |
| 2673 | fi | |
| 2674 | ||
| 2675 | if inner? then | |
| 2676 | argument_types[0] = inner | |
| 2677 | fi | |
| 2678 | fi | |
| 2679 | fi | |
| 2680 | ||
| 2681 | // TODO handle if left is actually a type not a function or method | |
| 2682 | // in which case we should treat this as a constructor call | |
| 2683 | ||
| 2684 | // we could also treat consuming a bare type as a constructor call | |
| 2685 | // this would be done in the symbol loader | |
| 2686 | ||
| 2687 | let load_symbol: Semantic.Symbols.Symbol? mut = null | |
| 2688 | ||
| 2689 | if let load: Load.SYMBOL = function_value then | |
| 2690 | load_symbol = load.symbol | |
| 2691 | ||
| 2692 | if load_symbol.is_function_group then | |
| 2693 | let want_instance: bool mut | |
| 2694 | ||
| 2695 | want_instance = | |
| 2696 | if load.from? then | |
| 2697 | load.from.is_consumable | |
| 2698 | else | |
| 2699 | _symbol_table.current_instance_context? | |
| 2700 | fi | |
| 2701 | ||
| 2702 | let function_group = cast Semantic.Symbols.FUNCTION_GROUP?(load_symbol)! | |
| 2703 | ||
| 2704 | let named_restrict: Collections.List[Semantic.Symbols.Function]? mut = null | |
| 2705 | ||
| 2706 | if call.argument_names? then | |
| 2707 | let binding = _named_argument_binder.bind(call.arguments.location, function_group, call.argument_names, want_instance) | |
| 2708 | ||
| 2709 | if !binding? then | |
| 2710 | call.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), call.location) | |
| 2711 | return | |
| 2712 | fi | |
| 2713 | ||
| 2714 | _apply_named_permutation(call.arguments, arguments, argument_types, binding.permutation, binding.targets[0]) | |
| 2715 | ||
| 2716 | named_restrict = binding.targets | |
| 2717 | fi | |
| 2718 | ||
| 2719 | // Pass `call.expected_type` (the return-type context | |
| 2720 | // set by an enclosing assignment / return / typed | |
| 2721 | // initializer) so the resolver can tie-break | |
| 2722 | // between candidates with identical arg fit but | |
| 2723 | // different return types — e.g. | |
| 2724 | // `Tasks.TASK.from_exception(ex)` in a function | |
| 2725 | // returning `Tasks.TASK[int]` prefers the generic | |
| 2726 | // `from_exception[T]` overload over the non- | |
| 2727 | // generic one. | |
| 2728 | let overload_result mut = _overload_resolver.resolve(call.arguments.location, function_group, argument_types, true, want_instance, false, named_restrict, call.expected_type) | |
| 2729 | ||
| 2730 | if !overload_result? then | |
| 2731 | if _try_normalise_spread(function_group, arguments, argument_types, call.arguments, want_instance) then | |
| 2732 | overload_result = _overload_resolver.resolve(call.arguments.location, function_group, argument_types, true, want_instance, false, named_restrict, call.expected_type) | |
| 2733 | fi | |
| 2734 | fi | |
| 2735 | ||
| 2736 | if !overload_result? then | |
| 2737 | overload_result = try_overload_after_null(function_group, arguments, argument_types, want_instance, named_restrict, call.arguments.expressions, call.arguments.location, call) | |
| 2738 | fi | |
| 2739 | ||
| 2740 | if overload_result == null then | |
| 2741 | call.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), call.location) | |
| 2742 | return | |
| 2743 | fi | |
| 2744 | ||
| 2745 | if overload_result.needs_retry then | |
| 2746 | overload_result = try_overload_on_partial(overload_result, function_group, arguments, argument_types, want_instance, named_restrict, call.arguments.expressions, call.arguments.location, call) | |
| 2747 | ||
| 2748 | if !overload_result? then | |
| 2749 | call.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), call.location) | |
| 2750 | return | |
| 2751 | fi | |
| 2752 | fi | |
| 2753 | ||
| 2754 | let function mut = overload_result.function | |
| 2755 | ||
| 2756 | if _resolve_deferred_defaults(function, call.arguments.expressions, arguments, argument_types) then | |
| 2757 | // A bare group argument resolved to a delegate | |
| 2758 | // only now that the formal was known - re-resolve | |
| 2759 | // so the callee's own type variables bind from the | |
| 2760 | // delegate's shape rather than staying open. | |
| 2761 | let re_resolved = _overload_resolver.resolve(call.arguments.location, function_group, argument_types, true, want_instance, false, named_restrict, call.expected_type) | |
| 2762 | ||
| 2763 | if re_resolved? then | |
| 2764 | function = re_resolved.function | |
| 2765 | fi | |
| 2766 | fi | |
| 2767 | ||
| 2768 | _visitor.note_reference_arguments(call, function) | |
| 2769 | _feed_pack_from_expected(function, call.expected_type) | |
| 2770 | _bound_awaiting_sequence_elements(function, call.arguments.expressions) | |
| 2771 | ||
| 2772 | if function.is_unsafe_constraints then | |
| 2773 | _logger.warn(call.location, "unchecked-constraints", "call to {function} has unchecked constraints") | |
| 2774 | fi | |
| 2775 | ||
| 2776 | // A function whose type arguments were bound by | |
| 2777 | // inference keeps `is_generic` set with concrete | |
| 2778 | // `generic_arguments`; an explicitly specialized one | |
| 2779 | // has `is_generic` cleared and was already checked | |
| 2780 | // at `FUNCTION_GROUP.try_specialize`. | |
| 2781 | if | |
| 2782 | function.is_generic /\ | |
| 2783 | function.generic_arguments.count == function.generic_argument_names.count | |
| 2784 | then | |
| 2785 | Semantic.Symbols.GENERIC_CONSTRAINT_CHECKER().check_arguments( | |
| 2786 | call.location, | |
| 2787 | _logger, | |
| 2788 | function, | |
| 2789 | function.generic_argument_names, | |
| 2790 | function.generic_arguments | |
| 2791 | ) | |
| 2792 | fi | |
| 2793 | ||
| 2794 | _settle_packed_literal_names(function, call.arguments.expressions) | |
| 2795 | present_pack_arguments(call, call.arguments.expressions, function, arguments) | |
| 2796 | ||
| 2797 | let accessor_class = _symbol_table.current_accessor | |
| 2798 | ||
| 2799 | if !function.is_accessible_to(accessor_class) then | |
| 2800 | _logger.error(call.function.location, "{function} is not accessible here") | |
| 2801 | fi | |
| 2802 | ||
| 2803 | _symbol_use_locations.add_symbol_use(call.function.right_location, function) | |
| 2804 | ||
| 2805 | // A callee selected through `?.` short-circuits | |
| 2806 | // the whole call - argument evaluation included - | |
| 2807 | // on an absent receiver, so the call value is | |
| 2808 | // built inside the coalescing wrap against the | |
| 2809 | // unwrapped receiver. A static callee never | |
| 2810 | // consumes the tested receiver. | |
| 2811 | let coalesce_member = _try_coalescing_member(call) | |
| 2812 | ||
| 2813 | if coalesce_member? then | |
| 2814 | let wrapped = _access.build_coalesce_wrap( | |
| 2815 | coalesce_member, | |
| 2816 | function.is_instance, | |
| 2817 | from => function.call(call.function.location, from, arguments, null, _function_caller) | |
| 2818 | ) | |
| 2819 | ||
| 2820 | if wrapped? then | |
| 2821 | call.compile_expressions_state.value = wrapped | |
| 2822 | return | |
| 2823 | fi | |
| 2824 | fi | |
| 2825 | ||
| 2826 | // A static call has no receiver value of its own - | |
| 2827 | // `load.from` is always null - but a static virtual | |
| 2828 | // interface member reached through a bound type | |
| 2829 | // parameter (`T.parse(...)`) needs the qualifier's | |
| 2830 | // type to emit the CLR's `constrained.` call shape. | |
| 2831 | // Recover it from the callee expression's own left | |
| 2832 | // operand rather than through the discarded static | |
| 2833 | // load, since only a type-variable qualifier is | |
| 2834 | // ever relevant here. | |
| 2835 | let call_receiver: Value? mut = load.from | |
| 2836 | ||
| 2837 | if !call_receiver? then | |
| 2838 | if let member: Trees.Expressions.MEMBER = call.function then | |
| 2839 | if let left_type: Type = member.left.value?.type /\ left_type.is_type_variable then | |
| 2840 | call_receiver = member.left.value | |
| 2841 | fi | |
| 2842 | fi | |
| 2843 | fi | |
| 2844 | ||
| 2845 | // A `~>` thread-first call runs the whole call - | |
| 2846 | // argument evaluation included - inside a presence | |
| 2847 | // test on the threaded subject, against its | |
| 2848 | // unwrapped value as the first argument. | |
| 2849 | if call.propagates_absence then | |
| 2850 | let wrapped = _access.build_propagating_subject_wrap( | |
| 2851 | call.arguments.expressions[0], | |
| 2852 | from => ( | |
| 2853 | let threaded = Collections.LIST[Value](arguments) | |
| 2854 | threaded[0] = from | |
| 2855 | function.call(call.function.location, call_receiver, threaded, null, _function_caller) | |
| 2856 | ) | |
| 2857 | ) | |
| 2858 | ||
| 2859 | if wrapped? then | |
| 2860 | call.compile_expressions_state.value = wrapped | |
| 2861 | return | |
| 2862 | fi | |
| 2863 | fi | |
| 2864 | ||
| 2865 | if _try_wrap_return_pack(call, function, call_receiver, arguments) then | |
| 2866 | return | |
| 2867 | fi | |
| 2868 | ||
| 2869 | call.compile_expressions_state.value = function.call(call.function.location, call_receiver, arguments, null, _function_caller) | |
| 2870 | return | |
| 2871 | fi | |
| 2872 | fi | |
| 2873 | ||
| 2874 | let function_type = function_value_type | |
| 2875 | ||
| 2876 | // Run before the is_error check below so a callee whose | |
| 2877 | // return-slot is ERROR but whose formal-arg slots still | |
| 2878 | // carry placeholders gets its placeholders fed (e.g. | |
| 2879 | // `x => x.length` has an ERROR-typed body but its arg | |
| 2880 | // slot is recoverable once a call site supplies the | |
| 2881 | // actual). | |
| 2882 | if isa Semantic.Types.NAMED(function_type) then | |
| 2883 | _propagate_to_placeholder_formals(function_type, argument_types, arguments.count) | |
| 2884 | fi | |
| 2885 | ||
| 2886 | // Only short-circuit when the receiver is itself the ERROR | |
| 2887 | // sentinel — not when an ERROR sits inside an otherwise-usable | |
| 2888 | // function shape (`Function[good_formals, ERROR_return]`). | |
| 2889 | // For composites the formal-arg slots are still known, so the | |
| 2890 | // result-type path below can propagate a usable Function shape | |
| 2891 | // to the let-init binding. The body-retry loop can then back- | |
| 2892 | // feed actuals onto placeholder formals on the next iteration. | |
| 2893 | if isa Semantic.Types.ERROR(function_type) then | |
| 2894 | call.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), call.location) | |
| 2895 | return | |
| 2896 | elif isa Semantic.Types.INFERRED_VARIABLE_TYPE(function_type) then | |
| 2897 | _propagate_to_unresolved_callee(function_type, argument_types) | |
| 2898 | call.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), call.location) | |
| 2899 | return | |
| 2900 | elif !isa Semantic.Types.NAMED(function_type) then | |
| 2901 | _logger.error(call.function.location, "cannot call value of non-function type {function_value.type}") | |
| 2902 | call.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), call.location) | |
| 2903 | return | |
| 2904 | fi | |
| 2905 | ||
| 2906 | let function_generic_type = function_type | |
| 2907 | ||
| 2908 | let function_type_arguments = function_generic_type.arguments | |
| 2909 | ||
| 2910 | if call.argument_names? /\ (function_type.is_action \/ function_type.is_function) then | |
| 2911 | _logger.error(call.location, "cannot supply argument names here") | |
| 2912 | call.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), call.location) | |
| 2913 | return | |
| 2914 | fi | |
| 2915 | ||
| 2916 | if function_type.is_action then | |
| 2917 | if function_type_arguments.count != arguments.count then | |
| 2918 | _logger.error( | |
| 2919 | call.arguments.location, | |
| 2920 | "expected {function_type_arguments.count} arguments but {arguments.count} supplied") | |
| 2921 | call.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), call.location) | |
| 2922 | return | |
| 2923 | fi | |
| 2924 | elif function_type.is_function then | |
| 2925 | if function_type_arguments.count != arguments.count + 1 then | |
| 2926 | _logger.error( | |
| 2927 | call.arguments.location, | |
| 2928 | "expected {function_type_arguments.count - 1} arguments but {arguments.count} supplied") | |
| 2929 | call.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), call.location) | |
| 2930 | return | |
| 2931 | fi | |
| 2932 | else | |
| 2933 | if load_symbol? /\ load_symbol.is_type then | |
| 2934 | (call.function.compile_expressions_state.value, call.compile_expressions_state.value) = resolve_constructor(call.location, call.right_location, load_symbol.type!, call.arguments, call.argument_names, call.expected_type, call) | |
| 2935 | else | |
| 2936 | _logger.error(call.function.location, "cannot call value of non-function type {function_value.type}") | |
| 2937 | call.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), call.location) | |
| 2938 | fi | |
| 2939 | ||
| 2940 | return | |
| 2941 | fi | |
| 2942 | ||
| 2943 | let ok mut = true | |
| 2944 | ||
| 2945 | for i in 0..arguments.count do | |
| 2946 | // Back-feed BEFORE the compare so a Closure-call with | |
| 2947 | // a placeholder parameter type (`let f = x => ...; f(1)`) | |
| 2948 | // propagates the actual's concrete type to the | |
| 2949 | // placeholder's origin. The body retry loop's next | |
| 2950 | // iteration then sees a concrete x's-type and walks | |
| 2951 | // the lambda body cleanly. Without this the call path | |
| 2952 | // validated types but propagated nothing — local | |
| 2953 | // lambdas with use-site-only constraints failed to | |
| 2954 | // converge. | |
| 2955 | _overload_resolver.match_propagator.propagate_match(function_generic_type.arguments[i], argument_types[i]) | |
| 2956 | ||
| 2957 | ||
| 2958 | if cast int(function_generic_type.arguments[i].compare(argument_types[i])) > cast int(Semantic.Types.MATCH.CONVERTABLE) | |
| 2959 | then | |
| 2960 | ok = false | |
| 2961 | _logger.error(call.arguments.expressions[i].location, "expected argument of type {function_type_arguments[i]} but {argument_types[i]} supplied") | |
| 2962 | fi | |
| 2963 | od | |
| 2964 | ||
| 2965 | if !ok then | |
| 2966 | call.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), call.location) | |
| 2967 | return | |
| 2968 | fi | |
| 2969 | ||
| 2970 | // The closure-invocation argument boundary applies the | |
| 2971 | // same coercions an ordinary call's does — a bare T | |
| 2972 | // widening to a value-type optional T? among them — but | |
| 2973 | // against the function type's formal slots rather than a | |
| 2974 | // Function symbol's declared arguments. | |
| 2975 | let formal_types = | |
| 2976 | if function_type.is_action then | |
| 2977 | function_generic_type.arguments | |
| 2978 | else | |
| 2979 | let count = function_generic_type.arguments.count | |
| 2980 | let all = Collections.LIST[Semantic.Types.Type](count - 1) | |
| 2981 | ||
| 2982 | for i in 0..count - 1 do | |
| 2983 | all.add(function_generic_type.arguments[i]) | |
| 2984 | od | |
| 2985 | ||
| 2986 | all | |
| 2987 | fi | |
| 2988 | ||
| 2989 | let call_arguments = _function_caller.box_arguments(arguments, formal_types) | |
| 2990 | ||
| 2991 | let result_type = | |
| 2992 | if function_type.is_action then | |
| 2993 | _innate_symbol_lookup.get_void_type() | |
| 2994 | else | |
| 2995 | function_generic_type.arguments[function_type_arguments.count - 1] | |
| 2996 | fi | |
| 2997 | ||
| 2998 | // A function-typed member selected through `?.` arrives | |
| 2999 | // as a COALESCE_LOAD of the delegate; invoking that | |
| 3000 | // result would call through the null the absent arm | |
| 3001 | // produces. Re-seat the invocation inside the | |
| 3002 | // short-circuit arm instead, consuming the member load | |
| 3003 | // where the receiver is known present. With a statically | |
| 3004 | // present receiver the member value is the plain delegate | |
| 3005 | // load - invoke it directly and widen the result to the | |
| 3006 | // optional shape the `?.` asked for. | |
| 3007 | if _try_coalescing_member(call)? then | |
| 3008 | if let original: IR.Values.COALESCE_LOAD = function_value then | |
| 3009 | let arm_call = Call.CLOSURE( | |
| 3010 | original.member_load, | |
| 3011 | result_type, | |
| 3012 | function_type.is_action, | |
| 3013 | function_generic_type, | |
| 3014 | call_arguments | |
| 3015 | ) | |
| 3016 | ||
| 3017 | let rewrapped = _access.rewrap_coalesce_call(original, arm_call) | |
| 3018 | ||
| 3019 | if rewrapped? then | |
| 3020 | call.compile_expressions_state.value = rewrapped | |
| 3021 | return | |
| 3022 | fi | |
| 3023 | else | |
| 3024 | let direct = Call.CLOSURE( | |
| 3025 | function_value, | |
| 3026 | result_type, | |
| 3027 | function_type.is_action, | |
| 3028 | function_generic_type, | |
| 3029 | call_arguments | |
| 3030 | ) | |
| 3031 | ||
| 3032 | let widened = _access.widen_coalesce_result(direct) | |
| 3033 | ||
| 3034 | call.compile_expressions_state.value = | |
| 3035 | if widened? then widened else direct fi | |
| 3036 | ||
| 3037 | return | |
| 3038 | fi | |
| 3039 | fi | |
| 3040 | ||
| 3041 | // A `~>` thread-first call through a function-typed value | |
| 3042 | // (a parameter, local or field, rather than a call to a | |
| 3043 | // named function or method) runs the whole invocation - | |
| 3044 | // argument evaluation included - inside a presence test | |
| 3045 | // on the threaded subject, exactly as the named-function | |
| 3046 | // path above does. | |
| 3047 | if call.propagates_absence then | |
| 3048 | let callee = call.function.value! | |
| 3049 | ||
| 3050 | let wrapped = _access.build_propagating_subject_wrap( | |
| 3051 | call.arguments.expressions[0], | |
| 3052 | from => ( | |
| 3053 | let threaded = Collections.LIST[Value](call_arguments) | |
| 3054 | threaded[0] = from | |
| 3055 | Call.CLOSURE(callee, result_type, function_type.is_action, function_generic_type, threaded) | |
| 3056 | ) | |
| 3057 | ) | |
| 3058 | ||
| 3059 | if wrapped? then | |
| 3060 | call.compile_expressions_state.value = wrapped | |
| 3061 | return | |
| 3062 | fi | |
| 3063 | fi | |
| 3064 | ||
| 3065 | call.compile_expressions_state.value = | |
| 3066 | Call.CLOSURE( | |
| 3067 | call.function.value!, | |
| 3068 | result_type, | |
| 3069 | function_type.is_action, | |
| 3070 | function_generic_type, | |
| 3071 | call_arguments | |
| 3072 | ) | |
| 3073 | si | |
| 3074 | ||
| 3075 | // The MEMBER at call.function when this call selects its | |
| 3076 | // callee through `?.` - the shape whose short-circuit is | |
| 3077 | // lowered here at the call rather than at the member access. | |
| 3078 | _try_coalescing_member(call: Trees.Expressions.CALL) -> Trees.Expressions.MEMBER? is | |
| 3079 | let member = cast Trees.Expressions.MEMBER?(call.function) | |
| 3080 | ||
| 3081 | if member? /\ member.is_coalesce then | |
| 3082 | return member | |
| 3083 | fi | |
| 3084 | ||
| 3085 | return null | |
| 3086 | si | |
| 3087 | ||
| 3088 | // For a function-typed callee whose formal slots include | |
| 3089 | // INFERRED_VARIABLE_TYPE placeholders (typically a let-bound | |
| 3090 | // lambda whose arg types couldn't be pinned from the body | |
| 3091 | // alone), push the corresponding actual arg type onto each | |
| 3092 | // placeholder formal's origin Variable as a lower bound. The | |
| 3093 | // body-retry loop's next iteration then sees the placeholder | |
| 3094 | // resolved and walks the lambda body cleanly. | |
| 3095 | // | |
| 3096 | // Closed-root alternatives — union variants or subclasses | |
| 3097 | // of a closed class — are widened to their root before | |
| 3098 | // being pushed (see `INFERENCE_HELPERS.widen_to_closed_root`) | |
| 3099 | // to keep the lambda-arg LUB monotonic across siblings from | |
| 3100 | // different call sites. | |
| 3101 | _propagate_to_placeholder_formals( | |
| 3102 | function_type: Semantic.Types.Type, | |
| 3103 | argument_types: Collections.List[Semantic.Types.Type], | |
| 3104 | argument_count: int | |
| 3105 | ) is | |
| 3106 | let ft_named = cast Semantic.Types.NAMED?(function_type)! | |
| 3107 | let ft_args = ft_named.arguments | |
| 3108 | let formal_count = | |
| 3109 | if function_type.is_function /\ !function_type.is_action then | |
| 3110 | ft_args.count - 1 | |
| 3111 | else | |
| 3112 | ft_args.count | |
| 3113 | fi | |
| 3114 | ||
| 3115 | // A call through a value whose one formal is a pack slot still | |
| 3116 | // to be inferred takes its arguments as the tuple the pack binds | |
| 3117 | // to: `let safe = retry((a, b) => a + b, 1); safe(2, 3)` says | |
| 3118 | // the pack is `(int, int)`, and nothing else does. | |
| 3119 | if formal_count == 1 /\ argument_count >= 2 then | |
| 3120 | if let placeholder: Semantic.Types.INFERRED_VARIABLE_TYPE = ft_args[0] then | |
| 3121 | if let origin: Semantic.Symbols.INFERRED_TYPE_ARG_ORIGIN = placeholder.origin /\ origin.is_argument_pack then | |
| 3122 | let elements = Collections.LIST[Semantic.Types.Type]() | |
| 3123 | ||
| 3124 | for actual in argument_types do | |
| 3125 | elements.add(Semantic.INFERENCE_HELPERS.widen_to_closed_root(actual)!) | |
| 3126 | od | |
| 3127 | ||
| 3128 | let tuple = _innate_symbol_lookup.get_tuple_type(elements, null) | |
| 3129 | ||
| 3130 | _logger.mark_consumed_any_if(Semantic.INFERENCE_TRACE.add_lower_bound("calls.pack_call_arguments", origin, tuple)) | |
| 3131 | ||
| 3132 | return | |
| 3133 | fi | |
| 3134 | fi | |
| 3135 | fi | |
| 3136 | ||
| 3137 | if formal_count != argument_count then | |
| 3138 | return | |
| 3139 | fi | |
| 3140 | ||
| 3141 | for i in 0..argument_count do | |
| 3142 | let formal = ft_args[i] | |
| 3143 | let actual = argument_types[i] | |
| 3144 | ||
| 3145 | if isa Semantic.Types.INFERRED_VARIABLE_TYPE(formal) then | |
| 3146 | let placeholder = formal | |
| 3147 | let push_actual = Semantic.INFERENCE_HELPERS.widen_to_closed_root(actual)! | |
| 3148 | _logger.mark_consumed_any_if(Semantic.INFERENCE_TRACE.add_lower_bound("calls.placeholder_formal", placeholder.origin, push_actual)) | |
| 3149 | fi | |
| 3150 | od | |
| 3151 | si | |
| 3152 | ||
| 3153 | // When the call's receiver is itself an unresolved placeholder | |
| 3154 | // (`let f = ...; f(1)` while `f`'s body is still settling, or | |
| 3155 | // mutually-recursive lambdas where each side's signature | |
| 3156 | // depends on the other), record two constraints on the | |
| 3157 | // placeholder's origin: | |
| 3158 | // | |
| 3159 | // 1. A synthesised function-type shape from the actual arg | |
| 3160 | // types + a deferred return type, as a lower bound, so | |
| 3161 | // the next iteration sees the receiver resolved to a | |
| 3162 | // function type and the call can compile. Skipped when | |
| 3163 | // the LUB already has a candidate (typically from a | |
| 3164 | // direct `v = <lambda>` assignment in the same body) — | |
| 3165 | // the call's actual arg types may differ from the | |
| 3166 | // assigned shape and the per-position merge can't bridge | |
| 3167 | // them, leaving an ambiguous pair in the pool. | |
| 3168 | // | |
| 3169 | // 2. A CALL_CONSTRAINT capturing the actual arg types | |
| 3170 | // unconditionally, so the constraint-aware LUB can later | |
| 3171 | // filter candidate types to those that actually accept | |
| 3172 | // this call shape. Its discharge defers conservatively | |
| 3173 | // when the captured args still contain placeholders. | |
| 3174 | _propagate_to_unresolved_callee( | |
| 3175 | placeholder: Semantic.Types.INFERRED_VARIABLE_TYPE, | |
| 3176 | argument_types: Collections.List[Semantic.Types.Type] | |
| 3177 | ) is | |
| 3178 | // An argument typed over another function's type parameter - | |
| 3179 | // the `T[]` a `collect_array[T]` call still resolving reports - | |
| 3180 | // names no shape the callee could be asked to accept, and a | |
| 3181 | // constraint recorded from it would never discharge once the | |
| 3182 | // callee's type settles. A later walk supplies the type the | |
| 3183 | // argument settles to. | |
| 3184 | if argument_types |> any(a => a.has_function_generic_argument_foreign_to(_symbol_table.current_scope)) then | |
| 3185 | return | |
| 3186 | fi | |
| 3187 | ||
| 3188 | if !placeholder.origin.has_lub_candidate /\ argument_types |> all(a => a.is_settled) /\ | |
| 3189 | argument_types.count <= Semantic.Lookups.INNATE_TYPE_LIMITS.MAX_FUNCTION_PARAMETERS then | |
| 3190 | let function_type_components = Collections.LIST[Semantic.Types.Type](argument_types) | |
| 3191 | function_type_components.add(Semantic.Types.INFERRED_RETURN_TYPE()) | |
| 3192 | let synthesized = _innate_symbol_lookup.get_function_type(function_type_components) | |
| 3193 | _logger.mark_consumed_any_if(Semantic.INFERENCE_TRACE.add_lower_bound("calls.unresolved_callee_shape", placeholder.origin, synthesized)) | |
| 3194 | fi | |
| 3195 | ||
| 3196 | let call_args = Collections.LIST[Semantic.Types.Type](argument_types) | |
| 3197 | _logger.mark_consumed_any_if(Semantic.INFERENCE_TRACE.add_constraint("calls.unresolved_callee_call", placeholder.origin, Semantic.CALL_CONSTRAINT(call_args))) | |
| 3198 | si | |
| 3199 | si | |
| 3200 | si |