<commit_before>use std::default;
use std::io::Result;

use bytes::{
    Buf,
    BufMut,
    LittleEndian,
    Take,
};

use field::{Field, Type};
use encoding::*;

/// A numeric scalar Protobuf field type.
///
/// The `E` type parameter allows `Numeric` to be implemented multiple times for a
/// single type, in order to provide multiple encoding and decoding options for
/// a single Rust type. For instance, the Protobuf `fixed32` and `uint32` types
/// both correspond to the Rust `u32` type, so `u32` has two impls of `Numeric`
/// with different types for `E`, which correspond to `fixed32` and `uint32`.
/// Repeated numeric fields can optionally use packed encoding, which is
/// controlled using the `Packed` type.
pub trait Numeric<E=Default> : default::Default {
    /// Encodes the scalar field to the buffer, without a key.
    /// The buffer must have enough remaining space to hold the encoded key and field.
    fn encode<B>(self, buf: &mut B) where B: BufMut;

    /// Decodes an instance of the field from the buffer.
    fn decode<B>(buf: &mut B) -> Result<Self> where B: Buf;

    /// Returns the encoded length of the field, without a key.
    fn encoded_len(self) -> usize;

    /// Returns the wire type of the numeric scalar field.
    fn wire_type() -> WireType;
}

// Provides Field, Type, and repeated Field impls for numeric types.
macro_rules! numeric_field {
    ($ty: ty) => { numeric_field!($ty, Default); };
    ($ty: ty, $e: ty) => {
        impl Field<$e> for $ty {
            #[inline]
            fn encode<B>(&self, tag: u32, buf: &mut B) where B: BufMut {
                encode_key(tag, <$ty as Numeric<$e>>::wire_type(), buf);
                <$ty as Numeric<$e>>::encode(*self, buf);
            }
            #[inline]
            fn merge<B>(&mut self, _tag: u32, wire_type: WireType, buf: &mut Take<B>) -> Result<()> where B: Buf {
                check_wire_type(<$ty as Numeric<$e>>::wire_type(), wire_type)?;
                *self = <$ty as Numeric<$e>>::decode(buf)?;
                Ok(())
            }
            #[inline]
            fn encoded_len(&self, tag: u32) -> usize { key_len(tag) + <$ty as Numeric<$e>>::encoded_len(*self) }
        }
        impl Type<$e> for $ty {
            fn empty() -> $ty {
                ::std::default::Default::default()
            }
        }

        impl Field<$e> for Vec<$ty> {
            #[inline]
            fn encode<B>(&self, tag: u32, buf: &mut B) where B: BufMut {
                for value in self {
                    <$ty as Field<$e>>::encode(value, tag, buf);
                }
            }
            #[inline]
            fn merge<B>(&mut self, tag: u32, wire_type: WireType, buf: &mut Take<B>) -> Result<()> where B: Buf {
                if wire_type == WireType::LengthDelimited {
                    // Packed repeated encoding.
                    let len = decode_varint(buf)?;
                    if len > buf.remaining() as u64 {
                        return Err(invalid_data("failed to decode packed repeated field: buffer underflow"));
                    }

                    let limit = buf.limit();
                    buf.set_limit(len as usize);
                    while buf.has_remaining() {
                        self.push(<$ty as Numeric<$e>>::decode(buf)?);
                    }
                    buf.set_limit(limit - len as usize);
                } else {
                    // Default repeated encoding.
                    let mut value = default::Default::default();
                    <$ty as Field<$e>>::merge(&mut value, tag, wire_type, buf)?;
                    self.push(value);
                }
                Ok(())
            }
            #[inline]
            fn encoded_len(&self, tag: u32) -> usize {
                self.iter().map(|f| <$ty as Field<$e>>::encoded_len(f, tag)).sum()
            }
        }

        impl Field<(Packed, $e)> for Vec<$ty> {
            #[inline]
            fn encode<B>(&self, tag: u32, buf: &mut B) where B: BufMut {
                if self.is_empty() { return; }
                encode_key(tag, WireType::LengthDelimited, buf);
                let len: usize = self.iter().cloned().map(<$ty as Numeric<$e>>::encoded_len).sum();
                encode_varint(len as u64, buf);
                for &value in self {
                    <$ty as Numeric<$e>>::encode(value, buf);
                }
            }
            #[inline]
            fn merge<B>(&mut self, tag: u32, wire_type: WireType, buf: &mut Take<B>) -> Result<()> where B: Buf {
                <Vec<$ty> as Field<$e>>::merge(self, tag, wire_type, buf)
            }
            #[inline]
            fn encoded_len(&self, tag: u32) -> usize {
                if self.is_empty() { return 0; }
                let len: usize = self.iter().cloned().map(<$ty as Numeric<$e>>::encoded_len).sum();
                key_len(tag) + encoded_len_varint(len as _) + len
            }
        }
    };
}

// bool
impl Numeric for bool {
    #[inline]
    fn encode<B>(self, buf: &mut B) where B: BufMut {
        buf.put_u8(if self { 1u8 } else { 0u8 });
    }
    #[inline]
    fn decode<B>(buf: &mut B) -> Result<bool> where B: Buf {
        if !buf.has_remaining() {
            return Err(invalid_data("failed to decode bool: buffer underflow"));
        }
        match buf.get_u8() {
            0 => Ok(false),
            1 => Ok(true),
            b => Err(invalid_data(format!("failed to decode bool: invalid value: {}", b))),
        }
    }
    #[inline]
    fn encoded_len(self) -> usize { 1 }
    #[inline]
    fn wire_type() -> WireType { WireType::Varint }
}
numeric_field!(bool);

// int32
impl Numeric for i32 {
    #[inline]
    fn encode<B>(self, buf: &mut B) where B: BufMut { encode_varint(self as _, buf) }
    #[inline]
    fn decode<B>(buf: &mut B) -> Result<i32> where B: Buf { decode_varint(buf).map(|value| value as _) }
    #[inline]
    fn encoded_len(self) -> usize { encoded_len_varint(self as _) }
    #[inline]
    fn wire_type() -> WireType { WireType::Varint }
}
numeric_field!(i32);

// int64
impl Numeric for i64 {
    #[inline]
    fn encode<B>(self, buf: &mut B) where B: BufMut { encode_varint(self as _, buf) }
    #[inline]
    fn decode<B>(buf: &mut B) -> Result<i64> where B: Buf { decode_varint(buf).map(|value| value as _) }
    #[inline]
    fn encoded_len(self) -> usize { encoded_len_varint(self as _) }
    #[inline]
    fn wire_type() -> WireType {
        WireType::Varint
    }
}
numeric_field!(i64);

// uint32
impl Numeric for u32 {
    #[inline]
    fn encode<B>(self, buf: &mut B) where B: BufMut { encode_varint(self as _, buf) }
    #[inline]
    fn decode<B>(buf: &mut B) -> Result<u32> where B: Buf { decode_varint(buf).map(|value| value as _) }
    #[inline]
    fn encoded_len(self) -> usize { encoded_len_varint(self as _) }
    #[inline]
    fn wire_type() -> WireType { WireType::Varint }
}
numeric_field!(u32);

// uint64
impl Numeric for u64 {
    #[inline]
    fn encode<B>(self, buf: &mut B) where B: BufMut { encode_varint(self as _, buf) }
    #[inline]
    fn decode<B>(buf: &mut B) -> Result<u64> where B: Buf { decode_varint(buf).map(|value| value as _) }
    #[inline]
    fn encoded_len(self) -> usize { encoded_len_varint(self as _) }
    #[inline]
    fn wire_type() -> WireType { WireType::Varint }
}
numeric_field!(u64);

// float
impl Numeric for f32 {
    #[inline]
    fn encode<B>(self, buf: &mut B) where B: BufMut { buf.put_f32::<LittleEndian>(self) }
    #[inline]
    fn decode<B>(buf: &mut B) -> Result<f32> where B: Buf {
        if buf.remaining() < 4 {
            return Err(invalid_input("failed to decode float: buffer underflow"));
        }
        Ok(buf.get_f32::<LittleEndian>())
    }
    #[inline]
    fn encoded_len(self) -> usize { 4 }
    #[inline]
    fn wire_type() -> WireType { WireType::ThirtyTwoBit }
}
numeric_field!(f32);

// double
impl Numeric for f64 {
    #[inline]
    fn encode<B>(self, buf: &mut B) where B: BufMut { buf.put_f64::<LittleEndian>(self) }
    #[inline]
    fn decode<B>(buf: &mut B) -> Result<f64> where B: Buf {
        if buf.remaining() < 8 {
            return Err(invalid_input("failed to decode double: buffer underflow"));
        }
        Ok(buf.get_f64::<LittleEndian>())
    }
    #[inline]
    fn encoded_len(self) -> usize { 8 }
    #[inline]
    fn wire_type() -> WireType { WireType::SixtyFourBit }
}
numeric_field!(f64);

// sint32
impl Numeric<Signed> for i32 {
    #[inline]
    fn encode<B>(self, buf: &mut B) where B: BufMut {
        encode_varint(((self << 1) ^ (self >> 31)) as u64, buf)
    }
    #[inline]
    fn decode<B>(buf: &mut B) -> Result<i32> where B: Buf {
        decode_varint(buf).map(|value| {
            let value = value as i32;
            (value >> 1) ^ -(value & 1)
        })
    }
    #[inline]
    fn encoded_len(self) -> usize {
        encoded_len_varint(((self << 1) ^ (self >> 31)) as u64)
    }
    #[inline]
    fn wire_type() -> WireType { WireType::Varint }
}
numeric_field!(i32, Signed);

// sint64
impl Numeric<Signed> for i64 {
    #[inline]
    fn encode<B>(self, buf: &mut B) where B: BufMut {
        encode_varint(((self << 1) ^ (self >> 63)) as u64, buf)
    }
    #[inline]
    fn decode<B>(buf: &mut B) -> Result<i64> where B: Buf {
        decode_varint(buf).map(|value| {
            let value = value as i64;
            (value >> 1) ^ -(value & 1)
        })
    }
    #[inline]
    fn encoded_len(self) -> usize {
        encoded_len_varint(((self << 1) ^ (self >> 63)) as u64)
    }
    #[inline]
    fn wire_type() -> WireType { WireType::Varint }
}
numeric_field!(i64, Signed);

// fixed32
impl Numeric<Fixed> for u32 {
    #[inline]
    fn encode<B>(self, buf: &mut B) where B: BufMut { buf.put_u32::<LittleEndian>(self) }
    #[inline]
    fn decode<B>(buf: &mut B) -> Result<u32> where B: Buf {
        if buf.remaining() < 4 {
            return Err(invalid_input("failed to decode fixed32: buffer underflow"));
        }
        Ok(buf.get_u32::<LittleEndian>())
    }
    #[inline]
    fn encoded_len(self) -> usize { 4 }
    #[inline]
    fn wire_type() -> WireType { WireType::ThirtyTwoBit }
}
numeric_field!(u32, Fixed);

// fixed64
impl Numeric<Fixed> for u64 {
    #[inline]
    fn encode<B>(self, buf: &mut B) where B: BufMut { buf.put_u64::<LittleEndian>(self) }
    #[inline]
    fn decode<B>(buf: &mut B) -> Result<u64> where B: Buf {
        if buf.remaining() < 8 {
            return Err(invalid_input("failed to decode fixed64: buffer underflow"));
        }
        Ok(buf.get_u64::<LittleEndian>())
    }
    #[inline]
    fn encoded_len(self) -> usize { 8 }
    #[inline]
    fn wire_type() -> WireType { WireType::SixtyFourBit }
}
numeric_field!(u64, Fixed);

// sfixed32
impl Numeric<Fixed> for i32 {
    #[inline]
    fn encode<B>(self, buf: &mut B) where B: BufMut { buf.put_i32::<LittleEndian>(self) }
    #[inline]
    fn decode<B>(buf: &mut B) -> Result<i32> where B: Buf {
        if buf.remaining() < 4 {
            return Err(invalid_input("failed to decode sfixed32: buffer underflow"));
        }
        Ok(buf.get_i32::<LittleEndian>())
    }
    #[inline]
    fn encoded_len(self) -> usize { 4 }
    #[inline]
    fn wire_type() -> WireType { WireType::ThirtyTwoBit }
}
numeric_field!(i32, Fixed);

// sfixed64
impl Numeric<Fixed> for i64 {
    #[inline]
    fn encode<B>(self, buf: &mut B) where B: BufMut { buf.put_i64::<LittleEndian>(self); }
    #[inline]
    fn decode<B>(buf: &mut B) -> Result<i64> where B: Buf {
        if buf.remaining() < 8 {
            return Err(invalid_input("failed to decode sfixed64 field: buffer underflow"));
        }
        Ok(buf.get_i64::<LittleEndian>())
    }
    #[inline]
    fn encoded_len(self) -> usize { 8 }
    #[inline]
    fn wire_type() -> WireType { WireType::SixtyFourBit }
}
numeric_field!(i64, Fixed);
<commit_msg>Apparently protobuf allows bools > 1<commit_after>use std::default;
use std::io::Result;

use bytes::{
    Buf,
    BufMut,
    LittleEndian,
    Take,
};

use field::{Field, Type};
use encoding::*;

/// A numeric scalar Protobuf field type.
///
/// The `E` type parameter allows `Numeric` to be implemented multiple times for a
/// single type, in order to provide multiple encoding and decoding options for
/// a single Rust type. For instance, the Protobuf `fixed32` and `uint32` types
/// both correspond to the Rust `u32` type, so `u32` has two impls of `Numeric`
/// with different types for `E`, which correspond to `fixed32` and `uint32`.
/// Repeated numeric fields can optionally use packed encoding, which is
/// controlled using the `Packed` type.
pub trait Numeric<E=Default> : default::Default {
    /// Encodes the scalar field to the buffer, without a key.
    /// The buffer must have enough remaining space to hold the encoded key and field.
    fn encode<B>(self, buf: &mut B) where B: BufMut;

    /// Decodes an instance of the field from the buffer.
    fn decode<B>(buf: &mut B) -> Result<Self> where B: Buf;

    /// Returns the encoded length of the field, without a key.
    fn encoded_len(self) -> usize;

    /// Returns the wire type of the numeric scalar field.
    fn wire_type() -> WireType;
}

// Provides Field, Type, and repeated Field impls for numeric types.
macro_rules! numeric_field {
    ($ty: ty) => { numeric_field!($ty, Default); };
    ($ty: ty, $e: ty) => {
        impl Field<$e> for $ty {
            #[inline]
            fn encode<B>(&self, tag: u32, buf: &mut B) where B: BufMut {
                encode_key(tag, <$ty as Numeric<$e>>::wire_type(), buf);
                <$ty as Numeric<$e>>::encode(*self, buf);
            }
            #[inline]
            fn merge<B>(&mut self, _tag: u32, wire_type: WireType, buf: &mut Take<B>) -> Result<()> where B: Buf {
                check_wire_type(<$ty as Numeric<$e>>::wire_type(), wire_type)?;
                *self = <$ty as Numeric<$e>>::decode(buf)?;
                Ok(())
            }
            #[inline]
            fn encoded_len(&self, tag: u32) -> usize { key_len(tag) + <$ty as Numeric<$e>>::encoded_len(*self) }
        }
        impl Type<$e> for $ty {
            fn empty() -> $ty {
                ::std::default::Default::default()
            }
        }

        impl Field<$e> for Vec<$ty> {
            #[inline]
            fn encode<B>(&self, tag: u32, buf: &mut B) where B: BufMut {
                for value in self {
                    <$ty as Field<$e>>::encode(value, tag, buf);
                }
            }
            #[inline]
            fn merge<B>(&mut self, tag: u32, wire_type: WireType, buf: &mut Take<B>) -> Result<()> where B: Buf {
                if wire_type == WireType::LengthDelimited {
                    // Packed repeated encoding.
                    let len = decode_varint(buf)?;
                    if len > buf.remaining() as u64 {
                        return Err(invalid_data("failed to decode packed repeated field: buffer underflow"));
                    }

                    let limit = buf.limit();
                    buf.set_limit(len as usize);
                    while buf.has_remaining() {
                        self.push(<$ty as Numeric<$e>>::decode(buf)?);
                    }
                    buf.set_limit(limit - len as usize);
                } else {
                    // Default repeated encoding.
                    let mut value = default::Default::default();
                    <$ty as Field<$e>>::merge(&mut value, tag, wire_type, buf)?;
                    self.push(value);
                }
                Ok(())
            }
            #[inline]
            fn encoded_len(&self, tag: u32) -> usize {
                self.iter().map(|f| <$ty as Field<$e>>::encoded_len(f, tag)).sum()
            }
        }

        impl Field<(Packed, $e)> for Vec<$ty> {
            #[inline]
            fn encode<B>(&self, tag: u32, buf: &mut B) where B: BufMut {
                if self.is_empty() { return; }
                encode_key(tag, WireType::LengthDelimited, buf);
                let len: usize = self.iter().cloned().map(<$ty as Numeric<$e>>::encoded_len).sum();
                encode_varint(len as u64, buf);
                for &value in self {
                    <$ty as Numeric<$e>>::encode(value, buf);
                }
            }
            #[inline]
            fn merge<B>(&mut self, tag: u32, wire_type: WireType, buf: &mut Take<B>) -> Result<()> where B: Buf {
                <Vec<$ty> as Field<$e>>::merge(self, tag, wire_type, buf)
            }
            #[inline]
            fn encoded_len(&self, tag: u32) -> usize {
                if self.is_empty() { return 0; }
                let len: usize = self.iter().cloned().map(<$ty as Numeric<$e>>::encoded_len).sum();
                key_len(tag) + encoded_len_varint(len as _) + len
            }
        }
    };
}

// bool
impl Numeric for bool {
    #[inline]
    fn encode<B>(self, buf: &mut B) where B: BufMut {
        buf.put_u8(if self { 1u8 } else { 0u8 });
    }
    #[inline]
    fn decode<B>(buf: &mut B) -> Result<bool> where B: Buf { decode_varint(buf).map(|value| value != 0) }
    #[inline]
    fn encoded_len(self) -> usize { 1 }
    #[inline]
    fn wire_type() -> WireType { WireType::Varint }
}
numeric_field!(bool);

// int32
impl Numeric for i32 {
    #[inline]
    fn encode<B>(self, buf: &mut B) where B: BufMut { encode_varint(self as _, buf) }
    #[inline]
    fn decode<B>(buf: &mut B) -> Result<i32> where B: Buf { decode_varint(buf).map(|value| value as _) }
    #[inline]
    fn encoded_len(self) -> usize { encoded_len_varint(self as _) }
    #[inline]
    fn wire_type() -> WireType { WireType::Varint }
}
numeric_field!(i32);

// int64
impl Numeric for i64 {
    #[inline]
    fn encode<B>(self, buf: &mut B) where B: BufMut { encode_varint(self as _, buf) }
    #[inline]
    fn decode<B>(buf: &mut B) -> Result<i64> where B: Buf { decode_varint(buf).map(|value| value as _) }
    #[inline]
    fn encoded_len(self) -> usize { encoded_len_varint(self as _) }
    #[inline]
    fn wire_type() -> WireType {
        WireType::Varint
    }
}
numeric_field!(i64);

// uint32
impl Numeric for u32 {
    #[inline]
    fn encode<B>(self, buf: &mut B) where B: BufMut { encode_varint(self as _, buf) }
    #[inline]
    fn decode<B>(buf: &mut B) -> Result<u32> where B: Buf { decode_varint(buf).map(|value| value as _) }
    #[inline]
    fn encoded_len(self) -> usize { encoded_len_varint(self as _) }
    #[inline]
    fn wire_type() -> WireType { WireType::Varint }
}
numeric_field!(u32);

// uint64
impl Numeric for u64 {
    #[inline]
    fn encode<B>(self, buf: &mut B) where B: BufMut { encode_varint(self as _, buf) }
    #[inline]
    fn decode<B>(buf: &mut B) -> Result<u64> where B: Buf { decode_varint(buf).map(|value| value as _) }
    #[inline]
    fn encoded_len(self) -> usize { encoded_len_varint(self as _) }
    #[inline]
    fn wire_type() -> WireType { WireType::Varint }
}
numeric_field!(u64);

// float
impl Numeric for f32 {
    #[inline]
    fn encode<B>(self, buf: &mut B) where B: BufMut { buf.put_f32::<LittleEndian>(self) }
    #[inline]
    fn decode<B>(buf: &mut B) -> Result<f32> where B: Buf {
        if buf.remaining() < 4 {
            return Err(invalid_input("failed to decode float: buffer underflow"));
        }
        Ok(buf.get_f32::<LittleEndian>())
    }
    #[inline]
    fn encoded_len(self) -> usize { 4 }
    #[inline]
    fn wire_type() -> WireType { WireType::ThirtyTwoBit }
}
numeric_field!(f32);

// double
impl Numeric for f64 {
    #[inline]
    fn encode<B>(self, buf: &mut B) where B: BufMut { buf.put_f64::<LittleEndian>(self) }
    #[inline]
    fn decode<B>(buf: &mut B) -> Result<f64> where B: Buf {
        if buf.remaining() < 8 {
            return Err(invalid_input("failed to decode double: buffer underflow"));
        }
        Ok(buf.get_f64::<LittleEndian>())
    }
    #[inline]
    fn encoded_len(self) -> usize { 8 }
    #[inline]
    fn wire_type() -> WireType { WireType::SixtyFourBit }
}
numeric_field!(f64);

// sint32
impl Numeric<Signed> for i32 {
    #[inline]
    fn encode<B>(self, buf: &mut B) where B: BufMut {
        encode_varint(((self << 1) ^ (self >> 31)) as u64, buf)
    }
    #[inline]
    fn decode<B>(buf: &mut B) -> Result<i32> where B: Buf {
        decode_varint(buf).map(|value| {
            let value = value as i32;
            (value >> 1) ^ -(value & 1)
        })
    }
    #[inline]
    fn encoded_len(self) -> usize {
        encoded_len_varint(((self << 1) ^ (self >> 31)) as u64)
    }
    #[inline]
    fn wire_type() -> WireType { WireType::Varint }
}
numeric_field!(i32, Signed);

// sint64
impl Numeric<Signed> for i64 {
    #[inline]
    fn encode<B>(self, buf: &mut B) where B: BufMut {
        encode_varint(((self << 1) ^ (self >> 63)) as u64, buf)
    }
    #[inline]
    fn decode<B>(buf: &mut B) -> Result<i64> where B: Buf {
        decode_varint(buf).map(|value| {
            let value = value as i64;
            (value >> 1) ^ -(value & 1)
        })
    }
    #[inline]
    fn encoded_len(self) -> usize {
        encoded_len_varint(((self << 1) ^ (self >> 63)) as u64)
    }
    #[inline]
    fn wire_type() -> WireType { WireType::Varint }
}
numeric_field!(i64, Signed);

// fixed32
impl Numeric<Fixed> for u32 {
    #[inline]
    fn encode<B>(self, buf: &mut B) where B: BufMut { buf.put_u32::<LittleEndian>(self) }
    #[inline]
    fn decode<B>(buf: &mut B) -> Result<u32> where B: Buf {
        if buf.remaining() < 4 {
            return Err(invalid_input("failed to decode fixed32: buffer underflow"));
        }
        Ok(buf.get_u32::<LittleEndian>())
    }
    #[inline]
    fn encoded_len(self) -> usize { 4 }
    #[inline]
    fn wire_type() -> WireType { WireType::ThirtyTwoBit }
}
numeric_field!(u32, Fixed);

// fixed64
impl Numeric<Fixed> for u64 {
    #[inline]
    fn encode<B>(self, buf: &mut B) where B: BufMut { buf.put_u64::<LittleEndian>(self) }
    #[inline]
    fn decode<B>(buf: &mut B) -> Result<u64> where B: Buf {
        if buf.remaining() < 8 {
            return Err(invalid_input("failed to decode fixed64: buffer underflow"));
        }
        Ok(buf.get_u64::<LittleEndian>())
    }
    #[inline]
    fn encoded_len(self) -> usize { 8 }
    #[inline]
    fn wire_type() -> WireType { WireType::SixtyFourBit }
}
numeric_field!(u64, Fixed);

// sfixed32
impl Numeric<Fixed> for i32 {
    #[inline]
    fn encode<B>(self, buf: &mut B) where B: BufMut { buf.put_i32::<LittleEndian>(self) }
    #[inline]
    fn decode<B>(buf: &mut B) -> Result<i32> where B: Buf {
        if buf.remaining() < 4 {
            return Err(invalid_input("failed to decode sfixed32: buffer underflow"));
        }
        Ok(buf.get_i32::<LittleEndian>())
    }
    #[inline]
    fn encoded_len(self) -> usize { 4 }
    #[inline]
    fn wire_type() -> WireType { WireType::ThirtyTwoBit }
}
numeric_field!(i32, Fixed);

// sfixed64
impl Numeric<Fixed> for i64 {
    #[inline]
    fn encode<B>(self, buf: &mut B) where B: BufMut { buf.put_i64::<LittleEndian>(self); }
    #[inline]
    fn decode<B>(buf: &mut B) -> Result<i64> where B: Buf {
        if buf.remaining() < 8 {
            return Err(invalid_input("failed to decode sfixed64 field: buffer underflow"));
        }
        Ok(buf.get_i64::<LittleEndian>())
    }
    #[inline]
    fn encoded_len(self) -> usize { 8 }
    #[inline]
    fn wire_type() -> WireType { WireType::SixtyFourBit }
}
numeric_field!(i64, Fixed);
<|endoftext|>


<commit_before>use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};

use {Future, Poll, Async};
use slot::{Slot, Token};
use lock::Lock;
use task::{self, Task};

/// A future representing the completion of a computation happening elsewhere in
/// memory.
///
/// This is created by the `oneshot` function.
#[must_use = "futures do nothing unless polled"]
pub struct Oneshot<T> {
    inner: Arc<Inner<T>>,
    cancel_token: Option<Token>,
}

/// Represents the completion half of a oneshot through which the result of a
/// computation is signaled.
///
/// This is created by the `oneshot` function.
pub struct Complete<T> {
    inner: Arc<Inner<T>>,
    completed: bool,
}

struct Inner<T> {
    slot: Slot<Option<T>>,
    oneshot_gone: AtomicBool,
    notify_cancel: Lock<Option<Task>>,
}

/// Creates a new in-memory oneshot used to represent completing a computation.
///
/// A oneshot in this library is a concrete implementation of the `Future` trait
/// used to complete a computation from one location with a future representing
/// what to do in another.
///
/// This function is similar to Rust's channels found in the standard library.
/// Two halves are returned, the first of which is a `Complete` handle, used to
/// signal the end of a computation and provide its value. The second half is a
/// `Oneshot` which implements the `Future` trait, resolving to the value that
/// was given to the `Complete` handle.
///
/// Each half can be separately owned and sent across threads.
///
/// # Examples
///
/// ```
/// use std::thread;
/// use futures::*;
///
/// let (c, p) = oneshot::<i32>();
///
/// thread::spawn(|| {
///     p.map(|i| {
///         println!("got: {}", i);
///     }).wait();
/// });
///
/// c.complete(3);
/// ```
pub fn oneshot<T>() -> (Complete<T>, Oneshot<T>) {
    let inner = Arc::new(Inner {
        slot: Slot::new(None),
        oneshot_gone: AtomicBool::new(false),
        notify_cancel: Lock::new(None),
    });
    let oneshot = Oneshot {
        inner: inner.clone(),
        cancel_token: None,
    };
    let complete = Complete {
        inner: inner,
        completed: false,
    };
    (complete, oneshot)
}

impl<T> Complete<T> {
    /// Completes this oneshot with a successful result.
    ///
    /// This function will consume `self` and indicate to the other end, the
    /// `Oneshot`, that the error provided is the result of the computation this
    /// represents.
    pub fn complete(mut self, t: T) {
        self.completed = true;
        self.send(Some(t))
    }

    /// Polls this `Complete` half to detect whether the `Oneshot` this has
    /// paired with has gone away.
    ///
    /// This function can be used to learn about when the `Oneshot` (consumer)
    /// half has gone away and nothing will be able to receive a message sent
    /// from `complete`.
    ///
    /// Like `Future::poll`, this function will panic if it's not called from
    /// within the context of a task. In otherwords, this should only ever be
    /// called from inside another future.
    ///
    /// If `Ready` is returned then it means that the `Oneshot` has disappeared
    /// and the result this `Complete` would otherwise produce should no longer
    /// be produced.
    ///
    /// If `NotReady` is returned then the `Oneshot` is still alive and may be
    /// able to receive a message if sent. The current task, however, is
    /// scheduled to receive a notification if the corresponding `Oneshot` goes
    /// away.
    pub fn poll_cancel(&mut self) -> Poll<(), ()> {
        // Fast path up first, just read the flag and see if our other half is
        // gone.
        if self.inner.oneshot_gone.load(Ordering::SeqCst) {
            return Ok(Async::Ready(()))
        }

        // If our other half is not gone then we need to park our current task
        // and move it into the `notify_cancel` slot to get notified when it's
        // actually gone.
        //
        // If `try_lock` fails, then the `Oneshot` is in the process of using
        // it, so we can deduce that it's now in the process of going away and
        // hence we're canceled. If it succeeds then we just store our handle.
        //
        // Crucially we then check `oneshot_gone` *again* before we return.
        // While we were storing our handle inside `notify_cancel` the `Oneshot`
        // may have been dropped. The first thing it does is set the flag, and
        // if it fails to acquire the lock it assumes that we'll see the flag
        // later on. So... we then try to see the flag later on!
        let handle = task::park();
        match self.inner.notify_cancel.try_lock() {
            Some(mut p) => *p = Some(handle),
            None => return Ok(Async::Ready(())),
        }
        if self.inner.oneshot_gone.load(Ordering::SeqCst) {
            Ok(Async::Ready(()))
        } else {
            Ok(Async::NotReady)
        }
    }

    fn send(&mut self, t: Option<T>) {
        if let Err(e) = self.inner.slot.try_produce(t) {
            self.inner.slot.on_empty(Some(e.into_inner()), |slot, item| {
                slot.try_produce(item.unwrap()).ok()
                    .expect("advertised as empty but wasn't");
            });
        }
    }
}

impl<T> Drop for Complete<T> {
    fn drop(&mut self) {
        if !self.completed {
            self.send(None);
        }
    }
}

/// Error returned from a `Oneshot<T>` whenever the correponding `Complete<T>`
/// is dropped.
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct Canceled;

impl<T> Future for Oneshot<T> {
    type Item = T;
    type Error = Canceled;

    fn poll(&mut self) -> Poll<T, Canceled> {
        if let Some(cancel_token) = self.cancel_token.take() {
            self.inner.slot.cancel(cancel_token);
        }
        match self.inner.slot.try_consume() {
            Ok(Some(e)) => Ok(Async::Ready(e)),
            Ok(None) => Err(Canceled),
            Err(_) => {
                let task = task::park();
                self.cancel_token = Some(self.inner.slot.on_full(move |_| {
                    task.unpark();
                }));
                Ok(Async::NotReady)
            }
        }
    }
}

impl<T> Drop for Oneshot<T> {
    fn drop(&mut self) {
        // First up, if we squirreled away a task to get notified once the
        // oneshot was filled in, we cancel that notification. We'll never end
        // up actually receiving data (as we're being dropped) so no need to
        // hold onto the task.
        if let Some(cancel_token) = self.cancel_token.take() {
            self.inner.slot.cancel(cancel_token)
        }

        // Next up, inform the `Complete` half that we're going away. First up
        // we flag ourselves as gone, and next we'll attempt to wake up any
        // handle that was stored.
        //
        // If we fail to acquire the lock on the handle, that means that a
        // `Complete` is in the process of storing one, and it'll check
        // `oneshot_gone` on its way out to see our write here.
        self.inner.oneshot_gone.store(true, Ordering::SeqCst);
        if let Some(mut handle) = self.inner.notify_cancel.try_lock() {
            if let Some(task) = handle.take() {
                drop(handle);
                task.unpark()
            }
        }
    }
}
<commit_msg>impl Error for Oneshot<commit_after>use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::error::Error;
use std::fmt;

use {Future, Poll, Async};
use slot::{Slot, Token};
use lock::Lock;
use task::{self, Task};

/// A future representing the completion of a computation happening elsewhere in
/// memory.
///
/// This is created by the `oneshot` function.
#[must_use = "futures do nothing unless polled"]
pub struct Oneshot<T> {
    inner: Arc<Inner<T>>,
    cancel_token: Option<Token>,
}

/// Represents the completion half of a oneshot through which the result of a
/// computation is signaled.
///
/// This is created by the `oneshot` function.
pub struct Complete<T> {
    inner: Arc<Inner<T>>,
    completed: bool,
}

struct Inner<T> {
    slot: Slot<Option<T>>,
    oneshot_gone: AtomicBool,
    notify_cancel: Lock<Option<Task>>,
}

/// Creates a new in-memory oneshot used to represent completing a computation.
///
/// A oneshot in this library is a concrete implementation of the `Future` trait
/// used to complete a computation from one location with a future representing
/// what to do in another.
///
/// This function is similar to Rust's channels found in the standard library.
/// Two halves are returned, the first of which is a `Complete` handle, used to
/// signal the end of a computation and provide its value. The second half is a
/// `Oneshot` which implements the `Future` trait, resolving to the value that
/// was given to the `Complete` handle.
///
/// Each half can be separately owned and sent across threads.
///
/// # Examples
///
/// ```
/// use std::thread;
/// use futures::*;
///
/// let (c, p) = oneshot::<i32>();
///
/// thread::spawn(|| {
///     p.map(|i| {
///         println!("got: {}", i);
///     }).wait();
/// });
///
/// c.complete(3);
/// ```
pub fn oneshot<T>() -> (Complete<T>, Oneshot<T>) {
    let inner = Arc::new(Inner {
        slot: Slot::new(None),
        oneshot_gone: AtomicBool::new(false),
        notify_cancel: Lock::new(None),
    });
    let oneshot = Oneshot {
        inner: inner.clone(),
        cancel_token: None,
    };
    let complete = Complete {
        inner: inner,
        completed: false,
    };
    (complete, oneshot)
}

impl<T> Complete<T> {
    /// Completes this oneshot with a successful result.
    ///
    /// This function will consume `self` and indicate to the other end, the
    /// `Oneshot`, that the error provided is the result of the computation this
    /// represents.
    pub fn complete(mut self, t: T) {
        self.completed = true;
        self.send(Some(t))
    }

    /// Polls this `Complete` half to detect whether the `Oneshot` this has
    /// paired with has gone away.
    ///
    /// This function can be used to learn about when the `Oneshot` (consumer)
    /// half has gone away and nothing will be able to receive a message sent
    /// from `complete`.
    ///
    /// Like `Future::poll`, this function will panic if it's not called from
    /// within the context of a task. In otherwords, this should only ever be
    /// called from inside another future.
    ///
    /// If `Ready` is returned then it means that the `Oneshot` has disappeared
    /// and the result this `Complete` would otherwise produce should no longer
    /// be produced.
    ///
    /// If `NotReady` is returned then the `Oneshot` is still alive and may be
    /// able to receive a message if sent. The current task, however, is
    /// scheduled to receive a notification if the corresponding `Oneshot` goes
    /// away.
    pub fn poll_cancel(&mut self) -> Poll<(), ()> {
        // Fast path up first, just read the flag and see if our other half is
        // gone.
        if self.inner.oneshot_gone.load(Ordering::SeqCst) {
            return Ok(Async::Ready(()))
        }

        // If our other half is not gone then we need to park our current task
        // and move it into the `notify_cancel` slot to get notified when it's
        // actually gone.
        //
        // If `try_lock` fails, then the `Oneshot` is in the process of using
        // it, so we can deduce that it's now in the process of going away and
        // hence we're canceled. If it succeeds then we just store our handle.
        //
        // Crucially we then check `oneshot_gone` *again* before we return.
        // While we were storing our handle inside `notify_cancel` the `Oneshot`
        // may have been dropped. The first thing it does is set the flag, and
        // if it fails to acquire the lock it assumes that we'll see the flag
        // later on. So... we then try to see the flag later on!
        let handle = task::park();
        match self.inner.notify_cancel.try_lock() {
            Some(mut p) => *p = Some(handle),
            None => return Ok(Async::Ready(())),
        }
        if self.inner.oneshot_gone.load(Ordering::SeqCst) {
            Ok(Async::Ready(()))
        } else {
            Ok(Async::NotReady)
        }
    }

    fn send(&mut self, t: Option<T>) {
        if let Err(e) = self.inner.slot.try_produce(t) {
            self.inner.slot.on_empty(Some(e.into_inner()), |slot, item| {
                slot.try_produce(item.unwrap()).ok()
                    .expect("advertised as empty but wasn't");
            });
        }
    }
}

impl<T> Drop for Complete<T> {
    fn drop(&mut self) {
        if !self.completed {
            self.send(None);
        }
    }
}

/// Error returned from a `Oneshot<T>` whenever the correponding `Complete<T>`
/// is dropped.
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct Canceled;

impl fmt::Display for Canceled {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "oneshot canceled")
    }
}

impl Error for Canceled {
    fn description(&self) -> &str {
        "oneshot canceled"
    }
}

impl<T> Future for Oneshot<T> {
    type Item = T;
    type Error = Canceled;

    fn poll(&mut self) -> Poll<T, Canceled> {
        if let Some(cancel_token) = self.cancel_token.take() {
            self.inner.slot.cancel(cancel_token);
        }
        match self.inner.slot.try_consume() {
            Ok(Some(e)) => Ok(Async::Ready(e)),
            Ok(None) => Err(Canceled),
            Err(_) => {
                let task = task::park();
                self.cancel_token = Some(self.inner.slot.on_full(move |_| {
                    task.unpark();
                }));
                Ok(Async::NotReady)
            }
        }
    }
}

impl<T> Drop for Oneshot<T> {
    fn drop(&mut self) {
        // First up, if we squirreled away a task to get notified once the
        // oneshot was filled in, we cancel that notification. We'll never end
        // up actually receiving data (as we're being dropped) so no need to
        // hold onto the task.
        if let Some(cancel_token) = self.cancel_token.take() {
            self.inner.slot.cancel(cancel_token)
        }

        // Next up, inform the `Complete` half that we're going away. First up
        // we flag ourselves as gone, and next we'll attempt to wake up any
        // handle that was stored.
        //
        // If we fail to acquire the lock on the handle, that means that a
        // `Complete` is in the process of storing one, and it'll check
        // `oneshot_gone` on its way out to see our write here.
        self.inner.oneshot_gone.store(true, Ordering::SeqCst);
        if let Some(mut handle) = self.inner.notify_cancel.try_lock() {
            if let Some(task) = handle.take() {
                drop(handle);
                task.unpark()
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::ffi::CString;
use std::ptr;

use class::TypeParams;
use ctxt::{Fct, FctParent, FctSrc, SemContext};
use ty::{BuiltinType, MachineMode};

use dora_parser::ast::*;
use dora_parser::ast::Expr::*;
use dora_parser::ast::Stmt::*;
use dora_parser::lexer::token::{FloatSuffix, IntSuffix};

use llvm;
use llvm::analysis::*;
use llvm::core::*;
use llvm::orc::*;
// use llvm::execution_engine::*;
// use llvm::target::*;

pub mod util;

pub fn generate_fct<'ast>(
    ctxt: &SemContext<'ast>,
    fct: &Fct<'ast>,
    src: &mut FctSrc,
    cls_type_params: &TypeParams,
    fct_type_params: &TypeParams,
) -> Result<*const u8, ()> {
    let name = fct.full_name(ctxt);

    let mut cg = CodeGen {
        ctxt: ctxt,
        fct: fct,
        ast: fct.ast,
        src: src,
        cls_type_params,
        fct_type_params,

        fct_name: CString::new(name).unwrap(),

        context: ptr::null_mut(),
        module: ptr::null_mut(),
        builder: ptr::null_mut(),
        function: ptr::null_mut(),
    };

    cg.generate()
}

type EmitResult<T> = Result<T, ()>;

fn fail<T>() -> EmitResult<T> {
    Err(())
}

fn ok<T>(value: T) -> EmitResult<T> {
    Ok(value)
}

struct CodeGen<'a, 'ast: 'a> {
    ctxt: &'a SemContext<'ast>,
    fct: &'a Fct<'ast>,
    ast: &'ast Function,
    src: &'a mut FctSrc,
    cls_type_params: &'a TypeParams,
    fct_type_params: &'a TypeParams,

    fct_name: CString,

    context: *mut llvm::LLVMContext,
    module: *mut llvm::LLVMModule,
    builder: *mut llvm::LLVMBuilder,
    function: *mut llvm::LLVMValue,
}

impl<'a, 'ast> CodeGen<'a, 'ast>
where
    'ast: 'a,
{
    fn generate(&mut self) -> EmitResult<*const u8> {
        self.init();
        self.create_function()?;
        self.add_entry_bb();

        let block = self.ast.block.as_ref().unwrap();
        self.emit_stmt(block)?;

        unsafe {
            LLVMDisposeBuilder(self.builder);
        }

        self.verify()?;

        if self.ctxt.args.flag_emit_llvm {
            unsafe {
                LLVMDumpModule(self.module);
            }
        }

        let orc = self.ctxt.llvm_jit.orc;
        let mut ptr = 0;

        unsafe {
            // add eagerly compiled IR

            if LLVMOrcGetSymbolAddress(orc, &mut ptr, self.fct_name.as_ptr()) == LLVMOrcErrorCode::LLVMOrcErrSuccess {
                assert!(ptr != 0);

                ok(ptr as *const u8)
            } else {
                fail()
            }
        }
    }

    fn init(&mut self) {
        unsafe {
            self.context = LLVMContextCreate();
            self.module = LLVMModuleCreateWithNameInContext(
                self.fct_name.as_ptr(),
                self.context,
            );
            self.builder = LLVMCreateBuilderInContext(self.context);
        }
    }

    fn create_function(&mut self) -> EmitResult<()> {
        let mut params = Vec::with_capacity(self.ast.params.len());

        for param in &self.ast.params {
            let ty = self.ty(param.id);
            params.push(self.llvm_ty(ty));
        }

        let return_type = self.specialize_type(self.fct.return_type);
        let llvm_return_type = self.llvm_ty(return_type);

        unsafe {
            let function_type = LLVMFunctionType(
                llvm_return_type,
                params.as_mut_ptr(),
                params.len() as u32,
                0);

            self.function = LLVMAddFunction(self.module, self.fct_name.as_ptr(), function_type);
        }

        ok(())
    }

    fn add_entry_bb(&mut self) {
        unsafe {
            let bb = LLVMAppendBasicBlockInContext(
                self.context,
                self.function,
                b"entry\0".as_ptr() as *const _);

            LLVMPositionBuilderAtEnd(self.builder, bb);
        }
    }

    fn verify(&mut self) -> EmitResult<()> {
        unsafe {
            if LLVMVerifyFunction(self.function,
                                  LLVMVerifierFailureAction::LLVMPrintMessageAction) == 1 {
                println!("invalid llvm function!");
                fail()
            } else {
                ok(())
            }
        }
    }

    fn emit_stmt(&mut self, s: &'ast Stmt) -> EmitResult<()> {
        match *s {
            StmtExpr(ref stmt) => {
                self.emit_expr(&stmt.expr)?;

                Ok(())
            }

            StmtIf(_) => fail(),
            StmtLoop(_) => fail(),
            StmtWhile(_) => fail(),
            StmtFor(_) => fail(),
            StmtReturn(ref stmt) => self.emit_return(stmt),
            StmtBreak(_) => fail(),
            StmtContinue(_) => fail(),
            StmtBlock(ref stmt) => self.emit_block(stmt),
            StmtVar(_) => fail(),
            StmtThrow(_) => fail(),
            StmtDefer(_) => fail(),
            StmtDo(_) => fail(),
            StmtSpawn(_) => fail(),
        }
    }

    fn emit_return(&mut self, s: &'ast StmtReturnType) -> EmitResult<()> {
        if let Some(ref expr) = s.expr {
            let value = self.emit_expr(expr)?;

            unsafe {
                LLVMBuildRet(self.builder, value);
            }

        } else {
            unsafe {
                LLVMBuildRetVoid(self.builder);
            }
        }

        ok(())
    }

    fn emit_block(&mut self, s: &'ast StmtBlockType) -> EmitResult<()> {
        for stmt in &s.stmts {
            self.emit_stmt(stmt)?;
        }

        ok(())
    }

    fn emit_expr(&mut self, e: &'ast Expr) -> EmitResult<*mut llvm::LLVMValue> {
        match *e {
            ExprLitChar(ref lit) => self.emit_lit_char(lit),
            ExprLitInt(ref lit) => self.emit_lit_int(lit),
            ExprLitFloat(ref lit) => self.emit_lit_float(lit),
            ExprLitBool(_) => fail(),
            ExprLitStr(_) => fail(),
            ExprLitStruct(_) => fail(),
            ExprUn(_) => fail(),
            ExprIdent(_) => fail(),
            ExprAssign(_) => fail(),
            ExprBin(_) => fail(),
            ExprCall(_) => fail(),
            ExprDelegation(_) => fail(),
            ExprField(_) => fail(),
            ExprSelf(_) => fail(),
            ExprSuper(_) => fail(),
            ExprNil(_) => fail(),
            ExprArray(_) => fail(),
            ExprConv(_) => fail(),
            ExprTry(_) => fail(),
            ExprLambda(_) => fail(),
        }
    }

    fn emit_lit_char(&mut self, e: &'ast ExprLitCharType) -> EmitResult<*mut llvm::LLVMValue> {
        unsafe {
            let ty = LLVMInt32TypeInContext(self.context);
            let value = LLVMConstInt(ty, e.value as u64, 0);
            ok(value)
        }
    }

    fn emit_lit_int(&mut self, e: &'ast ExprLitIntType) -> EmitResult<*mut llvm::LLVMValue> {
        unsafe {
            let ty = match e.suffix {
                IntSuffix::Byte => LLVMInt8TypeInContext(self.context),
                IntSuffix::Int => LLVMInt32TypeInContext(self.context),
                IntSuffix::Long => LLVMInt64TypeInContext(self.context),
            };

            let value = LLVMConstInt(ty, e.value, 0);
            ok(value)
        }
    }

    fn emit_lit_float(&mut self, e: &'ast ExprLitFloatType) -> EmitResult<*mut llvm::LLVMValue> {
        unsafe {
            let ty = match e.suffix {
                FloatSuffix::Float => LLVMFloatTypeInContext(self.context),
                FloatSuffix::Double => LLVMDoubleTypeInContext(self.context),
            };

            let value = LLVMConstReal(ty, e.value);
            ok(value)
        }
    }

    fn ty(&self, id: NodeId) -> BuiltinType {
        let ty = self.src.ty(id);
        self.specialize_type(ty)
    }

    fn specialize_type(&self, ty: BuiltinType) -> BuiltinType {
        match ty {
            BuiltinType::ClassTypeParam(cls_id, id) => {
                assert!(self.fct.parent == FctParent::Class(cls_id));
                self.cls_type_params[id.idx()]
            }

            BuiltinType::FctTypeParam(fct_id, id) => {
                assert!(self.fct.id == fct_id);
                self.fct_type_params[id.idx()]
            }

            BuiltinType::Class(cls_id, list_id) => {
                let params = self.ctxt.lists.borrow().get(list_id);

                let params: Vec<_> = params.iter().map(|t| self.specialize_type(t)).collect();

                let list_id = self.ctxt.lists.borrow_mut().insert(params.into());

                BuiltinType::Class(cls_id, list_id)
            }

            BuiltinType::Lambda(_) => unimplemented!(),

            _ => ty,
        }
    }

    fn llvm_ty(&self, ty: BuiltinType) -> *mut llvm::LLVMType {
        let mode = ty.mode();

        unsafe {
            match mode {
                MachineMode::Int64 => LLVMInt64TypeInContext(self.context),
                MachineMode::Int32 => LLVMInt32TypeInContext(self.context),
                MachineMode::Int8 => LLVMInt8TypeInContext(self.context),
                MachineMode::Float32 => LLVMFloatTypeInContext(self.context),
                MachineMode::Float64 => LLVMDoubleTypeInContext(self.context),
                MachineMode::Ptr => {
                    let int8 = LLVMInt8TypeInContext(self.context);
                    LLVMPointerType(int8, 1)
                }
            }
        }
    }
}
<commit_msg>opt: added module to JIT<commit_after>use std::ffi::{CStr, CString};
use std::ptr;

use libc;

use class::TypeParams;
use ctxt::{Fct, FctParent, FctSrc, SemContext};
use ty::{BuiltinType, MachineMode};

use dora_parser::ast::*;
use dora_parser::ast::Expr::*;
use dora_parser::ast::Stmt::*;
use dora_parser::lexer::token::{FloatSuffix, IntSuffix};

use llvm;
use llvm::analysis::*;
use llvm::core::*;
use llvm::orc::*;
// use llvm::execution_engine::*;
// use llvm::target::*;

pub mod util;

pub fn generate_fct<'ast>(
    ctxt: &SemContext<'ast>,
    fct: &Fct<'ast>,
    src: &mut FctSrc,
    cls_type_params: &TypeParams,
    fct_type_params: &TypeParams,
) -> Result<*const u8, ()> {
    let name = fct.full_name(ctxt);

    let mut cg = CodeGen {
        ctxt: ctxt,
        fct: fct,
        ast: fct.ast,
        src: src,
        cls_type_params,
        fct_type_params,

        fct_name: CString::new(name).unwrap(),

        context: ptr::null_mut(),
        module: ptr::null_mut(),
        builder: ptr::null_mut(),
        function: ptr::null_mut(),
    };

    cg.generate()
}

type EmitResult<T> = Result<T, ()>;

fn fail<T>() -> EmitResult<T> {
    Err(())
}

fn ok<T>(value: T) -> EmitResult<T> {
    Ok(value)
}

struct CodeGen<'a, 'ast: 'a> {
    ctxt: &'a SemContext<'ast>,
    fct: &'a Fct<'ast>,
    ast: &'ast Function,
    src: &'a mut FctSrc,
    cls_type_params: &'a TypeParams,
    fct_type_params: &'a TypeParams,

    fct_name: CString,

    context: *mut llvm::LLVMContext,
    module: *mut llvm::LLVMModule,
    builder: *mut llvm::LLVMBuilder,
    function: *mut llvm::LLVMValue,
}

impl<'a, 'ast> CodeGen<'a, 'ast>
where
    'ast: 'a,
{
    fn generate(&mut self) -> EmitResult<*const u8> {
        self.init();
        self.create_function()?;
        self.add_entry_bb();

        let block = self.ast.block.as_ref().unwrap();
        self.emit_stmt(block)?;

        unsafe {
            LLVMDisposeBuilder(self.builder);
        }

        self.verify()?;

        if self.ctxt.args.flag_emit_llvm {
            unsafe {
                LLVMDumpModule(self.module);
            }
        }

        let orc = self.ctxt.llvm_jit.orc;
        let mut ptr = 0;

        unsafe {
            // add eagerly compiled IR
            LLVMOrcAddEagerlyCompiledIR(orc, ptr::null_mut(), self.module, resolver, self.ctxt as *const _ as *mut _);

            if LLVMOrcGetSymbolAddress(orc, &mut ptr, self.fct_name.as_ptr()) == LLVMOrcErrorCode::LLVMOrcErrSuccess {
                assert!(ptr != 0);

                ok(ptr as *const u8)
            } else {
                fail()
            }
        }
    }

    fn init(&mut self) {
        unsafe {
            self.context = LLVMContextCreate();
            self.module = LLVMModuleCreateWithNameInContext(
                self.fct_name.as_ptr(),
                self.context,
            );
            self.builder = LLVMCreateBuilderInContext(self.context);
        }
    }

    fn create_function(&mut self) -> EmitResult<()> {
        let mut params = Vec::with_capacity(self.ast.params.len());

        for param in &self.ast.params {
            let ty = self.ty(param.id);
            params.push(self.llvm_ty(ty));
        }

        let return_type = self.specialize_type(self.fct.return_type);
        let llvm_return_type = self.llvm_ty(return_type);

        unsafe {
            let function_type = LLVMFunctionType(
                llvm_return_type,
                params.as_mut_ptr(),
                params.len() as u32,
                0);

            self.function = LLVMAddFunction(self.module, self.fct_name.as_ptr(), function_type);
        }

        ok(())
    }

    fn add_entry_bb(&mut self) {
        unsafe {
            let bb = LLVMAppendBasicBlockInContext(
                self.context,
                self.function,
                b"entry\0".as_ptr() as *const _);

            LLVMPositionBuilderAtEnd(self.builder, bb);
        }
    }

    fn verify(&mut self) -> EmitResult<()> {
        unsafe {
            if LLVMVerifyFunction(self.function,
                                  LLVMVerifierFailureAction::LLVMPrintMessageAction) == 1 {
                println!("invalid llvm function!");
                fail()
            } else {
                ok(())
            }
        }
    }

    fn emit_stmt(&mut self, s: &'ast Stmt) -> EmitResult<()> {
        match *s {
            StmtExpr(ref stmt) => {
                self.emit_expr(&stmt.expr)?;

                Ok(())
            }

            StmtIf(_) => fail(),
            StmtLoop(_) => fail(),
            StmtWhile(_) => fail(),
            StmtFor(_) => fail(),
            StmtReturn(ref stmt) => self.emit_return(stmt),
            StmtBreak(_) => fail(),
            StmtContinue(_) => fail(),
            StmtBlock(ref stmt) => self.emit_block(stmt),
            StmtVar(_) => fail(),
            StmtThrow(_) => fail(),
            StmtDefer(_) => fail(),
            StmtDo(_) => fail(),
            StmtSpawn(_) => fail(),
        }
    }

    fn emit_return(&mut self, s: &'ast StmtReturnType) -> EmitResult<()> {
        if let Some(ref expr) = s.expr {
            let value = self.emit_expr(expr)?;

            unsafe {
                LLVMBuildRet(self.builder, value);
            }

        } else {
            unsafe {
                LLVMBuildRetVoid(self.builder);
            }
        }

        ok(())
    }

    fn emit_block(&mut self, s: &'ast StmtBlockType) -> EmitResult<()> {
        for stmt in &s.stmts {
            self.emit_stmt(stmt)?;
        }

        ok(())
    }

    fn emit_expr(&mut self, e: &'ast Expr) -> EmitResult<*mut llvm::LLVMValue> {
        match *e {
            ExprLitChar(ref lit) => self.emit_lit_char(lit),
            ExprLitInt(ref lit) => self.emit_lit_int(lit),
            ExprLitFloat(ref lit) => self.emit_lit_float(lit),
            ExprLitBool(_) => fail(),
            ExprLitStr(_) => fail(),
            ExprLitStruct(_) => fail(),
            ExprUn(_) => fail(),
            ExprIdent(_) => fail(),
            ExprAssign(_) => fail(),
            ExprBin(_) => fail(),
            ExprCall(_) => fail(),
            ExprDelegation(_) => fail(),
            ExprField(_) => fail(),
            ExprSelf(_) => fail(),
            ExprSuper(_) => fail(),
            ExprNil(_) => fail(),
            ExprArray(_) => fail(),
            ExprConv(_) => fail(),
            ExprTry(_) => fail(),
            ExprLambda(_) => fail(),
        }
    }

    fn emit_lit_char(&mut self, e: &'ast ExprLitCharType) -> EmitResult<*mut llvm::LLVMValue> {
        unsafe {
            let ty = LLVMInt32TypeInContext(self.context);
            let value = LLVMConstInt(ty, e.value as u64, 0);
            ok(value)
        }
    }

    fn emit_lit_int(&mut self, e: &'ast ExprLitIntType) -> EmitResult<*mut llvm::LLVMValue> {
        unsafe {
            let ty = match e.suffix {
                IntSuffix::Byte => LLVMInt8TypeInContext(self.context),
                IntSuffix::Int => LLVMInt32TypeInContext(self.context),
                IntSuffix::Long => LLVMInt64TypeInContext(self.context),
            };

            let value = LLVMConstInt(ty, e.value, 0);
            ok(value)
        }
    }

    fn emit_lit_float(&mut self, e: &'ast ExprLitFloatType) -> EmitResult<*mut llvm::LLVMValue> {
        unsafe {
            let ty = match e.suffix {
                FloatSuffix::Float => LLVMFloatTypeInContext(self.context),
                FloatSuffix::Double => LLVMDoubleTypeInContext(self.context),
            };

            let value = LLVMConstReal(ty, e.value);
            ok(value)
        }
    }

    fn ty(&self, id: NodeId) -> BuiltinType {
        let ty = self.src.ty(id);
        self.specialize_type(ty)
    }

    fn specialize_type(&self, ty: BuiltinType) -> BuiltinType {
        match ty {
            BuiltinType::ClassTypeParam(cls_id, id) => {
                assert!(self.fct.parent == FctParent::Class(cls_id));
                self.cls_type_params[id.idx()]
            }

            BuiltinType::FctTypeParam(fct_id, id) => {
                assert!(self.fct.id == fct_id);
                self.fct_type_params[id.idx()]
            }

            BuiltinType::Class(cls_id, list_id) => {
                let params = self.ctxt.lists.borrow().get(list_id);

                let params: Vec<_> = params.iter().map(|t| self.specialize_type(t)).collect();

                let list_id = self.ctxt.lists.borrow_mut().insert(params.into());

                BuiltinType::Class(cls_id, list_id)
            }

            BuiltinType::Lambda(_) => unimplemented!(),

            _ => ty,
        }
    }

    fn llvm_ty(&self, ty: BuiltinType) -> *mut llvm::LLVMType {
        let mode = ty.mode();

        unsafe {
            match mode {
                MachineMode::Int64 => LLVMInt64TypeInContext(self.context),
                MachineMode::Int32 => LLVMInt32TypeInContext(self.context),
                MachineMode::Int8 => LLVMInt8TypeInContext(self.context),
                MachineMode::Float32 => LLVMFloatTypeInContext(self.context),
                MachineMode::Float64 => LLVMDoubleTypeInContext(self.context),
                MachineMode::Ptr => {
                    let int8 = LLVMInt8TypeInContext(self.context);
                    LLVMPointerType(int8, 1)
                }
            }
        }
    }
}

extern "C" fn resolver(name: *const i8, _: *mut libc::c_void) -> u64 {
    let name = unsafe { CStr::from_ptr(name) };
    panic!("resolver unimplemented: {:?}", name);
}<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use check::{FnCtxt, structurally_resolved_type};
use middle::traits::{self, ObjectSafetyViolation, MethodViolationCode};
use middle::traits::{Obligation, ObligationCause};
use middle::traits::report_fulfillment_errors;
use middle::ty::{self, Ty, AsPredicate};
use middle::infer;
use syntax::ast;
use syntax::codemap::Span;
use util::nodemap::FnvHashSet;
use util::ppaux::{Repr, UserString};

pub fn check_object_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                   cast_expr: &ast::Expr,
                                   source_expr: &ast::Expr,
                                   target_object_ty: Ty<'tcx>)
{
    debug!("check_object_cast(cast_expr={}, target_object_ty={})",
           cast_expr.repr(fcx.tcx()),
           target_object_ty.repr(fcx.tcx()));

    // Look up vtables for the type we're casting to,
    // passing in the source and target type.  The source
    // must be a pointer type suitable to the object sigil,
    // e.g.: `&x as &Trait` or `box x as Box<Trait>`
    let source_ty = fcx.expr_ty(source_expr);
    let source_ty = structurally_resolved_type(fcx, source_expr.span, source_ty);
    debug!("source_ty={}", source_ty.repr(fcx.tcx()));
    match (&source_ty.sty, &target_object_ty.sty) {
        (&ty::ty_uniq(referent_ty), &ty::ty_uniq(object_trait_ty)) => {
            let object_trait = object_trait(&object_trait_ty);

            // Ensure that if ~T is cast to ~Trait, then T : Trait
            push_cast_obligation(fcx, cast_expr, object_trait, referent_ty);
            check_object_safety(fcx.tcx(), object_trait, source_expr.span);
        }

        (&ty::ty_rptr(referent_region, ty::mt { ty: referent_ty,
                                                mutbl: referent_mutbl }),
         &ty::ty_rptr(target_region, ty::mt { ty: object_trait_ty,
                                              mutbl: target_mutbl })) =>
        {
            let object_trait = object_trait(&object_trait_ty);
            if !mutability_allowed(referent_mutbl, target_mutbl) {
                span_err!(fcx.tcx().sess, source_expr.span, E0188,
                                        "types differ in mutability");
            } else {
                // Ensure that if &'a T is cast to &'b Trait, then T : Trait
                push_cast_obligation(fcx, cast_expr,
                                     object_trait,
                                     referent_ty);

                // Ensure that if &'a T is cast to &'b Trait, then 'b <= 'a
                infer::mk_subr(fcx.infcx(),
                               infer::RelateObjectBound(source_expr.span),
                               *target_region,
                               *referent_region);

                check_object_safety(fcx.tcx(), object_trait, source_expr.span);
            }
        }

        (_, &ty::ty_uniq(..)) => {
            span_err!(fcx.ccx.tcx.sess, source_expr.span, E0189,
                "can only cast a boxed pointer \
                         to a boxed object, not a {}",
                      ty::ty_sort_string(fcx.tcx(), source_ty));
        }

        (_, &ty::ty_rptr(..)) => {
            span_err!(fcx.ccx.tcx.sess, source_expr.span, E0190,
                "can only cast a &-pointer \
                         to an &-object, not a {}",
                        ty::ty_sort_string(fcx.tcx(), source_ty));
        }

        _ => {
            fcx.tcx().sess.span_bug(
                source_expr.span,
                "expected object type");
        }
    }

    fn object_trait<'a, 'tcx>(t: &'a Ty<'tcx>) -> &'a ty::TyTrait<'tcx> {
        match t.sty {
            ty::ty_trait(ref ty_trait) => &**ty_trait,
            _ => panic!("expected ty_trait")
        }
    }

    fn mutability_allowed(a_mutbl: ast::Mutability,
                          b_mutbl: ast::Mutability)
                          -> bool {
        a_mutbl == b_mutbl ||
            (a_mutbl == ast::MutMutable && b_mutbl == ast::MutImmutable)
    }

    fn push_cast_obligation<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                      cast_expr: &ast::Expr,
                                      object_trait: &ty::TyTrait<'tcx>,
                                      referent_ty: Ty<'tcx>) {
        let object_trait_ref =
            register_object_cast_obligations(fcx,
                                             cast_expr.span,
                                             object_trait,
                                             referent_ty);

        // Finally record the object_trait_ref for use during trans
        // (it would prob be better not to do this, but it's just kind
        // of a pain to have to reconstruct it).
        fcx.write_object_cast(cast_expr.id, object_trait_ref);
    }
}

// Check that a trait is 'object-safe'. This should be checked whenever a trait object
// is created (by casting or coercion, etc.). A trait is object-safe if all its
// methods are object-safe. A trait method is object-safe if it does not take
// self by value, has no type parameters and does not use the `Self` type, except
// in self position.
pub fn check_object_safety<'tcx>(tcx: &ty::ctxt<'tcx>,
                                 object_trait: &ty::TyTrait<'tcx>,
                                 span: Span)
{
    let object_trait_ref =
        object_trait.principal_trait_ref_with_self_ty(tcx, tcx.types.err);

    if traits::is_object_safe(tcx, object_trait_ref.clone()) {
        return;
    }

    span_err!(tcx.sess, span, E0038,
              "cannot convert to a trait object because trait `{}` is not object-safe",
              ty::item_path_str(tcx, object_trait_ref.def_id()));

    let violations = traits::object_safety_violations(tcx, object_trait_ref.clone());
    for violation in violations {
        match violation {
            ObjectSafetyViolation::SizedSelf => {
                tcx.sess.span_note(
                    span,
                    "the trait cannot require that `Self : Sized`");
            }

            ObjectSafetyViolation::Method(method, MethodViolationCode::ByValueSelf) => {
                tcx.sess.span_note(
                    span,
                    &format!("method `{}` has a receiver type of `Self`, \
                              which cannot be used with a trait object",
                             method.name.user_string(tcx)));
            }

            ObjectSafetyViolation::Method(method, MethodViolationCode::StaticMethod) => {
                tcx.sess.span_note(
                    span,
                    &format!("method `{}` has no receiver",
                             method.name.user_string(tcx)));
            }

            ObjectSafetyViolation::Method(method, MethodViolationCode::ReferencesSelf) => {
                tcx.sess.span_note(
                    span,
                    &format!("method `{}` references the `Self` type \
                              in its arguments or return type",
                             method.name.user_string(tcx)));
            }

            ObjectSafetyViolation::Method(method, MethodViolationCode::Generic) => {
                tcx.sess.span_note(
                    span,
                    &format!("method `{}` has generic type parameters",
                             method.name.user_string(tcx)));
            }
        }
    }
}

pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                                  span: Span,
                                                  object_trait: &ty::TyTrait<'tcx>,
                                                  referent_ty: Ty<'tcx>)
                                                  -> ty::PolyTraitRef<'tcx>
{
    // We can only make objects from sized types.
    fcx.register_builtin_bound(
        referent_ty,
        ty::BoundSized,
        traits::ObligationCause::new(span, fcx.body_id, traits::ObjectSized));

    // This is just for better error reporting. Kinda goofy. The object type stuff
    // needs some refactoring so there is a more convenient type to pass around.
    let object_trait_ty =
        ty::mk_trait(fcx.tcx(),
                     object_trait.principal.clone(),
                     object_trait.bounds.clone());

    debug!("register_object_cast_obligations: referent_ty={} object_trait_ty={}",
           referent_ty.repr(fcx.tcx()),
           object_trait_ty.repr(fcx.tcx()));

    let cause = ObligationCause::new(span,
                                     fcx.body_id,
                                     traits::ObjectCastObligation(object_trait_ty));

    // Create the obligation for casting from T to Trait.
    let object_trait_ref =
        object_trait.principal_trait_ref_with_self_ty(fcx.tcx(), referent_ty);
    let object_obligation =
        Obligation::new(cause.clone(), object_trait_ref.as_predicate());
    fcx.register_predicate(object_obligation);

    // Create additional obligations for all the various builtin
    // bounds attached to the object cast. (In other words, if the
    // object type is Foo+Send, this would create an obligation
    // for the Send check.)
    for builtin_bound in &object_trait.bounds.builtin_bounds {
        fcx.register_builtin_bound(
            referent_ty,
            builtin_bound,
            cause.clone());
    }

    // Create obligations for the projection predicates.
    let projection_bounds =
        object_trait.projection_bounds_with_self_ty(fcx.tcx(), referent_ty);
    for projection_bound in &projection_bounds {
        let projection_obligation =
            Obligation::new(cause.clone(), projection_bound.as_predicate());
        fcx.register_predicate(projection_obligation);
    }

    // Finally, check that there IS a projection predicate for every associated type.
    check_object_type_binds_all_associated_types(fcx.tcx(),
                                                 span,
                                                 object_trait);

    object_trait_ref
}

fn check_object_type_binds_all_associated_types<'tcx>(tcx: &ty::ctxt<'tcx>,
                                                      span: Span,
                                                      object_trait: &ty::TyTrait<'tcx>)
{
    let object_trait_ref =
        object_trait.principal_trait_ref_with_self_ty(tcx, tcx.types.err);

    let mut associated_types: FnvHashSet<(ast::DefId, ast::Name)> =
        traits::supertraits(tcx, object_trait_ref.clone())
        .flat_map(|tr| {
            let trait_def = ty::lookup_trait_def(tcx, tr.def_id());
            trait_def.associated_type_names
                .clone()
                .into_iter()
                .map(move |associated_type_name| (tr.def_id(), associated_type_name))
        })
        .collect();

    for projection_bound in &object_trait.bounds.projection_bounds {
        let pair = (projection_bound.0.projection_ty.trait_ref.def_id,
                    projection_bound.0.projection_ty.item_name);
        associated_types.remove(&pair);
    }

    for (trait_def_id, name) in associated_types {
        span_err!(tcx.sess, span, E0191,
            "the value of the associated type `{}` (from the trait `{}`) must be specified",
                    name.user_string(tcx),
                    ty::item_path_str(tcx, trait_def_id));
    }
}

pub fn select_all_fcx_obligations_and_apply_defaults(fcx: &FnCtxt) {
    debug!("select_all_fcx_obligations_and_apply_defaults");

    select_fcx_obligations_where_possible(fcx);
    fcx.default_type_parameters();
    select_fcx_obligations_where_possible(fcx);
}

pub fn select_all_fcx_obligations_or_error(fcx: &FnCtxt) {
    debug!("select_all_fcx_obligations_or_error");

    // upvar inference should have ensured that all deferred call
    // resolutions are handled by now.
    assert!(fcx.inh.deferred_call_resolutions.borrow().is_empty());

    select_all_fcx_obligations_and_apply_defaults(fcx);
    let mut fulfillment_cx = fcx.inh.fulfillment_cx.borrow_mut();
    let r = fulfillment_cx.select_all_or_error(fcx.infcx(), fcx);
    match r {
        Ok(()) => { }
        Err(errors) => { report_fulfillment_errors(fcx.infcx(), &errors); }
    }
}

/// Select as many obligations as we can at present.
pub fn select_fcx_obligations_where_possible(fcx: &FnCtxt)
{
    match
        fcx.inh.fulfillment_cx
        .borrow_mut()
        .select_where_possible(fcx.infcx(), fcx)
    {
        Ok(()) => { }
        Err(errors) => { report_fulfillment_errors(fcx.infcx(), &errors); }
    }
}

/// Try to select any fcx obligation that we haven't tried yet, in an effort to improve inference.
/// You could just call `select_fcx_obligations_where_possible` except that it leads to repeated
/// work.
pub fn select_new_fcx_obligations(fcx: &FnCtxt) {
    match
        fcx.inh.fulfillment_cx
        .borrow_mut()
        .select_new_obligations(fcx.infcx(), fcx)
    {
        Ok(()) => { }
        Err(errors) => { report_fulfillment_errors(fcx.infcx(), &errors); }
    }
}

<commit_msg>Given `<expr> as Box<Trait>`, infer that `Box<_>` is expected type for `<expr>`.<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use check::{FnCtxt, structurally_resolved_type};
use check::demand;
use middle::traits::{self, ObjectSafetyViolation, MethodViolationCode};
use middle::traits::{Obligation, ObligationCause};
use middle::traits::report_fulfillment_errors;
use middle::ty::{self, Ty, AsPredicate};
use syntax::ast;
use syntax::codemap::Span;
use util::nodemap::FnvHashSet;
use util::ppaux::{Repr, UserString};

pub fn check_object_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                   cast_expr: &ast::Expr,
                                   source_expr: &ast::Expr,
                                   target_object_ty: Ty<'tcx>)
{
    let tcx = fcx.tcx();
    debug!("check_object_cast(cast_expr={}, target_object_ty={})",
           cast_expr.repr(tcx),
           target_object_ty.repr(tcx));

    // Look up vtables for the type we're casting to,
    // passing in the source and target type.  The source
    // must be a pointer type suitable to the object sigil,
    // e.g.: `&x as &Trait` or `box x as Box<Trait>`

    // First, construct a fresh type that we can feed into `<expr>`
    // within `<expr> as <type>` to inform type inference (e.g. to
    // tell it that we are expecting a `Box<_>` or an `&_`).
    let fresh_ty = fcx.infcx().next_ty_var();
    let (object_trait_ty, source_expected_ty) = match target_object_ty.sty {
        ty::ty_uniq(object_trait_ty) => {
            (object_trait_ty, ty::mk_uniq(fcx.tcx(), fresh_ty))
        }
        ty::ty_rptr(target_region, ty::mt { ty: object_trait_ty,
                                            mutbl: target_mutbl }) => {
            (object_trait_ty,
             ty::mk_rptr(fcx.tcx(),
                         target_region, ty::mt { ty: fresh_ty,
                                                 mutbl: target_mutbl }))
        }
        _ => {
            fcx.tcx().sess.span_bug(source_expr.span, "expected object type");
        }
    };

    let source_ty = fcx.expr_ty(source_expr);
    debug!("check_object_cast pre unify source_ty={}", source_ty.repr(tcx));

    // This ensures that the source_ty <: source_expected_ty, which
    // will ensure e.g. that &'a T <: &'b T when doing `&'a T as &'b Trait`
    //
    // FIXME (pnkfelix): do we need to use suptype_with_fn in order to
    // override the error message emitted when the types do not work
    // out in the manner desired?
    demand::suptype(fcx, source_expr.span, source_expected_ty, source_ty);

    debug!("check_object_cast postunify source_ty={}", source_ty.repr(tcx));
    let source_ty = structurally_resolved_type(fcx, source_expr.span, source_ty);
    debug!("check_object_cast resolveto source_ty={}", source_ty.repr(tcx));

    let object_trait = object_trait(&object_trait_ty);

    let referent_ty = match source_ty.sty {
        ty::ty_uniq(ty) => ty,
        ty::ty_rptr(_, ty::mt { ty, mutbl: _ }) => ty,
        _ => fcx.tcx().sess.span_bug(source_expr.span,
                                     "expected appropriate reference type"),
    };

    // Ensure that if Ptr<T> is cast to Ptr<Trait>, then T : Trait.
    push_cast_obligation(fcx, cast_expr, object_trait, referent_ty);
    check_object_safety(tcx, object_trait, source_expr.span);

    fn object_trait<'a, 'tcx>(t: &'a Ty<'tcx>) -> &'a ty::TyTrait<'tcx> {
        match t.sty {
            ty::ty_trait(ref ty_trait) => &**ty_trait,
            _ => panic!("expected ty_trait")
        }
    }

    fn push_cast_obligation<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                      cast_expr: &ast::Expr,
                                      object_trait: &ty::TyTrait<'tcx>,
                                      referent_ty: Ty<'tcx>) {
        let object_trait_ref =
            register_object_cast_obligations(fcx,
                                             cast_expr.span,
                                             object_trait,
                                             referent_ty);

        // Finally record the object_trait_ref for use during trans
        // (it would prob be better not to do this, but it's just kind
        // of a pain to have to reconstruct it).
        fcx.write_object_cast(cast_expr.id, object_trait_ref);
    }
}

// Check that a trait is 'object-safe'. This should be checked whenever a trait object
// is created (by casting or coercion, etc.). A trait is object-safe if all its
// methods are object-safe. A trait method is object-safe if it does not take
// self by value, has no type parameters and does not use the `Self` type, except
// in self position.
pub fn check_object_safety<'tcx>(tcx: &ty::ctxt<'tcx>,
                                 object_trait: &ty::TyTrait<'tcx>,
                                 span: Span)
{
    let object_trait_ref =
        object_trait.principal_trait_ref_with_self_ty(tcx, tcx.types.err);

    if traits::is_object_safe(tcx, object_trait_ref.clone()) {
        return;
    }

    span_err!(tcx.sess, span, E0038,
              "cannot convert to a trait object because trait `{}` is not object-safe",
              ty::item_path_str(tcx, object_trait_ref.def_id()));

    let violations = traits::object_safety_violations(tcx, object_trait_ref.clone());
    for violation in violations {
        match violation {
            ObjectSafetyViolation::SizedSelf => {
                tcx.sess.span_note(
                    span,
                    "the trait cannot require that `Self : Sized`");
            }

            ObjectSafetyViolation::Method(method, MethodViolationCode::ByValueSelf) => {
                tcx.sess.span_note(
                    span,
                    &format!("method `{}` has a receiver type of `Self`, \
                              which cannot be used with a trait object",
                             method.name.user_string(tcx)));
            }

            ObjectSafetyViolation::Method(method, MethodViolationCode::StaticMethod) => {
                tcx.sess.span_note(
                    span,
                    &format!("method `{}` has no receiver",
                             method.name.user_string(tcx)));
            }

            ObjectSafetyViolation::Method(method, MethodViolationCode::ReferencesSelf) => {
                tcx.sess.span_note(
                    span,
                    &format!("method `{}` references the `Self` type \
                              in its arguments or return type",
                             method.name.user_string(tcx)));
            }

            ObjectSafetyViolation::Method(method, MethodViolationCode::Generic) => {
                tcx.sess.span_note(
                    span,
                    &format!("method `{}` has generic type parameters",
                             method.name.user_string(tcx)));
            }
        }
    }
}

pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                                  span: Span,
                                                  object_trait: &ty::TyTrait<'tcx>,
                                                  referent_ty: Ty<'tcx>)
                                                  -> ty::PolyTraitRef<'tcx>
{
    // We can only make objects from sized types.
    fcx.register_builtin_bound(
        referent_ty,
        ty::BoundSized,
        traits::ObligationCause::new(span, fcx.body_id, traits::ObjectSized));

    // This is just for better error reporting. Kinda goofy. The object type stuff
    // needs some refactoring so there is a more convenient type to pass around.
    let object_trait_ty =
        ty::mk_trait(fcx.tcx(),
                     object_trait.principal.clone(),
                     object_trait.bounds.clone());

    debug!("register_object_cast_obligations: referent_ty={} object_trait_ty={}",
           referent_ty.repr(fcx.tcx()),
           object_trait_ty.repr(fcx.tcx()));

    let cause = ObligationCause::new(span,
                                     fcx.body_id,
                                     traits::ObjectCastObligation(object_trait_ty));

    // Create the obligation for casting from T to Trait.
    let object_trait_ref =
        object_trait.principal_trait_ref_with_self_ty(fcx.tcx(), referent_ty);
    let object_obligation =
        Obligation::new(cause.clone(), object_trait_ref.as_predicate());
    fcx.register_predicate(object_obligation);

    // Create additional obligations for all the various builtin
    // bounds attached to the object cast. (In other words, if the
    // object type is Foo+Send, this would create an obligation
    // for the Send check.)
    for builtin_bound in &object_trait.bounds.builtin_bounds {
        fcx.register_builtin_bound(
            referent_ty,
            builtin_bound,
            cause.clone());
    }

    // Create obligations for the projection predicates.
    let projection_bounds =
        object_trait.projection_bounds_with_self_ty(fcx.tcx(), referent_ty);
    for projection_bound in &projection_bounds {
        let projection_obligation =
            Obligation::new(cause.clone(), projection_bound.as_predicate());
        fcx.register_predicate(projection_obligation);
    }

    // Finally, check that there IS a projection predicate for every associated type.
    check_object_type_binds_all_associated_types(fcx.tcx(),
                                                 span,
                                                 object_trait);

    object_trait_ref
}

fn check_object_type_binds_all_associated_types<'tcx>(tcx: &ty::ctxt<'tcx>,
                                                      span: Span,
                                                      object_trait: &ty::TyTrait<'tcx>)
{
    let object_trait_ref =
        object_trait.principal_trait_ref_with_self_ty(tcx, tcx.types.err);

    let mut associated_types: FnvHashSet<(ast::DefId, ast::Name)> =
        traits::supertraits(tcx, object_trait_ref.clone())
        .flat_map(|tr| {
            let trait_def = ty::lookup_trait_def(tcx, tr.def_id());
            trait_def.associated_type_names
                .clone()
                .into_iter()
                .map(move |associated_type_name| (tr.def_id(), associated_type_name))
        })
        .collect();

    for projection_bound in &object_trait.bounds.projection_bounds {
        let pair = (projection_bound.0.projection_ty.trait_ref.def_id,
                    projection_bound.0.projection_ty.item_name);
        associated_types.remove(&pair);
    }

    for (trait_def_id, name) in associated_types {
        span_err!(tcx.sess, span, E0191,
            "the value of the associated type `{}` (from the trait `{}`) must be specified",
                    name.user_string(tcx),
                    ty::item_path_str(tcx, trait_def_id));
    }
}

pub fn select_all_fcx_obligations_and_apply_defaults(fcx: &FnCtxt) {
    debug!("select_all_fcx_obligations_and_apply_defaults");

    select_fcx_obligations_where_possible(fcx);
    fcx.default_type_parameters();
    select_fcx_obligations_where_possible(fcx);
}

pub fn select_all_fcx_obligations_or_error(fcx: &FnCtxt) {
    debug!("select_all_fcx_obligations_or_error");

    // upvar inference should have ensured that all deferred call
    // resolutions are handled by now.
    assert!(fcx.inh.deferred_call_resolutions.borrow().is_empty());

    select_all_fcx_obligations_and_apply_defaults(fcx);
    let mut fulfillment_cx = fcx.inh.fulfillment_cx.borrow_mut();
    let r = fulfillment_cx.select_all_or_error(fcx.infcx(), fcx);
    match r {
        Ok(()) => { }
        Err(errors) => { report_fulfillment_errors(fcx.infcx(), &errors); }
    }
}

/// Select as many obligations as we can at present.
pub fn select_fcx_obligations_where_possible(fcx: &FnCtxt)
{
    match
        fcx.inh.fulfillment_cx
        .borrow_mut()
        .select_where_possible(fcx.infcx(), fcx)
    {
        Ok(()) => { }
        Err(errors) => { report_fulfillment_errors(fcx.infcx(), &errors); }
    }
}

/// Try to select any fcx obligation that we haven't tried yet, in an effort to improve inference.
/// You could just call `select_fcx_obligations_where_possible` except that it leads to repeated
/// work.
pub fn select_new_fcx_obligations(fcx: &FnCtxt) {
    match
        fcx.inh.fulfillment_cx
        .borrow_mut()
        .select_new_obligations(fcx.infcx(), fcx)
    {
        Ok(()) => { }
        Err(errors) => { report_fulfillment_errors(fcx.infcx(), &errors); }
    }
}

<|endoftext|>