mirror of
https://github.com/roc-lang/roc.git
synced 2025-12-23 08:48:03 +00:00
Improve error message for rigid vars
This commit is contained in:
parent
4d87de2927
commit
d487cb6300
2 changed files with 34 additions and 17 deletions
|
|
@ -99,8 +99,8 @@ bool_var: Var,
|
|||
deferred_static_dispatch_constraints: DeferredConstraintCheck.SafeList,
|
||||
/// Used when looking up static dispatch functions
|
||||
static_dispatch_method_name_buf: std.ArrayList(u8),
|
||||
/// Map representation of Idet -> Var, user in checking static dispatch constraints
|
||||
static_dispatch_constraints_map: std.AutoHashMap(Ident.Idx, Var),
|
||||
/// Map representation of Ident -> Var, used in checking static dispatch constraints
|
||||
ident_to_var_map: std.AutoHashMap(Ident.Idx, Var),
|
||||
|
||||
/// A map of rigid variables that we build up during a branch of type checking
|
||||
const FreeVar = struct { ident: base.Ident.Idx, var_: Var };
|
||||
|
|
@ -161,7 +161,7 @@ pub fn init(
|
|||
.bool_var = undefined, // Will be initialized in copyBuiltinTypes()
|
||||
.deferred_static_dispatch_constraints = try DeferredConstraintCheck.SafeList.initCapacity(gpa, 128),
|
||||
.static_dispatch_method_name_buf = try std.ArrayList(u8).initCapacity(gpa, 32),
|
||||
.static_dispatch_constraints_map = std.AutoHashMap(Ident.Idx, Var).init(gpa),
|
||||
.ident_to_var_map = std.AutoHashMap(Ident.Idx, Var).init(gpa),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -186,7 +186,7 @@ pub fn deinit(self: *Self) void {
|
|||
self.constraint_origins.deinit();
|
||||
self.deferred_static_dispatch_constraints.deinit(self.gpa);
|
||||
self.static_dispatch_method_name_buf.deinit(self.gpa);
|
||||
self.static_dispatch_constraints_map.deinit();
|
||||
self.ident_to_var_map.deinit();
|
||||
}
|
||||
|
||||
/// Assert that type vars and regions in sync
|
||||
|
|
@ -3774,16 +3774,16 @@ fn checkDeferredStaticDispatchConstraints(self: *Self) std.mem.Allocator.Error!v
|
|||
try self.reportConstraintError(
|
||||
deferred_constraint.var_,
|
||||
constraint,
|
||||
.missing_method,
|
||||
.{ .missing_method = .rigid },
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Build a map of constraints the rigid has
|
||||
self.static_dispatch_constraints_map.clearRetainingCapacity();
|
||||
try self.static_dispatch_constraints_map.ensureUnusedCapacity(@intCast(rigid_constraints.len));
|
||||
self.ident_to_var_map.clearRetainingCapacity();
|
||||
try self.ident_to_var_map.ensureUnusedCapacity(@intCast(rigid_constraints.len));
|
||||
for (rigid_constraints) |rigid_constraint| {
|
||||
self.static_dispatch_constraints_map.putAssumeCapacity(rigid_constraint.fn_name, rigid_constraint.fn_var);
|
||||
self.ident_to_var_map.putAssumeCapacity(rigid_constraint.fn_name, rigid_constraint.fn_var);
|
||||
}
|
||||
|
||||
// Iterate over the constraints
|
||||
|
|
@ -3795,7 +3795,7 @@ fn checkDeferredStaticDispatchConstraints(self: *Self) std.mem.Allocator.Error!v
|
|||
const resolved_func = mb_resolved_func.?;
|
||||
|
||||
// Then, lookup the inferred constraint in the actual list of rigid constraints
|
||||
if (self.static_dispatch_constraints_map.get(constraint.fn_name)) |rigid_var| {
|
||||
if (self.ident_to_var_map.get(constraint.fn_name)) |rigid_var| {
|
||||
// Unify the actual function var against the inferred var
|
||||
//
|
||||
// TODO: For better error messages, we should check if these
|
||||
|
|
@ -3810,7 +3810,7 @@ fn checkDeferredStaticDispatchConstraints(self: *Self) std.mem.Allocator.Error!v
|
|||
try self.reportConstraintError(
|
||||
deferred_constraint.var_,
|
||||
constraint,
|
||||
.missing_method,
|
||||
.{ .missing_method = .nominal },
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
|
@ -3877,7 +3877,7 @@ fn checkDeferredStaticDispatchConstraints(self: *Self) std.mem.Allocator.Error!v
|
|||
try self.reportConstraintError(
|
||||
deferred_constraint.var_,
|
||||
constraint,
|
||||
.missing_method,
|
||||
.{ .missing_method = .nominal },
|
||||
);
|
||||
continue;
|
||||
};
|
||||
|
|
@ -3890,7 +3890,7 @@ fn checkDeferredStaticDispatchConstraints(self: *Self) std.mem.Allocator.Error!v
|
|||
try self.reportConstraintError(
|
||||
deferred_constraint.var_,
|
||||
constraint,
|
||||
.missing_method,
|
||||
.{ .missing_method = .nominal },
|
||||
);
|
||||
continue;
|
||||
};
|
||||
|
|
@ -3946,15 +3946,19 @@ fn reportConstraintError(
|
|||
self: *Self,
|
||||
dispatcher_var: Var,
|
||||
constraint: StaticDispatchConstraint,
|
||||
kind: enum { missing_method, not_nominal },
|
||||
kind: union(enum) {
|
||||
missing_method: problem.DispatcherDoesNotImplMethod.DispatcherType,
|
||||
not_nominal,
|
||||
},
|
||||
) !void {
|
||||
const snapshot = try self.snapshots.deepCopyVar(self.types, dispatcher_var);
|
||||
|
||||
const constraint_problem = switch (kind) {
|
||||
.missing_method => problem.Problem{ .static_dispach = .{
|
||||
.missing_method => |dispatcher_type| problem.Problem{ .static_dispach = .{
|
||||
.dispatcher_does_not_impl_method = .{
|
||||
.dispatcher_var = dispatcher_var,
|
||||
.dispatcher_snapshot = snapshot,
|
||||
.dispatcher_type = dispatcher_type,
|
||||
.fn_var = constraint.fn_var,
|
||||
.method_name = constraint.fn_name,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -222,8 +222,12 @@ pub const DispatcherNotNominal = struct {
|
|||
pub const DispatcherDoesNotImplMethod = struct {
|
||||
dispatcher_var: Var,
|
||||
dispatcher_snapshot: SnapshotContentIdx,
|
||||
dispatcher_type: DispatcherType,
|
||||
fn_var: Var,
|
||||
method_name: Ident.Idx,
|
||||
|
||||
/// Type of the dispatcher
|
||||
pub const DispatcherType = enum { nominal, rigid };
|
||||
};
|
||||
|
||||
// bug //
|
||||
|
|
@ -1695,9 +1699,18 @@ pub const ReportBuilder = struct {
|
|||
try report.document.addLineBreak();
|
||||
try report.document.addLineBreak();
|
||||
try report.document.addAnnotated("Hint:", .emphasized);
|
||||
try report.document.addReflowingText(" Did you forget to define ");
|
||||
try report.document.addAnnotated(method_name_str, .emphasized);
|
||||
try report.document.addReflowingText(" in the type's method block?");
|
||||
switch (data.dispatcher_type) {
|
||||
.nominal => {
|
||||
try report.document.addReflowingText(" Did you forget to define ");
|
||||
try report.document.addAnnotated(method_name_str, .emphasized);
|
||||
try report.document.addReflowingText(" in the type's method block?");
|
||||
},
|
||||
.rigid => {
|
||||
try report.document.addReflowingText(" Did you forget to specify ");
|
||||
try report.document.addAnnotated(method_name_str, .emphasized);
|
||||
try report.document.addReflowingText(" in the type annotation?");
|
||||
},
|
||||
}
|
||||
|
||||
return report;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue