lib/std/lang/resolver/printer.rad 24.6 KiB raw
1
//! Resolver scope printer.
2
use std::io;
3
use std::lang::ast;
4
use std::lang::types;
5
use std::lang::scanner;
6
use std::lang::module;
7
8
/// Print a span in `@offset:length` form.
9
fn printSpan(span: ast::Span) {
10
    io::print("@");
11
    io::printU32(span.offset);
12
    io::print(":");
13
    io::printU32(span.length);
14
}
15
16
/// Print a count mismatch message: `<prefix>: <verb> <expected>, got <actual>`.
17
fn printMismatch(prefix: *[u8], verb: *[u8], m: super::CountMismatch) {
18
    io::print(prefix);
19
    io::print(": ");
20
    io::print(verb);
21
    io::print(" ");
22
    io::printU32(m.expected);
23
    io::print(", got ");
24
    io::printU32(m.actual);
25
}
26
27
/// Print `<prefix>'<name>'`.
28
fn printQuoted(prefix: *[u8], name: *[u8]) {
29
    io::print(prefix);
30
    io::print(name);
31
    io::print("'");
32
}
33
34
/// Print a pointer-like type prefix.
35
unsafe fn printPtrPrefix(class: types::PointerClass, mutable: bool) {
36
    match class {
37
        case types::PointerClass::Owned => io::print("*"),
38
        case types::PointerClass::Ref => io::print("&"),
39
        case types::PointerClass::Region(region) => {
40
            io::print("&");
41
            io::print(region.name);
42
            io::print(" ");
43
        }
44
        case types::PointerClass::Unsafe => io::print("*unsafe "),
45
    }
46
    if mutable {
47
        io::print("mut ");
48
    }
49
}
50
51
/// Print a resolved type in a textual form.
52
unsafe fn printType(ty: super::Type) {
53
    printTypeBody(ty, false);
54
}
55
56
/// Print just the type name without detailed structure info.
57
unsafe fn printTypeName(ty: super::Type) {
58
    printTypeBody(ty, true);
59
}
60
61
/// Print a resolved type, optionally abbreviated for function signatures.
62
unsafe fn printTypeBody(ty: super::Type, brief: bool) {
63
    match ty {
64
        case super::Type::Unknown => {
65
            io::print("<unknown>");
66
        }
67
        case super::Type::Undefined => {
68
            io::print("<undefined>");
69
        }
70
        case super::Type::Int => {
71
            io::print("<int>");
72
        }
73
        case super::Type::Nil => {
74
            io::print("<nil>");
75
        }
76
        case super::Type::Opaque => {
77
            io::print("opaque");
78
        }
79
        case super::Type::Never => {
80
            io::print("!");
81
        }
82
        case super::Type::Void => {
83
            io::print("void");
84
        }
85
        case super::Type::Bool => {
86
            io::print("bool");
87
        }
88
        case super::Type::U8 => {
89
            io::print("u8");
90
        }
91
        case super::Type::U16 => {
92
            io::print("u16");
93
        }
94
        case super::Type::U32 => {
95
            io::print("u32");
96
        }
97
        case super::Type::U64 => {
98
            io::print("u64");
99
        }
100
        case super::Type::I8 => {
101
            io::print("i8");
102
        }
103
        case super::Type::I16 => {
104
            io::print("i16");
105
        }
106
        case super::Type::I32 => {
107
            io::print("i32");
108
        }
109
        case super::Type::I64 => {
110
            io::print("i64");
111
        }
112
        case super::Type::Cell { class, payload } => {
113
            printPtrPrefix(class, false);
114
            io::print("cell ");
115
            printTypeBody(*payload, brief);
116
        }
117
        case super::Type::Session(region) => {
118
            io::print("Session ");
119
            io::print(region.name);
120
        }
121
        case super::Type::Pointer { class, target, mutable } => {
122
            printPtrPrefix(class, mutable);
123
            printTypeBody(*target, brief);
124
        }
125
        case super::Type::Slice { class, item, mutable } => {
126
            printPtrPrefix(class, mutable);
127
            io::print("[");
128
            printTypeBody(*item, brief);
129
            io::print("]");
130
        }
131
        case super::Type::Array(array) => {
132
            io::print("[");
133
            printTypeBody(*array.item, brief);
134
            io::print("; ");
135
            io::printU32(array.length);
136
            io::print("]");
137
        }
138
        case super::Type::Optional(inner) => {
139
            io::print("?");
140
            printTypeBody(*inner, brief);
141
        }
142
        case super::Type::Fn(fnType) => {
143
            if fnType.isUnsafe {
144
                io::print("unsafe ");
145
            }
146
            io::print("fn(");
147
            for paramType, i in fnType.paramTypes {
148
                if i > 0 {
149
                    io::print(", ");
150
                }
151
                printTypeName(*paramType);
152
            }
153
            io::print(")");
154
            io::print(" -> ");
155
            printTypeName(*fnType.returnType);
156
            if fnType.throwList.len > 0 {
157
                io::print(" throws ");
158
                for throwType, i in fnType.throwList {
159
                    if i > 0 {
160
                        io::print(", ");
161
                    }
162
                    printTypeName(*throwType);
163
                }
164
            }
165
        }
166
        case super::Type::Nominal(info) => {
167
            if brief {
168
                printNominalTypeName(info);
169
            } else {
170
                printNominalType(info);
171
            }
172
        }
173
        case super::Type::TraitObject { class, traitInfo, mutable } => {
174
            printPtrPrefix(class, mutable);
175
            io::print("opaque ");
176
            io::print(traitInfo.name);
177
        }
178
        case super::Type::Range { start, end } => {
179
            if let s = start {
180
                printTypeBody(*s, brief);
181
            }
182
            io::print("..");
183
            if let e = end {
184
                printTypeBody(*e, brief);
185
            }
186
        }
187
    }
188
}
189
190
/// Print detailed information about a nominal type (record or union).
191
unsafe fn printNominalType(info: *unsafe super::NominalType) {
192
    match *info {
193
        case super::NominalType::Placeholder(_), super::NominalType::Resolving(_) => {
194
            io::print("<placeholder>");
195
        }
196
        case super::NominalType::Application(applied) => {
197
            printNominalTypeName(applied.base);
198
            printNominalArguments(applied);
199
        }
200
        case super::NominalType::Record(recordType) => {
201
            io::print("record {");
202
            if recordType.fields.len > 0 {
203
                io::print(" ");
204
                for i in 0..recordType.fields.len {
205
                    if i > 0 {
206
                        io::print(", ");
207
                    }
208
                    let field = &recordType.fields[i];
209
                    if let name = field.name {
210
                        io::print(name);
211
                        io::print(": ");
212
                    }
213
                    printTypeName(field.fieldType);
214
215
                    if i >= 4 and i < recordType.fields.len - 1 {
216
                        io::print(", ...");
217
                        break;
218
                    }
219
                }
220
                io::print(" ");
221
            }
222
            io::print("}");
223
        }
224
        case super::NominalType::Union(unionType) => {
225
            io::print("union {");
226
            if unionType.variants.len > 0 {
227
                io::print(" ");
228
                for i in 0..unionType.variants.len {
229
                    if i > 0 {
230
                        io::print(", ");
231
                    }
232
                    let variant = &unionType.variants[i];
233
                    io::print(variant.name);
234
                    io::print(": ");
235
                    printTypeName(variant.valueType);
236
237
                    if i >= 4 and i < unionType.variants.len - 1 {
238
                        io::print(", ...");
239
                        break;
240
                    }
241
                }
242
                io::print(" ");
243
            }
244
            io::print("}");
245
        }
246
    }
247
    if let applied = super::nominalApplication(info) {
248
        if let case super::NominalType::Application(_) = *info {
249
            return;
250
        }
251
        printNominalArguments(applied);
252
    }
253
}
254
255
/// Print just the type kind for a nominal type, without detailed info.
256
unsafe fn printNominalTypeName(info: *unsafe super::NominalType) {
257
    match *info {
258
        case super::NominalType::Placeholder(_), super::NominalType::Resolving(_) => {
259
            io::print("<placeholder>");
260
        }
261
        case super::NominalType::Application(applied) => {
262
            printNominalTypeName(applied.base);
263
            printNominalArguments(applied);
264
        }
265
        case super::NominalType::Record(_) => {
266
            io::print("<record>");
267
        }
268
        case super::NominalType::Union(_) => {
269
            io::print("<union>");
270
        }
271
    }
272
    if let applied = super::nominalApplication(info) {
273
        if let case super::NominalType::Application(_) = *info {
274
            return;
275
        }
276
        printNominalArguments(applied);
277
    }
278
}
279
280
/// Print a single diagnostic entry.
281
unsafe fn printError 'arena (err: &super::Error, res: &super::Resolver 'arena) {
282
    if let node = err.node {
283
        // Find the module containing this error.
284
        if let moduleEntry = super::moduleFor(res, err.moduleId) {
285
            // Get the source text if available.
286
            if let source = module::sourceFor(moduleEntry) {
287
                // Convert offset to location.
288
                if let loc = scanner::getLocation(scanner::SourceLoc::File(moduleEntry.filePath), source, node.span.offset) {
289
                    // Print: filename:line:col: error: message
290
                    if let case scanner::SourceLoc::File(path) = loc.source {
291
                        io::print(path);
292
                        io::print(":");
293
                    }
294
                    io::printU32(loc.line as u32);
295
                    io::print(":");
296
                    io::printU32(loc.col as u32);
297
                    io::print(": error: ");
298
                } else {
299
                    io::print("error ");
300
                    io::print(" ");
301
                    printSpan(node.span);
302
                    io::print(": ");
303
                }
304
            } else {
305
                io::print(moduleEntry.name);
306
                io::print(": ");
307
                io::print("error ");
308
                io::print(" ");
309
                printSpan(node.span);
310
                io::print(": ");
311
            }
312
        }
313
    } else {
314
        io::print("error: ");
315
    }
316
317
    // Print the error message.
318
    match err.kind {
319
        case super::ErrorKind::TypeMismatch(mismatch) => {
320
            io::print("type mismatch: expected ");
321
            printType(mismatch.expected);
322
            io::print(", got ");
323
            printType(mismatch.actual);
324
        }
325
        case super::ErrorKind::UnresolvedSymbol(name) => {
326
            printQuoted("unresolved symbol '", name);
327
        }
328
        case super::ErrorKind::DuplicateBinding(name) => {
329
            printQuoted("duplicate binding '", name);
330
        }
331
        case super::ErrorKind::FnArgCountMismatch(m) =>
332
            printMismatch("function argument count mismatch", "expected", m),
333
        case super::ErrorKind::FnThrowCountMismatch(m) =>
334
            printMismatch("function throws count mismatch", "expected", m),
335
        case super::ErrorKind::RecordFieldCountMismatch(m) =>
336
            printMismatch("record field count mismatch", "expected", m),
337
        case super::ErrorKind::RecordFieldMissing(name) => {
338
            printQuoted("record field missing: '", name);
339
        }
340
        case super::ErrorKind::RecordFieldUnknown(name) => {
341
            printQuoted("record field unknown: '", name);
342
        }
343
        case super::ErrorKind::InvalidAsCast(info) => {
344
            io::print("invalid cast: cannot cast ");
345
            printType(info.from);
346
            io::print(" to ");
347
            printType(info.to);
348
        }
349
        case super::ErrorKind::ExpectedIterable => {
350
            io::print("expected iterable type");
351
        }
352
        case super::ErrorKind::FnMissingReturn => {
353
            io::print("function must return a value on all paths");
354
        }
355
        case super::ErrorKind::UnionMatchNonExhaustive(name) => {
356
            printQuoted("union match non-exhaustive: missing case for variant '", name);
357
        }
358
        case super::ErrorKind::OptionalMatchMissingValue => {
359
            io::print("optional match non-exhaustive: missing value case");
360
        }
361
        case super::ErrorKind::OptionalMatchMissingNil => {
362
            io::print("optional match non-exhaustive: missing nil case");
363
        }
364
        case super::ErrorKind::BoolMatchMissing(val) => {
365
            io::print("bool match non-exhaustive: missing case for `");
366
            io::print("true" if val else "false");
367
            io::print("`");
368
        }
369
        case super::ErrorKind::MatchNonExhaustive => {
370
            io::print("match non-exhaustive: requires `else` or binding catch-all");
371
        }
372
        case super::ErrorKind::DuplicateCatchAll => {
373
            io::print("match has multiple catch-all prongs");
374
        }
375
        case super::ErrorKind::DuplicateMatchPattern => {
376
            io::print("match has duplicate pattern");
377
        }
378
        case super::ErrorKind::UnreachableElse => {
379
            io::print("match has unreachable `else`, all cases are already handled");
380
        }
381
        case super::ErrorKind::ImmutableBinding => {
382
            io::print("cannot assign to immutable binding");
383
        }
384
        case super::ErrorKind::ConstExprRequired => {
385
            io::print("expected compile-time constant expression");
386
        }
387
        case super::ErrorKind::SymbolOverflow => {
388
            io::print("symbol arena overflow");
389
        }
390
        case super::ErrorKind::NumericLiteralOverflow => {
391
            io::print("numeric literal overflow");
392
        }
393
        case super::ErrorKind::RecordFieldStyleMismatch => {
394
            io::print("brace syntax not allowed for tuple-style records");
395
        }
396
        case super::ErrorKind::ExpectedIdentifier => {
397
            io::print("expected identifier");
398
        }
399
        case super::ErrorKind::ExpectedOptional => {
400
            io::print("expected optional type");
401
        }
402
        case super::ErrorKind::ExpectedNumeric => {
403
            io::print("expected numeric type");
404
        }
405
        case super::ErrorKind::ExpectedPointer => {
406
            io::print("expected pointer type");
407
        }
408
        case super::ErrorKind::InvalidSliceAllocator => {
409
            io::print("expected allocator with func callback and matching opaque ctx pointer");
410
        }
411
        case super::ErrorKind::ExpectedRecord => {
412
            io::print("expected record type");
413
        }
414
        case super::ErrorKind::ExpectedIndexable => {
415
            io::print("expected array or slice");
416
        }
417
        case super::ErrorKind::InvalidAlignmentValue(val) => {
418
            io::print("invalid alignment value: ");
419
            io::printU32(val);
420
        }
421
        case super::ErrorKind::InvalidModulePath => {
422
            io::print("invalid module path");
423
        }
424
        case super::ErrorKind::InvalidIdentifier(_) => {
425
            io::print("invalid identifier");
426
        }
427
        case super::ErrorKind::InvalidScopeAccess => {
428
            io::print("invalid scope access");
429
        }
430
        case super::ErrorKind::ArrayFieldUnknown(name) => {
431
            printQuoted("array field unknown: '", name);
432
        }
433
        case super::ErrorKind::SliceFieldUnknown(name) => {
434
            printQuoted("slice field unknown: '", name);
435
        }
436
        case super::ErrorKind::SliceRequiresAddress => {
437
            io::print("slicing requires taking an address with '&'");
438
        }
439
        case super::ErrorKind::SliceRangeOutOfBounds => {
440
            io::print("slice bounds exceed array length");
441
        }
442
        case super::ErrorKind::UnexpectedReturn => {
443
            io::print("unexpected return statement");
444
        }
445
        case super::ErrorKind::UnexpectedNode(n) => {
446
            io::print("unexpected expression");
447
        }
448
        case super::ErrorKind::UnexpectedModuleName => {
449
            io::print("unexpected module name");
450
        }
451
        case super::ErrorKind::FnMissingBody => {
452
            io::print("function is missing a body");
453
        }
454
        case super::ErrorKind::FnUnexpectedBody => {
455
            io::print("function body is not expected");
456
        }
457
        case super::ErrorKind::IntrinsicUnexpectedBody => {
458
            io::print("intrinsic function must not have a body");
459
        }
460
        case super::ErrorKind::InvalidLoopControl => {
461
            io::print("loop control outside of a loop construct");
462
        }
463
        case super::ErrorKind::TryRequiresThrows => {
464
            io::print("try used when function does not declare throws");
465
        }
466
        case super::ErrorKind::TryIncompatibleError => {
467
            io::print("try propagates error not declared by function");
468
        }
469
        case super::ErrorKind::ThrowRequiresThrows => {
470
            io::print("throw used when function does not declare throws");
471
        }
472
        case super::ErrorKind::ThrowIncompatibleError => {
473
            io::print("throw uses error type not declared by function");
474
        }
475
        case super::ErrorKind::TryNonThrowing => {
476
            io::print("try applied to expression that cannot throw");
477
        }
478
        case super::ErrorKind::TryCatchMultiError => {
479
            io::print("catch with inferred binding requires single error type; use typed catches for multiple error types");
480
        }
481
        case super::ErrorKind::TryCatchDuplicateType => {
482
            io::print("duplicate error type in catch clauses");
483
        }
484
        case super::ErrorKind::AmbiguousRegionalError => {
485
            io::print("error types must remain distinct after region erasure");
486
        }
487
        case super::ErrorKind::TryCatchNonExhaustive => {
488
            io::print("catch clauses do not cover all error types");
489
        }
490
        case super::ErrorKind::MissingTry => {
491
            io::print("called fallible function without using try");
492
        }
493
        case super::ErrorKind::CannotInferType => {
494
            io::print("cannot infer type from context");
495
        }
496
        case super::ErrorKind::CannotAssignVoid => {
497
            io::print("cannot assign void value to a variable");
498
        }
499
        case super::ErrorKind::DefaultAttrOnlyOnFn => {
500
            io::print("default attribute can only be used on functions");
501
        }
502
        case super::ErrorKind::UnionVariantPayloadMissing(name) => {
503
            io::print("union variant '");
504
            io::print(name);
505
            io::print("' requires a payload");
506
        }
507
        case super::ErrorKind::UnionVariantPayloadUnexpected(name) => {
508
            io::print("union variant '");
509
            io::print(name);
510
            io::print("' does not expect a payload");
511
        }
512
        case super::ErrorKind::ReceiverMutabilityMismatch => {
513
            io::print("instance receiver mutability does not match trait declaration");
514
        }
515
        case super::ErrorKind::DuplicateInstance => {
516
            io::print("duplicate instance declaration for the same trait and type");
517
        }
518
        case super::ErrorKind::MissingTraitMethod(name) => {
519
            printQuoted("missing trait method '", name);
520
        }
521
        case super::ErrorKind::UnexpectedTraitName => {
522
            io::print("trait name cannot be used as a value");
523
        }
524
        case super::ErrorKind::TraitReceiverMismatch => {
525
            io::print("trait method receiver must be a pointer to the declaring trait");
526
        }
527
        case super::ErrorKind::TraitMethodSafetyMismatch => {
528
            io::print("trait method implementation has mismatched unsafe requirement");
529
        }
530
        case super::ErrorKind::FnParamOverflow(m) =>
531
            printMismatch("too many function parameters", "maximum", m),
532
        case super::ErrorKind::FnThrowOverflow(m) =>
533
            printMismatch("too many function throws", "maximum", m),
534
        case super::ErrorKind::TraitMethodOverflow(m) =>
535
            printMismatch("too many trait methods", "maximum", m),
536
        case super::ErrorKind::MissingSupertraitInstance(name) => {
537
            printQuoted("missing instance for supertrait '", name);
538
        }
539
        case super::ErrorKind::AffineUseAfterMove(name) => {
540
            printQuoted("affine value used after move: '", name);
541
        }
542
        case super::ErrorKind::LinearUseAfterConsume(name) => {
543
            printQuoted("linear value used after consumption: '", name);
544
        }
545
        case super::ErrorKind::LinearNotConsumed(name) => {
546
            printQuoted("linear value is not consumed: '", name);
547
        }
548
        case super::ErrorKind::LinearLetElseMustTerminate => {
549
            io::print("`let-else` fallback must terminate control flow");
550
        }
551
        case super::ErrorKind::LinearBranchMismatch(name) => {
552
            printQuoted("linear value has inconsistent branch state: '", name);
553
        }
554
        case super::ErrorKind::LinearPartialMove => {
555
            io::print("cannot move a field out of a linear value");
556
        }
557
        case super::ErrorKind::LinearDiscard => {
558
            io::print("linear value cannot be discarded");
559
        }
560
        case super::ErrorKind::LinearOverwrite => {
561
            io::print("assignment would overwrite a linear value");
562
        }
563
        case super::ErrorKind::LinearUndefined => {
564
            io::print("linear values cannot be undefined");
565
        }
566
        case super::ErrorKind::CopyContainsNonCopy => {
567
            io::print("`Copy` composite contains a non-copy value");
568
        }
569
        case super::ErrorKind::ConflictingOwnershipMarkers => {
570
            io::print("a composite cannot be both `Copy` and `Once`");
571
        }
572
        case super::ErrorKind::UnknownRegion(name) => {
573
            io::print("unknown region ");
574
            io::print(name);
575
        }
576
        case super::ErrorKind::RegionArgumentCount(count) => {
577
            printMismatch("region argument count", "expected", count);
578
        }
579
        case super::ErrorKind::RegionInference(name) => {
580
            io::print("cannot infer a consistent argument for region ");
581
            io::print(name);
582
        }
583
        case super::ErrorKind::RegionParent(name) => {
584
            io::print("region argument does not satisfy the parent relation for ");
585
            io::print(name);
586
        }
587
        case super::ErrorKind::RecursiveType => io::print("recursive value type has no finite layout"),
588
        case super::ErrorKind::RegionCycle(name) => {
589
            io::print("cyclic region parent relation for ");
590
            io::print(name);
591
        }
592
        case super::ErrorKind::InvalidRefPosition => {
593
            io::print("reference type is only allowed as a parameter or local binding");
594
        }
595
        case super::ErrorKind::RefBinding => {
596
            io::print("reference local requires an immutable binding to existing storage");
597
        }
598
        case super::ErrorKind::BorrowConflict(name) => {
599
            printQuoted("conflicting borrow of '", name);
600
        }
601
        case super::ErrorKind::UnsafeOperation => {
602
            io::print("unsafe operation requires an unsafe function or block");
603
        }
604
        case super::ErrorKind::UnsafeCall => {
605
            io::print("calling an unsafe function requires an unsafe function or block");
606
        }
607
        case super::ErrorKind::InvalidAllocationValue => {
608
            io::print("session allocation requires a value safe for bulk reclamation and plain Copy elements for slices");
609
        }
610
        case super::ErrorKind::InvalidAllocationLayout => {
611
            io::print("invalid or overflowing allocation layout");
612
        }
613
        case super::ErrorKind::InvalidAllocationRuntime => {
614
            io::print("invalid standard allocation trait signature");
615
        }
616
        case super::ErrorKind::InvalidCellPayload => {
617
            io::print("cell payload must be a storable plain Copy value");
618
        }
619
        case super::ErrorKind::InvalidSessionSource => {
620
            io::print("session requires one exclusive borrow of an std::lang::alloc::Alloc implementer");
621
        }
622
        case super::ErrorKind::RegionalLoanOverflow => io::print("too many simultaneous regional projections"),
623
        case super::ErrorKind::RegionEscape(name) => {
624
            io::print("value outlives region ");
625
            io::print(name);
626
        }
627
        case super::ErrorKind::Internal => {
628
            io::print("internal compiler error");
629
        }
630
        case super::ErrorKind::RecordFieldOutOfOrder { .. } => {
631
            io::print("record field out of order");
632
        }
633
        case super::ErrorKind::OpaqueTypeNotAllowed => {
634
            io::print("opaque type not allowed");
635
        }
636
        case super::ErrorKind::OpaqueTypeDeref => {
637
            io::print("opaque types cannot be dereferenced");
638
        }
639
        case super::ErrorKind::OpaquePointerArithmetic => {
640
            io::print("opaque pointer arithmetic is not allowed");
641
        }
642
        case super::ErrorKind::BuiltinArgCountMismatch { .. } => {
643
            io::print("built-in argument count mismatch");
644
        }
645
    }
646
    io::print("\n");
647
}
648
649
/// Entry point for printing resolver diagnostics in vim quickfix format.
650
export unsafe fn printDiagnostics 'arena (diag: &super::Diagnostics, res: &super::Resolver 'arena) {
651
    for i in 0..diag.errors.len {
652
        printError(&diag.errors[i], res);
653
    }
654
}
655
656
/// Print an applied nominal type's explicit region arguments.
657
unsafe fn printNominalArguments(applied: *unsafe super::NominalApplication) {
658
    for region in applied.arguments {
659
        io::print(" ");
660
        io::print(region.name);
661
    }
662
}