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