Problem Types

Problems are categorized by compiler phase and converted to diagnostics for display.

Problem Enum

pub enum Problem {
    // === Lexer Problems (E0xxx) ===
    InvalidCharacter {
        char: char,
        span: Span,
    },
    UnterminatedString {
        start: Span,
    },
    InvalidEscape {
        escape: char,
        span: Span,
    },
    InvalidNumber {
        text: String,
        span: Span,
    },

    // === Parser Problems (E1xxx) ===
    UnexpectedToken {
        expected: Vec<TokenKind>,
        found: TokenKind,
        span: Span,
    },
    UnexpectedEof {
        expected: Vec<TokenKind>,
    },
    ExpectedExpression {
        found: TokenKind,
        span: Span,
    },
    MissingClosingDelimiter {
        delimiter: TokenKind,
        opening: Span,
        span: Span,
    },
    InvalidPattern {
        span: Span,
    },

    // === Type Problems (E2xxx) ===
    TypeMismatch {
        expected: Type,
        found: Type,
        span: Span,
        context: Option<String>,
    },
    UndefinedVariable {
        name: Name,
        span: Span,
        similar: Vec<Name>,
    },
    UndefinedType {
        name: Name,
        span: Span,
        similar: Vec<Name>,
    },
    UndefinedFunction {
        name: Name,
        span: Span,
        similar: Vec<Name>,
    },
    MissingCapability {
        required: Capability,
        span: Span,
    },
    InfiniteType {
        var: TypeVarId,
        ty: Type,
        span: Span,
    },
    NotCallable {
        ty: Type,
        span: Span,
    },
    WrongArgCount {
        expected: usize,
        found: usize,
        span: Span,
    },
    MissingField {
        struct_name: Name,
        field: Name,
        span: Span,
    },

    // === Pattern Problems (E3xxx) ===
    UnknownPattern {
        name: Name,
        span: Span,
        similar: Vec<Name>,
    },
    MissingRequiredArg {
        pattern: Name,
        arg: String,
        span: Span,
    },
    UnexpectedArg {
        pattern: Name,
        arg: Name,
        span: Span,
    },
    InvalidPatternArg {
        pattern: Name,
        arg: String,
        expected: Type,
        found: Type,
        span: Span,
    },

    // === Evaluation Problems (E4xxx) ===
    DivisionByZero {
        span: Span,
    },
    IndexOutOfBounds {
        index: i64,
        length: usize,
        span: Span,
    },
    AssertionFailed {
        message: Option<String>,
        span: Span,
    },
    Panic {
        message: String,
        span: Span,
    },

    // === Import Problems (E5xxx) ===
    ModuleNotFound {
        path: String,
        span: Span,
    },
    ItemNotExported {
        module: String,
        item: Name,
        span: Span,
    },
    CircularImport {
        path: PathBuf,
        cycle: Vec<PathBuf>,
        span: Span,
    },

    // === Internal Problems (E9xxx) ===
    InternalError {
        message: String,
        span: Option<Span>,
    },
}

Problem to Diagnostic Conversion

impl Problem {
    pub fn to_diagnostic(&self, interner: &Interner) -> Diagnostic {
        match self {
            Problem::TypeMismatch { expected, found, span, context } => {
                Diagnostic {
                    code: ErrorCode::E2001,
                    severity: Severity::Error,
                    message: format!(
                        "expected `{}`, found `{}`",
                        expected.display(),
                        found.display()
                    ),
                    span: *span,
                    labels: vec![
                        Label::primary(*span, format!("expected `{}`", expected.display())),
                    ],
                    fixes: self.suggest_type_conversion(expected, found, *span),
                    help: context.clone(),
                    related: vec![],
                }
            }

            Problem::UndefinedVariable { name, span, similar } => {
                let mut diagnostic = Diagnostic {
                    code: ErrorCode::E2002,
                    severity: Severity::Error,
                    message: format!(
                        "cannot find value `{}` in this scope",
                        interner.resolve(*name)
                    ),
                    span: *span,
                    labels: vec![
                        Label::primary(*span, "not found in this scope"),
                    ],
                    fixes: vec![],
                    help: None,
                    related: vec![],
                };

                // Add "did you mean?" suggestion
                if !similar.is_empty() {
                    let suggestions: Vec<_> = similar
                        .iter()
                        .map(|n| interner.resolve(*n))
                        .collect();
                    diagnostic.help = Some(format!(
                        "did you mean: {}?",
                        suggestions.join(", ")
                    ));
                }

                diagnostic
            }

            // ... more conversions
        }
    }
}

Error Code Documentation

Each error code has documentation:

impl ErrorCode {
    pub fn explanation(&self) -> &'static str {
        match self {
            ErrorCode::E2001 => r#"
This error occurs when a value's type doesn't match what was expected.

Example:
```ori
let x: int = "hello"  // Error: expected int, found str

To fix this, ensure the value matches the expected type, or use explicit type conversion if appropriate. ”#, // … } } }


## Severity Levels

```rust
pub enum Severity {
    /// Compilation cannot continue
    Error,

    /// Potential problem, but compilation succeeds
    Warning,

    /// Informational note
    Info,

    /// Suggestion for improvement
    Hint,
}

Error

Compilation fails:

error[E2001]: type mismatch

Warning

Compilation succeeds, but something is suspicious:

warning: unused variable `x`

Info

Additional context:

info: type inferred as `int`

Hint

Suggestions:

hint: consider using `map` instead of `for..yield`

Link to related locations:

pub struct RelatedInfo {
    pub message: String,
    pub span: Span,
}

// Example: "expected due to this annotation"
diagnostic.related.push(RelatedInfo {
    message: "expected due to this annotation".into(),
    span: type_annotation_span,
});

Labels

Mark specific locations:

pub struct Label {
    pub span: Span,
    pub message: String,
    pub style: LabelStyle,
}

pub enum LabelStyle {
    Primary,   // Main error location
    Secondary, // Related context
}