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