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 `new` expression, | |
| 12 | // function / method / closure / indexer calls, and the shared | |
| 13 | // constructor-resolution path. Split out of COMPILE_EXPRESSIONS, | |
| 14 | // which delegates visit(new) and the enclosed logic of | |
| 15 | // visit(call) here. The try/catch wrapper of visit(call) — with | |
| 16 | // its speculation bracket around the argument walk — stays on the | |
| 17 | // visitor; visit_call is the enclosed logic. | |
| 18 | class COMPILE_CALLS is | |
| 19 | _logger: Logger; | |
| 20 | _symbol_table: Semantic.SYMBOL_TABLE; | |
| 21 | _symbol_use_locations: Semantic.SYMBOL_USE_LOCATIONS; | |
| 22 | _innate_symbol_lookup: Semantic.Lookups.InnateSymbolLookup; | |
| 23 | _overload_resolver: Semantic.OVERLOAD_RESOLVER; | |
| 24 | _function_caller: Semantic.FUNCTION_CALLER; | |
| 25 | _owner_constraint_specializer: Semantic.OWNER_CONSTRAINT_SPECIALIZER; | |
| 26 | _owner_type_arg_specializer: Semantic.OWNER_TYPE_ARG_SPECIALIZER; | |
| 27 | _constructor_constraint_retry: Semantic.CONSTRUCTOR_CONSTRAINT_RETRY; | |
| 28 | _under_determination_detector: Semantic.UNDER_DETERMINATION_DETECTOR; | |
| 29 | _type_arg_placeholder_registry: Semantic.TYPE_ARG_PLACEHOLDER_REGISTRY; | |
| 30 | _access: COMPILE_ACCESS; | |
| 31 | _visitor: COMPILE_EXPRESSIONS; | |
| 32 | _named_argument_binder: NAMED_ARGUMENT_BINDER; | |
| 33 | _flow: NARROWING_FLOW; | |
| 34 | _delegate_shape: Semantic.DELEGATE_SHAPE; | |
| 35 | _delegate_push_candidates: Semantic.DELEGATE_PUSH_CANDIDATES; | |
| 36 | _symbol_loader: Semantic.SYMBOL_LOADER; | |
| 37 | ||
| 38 | init( | |
| 39 | logger: Logger, | |
| 40 | symbol_table: Semantic.SYMBOL_TABLE, | |
| 41 | symbol_use_locations: Semantic.SYMBOL_USE_LOCATIONS, | |
| 42 | innate_symbol_lookup: Semantic.Lookups.InnateSymbolLookup, | |
| 43 | overload_resolver: Semantic.OVERLOAD_RESOLVER, | |
| 44 | function_caller: Semantic.FUNCTION_CALLER, | |
| 45 | owner_constraint_specializer: Semantic.OWNER_CONSTRAINT_SPECIALIZER, | |
| 46 | owner_type_arg_specializer: Semantic.OWNER_TYPE_ARG_SPECIALIZER, | |
| 47 | under_determination_detector: Semantic.UNDER_DETERMINATION_DETECTOR, | |
| 48 | type_arg_placeholder_registry: Semantic.TYPE_ARG_PLACEHOLDER_REGISTRY, | |
| 49 | access: COMPILE_ACCESS, | |
| 50 | visitor: COMPILE_EXPRESSIONS, | |
| 51 | flow: NARROWING_FLOW, | |
| 52 | symbol_loader: Semantic.SYMBOL_LOADER | |
| 53 | ) is | |
| 54 | super.init(); | |
| 55 | ||
| 56 | _logger = logger; | |
| 57 | _symbol_table = symbol_table; | |
| 58 | _symbol_use_locations = symbol_use_locations; | |
| 59 | _innate_symbol_lookup = innate_symbol_lookup; | |
| 60 | _overload_resolver = overload_resolver; | |
| 61 | _function_caller = function_caller; | |
| 62 | _owner_constraint_specializer = owner_constraint_specializer; | |
| 63 | _owner_type_arg_specializer = owner_type_arg_specializer; | |
| 64 | _constructor_constraint_retry = Semantic.CONSTRUCTOR_CONSTRAINT_RETRY(owner_constraint_specializer); | |
| 65 | _under_determination_detector = under_determination_detector; | |
| 66 | _type_arg_placeholder_registry = type_arg_placeholder_registry; | |
| 67 | _access = access; | |
| 68 | _visitor = visitor; | |
| 69 | _named_argument_binder = NAMED_ARGUMENT_BINDER(logger); | |
| 70 | _flow = flow; | |
| 71 | _delegate_shape = Semantic.DELEGATE_SHAPE(); | |
| 72 | _delegate_push_candidates = Semantic.DELEGATE_PUSH_CANDIDATES(_delegate_shape, innate_symbol_lookup); | |
| 73 | _symbol_loader = symbol_loader; | |
| 74 | si | |
| 75 | ||
| 76 | // Rebuild a named call's already-collected argument lists - the | |
| 77 | // AST expressions and the parallel value / type lists - into | |
| 78 | // the resolved overload's parameter order. `permutation` is | |
| 79 | // indexed by formal parameter; a negative entry marks a | |
| 80 | // parameter the call omitted, which is filled with a `default` | |
| 81 | // value of that parameter's type (taken from `target`). | |
| 82 | _apply_named_permutation( | |
| 83 | argument_expressions: Trees.Expressions.LIST, | |
| 84 | arguments: Collections.LIST[Value], | |
| 85 | argument_types: Collections.LIST[Type], | |
| 86 | permutation: Collections.List[int], | |
| 87 | target: Semantic.Symbols.Function | |
| 88 | ) is | |
| 89 | let source_expressions = Collections.LIST[Trees.Expressions.Expression](argument_expressions); | |
| 90 | let source_arguments = Collections.LIST[Value](arguments); | |
| 91 | let source_argument_types = Collections.LIST[Type](argument_types); | |
| 92 | ||
| 93 | argument_expressions.expressions.clear(); | |
| 94 | arguments.clear(); | |
| 95 | argument_types.clear(); | |
| 96 | ||
| 97 | for formal_index in 0..permutation.count do | |
| 98 | let source_index = permutation[formal_index]; | |
| 99 | ||
| 100 | if source_index >= 0 then | |
| 101 | argument_expressions.expressions.add(source_expressions[source_index]); | |
| 102 | arguments.add(source_arguments[source_index]); | |
| 103 | argument_types.add(source_argument_types[source_index]); | |
| 104 | else | |
| 105 | let formal_type = target.arguments[formal_index]; | |
| 106 | let stored = target.argument_defaults[formal_index]; | |
| 107 | let default_value = DEFAULT_ARGUMENT_VALUES.build(stored, formal_type, _innate_symbol_lookup); | |
| 108 | ||
| 109 | let default_expression = Trees.Expressions.DEFAULT(argument_expressions.location, null); | |
| 110 | default_expression.set_expected_type(formal_type, ""); | |
| 111 | default_expression.compile_expressions_state.value = default_value; | |
| 112 | ||
| 113 | argument_expressions.expressions.add(default_expression); | |
| 114 | arguments.add(default_value); | |
| 115 | argument_types.add(formal_type); | |
| 116 | fi | |
| 117 | od | |
| 118 | si | |
| 119 | ||
| 120 | visit_new(`new: Trees.Expressions.NEW) is | |
| 121 | // TODO call resolve_constructor() instead | |
| 122 | ||
| 123 | `new.compile_expressions_state.value = null; | |
| 124 | ||
| 125 | let type: Type? mut; | |
| 126 | ||
| 127 | if `new.type_expression? then | |
| 128 | type = `new.type_expression.type; | |
| 129 | ||
| 130 | if type == null then | |
| 131 | _logger.poison(`new.type_expression!.location, "has no type"); | |
| 132 | `new.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), `new.location); | |
| 133 | return; | |
| 134 | fi | |
| 135 | elif let `new.expected_type? then | |
| 136 | // `new(args)` form: no explicit type, take the type | |
| 137 | // from the parent context's constraint (LHS of an | |
| 138 | // assignment / typed initializer / call arg whose | |
| 139 | // formal type is known). A `BOX?` constraint is | |
| 140 | // peeled — a constructor produces the underlying | |
| 141 | // instance and is widened to the optional at the | |
| 142 | // assignment site, so the NEW value carries the | |
| 143 | // non-optional class type rather than masquerading | |
| 144 | // as `BOX?`. | |
| 145 | type = expected_type.as_non_optional(); | |
| 146 | else | |
| 147 | _logger.error(`new.location, "cannot infer type for new"); | |
| 148 | `new.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), `new.location); | |
| 149 | return; | |
| 150 | fi | |
| 151 | ||
| 152 | if !isa Semantic.Types.NAMED(type) then | |
| 153 | if `new.type_expression? then | |
| 154 | _logger.error(`new.type_expression.location, "cannot instantiate {type}"); | |
| 155 | else | |
| 156 | _logger.error(`new.location, "cannot instantiate {type}"); | |
| 157 | fi | |
| 158 | `new.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), `new.location); | |
| 159 | return; | |
| 160 | fi | |
| 161 | ||
| 162 | if `new.type_expression? then | |
| 163 | `new.type_expression.check_is_not_void(_logger, "cannot use void type here"); | |
| 164 | fi | |
| 165 | ||
| 166 | let named_type = type; | |
| 167 | let type_symbol mut = named_type.symbol; | |
| 168 | ||
| 169 | if let abstract_class: Semantic.Symbols.CLASS = type_symbol then | |
| 170 | if abstract_class.is_abstract then | |
| 171 | _logger.error(`new.location, "cannot instantiate abstract class {abstract_class.name}"); | |
| 172 | fi | |
| 173 | fi | |
| 174 | ||
| 175 | let symbol = named_type.scope.find_direct("init"); | |
| 176 | ||
| 177 | let function_group = cast Semantic.Symbols.FUNCTION_GROUP?(symbol); | |
| 178 | ||
| 179 | let arguments = Collections.LIST[Value](); | |
| 180 | let argument_types = Collections.LIST[Type](); | |
| 181 | ||
| 182 | for a in `new.arguments do | |
| 183 | let value = a.value; | |
| 184 | ||
| 185 | if value? /\ value.type? /\ value.check_is_consumable(_logger, a.location) then | |
| 186 | arguments.add(value); | |
| 187 | argument_types.add(value.type!); | |
| 188 | else | |
| 189 | let t = Semantic.Types.ERROR(); | |
| 190 | ||
| 191 | arguments.add(DUMMY(t, a.location)); | |
| 192 | ||
| 193 | argument_types.add(t); | |
| 194 | fi | |
| 195 | od | |
| 196 | ||
| 197 | if !function_group? then | |
| 198 | `new.compile_expressions_state.value = | |
| 199 | DUMMY( | |
| 200 | type, | |
| 201 | `new.location | |
| 202 | ); | |
| 203 | ||
| 204 | _logger.error(`new.location, "no constructor found init({argument_types|})"); | |
| 205 | ||
| 206 | return; | |
| 207 | fi | |
| 208 | ||
| 209 | let overload_result = _overload_resolver.resolve(`new.location, function_group, argument_types, false, true, true); | |
| 210 | ||
| 211 | if overload_result == null then | |
| 212 | `new.compile_expressions_state.value = | |
| 213 | DUMMY( | |
| 214 | type, | |
| 215 | `new.location | |
| 216 | ); | |
| 217 | ||
| 218 | return; | |
| 219 | fi | |
| 220 | ||
| 221 | let function mut = overload_result.function; | |
| 222 | ||
| 223 | function = _owner_constraint_specializer.specialize_from_constraint(`new.location, function, `new.expected_type); | |
| 224 | ||
| 225 | if isa Semantic.Symbols.GENERIC(function.owner) then | |
| 226 | type_symbol = cast Semantic.Symbols.Symbol(function.owner); | |
| 227 | // The GENERIC owner of a resolved constructor always carries | |
| 228 | // a concrete type (the specialized class) by this point. | |
| 229 | type = function.owner.type; | |
| 230 | fi; | |
| 231 | ||
| 232 | let is_directly_owned mut = false; | |
| 233 | ||
| 234 | if isa Semantic.Symbols.GENERIC(type_symbol) /\ isa Semantic.Symbols.Symbol(function.owner) then | |
| 235 | is_directly_owned = type_symbol =~ cast Semantic.Symbols.Symbol(function.owner); | |
| 236 | else | |
| 237 | is_directly_owned = type_symbol == function.owner; | |
| 238 | fi | |
| 239 | ||
| 240 | if !is_directly_owned then | |
| 241 | _logger.error(`new.location, "cannot call superclass constructor {function}"); | |
| 242 | fi | |
| 243 | ||
| 244 | if `new.type_expression? then | |
| 245 | let right_location = `new.type_expression.right_location; | |
| 246 | _symbol_use_locations.add_symbol_use(right_location, function); | |
| 247 | _symbol_use_locations.add_symbol_use(right_location, type_symbol.root_unspecialized_symbol); | |
| 248 | fi | |
| 249 | ||
| 250 | `new.compile_expressions_state.value = | |
| 251 | NEW( | |
| 252 | // every branch above either sets type or early-returns | |
| 253 | type, | |
| 254 | function, | |
| 255 | arguments | |
| 256 | ); | |
| 257 | si | |
| 258 | ||
| 259 | // Sibling-arg specialisation entry: produce the phantom- | |
| 260 | // origin list for unbound slots from the per-AST cache, then | |
| 261 | // delegate to `OWNER_TYPE_ARG_SPECIALIZER` for the binding | |
| 262 | // and specialisation logic. Phantom origins live on the | |
| 263 | // placeholder registry so match propagation across body-retry | |
| 264 | // iterations lands on the same Variables; the specialiser | |
| 265 | // itself is stateless, which lets the binding contract be | |
| 266 | // unit-tested in isolation. | |
| 267 | _specialise_candidate_from_concrete_siblings( | |
| 268 | candidate: Semantic.Symbols.Function, | |
| 269 | argument_types: Collections.List[Semantic.Types.Type], | |
| 270 | cache_key: Trees.Node, | |
| 271 | location: LOCATION | |
| 272 | ) -> Semantic.Symbols.Function? is | |
| 273 | if isa Semantic.Symbols.GENERIC(candidate.owner) then | |
| 274 | return candidate; | |
| 275 | fi | |
| 276 | ||
| 277 | let owner_classy = cast Semantic.Symbols.Classy?(candidate.owner); | |
| 278 | ||
| 279 | if !owner_classy? \/ !owner_classy.is_generic then | |
| 280 | return candidate; | |
| 281 | fi | |
| 282 | ||
| 283 | let origins = _type_arg_placeholder_registry.get_or_create(cache_key, location, owner_classy); | |
| 284 | ||
| 285 | return _owner_type_arg_specializer.specialize_from_concrete_siblings(candidate, argument_types, origins, location); | |
| 286 | si | |
| 287 | ||
| 288 | // Find the single arity- and instance-matching candidate in a | |
| 289 | // function group, or null if there are zero or multiple. Used | |
| 290 | // by `visit_call`'s constraint-push retry: when the first | |
| 291 | // overload resolution fails, having exactly one candidate to | |
| 292 | // push formal arg types from disambiguates the constraint | |
| 293 | // direction. Multi-candidate disambiguation under constraint | |
| 294 | // push is bigger work tracked under #1174. | |
| 295 | _try_find_single_arity_candidate( | |
| 296 | group: Semantic.Symbols.FUNCTION_GROUP, | |
| 297 | arg_count: int, | |
| 298 | want_instance: bool | |
| 299 | ) -> Semantic.Symbols.Function? is | |
| 300 | let result: Semantic.Symbols.Function? mut = null; | |
| 301 | let count mut = 0; | |
| 302 | ||
| 303 | for f in group.functions do | |
| 304 | if !want_instance /\ f.is_instance then | |
| 305 | continue; | |
| 306 | fi | |
| 307 | ||
| 308 | if !f.are_arguments_declared then | |
| 309 | continue; | |
| 310 | fi | |
| 311 | ||
| 312 | if f.arguments.count != arg_count then | |
| 313 | continue; | |
| 314 | fi | |
| 315 | ||
| 316 | result = f; | |
| 317 | count = count + 1; | |
| 318 | od | |
| 319 | ||
| 320 | if count == 1 then | |
| 321 | return result; | |
| 322 | fi | |
| 323 | ||
| 324 | return null; | |
| 325 | si | |
| 326 | ||
| 327 | // should be called with logger speculating | |
| 328 | _compile_call_arguments( | |
| 329 | argument_expressions: Trees.Expressions.LIST, | |
| 330 | arguments: Collections.LIST[Value], | |
| 331 | argument_types: Collections.LIST[Type] | |
| 332 | ) is | |
| 333 | for a in argument_expressions do | |
| 334 | _compile_one_argument(a, arguments, argument_types); | |
| 335 | od | |
| 336 | si | |
| 337 | ||
| 338 | // True for a bare `_` argument (no explicit `_[T]` type | |
| 339 | // argument) that failed to infer a type on the first walk - | |
| 340 | // before the callee was resolved, nothing had pushed it an | |
| 341 | // expected type yet. | |
| 342 | is_unresolved_default_argument(a: Trees.Expressions.Expression) -> bool static is | |
| 343 | if !isa Trees.Expressions.DEFAULT(a) \/ a.type_expression? then | |
| 344 | return false; | |
| 345 | fi | |
| 346 | ||
| 347 | if let value: Value = a.value then | |
| 348 | if let type: Type = value.type then | |
| 349 | return type.is_error; | |
| 350 | fi | |
| 351 | ||
| 352 | return true; | |
| 353 | fi | |
| 354 | ||
| 355 | return true; | |
| 356 | si | |
| 357 | ||
| 358 | // True when the call carries at least one unresolved `default` | |
| 359 | // argument. | |
| 360 | has_unresolved_default_argument(argument_expressions: Collections.List[Trees.Expressions.Expression]) -> bool static => | |
| 361 | argument_expressions |> any(a => COMPILE_CALLS.is_unresolved_default_argument(a)); | |
| 362 | ||
| 363 | // Once overload resolution has settled on a single, unambiguous | |
| 364 | // `function`, retry any bare `_` argument that had no type to | |
| 365 | // infer against on the first walk - the resolved callee's | |
| 366 | // formal types are available now. Re-walks every argument | |
| 367 | // under a fresh speculation level, since the roll-back below | |
| 368 | // discards whatever the first walk logged for the whole call, | |
| 369 | // not just the `_` arguments. | |
| 370 | // | |
| 371 | // A `_` argument is only ever pushed a type when the resolved | |
| 372 | // formal at that position is itself concrete: a generic | |
| 373 | // candidate whose type variable is pinned by a sibling | |
| 374 | // argument or an enclosing constraint is already specialized | |
| 375 | // by this point, so the formal there is concrete too, but a | |
| 376 | // type variable free only in the `_` slot leaves the formal | |
| 377 | // wild and the argument is left to re-report its original | |
| 378 | // "cannot infer type of default here" error - a `_` argument | |
| 379 | // never itself contributes to binding a type variable. | |
| 380 | // | |
| 381 | // A resolved formal with a declared .NET default value (an | |
| 382 | // optional CLR parameter) takes that value rather than the | |
| 383 | // type's zero value, so a positionally-written `_` behaves | |
| 384 | // exactly like omitting the same parameter by name. | |
| 385 | _resolve_deferred_defaults( | |
| 386 | function: Semantic.Symbols.Function, | |
| 387 | argument_expressions: Collections.List[Trees.Expressions.Expression], | |
| 388 | arguments: Collections.LIST[Value], | |
| 389 | argument_types: Collections.LIST[Type] | |
| 390 | ) is | |
| 391 | if !has_unresolved_default_argument(argument_expressions) then | |
| 392 | return; | |
| 393 | fi | |
| 394 | ||
| 395 | _logger.roll_back(); | |
| 396 | _logger.speculate(); | |
| 397 | _flow.restore(); | |
| 398 | ||
| 399 | for (index, a) in argument_expressions |> index() do | |
| 400 | if | |
| 401 | COMPILE_CALLS.is_unresolved_default_argument(a) /\ | |
| 402 | index < function.arguments.count /\ | |
| 403 | !function.arguments[index].is_wild | |
| 404 | then | |
| 405 | let formal_type = function.arguments[index]; | |
| 406 | ||
| 407 | let stored = | |
| 408 | if index < function.argument_defaults.count then | |
| 409 | function.argument_defaults[index] | |
| 410 | else | |
| 411 | null | |
| 412 | fi; | |
| 413 | ||
| 414 | if stored? then | |
| 415 | a.compile_expressions_state.value = DEFAULT_ARGUMENT_VALUES.build(stored, formal_type, _innate_symbol_lookup); | |
| 416 | else | |
| 417 | a.set_expected_type(formal_type, ""); | |
| 418 | a.walk(_visitor); | |
| 419 | fi | |
| 420 | elif isa Trees.Expressions.DEFAULT(a) then | |
| 421 | // A `_[T]` argument, or a `DEFAULT` node | |
| 422 | // `_apply_named_permutation` synthesised to fill an | |
| 423 | // omitted named argument with the callee's own | |
| 424 | // declared default value, already carries its | |
| 425 | // final value. Re-walking either through | |
| 426 | // `visit_default` would overwrite that value with | |
| 427 | // the type's zero value - visit_default has no way | |
| 428 | // to tell "already resolved to the right thing" | |
| 429 | // from "resolved once, resolve again" - so leave | |
| 430 | // it untouched. A still-unresolved `_` whose | |
| 431 | // formal is wild has no value to protect and is | |
| 432 | // walked below to re-report its own error under | |
| 433 | // this fresh speculation level. | |
| 434 | if COMPILE_CALLS.is_unresolved_default_argument(a) then | |
| 435 | a.walk(_visitor); | |
| 436 | fi | |
| 437 | else | |
| 438 | // ensure any error messages are committed | |
| 439 | a.walk(_visitor); | |
| 440 | fi | |
| 441 | ||
| 442 | if let value: Value = a.value /\ value.type? then | |
| 443 | arguments[index] = value; | |
| 444 | argument_types[index] = value.type!; | |
| 445 | fi | |
| 446 | od | |
| 447 | si | |
| 448 | ||
| 449 | _compile_one_argument( | |
| 450 | a: Trees.Expressions.Expression, | |
| 451 | arguments: Collections.LIST[Value], | |
| 452 | argument_types: Collections.LIST[Type] | |
| 453 | ) is | |
| 454 | let value = a.value; | |
| 455 | ||
| 456 | if value? /\ value.type? /\ value.check_is_consumable(_logger, a.location) then | |
| 457 | arguments.add(value); | |
| 458 | argument_types.add(value.type!); | |
| 459 | else | |
| 460 | let t = Semantic.Types.ERROR(); | |
| 461 | ||
| 462 | arguments.add(DUMMY(t, a.location)); | |
| 463 | ||
| 464 | argument_types.add(t); | |
| 465 | fi | |
| 466 | si | |
| 467 | ||
| 468 | // Find the delegate type's own compiler-synthesized | |
| 469 | // constructor - `.ctor(object, native int)`, the only one a | |
| 470 | // real .NET delegate type ever declares. | |
| 471 | _find_delegate_constructor(type: Semantic.Types.Type) -> Semantic.Symbols.Function? is | |
| 472 | let named = cast Semantic.Types.NAMED?(type); | |
| 473 | ||
| 474 | if !named? then | |
| 475 | return null; | |
| 476 | fi | |
| 477 | ||
| 478 | let symbol = named.scope.find_direct("init"); | |
| 479 | ||
| 480 | if let group: Semantic.Symbols.FUNCTION_GROUP = symbol then | |
| 481 | if group.count == 1 then | |
| 482 | return group.functions[0]; | |
| 483 | fi | |
| 484 | ||
| 485 | return null; | |
| 486 | fi | |
| 487 | ||
| 488 | return cast Semantic.Symbols.Function?(symbol); | |
| 489 | si | |
| 490 | ||
| 491 | // Resolve a member that is either a bare Function or a | |
| 492 | // single-member FUNCTION_GROUP - the shape `find_member` | |
| 493 | // returns for a non-overloaded method (mirrors | |
| 494 | // DELEGATE_SHAPE._find_invoke). | |
| 495 | _find_single_function_member(type: Semantic.Types.Type, name: string) -> Semantic.Symbols.Function? is | |
| 496 | let symbol = type.find_member(name); | |
| 497 | ||
| 498 | if let group: Semantic.Symbols.FUNCTION_GROUP = symbol then | |
| 499 | if group.count == 1 then | |
| 500 | return group.functions[0]; | |
| 501 | fi | |
| 502 | ||
| 503 | return null; | |
| 504 | fi | |
| 505 | ||
| 506 | return cast Semantic.Symbols.Function?(symbol); | |
| 507 | si | |
| 508 | ||
| 509 | // A real .NET delegate type's sole constructor is the | |
| 510 | // compiler-synthesized `.ctor(object, native int)`, which no | |
| 511 | // ghūl call site can satisfy (nothing produces a usable | |
| 512 | // `native int`), so a single-argument constructor call | |
| 513 | // against a named delegate type is free to mean explicit | |
| 514 | // conversion: `TargetDelegate(functionValue)`. | |
| 515 | // | |
| 516 | // A literal written directly as the argument is pushed the | |
| 517 | // delegate type as its expected type, the same way an | |
| 518 | // assignment or argument-formal context does (see | |
| 519 | // COMPILE_LAMBDAS.visit_function), and constructs the | |
| 520 | // delegate directly via ldftn/newobj. An existing | |
| 521 | // function/delegate-typed value has no compile-time method | |
| 522 | // token to `ldftn` - its method is only known at runtime, via | |
| 523 | // its own `Method` property - so it is reconstructed over | |
| 524 | // (Target, MethodHandle function pointer) via the target | |
| 525 | // delegate's own constructor instead. | |
| 526 | _resolve_delegate_value_construction( | |
| 527 | location: LOCATION, | |
| 528 | type: Semantic.Types.Type, | |
| 529 | argument_expression: Trees.Expressions.Expression | |
| 530 | ) -> (Value, Value) is | |
| 531 | if isa Trees.Expressions.FUNCTION(argument_expression) then | |
| 532 | _logger.roll_back(); | |
| 533 | _logger.speculate(); | |
| 534 | _flow.restore(); | |
| 535 | ||
| 536 | argument_expression.set_expected_type(type, "{{0}} is not assignable to {{1}}"); | |
| 537 | argument_expression.walk(_visitor); | |
| 538 | ||
| 539 | let value = argument_expression.value; | |
| 540 | ||
| 541 | if !value? \/ !value.type? \/ !value.check_is_consumable(_logger, argument_expression.location) then | |
| 542 | return (cast Value(DUMMY(type, location)), cast Value(DUMMY(type, location))); | |
| 543 | fi | |
| 544 | ||
| 545 | return (cast Value(DUMMY(type, location)), value); | |
| 546 | fi | |
| 547 | ||
| 548 | let value = argument_expression.value; | |
| 549 | ||
| 550 | if !value? \/ !value.type? \/ !value.check_is_consumable(_logger, argument_expression.location) then | |
| 551 | return (cast Value(DUMMY(type, location)), cast Value(DUMMY(type, location))); | |
| 552 | fi | |
| 553 | ||
| 554 | let source_type = value.type!; | |
| 555 | ||
| 556 | if !source_type.is_function /\ !_delegate_shape.is_named_delegate(source_type) then | |
| 557 | _logger.error(argument_expression.location, "no constructor found init({source_type})"); | |
| 558 | return (cast Value(DUMMY(type, location)), cast Value(DUMMY(type, location))); | |
| 559 | fi | |
| 560 | ||
| 561 | // Compile-time shape check: the two call shapes must | |
| 562 | // actually agree. `Delegate.CreateDelegate` would have | |
| 563 | // caught a mismatch for us at construction time, but | |
| 564 | // going straight to a raw function pointer below bypasses | |
| 565 | // that check entirely, so it has to happen here instead. | |
| 566 | let source_shape = | |
| 567 | if source_type.is_function then | |
| 568 | source_type | |
| 569 | else | |
| 570 | _delegate_shape.try_get_function_type(source_type, _innate_symbol_lookup) | |
| 571 | fi; | |
| 572 | ||
| 573 | let target_shape = _delegate_shape.try_get_function_type(type, _innate_symbol_lookup); | |
| 574 | ||
| 575 | if !source_shape? \/ !target_shape? \/ !target_shape.is_assignable_from(source_shape) then | |
| 576 | _logger.error(argument_expression.location, "{source_type} is not assignable to {type}"); | |
| 577 | return (cast Value(DUMMY(type, location)), cast Value(DUMMY(type, location))); | |
| 578 | fi | |
| 579 | ||
| 580 | // `Target`/`Method` report only the last entry of a | |
| 581 | // combined (multicast) delegate's invocation list, so a | |
| 582 | // source built via `Delegate.Combine` would silently lose | |
| 583 | // every earlier target. Not guarded against: ghūl has no | |
| 584 | // syntax to combine delegates, so no ghūl-produced value | |
| 585 | // reaching here is ever multicast. | |
| 586 | let target_property = cast Semantic.Symbols.Property?(source_type.find_member("target")); | |
| 587 | let method_property = cast Semantic.Symbols.Property?(source_type.find_member("method")); | |
| 588 | ||
| 589 | if !target_property? \/ !method_property? then | |
| 590 | _logger.error(argument_expression.location, "cannot convert {source_type} to {type}"); | |
| 591 | return (cast Value(DUMMY(type, location)), cast Value(DUMMY(type, location))); | |
| 592 | fi | |
| 593 | ||
| 594 | let target_value = target_property.load(location, value, _symbol_loader); | |
| 595 | let method_value = method_property.load(location, value, _symbol_loader); | |
| 596 | let method_type = method_value.type!; | |
| 597 | ||
| 598 | let handle_property = cast Semantic.Symbols.Property?(method_type.find_member("method_handle")); | |
| 599 | ||
| 600 | if !handle_property? then | |
| 601 | _logger.error(argument_expression.location, "cannot convert {source_type} to {type}"); | |
| 602 | return (cast Value(DUMMY(type, location)), cast Value(DUMMY(type, location))); | |
| 603 | fi | |
| 604 | ||
| 605 | let handle_value = handle_property.load(location, method_value, _symbol_loader); | |
| 606 | let handle_type = handle_value.type!; | |
| 607 | ||
| 608 | let get_function_pointer_function = _find_single_function_member(handle_type, "get_function_pointer"); | |
| 609 | ||
| 610 | if !get_function_pointer_function? then | |
| 611 | _logger.error(argument_expression.location, "cannot convert {source_type} to {type}"); | |
| 612 | return (cast Value(DUMMY(type, location)), cast Value(DUMMY(type, location))); | |
| 613 | fi | |
| 614 | ||
| 615 | let pointer_value = get_function_pointer_function.call(location, handle_value, Collections.LIST[Value](), null, _function_caller); | |
| 616 | ||
| 617 | let ctor = _find_delegate_constructor(type); | |
| 618 | ||
| 619 | if !ctor? then | |
| 620 | _logger.error(argument_expression.location, "cannot convert {source_type} to {type}"); | |
| 621 | return (cast Value(DUMMY(type, location)), cast Value(DUMMY(type, location))); | |
| 622 | fi | |
| 623 | ||
| 624 | let ctor_arguments = Collections.LIST[Value](); | |
| 625 | ctor_arguments.add(target_value); | |
| 626 | ctor_arguments.add(pointer_value); | |
| 627 | ||
| 628 | let constructed = _function_caller.call_constructor(ctor, ctor_arguments, type); | |
| 629 | ||
| 630 | return (cast Value(DUMMY(type, location)), constructed); | |
| 631 | si | |
| 632 | ||
| 633 | resolve_constructor( | |
| 634 | location: LOCATION, | |
| 635 | right_location: LOCATION, | |
| 636 | type: Semantic.Types.Type mut, | |
| 637 | argument_expressions: Trees.Expressions.LIST, | |
| 638 | argument_names: Collections.List[Trees.Identifiers.Identifier]?, | |
| 639 | constraint: Semantic.Types.Type?, | |
| 640 | cache_key: Trees.Node | |
| 641 | ) -> (Value, Value) is | |
| 642 | let result: Value mut; | |
| 643 | ||
| 644 | // An explicit `Foo[...]` callee enters already specialized | |
| 645 | // and was constraint-checked by `specialize_type`; an | |
| 646 | // inferred `Foo(...)` callee is specialized below by | |
| 647 | // overload resolution and is checked post-resolution. | |
| 648 | let was_generic_on_entry = isa Semantic.Types.GENERIC(type); | |
| 649 | ||
| 650 | let named_type = cast Semantic.Types.NAMED?(type)!; | |
| 651 | let type_symbol mut = named_type.symbol; | |
| 652 | ||
| 653 | if | |
| 654 | !argument_names? /\ | |
| 655 | argument_expressions.expressions.count == 1 /\ | |
| 656 | _delegate_shape.is_named_delegate(type) | |
| 657 | then | |
| 658 | return _resolve_delegate_value_construction(location, type, argument_expressions.expressions[0]); | |
| 659 | fi | |
| 660 | ||
| 661 | if let abstract_class: Semantic.Symbols.CLASS = type_symbol then | |
| 662 | if abstract_class.is_abstract then | |
| 663 | _logger.error(location, "cannot instantiate abstract class {abstract_class.name}"); | |
| 664 | fi | |
| 665 | fi | |
| 666 | ||
| 667 | let symbol = named_type.scope.find_direct("init"); | |
| 668 | ||
| 669 | let function_group = cast Semantic.Symbols.FUNCTION_GROUP?(symbol); | |
| 670 | ||
| 671 | let arguments = Collections.LIST[Value](); | |
| 672 | let argument_types = Collections.LIST[Type](); | |
| 673 | ||
| 674 | _compile_call_arguments(argument_expressions, arguments, argument_types); | |
| 675 | ||
| 676 | if !function_group? then | |
| 677 | _logger.error(location, "no constructor found init({argument_types|})"); | |
| 678 | ||
| 679 | return (cast Value(DUMMY(type, location)), cast Value(DUMMY(type, location))); | |
| 680 | fi | |
| 681 | ||
| 682 | let named_restrict: Collections.List[Semantic.Symbols.Function]? mut = null; | |
| 683 | ||
| 684 | if argument_names? then | |
| 685 | let binding = _named_argument_binder.bind(location, function_group, argument_names, true); | |
| 686 | ||
| 687 | if !binding? then | |
| 688 | return (cast Value(Load.SYMBOL(null, function_group)), cast Value(DUMMY(type, location))); | |
| 689 | fi | |
| 690 | ||
| 691 | _apply_named_permutation(argument_expressions, arguments, argument_types, binding.permutation, binding.targets[0]); | |
| 692 | ||
| 693 | named_restrict = binding.targets; | |
| 694 | fi | |
| 695 | ||
| 696 | let overload_result mut = _overload_resolver.resolve(location, function_group, argument_types, false, true, true, named_restrict); | |
| 697 | ||
| 698 | // Sibling-arg fall-back: first resolve returned null AND | |
| 699 | // there's at least one FUNCTION-literal arg in the call. | |
| 700 | // The lambda's body walked under no parameter-type | |
| 701 | // constraint and likely errored, leaving an actual type | |
| 702 | // that doesn't reflect the real signature; binding fails; | |
| 703 | // resolver returns null. Try tentatively binding the | |
| 704 | // candidate's owner-generic args from the *resolvable* | |
| 705 | // sibling actuals (skipping the failing lambda), fill the | |
| 706 | // remaining slots with cached phantoms, then push the | |
| 707 | // substituted formals as constraints to each arg and | |
| 708 | // re-walk. The second resolve sees the lambda's now- | |
| 709 | // resolved actual type and binds T from it. | |
| 710 | // | |
| 711 | // The lambda guard matters: if no arg is a lambda, the | |
| 712 | // original null result reflects a genuine type mismatch | |
| 713 | // (e.g. `Pair([1,2,3], LIST[int]([4,5,6]))` — int[] and | |
| 714 | // LIST[int] don't unify for T) and the user-facing | |
| 715 | // diagnostic is correct as-is. | |
| 716 | if overload_result == null /\ argument_types |> any(a => a.is_function_with_any_implicit_argument_types) then | |
| 717 | let candidate = _try_find_single_arity_candidate(function_group, argument_types.count, true); | |
| 718 | ||
| 719 | if candidate? then | |
| 720 | let specialized_candidate = _specialise_candidate_from_concrete_siblings(candidate, argument_types, cache_key, location); | |
| 721 | ||
| 722 | if specialized_candidate? /\ specialized_candidate != candidate then | |
| 723 | _logger.roll_back(); | |
| 724 | _logger.speculate(); | |
| 725 | _flow.restore(); | |
| 726 | ||
| 727 | for (index, a) in argument_expressions |> index() do | |
| 728 | let f = specialized_candidate.arguments[index]; | |
| 729 | ||
| 730 | a.set_expected_type(f, "{{0}} is not assignable to {{1}}"); | |
| 731 | ||
| 732 | a.walk(_visitor); | |
| 733 | ||
| 734 | if let a.value? /\ value.type? /\ value.check_is_consumable(_logger, a.location) then | |
| 735 | arguments[index] = value; | |
| 736 | argument_types[index] = value.type!; | |
| 737 | else | |
| 738 | let t = Semantic.Types.ERROR(); | |
| 739 | arguments[index] = DUMMY(t, a.location); | |
| 740 | argument_types[index] = t; | |
| 741 | fi | |
| 742 | od | |
| 743 | ||
| 744 | overload_result = _overload_resolver.resolve(location, function_group, argument_types, false, true, true, named_restrict); | |
| 745 | fi | |
| 746 | fi | |
| 747 | fi | |
| 748 | ||
| 749 | // Return-type-constraint fall-back: first resolve returned | |
| 750 | // null AND we have a constraint pushed in by an enclosing | |
| 751 | // return / let-init / assignment. The candidate's owner- | |
| 752 | // generic args may include slots no actual arg can bind | |
| 753 | // (e.g. `RESULT.OK(42)` against `RESULT[int, string]` — | |
| 754 | // OK's arg binds T, the constraint contributes S; without | |
| 755 | // a contribution from the constraint, binding fails and | |
| 756 | // the resolver returns null). Pre-specialise each candidate | |
| 757 | // from the constraint via CONSTRUCTOR_CONSTRAINT_RETRY, | |
| 758 | // then re-resolve with the specialised list. Now formals | |
| 759 | // are no-longer-wild concrete types and arg binding | |
| 760 | // becomes verification. | |
| 761 | if overload_result == null /\ constraint? then | |
| 762 | let search = if named_restrict? then named_restrict else function_group.functions fi; | |
| 763 | let pre_specialised = _constructor_constraint_retry.try_specialise_candidates(location, search, constraint); | |
| 764 | ||
| 765 | if pre_specialised? then | |
| 766 | _logger.roll_back(); | |
| 767 | _logger.speculate(); | |
| 768 | ||
| 769 | overload_result = _overload_resolver.resolve(location, function_group, argument_types, false, true, true, pre_specialised); | |
| 770 | fi | |
| 771 | fi | |
| 772 | ||
| 773 | if overload_result == null then | |
| 774 | return (cast Value(Load.SYMBOL(null, function_group)), cast Value(DUMMY(type, location))); | |
| 775 | fi | |
| 776 | ||
| 777 | if overload_result.needs_retry then | |
| 778 | _logger.roll_back(); | |
| 779 | _logger.speculate(); | |
| 780 | _flow.restore(); | |
| 781 | ||
| 782 | for (index, a) in argument_expressions |> index() do | |
| 783 | // let use debug_despose = debug_enter(); | |
| 784 | if a.value? /\ isa Trees.Expressions.FUNCTION(a) then | |
| 785 | let f = overload_result.function.arguments[index]; | |
| 786 | ||
| 787 | a.set_expected_type(f, "{{0}} is not assignable to {{1}}"); | |
| 788 | a.walk(_visitor); | |
| 789 | ||
| 790 | argument_types[index] = a.value!.type!; | |
| 791 | else | |
| 792 | // ensure any error messages are committed | |
| 793 | a.walk(_visitor); | |
| 794 | fi | |
| 795 | ||
| 796 | if a.value? then | |
| 797 | arguments[index] = a.value; | |
| 798 | fi | |
| 799 | od | |
| 800 | ||
| 801 | overload_result = _overload_resolver.resolve(location, function_group, argument_types, false, true, true, named_restrict); | |
| 802 | ||
| 803 | if !overload_result? then | |
| 804 | return (cast Value(Load.SYMBOL(null, function_group)), cast Value(DUMMY(type, location))); | |
| 805 | fi | |
| 806 | fi | |
| 807 | ||
| 808 | let function mut = overload_result.function; | |
| 809 | ||
| 810 | function = _owner_constraint_specializer.specialize_from_constraint(location, function, constraint); | |
| 811 | function = _type_arg_placeholder_registry.specialize_with_placeholders(location, function, cache_key); | |
| 812 | ||
| 813 | _resolve_deferred_defaults(function, argument_expressions.expressions, arguments, argument_types); | |
| 814 | ||
| 815 | if isa Semantic.Symbols.GENERIC(function.owner) then | |
| 816 | type_symbol = cast Semantic.Symbols.Symbol(function.owner); | |
| 817 | // The GENERIC owner of a resolved constructor always carries | |
| 818 | // a concrete type (the specialized class) by this point. | |
| 819 | type = function.owner.type; | |
| 820 | fi; | |
| 821 | ||
| 822 | let is_directly_owned mut = false; | |
| 823 | ||
| 824 | if isa Semantic.Symbols.GENERIC(type_symbol) /\ isa Semantic.Symbols.Symbol(function.owner) then | |
| 825 | is_directly_owned = type_symbol =~ cast Semantic.Symbols.Symbol(function.owner); | |
| 826 | else | |
| 827 | is_directly_owned = type_symbol == function.owner; | |
| 828 | fi | |
| 829 | ||
| 830 | if !is_directly_owned then | |
| 831 | _logger.error(location, "cannot call superclass constructor {function}"); | |
| 832 | fi | |
| 833 | ||
| 834 | _symbol_use_locations.add_symbol_use(right_location, function); | |
| 835 | _symbol_use_locations.add_symbol_use(right_location, type_symbol.root_unspecialized_symbol); | |
| 836 | ||
| 837 | if !was_generic_on_entry then | |
| 838 | if let constructed: Semantic.Types.GENERIC = type then | |
| 839 | if let generic_symbol: Semantic.Symbols.GENERIC = constructed.symbol then | |
| 840 | generic_symbol.symbol.check_argument_constraints(location, _logger, constructed.arguments); | |
| 841 | fi | |
| 842 | fi | |
| 843 | fi | |
| 844 | ||
| 845 | return (cast Value(Load.SYMBOL(null, function_group)), _function_caller.call_constructor(function, arguments, type)); | |
| 846 | si | |
| 847 | ||
| 848 | // True iff any formal arg in the resolver's PARTIAL function | |
| 849 | // is itself ERROR or contains an ERROR. Signal that the | |
| 850 | // partial binding was driven from a tainted lambda actual | |
| 851 | // (a typical free-function-with-lambda inference scenario) | |
| 852 | // and the PARTIAL formals shouldn't be pushed as constraints | |
| 853 | // unchanged. | |
| 854 | _partial_arguments_contain_error(function: Semantic.Symbols.Function) -> bool is | |
| 855 | if !function.are_arguments_declared then | |
| 856 | return false; | |
| 857 | fi | |
| 858 | ||
| 859 | let found = Ghul.BOX(false); | |
| 860 | ||
| 861 | for arg in function.arguments do | |
| 862 | arg.walk((t: Type) is | |
| 863 | if t.is_error then | |
| 864 | found.value = true; | |
| 865 | fi | |
| 866 | si); | |
| 867 | ||
| 868 | if found.value then | |
| 869 | return true; | |
| 870 | fi | |
| 871 | od | |
| 872 | ||
| 873 | return false; | |
| 874 | si | |
| 875 | ||
| 876 | // True iff any formal arg in the resolver's PARTIAL function | |
| 877 | // still references one of the function's own generic | |
| 878 | // type-variables (i.e. the resolver couldn't bind that slot | |
| 879 | // from any sibling actual). Same shape problem as | |
| 880 | // `_partial_arguments_contain_error`: pushing the formal as-is | |
| 881 | // burdens the lambda's re-walk with a constraint | |
| 882 | // (`int -> STEP[T]`) that can't be satisfied by anything | |
| 883 | // concrete the body produces. Re-specialise with phantoms in | |
| 884 | // those slots so the constraint pushed becomes | |
| 885 | // (`int -> STEP[<phantom>]`) — actually informative, and | |
| 886 | // open to match propagation from inside the body. | |
| 887 | _partial_arguments_contain_unbound_function_type_variable(function: Semantic.Symbols.Function) -> bool is | |
| 888 | let found = Ghul.BOX(false); | |
| 889 | ||
| 890 | for arg in function.arguments do | |
| 891 | arg.walk((t: Type) is | |
| 892 | if t.is_function_generic_argument then | |
| 893 | found.value = true; | |
| 894 | fi | |
| 895 | si); | |
| 896 | ||
| 897 | if found.value then | |
| 898 | return true; | |
| 899 | fi | |
| 900 | od | |
| 901 | ||
| 902 | return false; | |
| 903 | si | |
| 904 | ||
| 905 | // True if any of the actual argument expressions is a | |
| 906 | // Trees.Expressions.FUNCTION literal. Used to gate the | |
| 907 | // constraint-push retry on the recoverable case where a | |
| 908 | // not-yet-constrained lambda body walked with placeholder | |
| 909 | // args and produced an ERROR-tainted type that the under- | |
| 910 | // determination detector wouldn't otherwise recognise as | |
| 911 | // recoverable. | |
| 912 | // | |
| 913 | // Static so it can be exercised by unit tests with hand-built | |
| 914 | // expression lists, without spinning up COMPILE_CALLS's full | |
| 915 | // dependency graph. | |
| 916 | has_function_literal_argument(argument_expressions: Collections.List[Trees.Expressions.Expression]?) -> bool static is | |
| 917 | if !argument_expressions? then | |
| 918 | return false; | |
| 919 | fi | |
| 920 | ||
| 921 | for a in argument_expressions do | |
| 922 | if isa Trees.Expressions.FUNCTION(a) then | |
| 923 | return true; | |
| 924 | fi | |
| 925 | od | |
| 926 | ||
| 927 | return false; | |
| 928 | si | |
| 929 | ||
| 930 | // An empty array literal argument has no elements to infer its | |
| 931 | // element type from, so it walks to object[] and fails to match a | |
| 932 | // more specific array parameter. Like a function literal, it can be | |
| 933 | // re-walked under a pushed formal type, so it is a signal that a | |
| 934 | // null overload result might be recoverable. | |
| 935 | has_empty_array_literal_argument(argument_expressions: Collections.List[Trees.Expressions.Expression]?) -> bool static is | |
| 936 | if !argument_expressions? then | |
| 937 | return false; | |
| 938 | fi | |
| 939 | ||
| 940 | for a in argument_expressions do | |
| 941 | if let sequence: Trees.Expressions.SEQUENCE = a then | |
| 942 | if sequence.elements.expressions.count == 0 then | |
| 943 | return true; | |
| 944 | fi | |
| 945 | fi | |
| 946 | od | |
| 947 | ||
| 948 | return false; | |
| 949 | si | |
| 950 | ||
| 951 | // Walk the scope stack from current_function outward to find | |
| 952 | // the recursive closure a `rec` reference here would bind to. | |
| 953 | // Mirrors the lookup in `visit(RECURSE)`. | |
| 954 | _find_recursive_target() -> Semantic.Symbols.Closure? is | |
| 955 | let function = _symbol_table.current_function; | |
| 956 | ||
| 957 | if !function? \/ !function.is_closure then | |
| 958 | return null; | |
| 959 | fi | |
| 960 | ||
| 961 | let closure = cast Semantic.Symbols.Closure?(function)!; | |
| 962 | ||
| 963 | if closure.is_recursive then | |
| 964 | return closure; | |
| 965 | fi | |
| 966 | ||
| 967 | let stack = _symbol_table.stack; | |
| 968 | let index mut = stack.count - 1; | |
| 969 | let seen_self mut = false; | |
| 970 | ||
| 971 | while index >= 0 do | |
| 972 | let scope = stack[index]; | |
| 973 | ||
| 974 | if scope.is_closure then | |
| 975 | let c = cast Semantic.Symbols.Closure?(scope)!; | |
| 976 | ||
| 977 | if seen_self then | |
| 978 | if c.is_recursive then | |
| 979 | return c; | |
| 980 | fi | |
| 981 | elif c == closure then | |
| 982 | seen_self = true; | |
| 983 | fi | |
| 984 | fi | |
| 985 | ||
| 986 | index = index - 1; | |
| 987 | od | |
| 988 | ||
| 989 | return null; | |
| 990 | si | |
| 991 | ||
| 992 | // Push each actual argument of a `rec(actual...)` call onto | |
| 993 | // the recursive closure's parameter Variables as a LUB | |
| 994 | // candidate. When the actual isn't assignable to the | |
| 995 | // parameter's current type, reset that type back to an | |
| 996 | // INFERRED_VARIABLE_TYPE placeholder so the next outer-body | |
| 997 | // retry iteration's closure_arg_resolver re-derives the | |
| 998 | // parameter type from the widened LUB. Handles both self-rec | |
| 999 | // and nested-rec (rec referring to an outer recursive | |
| 1000 | // ancestor) — the target is determined by walking the | |
| 1001 | // closure stack mirroring `visit(RECURSE)`. | |
| 1002 | try_propagate_recursive_call_args(call: Trees.Expressions.CALL) is | |
| 1003 | if !isa Trees.Expressions.RECURSE(call.function) then | |
| 1004 | return; | |
| 1005 | fi | |
| 1006 | ||
| 1007 | let closure = _find_recursive_target(); | |
| 1008 | ||
| 1009 | if !closure? then | |
| 1010 | return; | |
| 1011 | fi | |
| 1012 | ||
| 1013 | let param_count = closure.argument_names.count; | |
| 1014 | let args = call.arguments.expressions; | |
| 1015 | let arg_count = args.count; | |
| 1016 | ||
| 1017 | let n = if param_count < arg_count then param_count else arg_count fi; | |
| 1018 | ||
| 1019 | let i mut = 0; | |
| 1020 | while i < n do | |
| 1021 | let name = closure.argument_names[i]; | |
| 1022 | let param = cast Semantic.Symbols.Variable?(closure.find_direct(name)); | |
| 1023 | let arg_expr = args[i]; | |
| 1024 | ||
| 1025 | // Prefer arg_expr.value.type, but fall back to the | |
| 1026 | // resolved symbol's type when the value's snapshot | |
| 1027 | // is null — happens for outer-scope locals captured | |
| 1028 | // into a nested closure before being typed. | |
| 1029 | let actual: Semantic.Types.Type? mut = null; | |
| 1030 | if let arg_expr?.value? /\ value.type? then | |
| 1031 | actual = value.type; | |
| 1032 | elif isa Trees.Expressions.IDENTIFIER(arg_expr) then | |
| 1033 | let id_expr = arg_expr; | |
| 1034 | let sym = _visitor.find(id_expr.identifier); | |
| 1035 | if sym? then | |
| 1036 | actual = sym.type; | |
| 1037 | fi | |
| 1038 | fi | |
| 1039 | ||
| 1040 | if param? /\ actual? then | |
| 1041 | if actual.is_settled then | |
| 1042 | _logger.mark_consumed_any_if(param.add_lower_bound(actual)); | |
| 1043 | ||
| 1044 | // Reset the param's type if currently | |
| 1045 | // resolved to something narrower than the | |
| 1046 | // actual — leaves it concrete when the | |
| 1047 | // actual fits. | |
| 1048 | if | |
| 1049 | param.type? /\ | |
| 1050 | !param.type.is_sentinel /\ | |
| 1051 | !param.type.is_assignable_from(actual) | |
| 1052 | then | |
| 1053 | param.set_type(Semantic.Types.INFERRED_VARIABLE_TYPE(param)); | |
| 1054 | _logger.mark_consumed_any(); | |
| 1055 | fi | |
| 1056 | fi | |
| 1057 | fi | |
| 1058 | ||
| 1059 | i = i + 1; | |
| 1060 | od | |
| 1061 | si | |
| 1062 | ||
| 1063 | // Constraint-push retry: when the first resolve fails AND | |
| 1064 | // there's exactly one arity-matching candidate AND at least | |
| 1065 | // one argument's first-walk type is under-determined for | |
| 1066 | // its corresponding formal type, push that candidate's | |
| 1067 | // formal arg types as constraints to each call argument | |
| 1068 | // and re-walk. This catches `apply(Box())` cases where a | |
| 1069 | // constructor argument's owner generic args were | |
| 1070 | // under-determined the first time round but become | |
| 1071 | // resolvable from the formal argument's type. The | |
| 1072 | // candidate's signature is the only signal we have for | |
| 1073 | // what the under-determined arg should resolve to — | |
| 1074 | // multi-candidate disambiguation under constraint push | |
| 1075 | // is left to a more general overload-as-constraint | |
| 1076 | // pass under #1174. | |
| 1077 | // Constraint-push retry for when the initial overload resolution | |
| 1078 | // returned null. Generalised over the source of the argument | |
| 1079 | // expressions: calls pass `call.arguments.expressions` / | |
| 1080 | // `call.arguments.location` / `call` as the cache key; binary | |
| 1081 | // operators pass `[left, right]`, `binary.location`, the BINARY | |
| 1082 | // node; unary operators pass `[right]`, `unary.location`, the | |
| 1083 | // UNARY node. Assumes the caller is inside a `_logger.speculate()` | |
| 1084 | // level: this method does `_logger.roll_back(); _logger.speculate();` | |
| 1085 | // to re-enter before re-walking, mirroring the visit_call wrapper. | |
| 1086 | try_overload_after_null( | |
| 1087 | function_group: Semantic.Symbols.FUNCTION_GROUP, | |
| 1088 | arguments: Collections.LIST[Value], | |
| 1089 | argument_types: Collections.LIST[Type], | |
| 1090 | want_instance: bool, | |
| 1091 | named_restrict: Collections.List[Semantic.Symbols.Function]?, | |
| 1092 | argument_expressions: Collections.List[Trees.Expressions.Expression], | |
| 1093 | argument_location: LOCATION, | |
| 1094 | cache_key: Trees.Node | |
| 1095 | ) -> Semantic.OVERLOAD_RESOLVE_RESULT? is | |
| 1096 | let candidate = _try_find_single_arity_candidate(function_group, argument_types.count, want_instance); | |
| 1097 | let effective_candidate = candidate ?? _delegate_push_candidates.find_single_pushable_candidate(function_group, argument_types, want_instance); | |
| 1098 | ||
| 1099 | // Trigger the retry when at least one actual | |
| 1100 | // is a FUNCTION literal even if its first-walk | |
| 1101 | // type has been ERROR-tainted by a body that | |
| 1102 | // walked without a constraint. The lambda can | |
| 1103 | // be re-walked under a pushed formal, so a | |
| 1104 | // FUNCTION arg is the natural signal that the | |
| 1105 | // null overload result might be recoverable. | |
| 1106 | // The pre-existing `any_arg_under_determined` | |
| 1107 | // path still covers the constructor-arg shape | |
| 1108 | // (e.g. `apply(Box())`). A named-delegate formal | |
| 1109 | // mismatched against a bare function-shaped actual | |
| 1110 | // (a named function reference, or a lambda that | |
| 1111 | // resolved to its own native shape) is the same kind | |
| 1112 | // of recoverable gap. | |
| 1113 | ||
| 1114 | if effective_candidate? /\ ( | |
| 1115 | _under_determination_detector.any_arg_under_determined(effective_candidate, argument_types) \/ | |
| 1116 | COMPILE_CALLS.has_function_literal_argument(argument_expressions) \/ | |
| 1117 | COMPILE_CALLS.has_empty_array_literal_argument(argument_expressions) \/ | |
| 1118 | _delegate_push_candidates.has_push_mismatch(effective_candidate, argument_types) | |
| 1119 | ) then | |
| 1120 | // Sibling-arg specialisation, symmetric to | |
| 1121 | // the path in `resolve_constructor`: when | |
| 1122 | // one actual is a not-yet-resolved FUNCTION | |
| 1123 | // literal AND the candidate has a generic | |
| 1124 | // owner, push specialised formals (bound | |
| 1125 | // from concrete sibling actuals) rather | |
| 1126 | // than unsubstituted formals containing | |
| 1127 | // free type variables that the lambda's | |
| 1128 | // argument-setup would reject as "type | |
| 1129 | // variable" anyway. Owners that aren't | |
| 1130 | // generic short-circuit inside | |
| 1131 | // OWNER_TYPE_ARG_SPECIALIZER and the | |
| 1132 | // pre-existing behaviour is preserved. | |
| 1133 | let push_candidate: Semantic.Symbols.Function? mut = effective_candidate; | |
| 1134 | ||
| 1135 | // Two-step specialisation: try | |
| 1136 | // owner-class generic args first (for | |
| 1137 | // method calls whose receiver class is | |
| 1138 | // generic), then if push_candidate is | |
| 1139 | // still the unsubstituted candidate and | |
| 1140 | // the candidate has its own generic | |
| 1141 | // args, try binding those from concrete | |
| 1142 | // siblings. The function-own path is | |
| 1143 | // what catches free-function HOFs like | |
| 1144 | // `generate[T,S]((0,1), state => ...)` — | |
| 1145 | // S binds from the (0,1) actual, T fills | |
| 1146 | // from a phantom, and the substituted | |
| 1147 | // formal-arg-type can then constrain the | |
| 1148 | // lambda's body re-walk. | |
| 1149 | push_candidate = _specialise_candidate_from_concrete_siblings(effective_candidate, argument_types, cache_key, argument_location); | |
| 1150 | ||
| 1151 | if push_candidate == effective_candidate /\ effective_candidate.is_generic then | |
| 1152 | let phantom_origins = _type_arg_placeholder_registry.get_or_create_for_function(cache_key, argument_location, effective_candidate); | |
| 1153 | push_candidate = _owner_type_arg_specializer.specialize_function_own_args_from_concrete_siblings(effective_candidate, argument_types, phantom_origins, argument_location); | |
| 1154 | fi | |
| 1155 | ||
| 1156 | _logger.roll_back(); | |
| 1157 | _logger.speculate(); | |
| 1158 | _flow.restore(); | |
| 1159 | ||
| 1160 | for (index, a) in argument_expressions |> index() do | |
| 1161 | let f = push_candidate!.arguments[index]; | |
| 1162 | ||
| 1163 | a.set_expected_type(f, "{{0}} is not assignable to {{1}}"); | |
| 1164 | ||
| 1165 | a.walk(_visitor); | |
| 1166 | ||
| 1167 | if let a.value? /\ value.type? /\ value.check_is_consumable(_logger, a.location) then | |
| 1168 | arguments[index] = value; | |
| 1169 | argument_types[index] = value.type!; | |
| 1170 | else | |
| 1171 | let t = Semantic.Types.ERROR(); | |
| 1172 | ||
| 1173 | arguments[index] = DUMMY(t, a.location); | |
| 1174 | argument_types[index] = t; | |
| 1175 | fi | |
| 1176 | od | |
| 1177 | ||
| 1178 | return _overload_resolver.resolve(argument_location, function_group, argument_types, true, want_instance, false, named_restrict); | |
| 1179 | fi | |
| 1180 | ||
| 1181 | return null; | |
| 1182 | si | |
| 1183 | ||
| 1184 | // PARTIAL re-specialisation: the resolver may | |
| 1185 | // have driven its type-arg binding from a | |
| 1186 | // tainted lambda actual whose body errored on | |
| 1187 | // the first walk (the free-function lambda- | |
| 1188 | // inference gap). Pushing those ERROR-bearing | |
| 1189 | // formals as constraints to the lambda would | |
| 1190 | // taint its re-walk too. Detect the case and | |
| 1191 | // re-specialise from CLEAN siblings via the | |
| 1192 | // function-own-args specialiser (which skips | |
| 1193 | // ERROR / placeholder-bearing actuals); push | |
| 1194 | // that cleaner form. | |
| 1195 | // | |
| 1196 | // Same shape for unbound function-own type | |
| 1197 | // variables: when the resolver couldn't bind a | |
| 1198 | // slot, the formal still contains the | |
| 1199 | // candidate's literal `T` / `S` /…, which is | |
| 1200 | // useless as a constraint downstream | |
| 1201 | // (literal `T` matches nothing concrete the | |
| 1202 | // body could produce). Re-specialise so those | |
| 1203 | // slots become phantoms — open to match propagation | |
| 1204 | // from inside the lambda body. | |
| 1205 | // PARTIAL-result retry. Generalised over the source of the | |
| 1206 | // argument expressions in the same way as `try_overload_after_null`. | |
| 1207 | // Assumes the caller is inside a `_logger.speculate()` level. | |
| 1208 | try_overload_on_partial( | |
| 1209 | overload_result: Semantic.OVERLOAD_RESOLVE_RESULT, | |
| 1210 | function_group: Semantic.Symbols.FUNCTION_GROUP, | |
| 1211 | arguments: Collections.LIST[Value], | |
| 1212 | argument_types: Collections.LIST[Type], | |
| 1213 | want_instance: bool, | |
| 1214 | named_restrict: Collections.List[Semantic.Symbols.Function]?, | |
| 1215 | argument_expressions: Collections.List[Trees.Expressions.Expression], | |
| 1216 | argument_location: LOCATION, | |
| 1217 | cache_key: Trees.Node | |
| 1218 | ) -> Semantic.OVERLOAD_RESOLVE_RESULT? is | |
| 1219 | let push_function mut = overload_result.function; | |
| 1220 | ||
| 1221 | if | |
| 1222 | _partial_arguments_contain_error(push_function) \/ | |
| 1223 | _partial_arguments_contain_unbound_function_type_variable(push_function) | |
| 1224 | then | |
| 1225 | let candidate = _try_find_single_arity_candidate(function_group, argument_types.count, want_instance); | |
| 1226 | ||
| 1227 | if candidate? /\ candidate.is_generic then | |
| 1228 | let phantom_origins = _type_arg_placeholder_registry.get_or_create_for_function(cache_key, argument_location, candidate); | |
| 1229 | let respecialized = _owner_type_arg_specializer.specialize_function_own_args_from_concrete_siblings(candidate, argument_types, phantom_origins, argument_location); | |
| 1230 | ||
| 1231 | if respecialized != candidate then | |
| 1232 | push_function = respecialized; | |
| 1233 | fi | |
| 1234 | fi | |
| 1235 | fi | |
| 1236 | ||
| 1237 | _logger.roll_back(); | |
| 1238 | _logger.speculate(); | |
| 1239 | _flow.restore(); | |
| 1240 | ||
| 1241 | for (index, a) in argument_expressions |> index() do | |
| 1242 | // A delegate formal is pushed onto any argument, not only | |
| 1243 | // a literal: an expression that merely contains literals | |
| 1244 | // (an `if` over two of them, say) forwards the constraint | |
| 1245 | // to them and joins at the delegate type. One that cannot | |
| 1246 | // act on it re-walks unchanged and is caught by the | |
| 1247 | // delegate check below. | |
| 1248 | if | |
| 1249 | a.value? /\ | |
| 1250 | ( | |
| 1251 | isa Trees.Expressions.FUNCTION(a) \/ | |
| 1252 | _delegate_shape.is_named_delegate(push_function.arguments[index]) | |
| 1253 | ) | |
| 1254 | then | |
| 1255 | let f = push_function.arguments[index]; | |
| 1256 | ||
| 1257 | a.set_expected_type(f, "{{0}} is not assignable to {{1}}"); | |
| 1258 | a.walk(_visitor); | |
| 1259 | ||
| 1260 | argument_types[index] = a.value!.type!; | |
| 1261 | else | |
| 1262 | // ensure any error messages are committed | |
| 1263 | a.walk(_visitor); | |
| 1264 | fi | |
| 1265 | ||
| 1266 | if a.value? then | |
| 1267 | arguments[index] = a.value; | |
| 1268 | fi | |
| 1269 | od | |
| 1270 | ||
| 1271 | // A delegate formal was matched partially on the strength of | |
| 1272 | // the actual being some function type, which only a literal | |
| 1273 | // can make good on - the re-walk above compiles a literal to | |
| 1274 | // the delegate and leaves anything else at its own type. | |
| 1275 | // Reject those here: letting one through would emit a value | |
| 1276 | // of one delegate type into a slot of another, which the CLR | |
| 1277 | // does not convert. | |
| 1278 | for (index, formal) in push_function.arguments |> index() do | |
| 1279 | if _delegate_shape.is_named_delegate(formal) /\ !formal.is_assignable_from(argument_types[index]) then | |
| 1280 | _logger.error( | |
| 1281 | argument_expressions[index].location, | |
| 1282 | "{argument_types[index]} is not assignable to {formal}"); | |
| 1283 | ||
| 1284 | return null; | |
| 1285 | fi | |
| 1286 | od | |
| 1287 | ||
| 1288 | return _overload_resolver.resolve(argument_location, function_group, argument_types, false, want_instance, false, named_restrict); | |
| 1289 | si | |
| 1290 | ||
| 1291 | visit_call(call: Trees.Expressions.CALL) is | |
| 1292 | // Recursive-call match propagation for self-recursive lambdas | |
| 1293 | // (`let f = x rec => ... rec(actual) ...`). The | |
| 1294 | // call-site match propagation below only widens a closure's | |
| 1295 | // argument type when the formal is still an | |
| 1296 | // INFERRED_VARIABLE_TYPE placeholder. For a rec call the | |
| 1297 | // formal is the closure's own parameter Variable, which | |
| 1298 | // by iter N is already resolved to (often the narrow) | |
| 1299 | // outer call-site type. Without further widening, a rec | |
| 1300 | // call with a wider actual fails type-check. | |
| 1301 | // | |
| 1302 | // Widen here: push each actual as a candidate on the | |
| 1303 | // closure parameter's LUB. When the actual isn't | |
| 1304 | // assignable to the current parameter type, reset the | |
| 1305 | // parameter's type back to a placeholder so the next | |
| 1306 | // outer-body-retry iteration's closure_arg_resolver pass | |
| 1307 | // re-derives from the now-wider LUB. | |
| 1308 | try_propagate_recursive_call_args(call); | |
| 1309 | ||
| 1310 | // Arity-aware refinement of MEMBER_CONSTRAINT for the | |
| 1311 | // `<placeholder>.<name>(args...)` shape. MEMBER.visit | |
| 1312 | // already emitted MEMBER_CONSTRAINT(name); pin the | |
| 1313 | // arity here so the resolved type must have `name` | |
| 1314 | // callable at this arg count, not merely present. The | |
| 1315 | // receiver may already have been ERROR-typed by | |
| 1316 | // MEMBER.visit's placeholder branch — read the *member's | |
| 1317 | // left*'s type to find the placeholder regardless. | |
| 1318 | if let member: Trees.Expressions.MEMBER = call.function then | |
| 1319 | if let member.left?, left.value? /\ value.type? then | |
| 1320 | if let placeholder: Semantic.Types.INFERRED_VARIABLE_TYPE = value.type then | |
| 1321 | let arity = call.arguments.count; | |
| 1322 | ||
| 1323 | _logger.mark_consumed_any_if(placeholder.origin.add_constraint( | |
| 1324 | Semantic.MEMBER_CONSTRAINT(member.identifier.name, arity) | |
| 1325 | )); | |
| 1326 | fi | |
| 1327 | fi | |
| 1328 | fi | |
| 1329 | ||
| 1330 | let function_value = call.function.value; | |
| 1331 | ||
| 1332 | if !function_value? \/ !function_value.type? then | |
| 1333 | call.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), call.location); | |
| 1334 | return; | |
| 1335 | fi | |
| 1336 | ||
| 1337 | // `|>` threads its subject in as the first argument, which is | |
| 1338 | // positional; it is spliced into the argument list but not into | |
| 1339 | // argument_names, so combining it with named written arguments | |
| 1340 | // is rejected rather than silently misaligned. Checked before | |
| 1341 | // the constructor dispatch below so it covers constructor calls | |
| 1342 | // too. | |
| 1343 | if call.is_thread_first /\ call.argument_names? then | |
| 1344 | _logger.error(call.location, "named arguments cannot be combined with |>"); | |
| 1345 | call.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), call.location); | |
| 1346 | return; | |
| 1347 | fi | |
| 1348 | ||
| 1349 | // Bare unit-variant accesses (`COLOR.RED`, `Option.NONE[int]`) | |
| 1350 | // already lowered to a NEW pointing at the singleton. Empty | |
| 1351 | // parens on top of that — `COLOR.RED()` — pass the value | |
| 1352 | // through; supplying any argument is an error because a unit | |
| 1353 | // variant carries no fields. Generic unit variants with the | |
| 1354 | // type arguments inferred from context still arrive as a | |
| 1355 | // TYPE_EXPRESSION (the lower step needs a constraint that | |
| 1356 | // only the parent has) and fall through to resolve_constructor. | |
| 1357 | if isa NEW(function_value) then | |
| 1358 | let new_value = cast NEW(function_value); | |
| 1359 | ||
| 1360 | if new_value.constructor.owner!.is_unit_variant then | |
| 1361 | if call.arguments.count == 0 then | |
| 1362 | call.compile_expressions_state.value = new_value; | |
| 1363 | return; | |
| 1364 | fi | |
| 1365 | ||
| 1366 | _logger.error( | |
| 1367 | call.location, | |
| 1368 | "unit variant {new_value.type} takes no arguments" | |
| 1369 | ); | |
| 1370 | ||
| 1371 | call.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), call.location); | |
| 1372 | return; | |
| 1373 | fi | |
| 1374 | fi | |
| 1375 | ||
| 1376 | if function_value.is_type_expression then | |
| 1377 | (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); | |
| 1378 | ||
| 1379 | return; | |
| 1380 | fi | |
| 1381 | ||
| 1382 | let arguments = Collections.LIST[Value](); | |
| 1383 | let argument_types = Collections.LIST[Type](); | |
| 1384 | ||
| 1385 | _compile_call_arguments(call.arguments, arguments, argument_types); | |
| 1386 | ||
| 1387 | // TODO handle if left is actually a type not a function or method | |
| 1388 | // in which case we should treat this as a constructor call | |
| 1389 | ||
| 1390 | // we could also treat consuming a bare type as a constructor call | |
| 1391 | // this would be done in the symbol loader | |
| 1392 | ||
| 1393 | let load_symbol: Semantic.Symbols.Symbol? mut = null; | |
| 1394 | ||
| 1395 | if let load: Load.SYMBOL = function_value then | |
| 1396 | load_symbol = load.symbol; | |
| 1397 | ||
| 1398 | if load_symbol.is_function_group then | |
| 1399 | let want_instance: bool mut; | |
| 1400 | ||
| 1401 | want_instance = | |
| 1402 | if load.from? then | |
| 1403 | load.from.is_consumable | |
| 1404 | else | |
| 1405 | _symbol_table.current_instance_context? | |
| 1406 | fi; | |
| 1407 | ||
| 1408 | let function_group = cast Semantic.Symbols.FUNCTION_GROUP?(load_symbol)!; | |
| 1409 | ||
| 1410 | let named_restrict: Collections.List[Semantic.Symbols.Function]? mut = null; | |
| 1411 | ||
| 1412 | if call.argument_names? then | |
| 1413 | let binding = _named_argument_binder.bind(call.arguments.location, function_group, call.argument_names, want_instance); | |
| 1414 | ||
| 1415 | if !binding? then | |
| 1416 | call.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), call.location); | |
| 1417 | return; | |
| 1418 | fi | |
| 1419 | ||
| 1420 | _apply_named_permutation(call.arguments, arguments, argument_types, binding.permutation, binding.targets[0]); | |
| 1421 | ||
| 1422 | named_restrict = binding.targets; | |
| 1423 | fi | |
| 1424 | ||
| 1425 | // Pass `call.expected_type` (the return-type context | |
| 1426 | // set by an enclosing assignment / return / typed | |
| 1427 | // initializer) so the resolver can tie-break | |
| 1428 | // between candidates with identical arg fit but | |
| 1429 | // different return types — e.g. | |
| 1430 | // `Tasks.TASK.from_exception(ex)` in a function | |
| 1431 | // returning `Tasks.TASK[int]` prefers the generic | |
| 1432 | // `from_exception[T]` overload over the non- | |
| 1433 | // generic one. | |
| 1434 | let overload_result mut = _overload_resolver.resolve(call.arguments.location, function_group, argument_types, true, want_instance, false, named_restrict, call.expected_type); | |
| 1435 | ||
| 1436 | if !overload_result? then | |
| 1437 | overload_result = try_overload_after_null(function_group, arguments, argument_types, want_instance, named_restrict, call.arguments.expressions, call.arguments.location, call); | |
| 1438 | fi | |
| 1439 | ||
| 1440 | if overload_result == null then | |
| 1441 | call.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), call.location); | |
| 1442 | return; | |
| 1443 | fi | |
| 1444 | ||
| 1445 | if overload_result.needs_retry then | |
| 1446 | overload_result = try_overload_on_partial(overload_result, function_group, arguments, argument_types, want_instance, named_restrict, call.arguments.expressions, call.arguments.location, call); | |
| 1447 | ||
| 1448 | if !overload_result? then | |
| 1449 | call.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), call.location); | |
| 1450 | return; | |
| 1451 | fi | |
| 1452 | fi | |
| 1453 | ||
| 1454 | let function = overload_result.function; | |
| 1455 | ||
| 1456 | _resolve_deferred_defaults(function, call.arguments.expressions, arguments, argument_types); | |
| 1457 | ||
| 1458 | _visitor.note_reference_arguments(call, function); | |
| 1459 | ||
| 1460 | if function.is_unsafe_constraints then | |
| 1461 | _logger.warn(call.location, "unchecked-constraints", "call to {function} has unchecked constraints"); | |
| 1462 | fi | |
| 1463 | ||
| 1464 | // A function whose type arguments were bound by | |
| 1465 | // inference keeps `is_generic` set with concrete | |
| 1466 | // `generic_arguments`; an explicitly specialized one | |
| 1467 | // has `is_generic` cleared and was already checked | |
| 1468 | // at `FUNCTION_GROUP.try_specialize`. | |
| 1469 | if | |
| 1470 | function.is_generic /\ | |
| 1471 | function.generic_arguments.count == function.generic_argument_names.count | |
| 1472 | then | |
| 1473 | Semantic.Symbols.GENERIC_CONSTRAINT_CHECKER().check_arguments( | |
| 1474 | call.location, | |
| 1475 | _logger, | |
| 1476 | function, | |
| 1477 | function.generic_argument_names, | |
| 1478 | function.generic_arguments | |
| 1479 | ); | |
| 1480 | fi | |
| 1481 | ||
| 1482 | let accessor_class = _symbol_table.current_accessor; | |
| 1483 | ||
| 1484 | if !function.is_accessible_to(accessor_class) then | |
| 1485 | _logger.error(call.function.location, "{function} is not accessible here"); | |
| 1486 | fi | |
| 1487 | ||
| 1488 | _symbol_use_locations.add_symbol_use(call.function.right_location, function); | |
| 1489 | ||
| 1490 | // A callee selected through `?.` short-circuits | |
| 1491 | // the whole call - argument evaluation included - | |
| 1492 | // on an absent receiver, so the call value is | |
| 1493 | // built inside the coalescing wrap against the | |
| 1494 | // unwrapped receiver. A static callee never | |
| 1495 | // consumes the tested receiver. | |
| 1496 | let coalesce_member = _try_coalescing_member(call); | |
| 1497 | ||
| 1498 | if coalesce_member? then | |
| 1499 | let wrapped = _access.build_coalesce_wrap( | |
| 1500 | coalesce_member, | |
| 1501 | function.is_instance, | |
| 1502 | from => function.call(call.function.location, from, arguments, null, _function_caller) | |
| 1503 | ); | |
| 1504 | ||
| 1505 | if wrapped? then | |
| 1506 | call.compile_expressions_state.value = wrapped; | |
| 1507 | return; | |
| 1508 | fi | |
| 1509 | fi | |
| 1510 | ||
| 1511 | // A static call has no receiver value of its own - | |
| 1512 | // `load.from` is always null - but a static virtual | |
| 1513 | // interface member reached through a bound type | |
| 1514 | // parameter (`T.parse(...)`) needs the qualifier's | |
| 1515 | // type to emit the CLR's `constrained.` call shape. | |
| 1516 | // Recover it from the callee expression's own left | |
| 1517 | // operand rather than through the discarded static | |
| 1518 | // load, since only a type-variable qualifier is | |
| 1519 | // ever relevant here. | |
| 1520 | let call_receiver: Value? mut = load.from; | |
| 1521 | ||
| 1522 | if !call_receiver? then | |
| 1523 | if let member: Trees.Expressions.MEMBER = call.function then | |
| 1524 | if let left_type: Type = member.left.value?.type /\ left_type.is_type_variable then | |
| 1525 | call_receiver = member.left.value; | |
| 1526 | fi | |
| 1527 | fi | |
| 1528 | fi | |
| 1529 | ||
| 1530 | call.compile_expressions_state.value = function.call(call.function.location, call_receiver, arguments, null, _function_caller); | |
| 1531 | return; | |
| 1532 | fi | |
| 1533 | fi | |
| 1534 | ||
| 1535 | let function_type = function_value.type; | |
| 1536 | ||
| 1537 | // Run before the is_error check below so a callee whose | |
| 1538 | // return-slot is ERROR but whose formal-arg slots still | |
| 1539 | // carry placeholders gets its placeholders fed (e.g. | |
| 1540 | // `x => x.length` has an ERROR-typed body but its arg | |
| 1541 | // slot is recoverable once a call site supplies the | |
| 1542 | // actual). | |
| 1543 | if isa Semantic.Types.NAMED(function_type) then | |
| 1544 | _propagate_to_placeholder_formals(function_type, argument_types, arguments.count); | |
| 1545 | fi | |
| 1546 | ||
| 1547 | // Only short-circuit when the receiver is itself the ERROR | |
| 1548 | // sentinel — not when an ERROR sits inside an otherwise-usable | |
| 1549 | // function shape (`Function[good_formals, ERROR_return]`). | |
| 1550 | // For composites the formal-arg slots are still known, so the | |
| 1551 | // result-type path below can propagate a usable Function shape | |
| 1552 | // to the let-init binding. The body-retry loop can then back- | |
| 1553 | // feed actuals onto placeholder formals on the next iteration. | |
| 1554 | if function_type? /\ isa Semantic.Types.ERROR(function_type) then | |
| 1555 | call.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), call.location); | |
| 1556 | return; | |
| 1557 | elif isa Semantic.Types.INFERRED_VARIABLE_TYPE(function_type) then | |
| 1558 | _propagate_to_unresolved_callee(function_type, argument_types); | |
| 1559 | call.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), call.location); | |
| 1560 | return; | |
| 1561 | elif !function_type? \/ !isa Semantic.Types.NAMED(function_type) then | |
| 1562 | _logger.error(call.function.location, "cannot call value of non-function type {function_value.type}"); | |
| 1563 | call.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), call.location); | |
| 1564 | return; | |
| 1565 | fi | |
| 1566 | ||
| 1567 | let function_generic_type = function_type; | |
| 1568 | ||
| 1569 | let function_type_arguments = function_generic_type.arguments; | |
| 1570 | ||
| 1571 | if call.argument_names? /\ (function_type.is_action \/ function_type.is_function) then | |
| 1572 | _logger.error(call.location, "cannot supply argument names here"); | |
| 1573 | call.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), call.location); | |
| 1574 | return; | |
| 1575 | fi | |
| 1576 | ||
| 1577 | if function_type.is_action then | |
| 1578 | if function_type_arguments.count != arguments.count then | |
| 1579 | _logger.error( | |
| 1580 | call.arguments.location, | |
| 1581 | "expected {function_type_arguments.count} arguments but {arguments.count} supplied"); | |
| 1582 | call.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), call.location); | |
| 1583 | return; | |
| 1584 | fi | |
| 1585 | elif function_type.is_function then | |
| 1586 | if function_type_arguments.count != arguments.count + 1 then | |
| 1587 | _logger.error( | |
| 1588 | call.arguments.location, | |
| 1589 | "expected {function_type_arguments.count - 1} arguments but {arguments.count} supplied"); | |
| 1590 | call.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), call.location); | |
| 1591 | return; | |
| 1592 | fi | |
| 1593 | else | |
| 1594 | if load_symbol? /\ load_symbol.is_type then | |
| 1595 | (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); | |
| 1596 | else | |
| 1597 | _logger.error(call.function.location, "cannot call value of non-function type {function_value.type}"); | |
| 1598 | call.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), call.location); | |
| 1599 | fi | |
| 1600 | ||
| 1601 | return; | |
| 1602 | fi | |
| 1603 | ||
| 1604 | let ok mut = true; | |
| 1605 | ||
| 1606 | for i in 0..arguments.count do | |
| 1607 | // Back-feed BEFORE the compare so a Closure-call with | |
| 1608 | // a placeholder parameter type (`let f = x => ...; f(1)`) | |
| 1609 | // propagates the actual's concrete type to the | |
| 1610 | // placeholder's origin. The body retry loop's next | |
| 1611 | // iteration then sees a concrete x's-type and walks | |
| 1612 | // the lambda body cleanly. Without this the call path | |
| 1613 | // validated types but propagated nothing — local | |
| 1614 | // lambdas with use-site-only constraints failed to | |
| 1615 | // converge. | |
| 1616 | _overload_resolver.match_propagator.propagate_match(function_generic_type.arguments[i], argument_types[i]); | |
| 1617 | ||
| 1618 | if cast int(function_generic_type.arguments[i].compare(argument_types[i])) > cast int(Semantic.Types.MATCH.CONVERTABLE) | |
| 1619 | then | |
| 1620 | ok = false; | |
| 1621 | _logger.error(call.arguments.expressions[i].location, "expected argument of type {function_type_arguments[i]} but {argument_types[i]} supplied"); | |
| 1622 | fi | |
| 1623 | od | |
| 1624 | ||
| 1625 | if !ok then | |
| 1626 | call.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), call.location); | |
| 1627 | return; | |
| 1628 | fi | |
| 1629 | ||
| 1630 | let result_type = | |
| 1631 | if function_type.is_action then | |
| 1632 | _innate_symbol_lookup.get_void_type(); | |
| 1633 | else | |
| 1634 | function_generic_type.arguments[function_type_arguments.count - 1]; | |
| 1635 | fi; | |
| 1636 | ||
| 1637 | // A function-typed member selected through `?.` arrives | |
| 1638 | // as a COALESCE_LOAD of the delegate; invoking that | |
| 1639 | // result would call through the null the absent arm | |
| 1640 | // produces. Re-seat the invocation inside the | |
| 1641 | // short-circuit arm instead, consuming the member load | |
| 1642 | // where the receiver is known present. With a statically | |
| 1643 | // present receiver the member value is the plain delegate | |
| 1644 | // load - invoke it directly and widen the result to the | |
| 1645 | // optional shape the `?.` asked for. | |
| 1646 | if _try_coalescing_member(call)? then | |
| 1647 | if let original: IR.Values.COALESCE_LOAD = function_value then | |
| 1648 | let arm_call = Call.CLOSURE( | |
| 1649 | original.member_load, | |
| 1650 | result_type, | |
| 1651 | function_type.is_action, | |
| 1652 | function_generic_type, | |
| 1653 | arguments | |
| 1654 | ); | |
| 1655 | ||
| 1656 | let rewrapped = _access.rewrap_coalesce_call(original, arm_call); | |
| 1657 | ||
| 1658 | if rewrapped? then | |
| 1659 | call.compile_expressions_state.value = rewrapped; | |
| 1660 | return; | |
| 1661 | fi | |
| 1662 | else | |
| 1663 | let direct = Call.CLOSURE( | |
| 1664 | function_value, | |
| 1665 | result_type, | |
| 1666 | function_type.is_action, | |
| 1667 | function_generic_type, | |
| 1668 | arguments | |
| 1669 | ); | |
| 1670 | ||
| 1671 | let widened = _access.widen_coalesce_result(direct); | |
| 1672 | ||
| 1673 | call.compile_expressions_state.value = | |
| 1674 | if widened? then widened else direct fi; | |
| 1675 | ||
| 1676 | return; | |
| 1677 | fi | |
| 1678 | fi | |
| 1679 | ||
| 1680 | call.compile_expressions_state.value = | |
| 1681 | Call.CLOSURE( | |
| 1682 | call.function.value!, | |
| 1683 | result_type, | |
| 1684 | function_type.is_action, | |
| 1685 | function_generic_type, | |
| 1686 | arguments | |
| 1687 | ); | |
| 1688 | si | |
| 1689 | ||
| 1690 | // The MEMBER at call.function when this call selects its | |
| 1691 | // callee through `?.` - the shape whose short-circuit is | |
| 1692 | // lowered here at the call rather than at the member access. | |
| 1693 | _try_coalescing_member(call: Trees.Expressions.CALL) -> Trees.Expressions.MEMBER? is | |
| 1694 | let member = cast Trees.Expressions.MEMBER?(call.function); | |
| 1695 | ||
| 1696 | if member? /\ member.is_coalesce then | |
| 1697 | return member; | |
| 1698 | fi | |
| 1699 | ||
| 1700 | return null; | |
| 1701 | si | |
| 1702 | ||
| 1703 | // For a function-typed callee whose formal slots include | |
| 1704 | // INFERRED_VARIABLE_TYPE placeholders (typically a let-bound | |
| 1705 | // lambda whose arg types couldn't be pinned from the body | |
| 1706 | // alone), push the corresponding actual arg type onto each | |
| 1707 | // placeholder formal's origin Variable as a lower bound. The | |
| 1708 | // body-retry loop's next iteration then sees the placeholder | |
| 1709 | // resolved and walks the lambda body cleanly. | |
| 1710 | // | |
| 1711 | // Closed-root alternatives — union variants or subclasses | |
| 1712 | // of a closed class — are widened to their root before | |
| 1713 | // being pushed (see `INFERENCE_HELPERS.widen_to_closed_root`) | |
| 1714 | // to keep the lambda-arg LUB monotonic across siblings from | |
| 1715 | // different call sites. | |
| 1716 | _propagate_to_placeholder_formals( | |
| 1717 | function_type: Semantic.Types.Type, | |
| 1718 | argument_types: Collections.List[Semantic.Types.Type], | |
| 1719 | argument_count: int | |
| 1720 | ) is | |
| 1721 | let ft_named = cast Semantic.Types.NAMED?(function_type)!; | |
| 1722 | let ft_args = ft_named.arguments; | |
| 1723 | let formal_count = | |
| 1724 | if function_type.is_function then | |
| 1725 | ft_args.count - 1; | |
| 1726 | else | |
| 1727 | ft_args.count; | |
| 1728 | fi; | |
| 1729 | ||
| 1730 | if formal_count != argument_count then | |
| 1731 | return; | |
| 1732 | fi | |
| 1733 | ||
| 1734 | for i in 0..argument_count do | |
| 1735 | let formal = ft_args[i]; | |
| 1736 | let actual = argument_types[i]; | |
| 1737 | ||
| 1738 | if isa Semantic.Types.INFERRED_VARIABLE_TYPE(formal) then | |
| 1739 | let placeholder = formal; | |
| 1740 | let push_actual = Semantic.INFERENCE_HELPERS.widen_to_closed_root(actual)!; | |
| 1741 | _logger.mark_consumed_any_if(placeholder.origin.add_lower_bound(push_actual)); | |
| 1742 | fi | |
| 1743 | od | |
| 1744 | si | |
| 1745 | ||
| 1746 | // When the call's receiver is itself an unresolved placeholder | |
| 1747 | // (`let f = ...; f(1)` while `f`'s body is still settling, or | |
| 1748 | // mutually-recursive lambdas where each side's signature | |
| 1749 | // depends on the other), record two constraints on the | |
| 1750 | // placeholder's origin: | |
| 1751 | // | |
| 1752 | // 1. A synthesised function-type shape from the actual arg | |
| 1753 | // types + a deferred return type, as a lower bound, so | |
| 1754 | // the next iteration sees the receiver resolved to a | |
| 1755 | // function type and the call can compile. Skipped when | |
| 1756 | // the LUB already has a candidate (typically from a | |
| 1757 | // direct `v = <lambda>` assignment in the same body) — | |
| 1758 | // the call's actual arg types may differ from the | |
| 1759 | // assigned shape and the per-position merge can't bridge | |
| 1760 | // them, leaving an ambiguous pair in the pool. | |
| 1761 | // | |
| 1762 | // 2. A CALL_CONSTRAINT capturing the actual arg types | |
| 1763 | // unconditionally, so the constraint-aware LUB can later | |
| 1764 | // filter candidate types to those that actually accept | |
| 1765 | // this call shape. Its discharge defers conservatively | |
| 1766 | // when the captured args still contain placeholders. | |
| 1767 | _propagate_to_unresolved_callee( | |
| 1768 | placeholder: Semantic.Types.INFERRED_VARIABLE_TYPE, | |
| 1769 | argument_types: Collections.List[Semantic.Types.Type] | |
| 1770 | ) is | |
| 1771 | if !placeholder.origin.has_lub_candidate /\ argument_types |> all(a => a.is_settled) then | |
| 1772 | let function_type_components = Collections.LIST[Semantic.Types.Type](argument_types); | |
| 1773 | function_type_components.add(Semantic.Types.INFERRED_RETURN_TYPE()); | |
| 1774 | let synthesized = _innate_symbol_lookup.get_function_type(function_type_components); | |
| 1775 | _logger.mark_consumed_any_if(placeholder.origin.add_lower_bound(synthesized)); | |
| 1776 | fi | |
| 1777 | ||
| 1778 | let call_args = Collections.LIST[Semantic.Types.Type](argument_types); | |
| 1779 | _logger.mark_consumed_any_if(placeholder.origin.add_constraint(Semantic.CALL_CONSTRAINT(call_args))); | |
| 1780 | si | |
| 1781 | si | |
| 1782 | si |