Closed
Description
Platform:
Archlinux x86_64
rustc 0.11.0-pre (4462687 2014-05-23 16:31:20 -0700)
host: x86_64-unknown-linux-gnu
While using macros, I got this error:
error: internal compiler error: unexpected failure
note: the compiler hit an unexpected failure path. this is a bug.
task 'rustc' failed at 'could not find method while translating', /home/chris/pkg/rust-git/src/rust/src/libstd/option.rs:167
Here is the code, let me know if you prefer a backtrace:
#![feature(macro_rules)]
macro_rules! new_test(
($member:ident, String) => (
self.$member.to_owned()
);
($member:ident, Struct) => (
self.$member.clone()
);
($member:ident, $yep:expr) => (
self.$member
)
)
macro_rules! new_test_set(
($member:ident, String) => (
match value {
&String(ref s) => {
self.$member = s.to_owned()
}
_ => {
println!("cant set {:?} to {}, because it is a String", value, name);
}
}
);
($member:ident, Struct) => (
match value {
&Struct(ref s) => {
for p in s.fields().iter() {
self.$member.set_property(
p.as_slice(),
& s.get_property(p.as_slice()));
}
}
_ => {
println!("cant set {:?} to {}, because it is a Struct", value, name);
}
}
);
($member:ident, $yep:ident) => (
match value {
&$yep(f) => {
self.$member = f;
}
_ => {
println!("cant set {:?} to {}, because it is a {}", value, name, stringify!($yep));
}
}
)
)
macro_rules! property_impl(
($my_type:ty, [ $($member:ident,$mytype:ident)|+ ]) => (
impl Property for $my_type
{
fn fields(&self) -> Vec<StrBuf>
{
return vec!(
$(
stringify!($member).to_owned(),
)+
);
}
fn get_property(&self, name: &str) -> PropertyType
{
$(
if name == stringify!($member)
{
return $mytype(new_test!($member, $mytype))
}
)+
else {
Float(0.0)
}
}
fn set_property(&mut self, name: &str, value: &PropertyType)
{
$(
if name == stringify!($member)
{
new_test_set!($member, $mytype)
return;
}
)+
}
}
);
)
#[deriving(Clone)]
pub struct Vec3
{
x : f64,
y : f64,
z : f64
}
#[deriving(Clone)]
pub struct Quat
{
x : f64,
y : f64,
z : f64,
w : f64,
t : i32,
v : Box<Vec3>,
txt : StrBuf
}
property_impl!(Vec3, [x,Float|y,Float|z,Float])
// Change this line to avoid the bug
//property_impl!(Quat, [x,Float|y,Float|z,Float|t,Int|txt,String])
property_impl!(Quat, [x,Float|y,Float|z,Float|t,Int|txt,String|v,Struct])
enum PropertyType {
Int(i32),
Float(f64),
String(StrBuf),
Struct(Box<Property>),
}
trait Property {
fn fields(&self) -> Vec<StrBuf>;
fn get_property(&self, name: &str) -> PropertyType;
fn set_property(&mut self, name: &str, value: &PropertyType);
}
fn main() {
let q = Quat{x:1.0, y:999.0, z:22.0, w:123.0,t:44,v:box Vec3{x:4.0,y:6.7,z:8.9}, txt:"test".to_owned()};
println!(" quat {:?} ", q.get_property("z"));
}
Activity
huonw commentedon May 24, 2014
Thanks for the report!
I reduced it to the following (with the assistance of creduce):
huonw commentedon May 24, 2014
Ah! But it works with an explicit cast to the trait object:
i.e. it seems to be problem with implicit trait object coercions. cc @luqmana
(This has the same error message as #6334 but the causes don't look the same.)
luqmana commentedon Jun 10, 2014
The reason for this seems to be because in
typeck::check::vtable::early_resolve_expr
we first encounter the method call expr (self.v.clone()
in this code) and lookup the vtables for it which we then insert into thevtable_map
. The key for this map (essentially) being the expression'sNodeId
. (It's actually a struct containing the expression id and how many times to deref) Then we go on to check if there are any adjustments for the current expression. In this case there is, since we can coerce to a trait object here. So then go on to lookup vtables for the adjusted expression and once again we insert it into thevtable_map
. The problem is that we use the same key, and thus we overwrite the entry from earlier. We don't run into this if you use an explicit cast since the method call and the cast would be 2 expressions we consider separately and thus no clash.auto merge of #14830 : luqmana/rust/cmtrttcbctto, r=nikomatsakis
Update copyright year (rust-lang#14399)