E3035
E3035 — A method name that more than one impl block defines for the same type. The impls are kept in a hash map, so which body a call reached used to change from one run of the compiler to the next; refusing the call is the only answer that is the same twice.
What the compiler reports
E3035
Method 'describe' on 'i64' is defined by more than one impl (Loud, Quiet)
The fragments the test suite holds the compiler to. An ellipsis marks text the test does not constrain; the emitted message also carries a source location.
A program that triggers it
//
// Part of the Vx Project, under the Apache License v2.0 with LLVM Exceptions.
// See LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Two traits define `describe` for `i64`, and a call has no way to say which one it means.
//
// This has to be refused rather than resolved: the impl blocks live in a hash map, and the
// body a call reached used to be whichever came first in that order. Three runs of this
// program printed 1, 1 and 2. The diagnostic names both impls, so the reader knows what to
// rename.
//
// Two impls of ONE trait are a different case and are no longer refused: their methods take
// different types, so the argument says which is meant. That is
// tests/backend/pass/static_call_picks_the_impl_by_argument.vx. What is left here is the case
// no argument can decide, because both signatures are identical.
//
// The call is an instance call. Static dispatch narrows by argument type; instance dispatch
// does not, because `resolve_method_in_impls` is not given the argument types -- so this file
// would be refused either way, and it is not evidence about the static path.
//
trait Loud {
fn describe(self : &i64) -> i32;
}
trait Quiet {
fn describe(self : &i64) -> i32;
}
impl Loud for i64 {
fn describe(self : &i64) -> i32 {
return 1;
}
}
impl Quiet for i64 {
fn describe(self : &i64) -> i32 {
return 2;
}
}
fn main() -> i32 {
let x : i64 = 5;
print(x.describe());
return 0;
}
From tests/frontend/fail/two_impls_one_method_is_refused.vx, which asserts this diagnostic on every commit.
Related
A tour of VxThe chapter covering the rule this code enforces.
All diagnosticsEvery code the compiler can emit, grouped by stage.
E3034A
comptime block inside another one. The outer block already runs at compile time, so the inner one asks for nothing extra, and nesting them is what made a block's value depend on evaluating a closure defined inside another block.
E3037An impl of a trait that declares an associated type does not bind it. The trait's signatures are written against Self::Item, so with no binding there is nothing to put in their place, and the method's type becomes whatever the impl happened to write.