<commit_before>use std::cell::RefCell;
use std::collections::HashMap;
use std::ptr;
use std::sync::RwLock;

use baseline::stub::ensure_stub;
use class::{self, ClassDef, ClassDefId, ClassId};
use ctxt::{SemContext, Fct, FctId, FctKind, FctParent, FctSrc, NodeMap, Var};
use mem;
use object::Header;
use vtable::{DISPLAY_SIZE, VTableBox};
use ty::{BuiltinType, TypeId};

pub fn specialize_class(ctxt: &SemContext,
                        cls: &class::Class,
                        type_params: Vec<BuiltinType>)
                        -> (ClassId, TypeId) {
    if let Some(&id) = cls.specializations.borrow().get(&type_params) {
        let type_id = ctxt.types.borrow_mut().insert(cls.id, type_params);
        return (id, type_id);
    }

    cls.specializations
        .borrow_mut()
        .insert(type_params.clone(), ClassId::max());

    let id = create_specialized_class(ctxt, cls, type_params.clone());
    cls.specializations
        .borrow_mut()
        .insert(type_params.clone(), id);

    let type_id = ctxt.types.borrow_mut().insert(cls.id, type_params);
    ctxt.types.borrow().set_cls_id(type_id, id);

    (id, type_id)
}

fn create_specialized_class(ctxt: &SemContext,
                            cls: &class::Class,
                            type_params: Vec<BuiltinType>)
                            -> ClassId {
    let id: ClassId = ctxt.classes.len().into();
    let specialize_for = SpecializeFor::Class;

    let mut is_array = false;
    let mut is_object_array = false;
    let mut element_size = 0;

    match cls.ty {
        BuiltinType::Generic(type_id) => {
            let ty = ctxt.types.borrow().get(type_id);

            if ty.cls_id == ctxt.primitive_classes.generic_array {
                is_array = true;

                let type_param = type_params[0].to_specialized(ctxt);

                if !type_param.is_type_param() {
                    is_object_array = type_param.reference_type();
                    element_size = type_param.size(ctxt);
                }
            }
        }

        _ => {}
    }

    let is_generic = type_params.iter().any(|t| t.is_type_param());

    ctxt.classes
        .push(class::Class {
                  id: id,
                  pos: cls.pos,
                  name: cls.name,
                  ty: BuiltinType::Class(id),
                  parent_class: cls.parent_class,
                  has_open: cls.has_open,
                  is_abstract: cls.is_abstract,
                  internal: cls.internal,
                  internal_resolved: true,
                  primary_ctor: cls.primary_ctor,

                  ctors: Vec::new(),
                  fields: Vec::new(),
                  methods: Vec::new(),
                  size: 0,
                  vtable: None,

                  traits: cls.traits.clone(),
                  impls: cls.impls.clone(),

                  type_params: Vec::new(),
                  is_generic: is_generic,
                  specialization_for: Some(cls.id),
                  specialization_params: type_params.clone(),
                  specializations: RefCell::new(HashMap::new()),
                  def_specializations: RefCell::new(HashMap::new()),

                  is_array: is_array,
                  is_object_array: is_object_array,
                  element_size: element_size,

                  ref_fields: Vec::new(),
              });

    let cloned_ctors = cls.ctors
        .iter()
        .map(|&ctor_id| {
                 let ctor = ctxt.fcts[ctor_id].borrow();
                 specialize_fct(ctxt,
                                FctParent::Class(id),
                                &*ctor,
                                specialize_for,
                                &type_params)
             })
        .collect();
    ctxt.classes[id].borrow_mut().ctors = cloned_ctors;

    let cloned_methods = cls.methods
        .iter()
        .map(|&method_id| {
                 let mtd = ctxt.fcts[method_id].borrow();
                 specialize_fct(ctxt,
                                FctParent::Class(id),
                                &*mtd,
                                specialize_for,
                                &type_params)
             })
        .collect();
    ctxt.classes[id].borrow_mut().methods = cloned_methods;

    let cloned_fields = cls.fields
        .iter()
        .map(|field| {
            class::Field {
                id: field.id,
                name: field.name,
                ty: specialize_type(ctxt, field.ty, specialize_for, &type_params),
                offset: field.offset,
                reassignable: field.reassignable,
            }
        })
        .collect();
    ctxt.classes[id].borrow_mut().fields = cloned_fields;

    id
}

pub fn specialize_fct<'ast>(ctxt: &SemContext<'ast>,
                            parent: FctParent,
                            fct: &Fct<'ast>,
                            specialize_for: SpecializeFor,
                            type_params: &[BuiltinType])
                            -> FctId {
    let fct_id = ctxt.fcts.len().into();

    let mut param_types: Vec<_> = fct.param_types
        .iter()
        .map(|&t| specialize_type(ctxt, t, specialize_for, &type_params))
        .collect();

    if fct.has_self() && fct.initialized {
        match parent {
            FctParent::Class(cls_id) => {
                param_types[0] = BuiltinType::Class(cls_id);
            }

            _ => unreachable!(),
        }
    }

    let cloned_kind = match fct.kind {
        FctKind::Source(ref src) => {
            let src = src.borrow();

            let cloned_vars = src.vars
                .iter()
                .map(|v| {
                    Var {
                        id: v.id,
                        name: v.name,
                        ty: specialize_type(ctxt, v.ty, specialize_for, &type_params),
                        reassignable: v.reassignable,
                        node_id: v.node_id,
                    }
                })
                .collect();

            let mut cloned_map_tys = NodeMap::new();

            for (&id, &ty) in src.map_tys.iter() {
                let ty = specialize_type(ctxt, ty, specialize_for, &type_params);
                cloned_map_tys.insert(id, ty);
            }

            FctKind::Source(RefCell::new(FctSrc {
                                             map_calls: src.map_calls.clone(),
                                             map_idents: src.map_idents.clone(),
                                             map_tys: cloned_map_tys,
                                             map_vars: src.map_vars.clone(),
                                             map_convs: src.map_convs.clone(),
                                             map_cls: src.map_cls.clone(),

                                             always_returns: src.always_returns,
                                             jit_fct: RwLock::new(None),
                                             specializations: RwLock::new(HashMap::new()),
                                             vars: cloned_vars,
                                         }))
        }

        FctKind::Definition => FctKind::Definition,
        FctKind::Native(ptr) => FctKind::Native(ptr),
        FctKind::Builtin(intr) => FctKind::Builtin(intr),
    };

    let fct = Fct {
        id: fct_id,
        ast: fct.ast,
        pos: fct.pos,
        name: fct.name,
        parent: parent,
        has_open: fct.has_open,
        has_override: fct.has_override,
        has_final: fct.has_final,
        is_static: fct.is_static,
        is_pub: fct.is_pub,
        is_abstract: fct.is_abstract,
        internal: fct.internal,
        internal_resolved: true,
        overrides: fct.overrides,
        param_types: param_types,
        return_type: specialize_type(ctxt, fct.return_type, specialize_for, &type_params),
        ctor: fct.ctor,

        vtable_index: fct.vtable_index,
        initialized: fct.initialized,
        throws: fct.throws,

        type_params: Vec::new(),
        kind: cloned_kind,
    };

    ctxt.fcts.push(fct);

    fct_id
}

pub fn specialize_type<'ast>(ctxt: &SemContext<'ast>,
                             ty: BuiltinType,
                             specialize_for: SpecializeFor,
                             type_params: &[BuiltinType])
                             -> BuiltinType {
    match ty {
        BuiltinType::ClassTypeParam(_, id) => {
            if specialize_for == SpecializeFor::Class {
                type_params[id.idx()]
            } else {
                ty
            }
        }

        BuiltinType::FctTypeParam(_, id) => {
            if specialize_for == SpecializeFor::Fct {
                type_params[id.idx()]
            } else {
                ty
            }
        }

        BuiltinType::Generic(type_id) => {
            let ty = ctxt.types.borrow().get(type_id);

            let params: Vec<_> = ty.params
                .iter()
                .map(|&t| specialize_type(ctxt, t, specialize_for, type_params))
                .collect();

            let cls_id = ty.cls_id;
            let cls = ctxt.classes[cls_id].borrow();

            let (_, type_id) = specialize_class(ctxt, &*cls, params.clone());
            BuiltinType::Generic(type_id)
        }

        _ => ty,
    }
}

#[derive(Copy, Clone, PartialEq, Eq)]
pub enum SpecializeFor {
    Fct,
    Class,
}

pub fn specialize_class_def(ctxt: &SemContext,
                            cls: &class::Class,
                            type_params: &[BuiltinType])
                            -> ClassDefId {
    if let Some(&id) = cls.def_specializations.borrow().get(type_params) {
        return id;
    }

    create_specialized_class_def(ctxt, cls, type_params)
}

fn create_specialized_class_def(ctxt: &SemContext,
                                cls: &class::Class,
                                type_params: &[BuiltinType])
                                -> ClassDefId {
    let id: ClassDefId = ctxt.class_defs.len().into();

    ctxt.class_defs
        .push(ClassDef {
                  id: id,
                  cls_id: cls.id,
                  type_params: type_params.to_vec(),
                  parent_id: None,
                  size: 0,
                  fields: Vec::new(),
                  ref_fields: Vec::new(),
                  vtable: None,
              });

    let mut fields;
    let mut ref_fields;
    let mut size;
    let mut vtable_entries = Vec::new();
    let parent_id;

    if let Some(super_id) = cls.parent_class {
        let sup = ctxt.classes[super_id].borrow();
        let id = specialize_class_def(ctxt, &*sup, &[]);
        let cls_def = ctxt.class_defs[id].borrow();

        fields = cls_def.fields.clone();
        ref_fields = cls_def.ref_fields.clone();
        size = cls_def.size;
        parent_id = Some(id);

        let vtable = sup.vtable.as_ref().unwrap();
        vtable_entries.extend_from_slice(vtable.table());

    } else {
        fields = Vec::with_capacity(cls.fields.len());
        ref_fields = Vec::new();
        size = Header::size();
        parent_id = None;
    };

    for f in &cls.fields {
        let ty = specialize_type(ctxt, f.ty, SpecializeFor::Class, &type_params);
        debug_assert!(!ty.contains_type_param(ctxt));

        let field_size = f.ty.size(ctxt);
        let field_align = f.ty.align(ctxt);

        let offset = mem::align_i32(size, field_align);
        fields.push(offset);

        size = offset + field_size;

        if ty.reference_type() {
            ref_fields.push(offset);
        }
    }

    size = mem::align_i32(size, mem::ptr_width());

    for &mid in &cls.methods {
        let mut fct = ctxt.fcts[mid].borrow_mut();

        if fct.vtable_index.is_some() {
            continue;
        }

        if fct.is_virtual() {
            let vtable_index = if let Some(overrides) = fct.overrides {
                ctxt.fcts[overrides].borrow().vtable_index.unwrap()

            } else {
                let vtable_index = vtable_entries.len();
                vtable_entries.push(ensure_stub(ctxt) as usize);

                vtable_index as u32
            };

            fct.vtable_index = Some(vtable_index);
        }
    }

    let clsptr = cls as *const class::Class as *mut class::Class;
    let vtable = VTableBox::new(clsptr, &vtable_entries);

    let mut cls_def = ctxt.class_defs[id].borrow_mut();
    cls_def.size = size;
    cls_def.fields = fields;
    cls_def.ref_fields = ref_fields;
    cls_def.vtable = Some(vtable);
    cls_def.parent_id = parent_id;

    ensure_display(ctxt, &mut cls_def);

    id
}

fn ensure_display<'ast>(ctxt: &SemContext<'ast>, cls_def: &mut ClassDef) -> usize {
    let vtable = cls_def.vtable.as_mut().unwrap();

    // if subtype_display[0] is set, vtable was already initialized
    if !vtable.subtype_display[0].is_null() {
        return vtable.subtype_depth as usize;
    }

    if let Some(parent_id) = cls_def.parent_id {
        let mut parent = ctxt.class_defs[parent_id].borrow_mut();
        let depth = 1 + ensure_display(ctxt, &mut *parent);

        let parent_vtable = parent.vtable.as_ref().unwrap();
        let depth_fixed;

        if depth >= DISPLAY_SIZE {
            depth_fixed = DISPLAY_SIZE;

            vtable.allocate_overflow(depth as usize - DISPLAY_SIZE + 1);

            unsafe {
                if depth > DISPLAY_SIZE {
                    ptr::copy_nonoverlapping(parent_vtable.subtype_overflow,
                                             vtable.subtype_overflow as *mut _,
                                             depth as usize - DISPLAY_SIZE);
                }

                let ptr = vtable
                    .subtype_overflow
                    .offset(depth as isize - DISPLAY_SIZE as isize) as
                          *mut _;

                *ptr = &**vtable as *const _;
            }

        } else {
            depth_fixed = depth;

            vtable.subtype_display[depth] = &**vtable as *const _;
        }

        vtable.subtype_depth = depth as i32;
        vtable.subtype_display[0..depth_fixed].clone_from_slice(&parent_vtable.subtype_display
                                                                     [0..depth_fixed]);

        depth

    } else {
        vtable.subtype_depth = 0;
        vtable.subtype_display[0] = &**vtable as *const _;

        0
    }
}<commit_msg>write ClassDefId into def_specializations<commit_after>use std::cell::RefCell;
use std::collections::HashMap;
use std::ptr;
use std::sync::RwLock;

use baseline::stub::ensure_stub;
use class::{self, ClassDef, ClassDefId, ClassId};
use ctxt::{SemContext, Fct, FctId, FctKind, FctParent, FctSrc, NodeMap, Var};
use mem;
use object::Header;
use vtable::{DISPLAY_SIZE, VTableBox};
use ty::{BuiltinType, TypeId};

pub fn specialize_class(ctxt: &SemContext,
                        cls: &class::Class,
                        type_params: Vec<BuiltinType>)
                        -> (ClassId, TypeId) {
    if let Some(&id) = cls.specializations.borrow().get(&type_params) {
        let type_id = ctxt.types.borrow_mut().insert(cls.id, type_params);
        return (id, type_id);
    }

    cls.specializations
        .borrow_mut()
        .insert(type_params.clone(), ClassId::max());

    let id = create_specialized_class(ctxt, cls, type_params.clone());
    cls.specializations
        .borrow_mut()
        .insert(type_params.clone(), id);

    let type_id = ctxt.types.borrow_mut().insert(cls.id, type_params);
    ctxt.types.borrow().set_cls_id(type_id, id);

    (id, type_id)
}

fn create_specialized_class(ctxt: &SemContext,
                            cls: &class::Class,
                            type_params: Vec<BuiltinType>)
                            -> ClassId {
    let id: ClassId = ctxt.classes.len().into();
    let specialize_for = SpecializeFor::Class;

    let mut is_array = false;
    let mut is_object_array = false;
    let mut element_size = 0;

    match cls.ty {
        BuiltinType::Generic(type_id) => {
            let ty = ctxt.types.borrow().get(type_id);

            if ty.cls_id == ctxt.primitive_classes.generic_array {
                is_array = true;

                let type_param = type_params[0].to_specialized(ctxt);

                if !type_param.is_type_param() {
                    is_object_array = type_param.reference_type();
                    element_size = type_param.size(ctxt);
                }
            }
        }

        _ => {}
    }

    let is_generic = type_params.iter().any(|t| t.is_type_param());

    ctxt.classes
        .push(class::Class {
                  id: id,
                  pos: cls.pos,
                  name: cls.name,
                  ty: BuiltinType::Class(id),
                  parent_class: cls.parent_class,
                  has_open: cls.has_open,
                  is_abstract: cls.is_abstract,
                  internal: cls.internal,
                  internal_resolved: true,
                  primary_ctor: cls.primary_ctor,

                  ctors: Vec::new(),
                  fields: Vec::new(),
                  methods: Vec::new(),
                  size: 0,
                  vtable: None,

                  traits: cls.traits.clone(),
                  impls: cls.impls.clone(),

                  type_params: Vec::new(),
                  is_generic: is_generic,
                  specialization_for: Some(cls.id),
                  specialization_params: type_params.clone(),
                  specializations: RefCell::new(HashMap::new()),
                  def_specializations: RefCell::new(HashMap::new()),

                  is_array: is_array,
                  is_object_array: is_object_array,
                  element_size: element_size,

                  ref_fields: Vec::new(),
              });

    let cloned_ctors = cls.ctors
        .iter()
        .map(|&ctor_id| {
                 let ctor = ctxt.fcts[ctor_id].borrow();
                 specialize_fct(ctxt,
                                FctParent::Class(id),
                                &*ctor,
                                specialize_for,
                                &type_params)
             })
        .collect();
    ctxt.classes[id].borrow_mut().ctors = cloned_ctors;

    let cloned_methods = cls.methods
        .iter()
        .map(|&method_id| {
                 let mtd = ctxt.fcts[method_id].borrow();
                 specialize_fct(ctxt,
                                FctParent::Class(id),
                                &*mtd,
                                specialize_for,
                                &type_params)
             })
        .collect();
    ctxt.classes[id].borrow_mut().methods = cloned_methods;

    let cloned_fields = cls.fields
        .iter()
        .map(|field| {
            class::Field {
                id: field.id,
                name: field.name,
                ty: specialize_type(ctxt, field.ty, specialize_for, &type_params),
                offset: field.offset,
                reassignable: field.reassignable,
            }
        })
        .collect();
    ctxt.classes[id].borrow_mut().fields = cloned_fields;

    id
}

pub fn specialize_fct<'ast>(ctxt: &SemContext<'ast>,
                            parent: FctParent,
                            fct: &Fct<'ast>,
                            specialize_for: SpecializeFor,
                            type_params: &[BuiltinType])
                            -> FctId {
    let fct_id = ctxt.fcts.len().into();

    let mut param_types: Vec<_> = fct.param_types
        .iter()
        .map(|&t| specialize_type(ctxt, t, specialize_for, &type_params))
        .collect();

    if fct.has_self() && fct.initialized {
        match parent {
            FctParent::Class(cls_id) => {
                param_types[0] = BuiltinType::Class(cls_id);
            }

            _ => unreachable!(),
        }
    }

    let cloned_kind = match fct.kind {
        FctKind::Source(ref src) => {
            let src = src.borrow();

            let cloned_vars = src.vars
                .iter()
                .map(|v| {
                    Var {
                        id: v.id,
                        name: v.name,
                        ty: specialize_type(ctxt, v.ty, specialize_for, &type_params),
                        reassignable: v.reassignable,
                        node_id: v.node_id,
                    }
                })
                .collect();

            let mut cloned_map_tys = NodeMap::new();

            for (&id, &ty) in src.map_tys.iter() {
                let ty = specialize_type(ctxt, ty, specialize_for, &type_params);
                cloned_map_tys.insert(id, ty);
            }

            FctKind::Source(RefCell::new(FctSrc {
                                             map_calls: src.map_calls.clone(),
                                             map_idents: src.map_idents.clone(),
                                             map_tys: cloned_map_tys,
                                             map_vars: src.map_vars.clone(),
                                             map_convs: src.map_convs.clone(),
                                             map_cls: src.map_cls.clone(),

                                             always_returns: src.always_returns,
                                             jit_fct: RwLock::new(None),
                                             specializations: RwLock::new(HashMap::new()),
                                             vars: cloned_vars,
                                         }))
        }

        FctKind::Definition => FctKind::Definition,
        FctKind::Native(ptr) => FctKind::Native(ptr),
        FctKind::Builtin(intr) => FctKind::Builtin(intr),
    };

    let fct = Fct {
        id: fct_id,
        ast: fct.ast,
        pos: fct.pos,
        name: fct.name,
        parent: parent,
        has_open: fct.has_open,
        has_override: fct.has_override,
        has_final: fct.has_final,
        is_static: fct.is_static,
        is_pub: fct.is_pub,
        is_abstract: fct.is_abstract,
        internal: fct.internal,
        internal_resolved: true,
        overrides: fct.overrides,
        param_types: param_types,
        return_type: specialize_type(ctxt, fct.return_type, specialize_for, &type_params),
        ctor: fct.ctor,

        vtable_index: fct.vtable_index,
        initialized: fct.initialized,
        throws: fct.throws,

        type_params: Vec::new(),
        kind: cloned_kind,
    };

    ctxt.fcts.push(fct);

    fct_id
}

pub fn specialize_type<'ast>(ctxt: &SemContext<'ast>,
                             ty: BuiltinType,
                             specialize_for: SpecializeFor,
                             type_params: &[BuiltinType])
                             -> BuiltinType {
    match ty {
        BuiltinType::ClassTypeParam(_, id) => {
            if specialize_for == SpecializeFor::Class {
                type_params[id.idx()]
            } else {
                ty
            }
        }

        BuiltinType::FctTypeParam(_, id) => {
            if specialize_for == SpecializeFor::Fct {
                type_params[id.idx()]
            } else {
                ty
            }
        }

        BuiltinType::Generic(type_id) => {
            let ty = ctxt.types.borrow().get(type_id);

            let params: Vec<_> = ty.params
                .iter()
                .map(|&t| specialize_type(ctxt, t, specialize_for, type_params))
                .collect();

            let cls_id = ty.cls_id;
            let cls = ctxt.classes[cls_id].borrow();

            let (_, type_id) = specialize_class(ctxt, &*cls, params.clone());
            BuiltinType::Generic(type_id)
        }

        _ => ty,
    }
}

#[derive(Copy, Clone, PartialEq, Eq)]
pub enum SpecializeFor {
    Fct,
    Class,
}

pub fn specialize_class_def(ctxt: &SemContext,
                            cls: &class::Class,
                            type_params: &[BuiltinType])
                            -> ClassDefId {
    if let Some(&id) = cls.def_specializations.borrow().get(type_params) {
        return id;
    }

    create_specialized_class_def(ctxt, cls, type_params)
}

fn create_specialized_class_def(ctxt: &SemContext,
                                cls: &class::Class,
                                type_params: &[BuiltinType])
                                -> ClassDefId {
    let id: ClassDefId = ctxt.class_defs.len().into();

    let old = cls.def_specializations.borrow_mut().insert(type_params.to_vec(), id);
    assert!(old.is_none());

    ctxt.class_defs
        .push(ClassDef {
                  id: id,
                  cls_id: cls.id,
                  type_params: type_params.to_vec(),
                  parent_id: None,
                  size: 0,
                  fields: Vec::new(),
                  ref_fields: Vec::new(),
                  vtable: None,
              });

    let mut fields;
    let mut ref_fields;
    let mut size;
    let mut vtable_entries = Vec::new();
    let parent_id;

    if let Some(super_id) = cls.parent_class {
        let sup = ctxt.classes[super_id].borrow();
        let id = specialize_class_def(ctxt, &*sup, &[]);
        let cls_def = ctxt.class_defs[id].borrow();

        fields = cls_def.fields.clone();
        ref_fields = cls_def.ref_fields.clone();
        size = cls_def.size;
        parent_id = Some(id);

        let vtable = sup.vtable.as_ref().unwrap();
        vtable_entries.extend_from_slice(vtable.table());

    } else {
        fields = Vec::with_capacity(cls.fields.len());
        ref_fields = Vec::new();
        size = Header::size();
        parent_id = None;
    };

    for f in &cls.fields {
        let ty = specialize_type(ctxt, f.ty, SpecializeFor::Class, &type_params);
        debug_assert!(!ty.contains_type_param(ctxt));

        let field_size = f.ty.size(ctxt);
        let field_align = f.ty.align(ctxt);

        let offset = mem::align_i32(size, field_align);
        fields.push(offset);

        size = offset + field_size;

        if ty.reference_type() {
            ref_fields.push(offset);
        }
    }

    size = mem::align_i32(size, mem::ptr_width());

    for &mid in &cls.methods {
        let mut fct = ctxt.fcts[mid].borrow_mut();

        if fct.vtable_index.is_some() {
            continue;
        }

        if fct.is_virtual() {
            let vtable_index = if let Some(overrides) = fct.overrides {
                ctxt.fcts[overrides].borrow().vtable_index.unwrap()

            } else {
                let vtable_index = vtable_entries.len();
                vtable_entries.push(ensure_stub(ctxt) as usize);

                vtable_index as u32
            };

            fct.vtable_index = Some(vtable_index);
        }
    }

    let clsptr = cls as *const class::Class as *mut class::Class;
    let vtable = VTableBox::new(clsptr, &vtable_entries);

    let mut cls_def = ctxt.class_defs[id].borrow_mut();
    cls_def.size = size;
    cls_def.fields = fields;
    cls_def.ref_fields = ref_fields;
    cls_def.vtable = Some(vtable);
    cls_def.parent_id = parent_id;

    ensure_display(ctxt, &mut cls_def);

    id
}

fn ensure_display<'ast>(ctxt: &SemContext<'ast>, cls_def: &mut ClassDef) -> usize {
    let vtable = cls_def.vtable.as_mut().unwrap();

    // if subtype_display[0] is set, vtable was already initialized
    if !vtable.subtype_display[0].is_null() {
        return vtable.subtype_depth as usize;
    }

    if let Some(parent_id) = cls_def.parent_id {
        let mut parent = ctxt.class_defs[parent_id].borrow_mut();
        let depth = 1 + ensure_display(ctxt, &mut *parent);

        let parent_vtable = parent.vtable.as_ref().unwrap();
        let depth_fixed;

        if depth >= DISPLAY_SIZE {
            depth_fixed = DISPLAY_SIZE;

            vtable.allocate_overflow(depth as usize - DISPLAY_SIZE + 1);

            unsafe {
                if depth > DISPLAY_SIZE {
                    ptr::copy_nonoverlapping(parent_vtable.subtype_overflow,
                                             vtable.subtype_overflow as *mut _,
                                             depth as usize - DISPLAY_SIZE);
                }

                let ptr = vtable
                    .subtype_overflow
                    .offset(depth as isize - DISPLAY_SIZE as isize) as
                          *mut _;

                *ptr = &**vtable as *const _;
            }

        } else {
            depth_fixed = depth;

            vtable.subtype_display[depth] = &**vtable as *const _;
        }

        vtable.subtype_depth = depth as i32;
        vtable.subtype_display[0..depth_fixed].clone_from_slice(&parent_vtable.subtype_display
                                                                     [0..depth_fixed]);

        depth

    } else {
        vtable.subtype_depth = 0;
        vtable.subtype_display[0] = &**vtable as *const _;

        0
    }
}<|endoftext|>


<commit_before>use std::cell::Cell;

use attributes::Attribute;
use drawing_ctx::RsvgDrawingCtx;
use filter_context::RsvgFilterContext;
use handle::RsvgHandle;
use length::{LengthDir, RsvgLength};
use node::{NodeTrait, NodeResult, RsvgNode, RsvgCNodeImpl};
use parsers::parse;
use property_bag::PropertyBag;
use state::State;

mod ffi;
use self::ffi::*;

pub mod offset;

/// A filter primitive interface.
trait Filter: NodeTrait {
    /// Renders this filter primitive.
    ///
    /// If this filter primitive can't be rendered for whatever reason (for instance, a required
    /// property hasn't been provided), return without drawing anything.
    fn render(&self, ctx: *mut RsvgFilterContext);
}

/// The base filter node containing common properties.
struct Primitive {
    // The only purpose of this field is to communicate the render callback back to C code.
    // TODO: get rid of this once all filters have been ported to Rust.
    c_struct: RsvgFilterPrimitive,

    x: Cell<Option<RsvgLength>>,
    y: Cell<Option<RsvgLength>>,
    width: Cell<Option<RsvgLength>>,
    height: Cell<Option<RsvgLength>>,
    result: Cell<Option<String>>,
}

/// The base node for filters which accept input.
struct PrimitiveWithInput {
    base: Primitive,
    in_: Cell<Option<String>>, // TODO: enum { SourceGraphic | ... }
}

impl Primitive {
    /// Constructs a new `Primitive` with empty properties.
    #[inline]
    fn new<T: Filter>() -> Primitive {
        Primitive {
            c_struct: RsvgFilterPrimitive::new::<T>(),

            x: Cell::new(None),
            y: Cell::new(None),
            width: Cell::new(None),
            height: Cell::new(None),
            result: Cell::new(None),
        }
    }
}

impl NodeTrait for Primitive {
    fn set_atts(&self, _: &RsvgNode, _: *const RsvgHandle, pbag: &PropertyBag) -> NodeResult {
        for (_key, attr, value) in pbag.iter() {
            match attr {
                Attribute::X => self.x.set(Some(parse("x", value, LengthDir::Horizontal, None)?)),
                Attribute::Y => self.y.set(Some(parse("y", value, LengthDir::Vertical, None)?)),
                Attribute::Width => self.width.set(Some(parse("width", value, LengthDir::Horizontal, None)?)),
                Attribute::Height => self.height.set(Some(parse("height", value, LengthDir::Vertical, None)?)),
                Attribute::Result => self.result.set(Some(value.to_string())),
                _ => (),
            }
        }

        Ok(())
    }

    #[inline]
    fn draw(&self, _: &RsvgNode, _: *mut RsvgDrawingCtx, _: &State, _: i32, _: bool) {
        // Nothing; filters are drawn in rsvg-cairo-draw.c.
    }

    #[inline]
    fn get_c_impl(&self) -> *const RsvgCNodeImpl {
        // At least for now we have to return a *const RsvgFilterPrimitive.
        &self.c_struct as *const RsvgFilterPrimitive as *const RsvgCNodeImpl
    }
}

impl PrimitiveWithInput {
    /// Constructs a new `PrimitiveWithInput` with empty properties.
    #[inline]
    fn new<T: Filter>() -> PrimitiveWithInput {
        PrimitiveWithInput {
            base: Primitive::new::<T>(),
            in_: Cell::new(None),
        }
    }
}

impl NodeTrait for PrimitiveWithInput {
    fn set_atts(&self, node: &RsvgNode, handle: *const RsvgHandle, pbag: &PropertyBag) -> NodeResult {
        self.base.set_atts(node, handle, pbag)?;

        for (_key, attr, value) in pbag.iter() {
            match attr {
                Attribute::In => self.in_.set(Some(value.to_string())),
                _ => (),
            }
        }

        Ok(())
    }

    #[inline]
    fn draw(&self, _: &RsvgNode, _: *mut RsvgDrawingCtx, _: &State, _: i32, _: bool) {
        // Nothing; filters are drawn in rsvg-cairo-draw.c.
    }

    #[inline]
    fn get_c_impl(&self) -> *const RsvgCNodeImpl {
        self.base.get_c_impl()
    }
}
<commit_msg>Add the filters::Input enum<commit_after>use std::cell::{Cell, RefCell};

use attributes::Attribute;
use drawing_ctx::RsvgDrawingCtx;
use filter_context::RsvgFilterContext;
use error::AttributeError;
use filter_context::{FilterContext, RsvgFilterContext};
use handle::RsvgHandle;
use length::{LengthDir, RsvgLength};
use node::{NodeResult, NodeTrait, RsvgCNodeImpl, RsvgNode};
use parsers::{parse, Parse};
use property_bag::PropertyBag;
use state::State;

mod ffi;
use self::ffi::*;

pub mod offset;

/// A filter primitive interface.
trait Filter: NodeTrait {
    /// Renders this filter primitive.
    ///
    /// If this filter primitive can't be rendered for whatever reason (for instance, a required
    /// property hasn't been provided), return without drawing anything.
    fn render(&self, ctx: *mut RsvgFilterContext);
}

/// The base filter node containing common properties.
struct Primitive {
    // The only purpose of this field is to communicate the render callback back to C code.
    // TODO: get rid of this once all filters have been ported to Rust.
    c_struct: RsvgFilterPrimitive,

    x: Cell<Option<RsvgLength>>,
    y: Cell<Option<RsvgLength>>,
    width: Cell<Option<RsvgLength>>,
    height: Cell<Option<RsvgLength>>,
    result: Cell<Option<String>>,
}

/// An enumeration of possible inputs for a filter primitive.
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
enum Input {
    SourceGraphic,
    SourceAlpha,
    BackgroundImage,
    BackgroundAlpha,
    FillPaint,
    StrokePaint,
    FilterResult(String),
}

/// The base node for filter primitives which accept input.
struct PrimitiveWithInput {
    base: Primitive,
    in_: RefCell<Option<Input>>,
}

impl Primitive {
    /// Constructs a new `Primitive` with empty properties.
    #[inline]
    fn new<T: Filter>() -> Primitive {
        Primitive {
            c_struct: RsvgFilterPrimitive::new::<T>(),

            x: Cell::new(None),
            y: Cell::new(None),
            width: Cell::new(None),
            height: Cell::new(None),
            result: Cell::new(None),
        }
    }
}

impl NodeTrait for Primitive {
    fn set_atts(&self, _: &RsvgNode, _: *const RsvgHandle, pbag: &PropertyBag) -> NodeResult {
        for (_key, attr, value) in pbag.iter() {
            match attr {
                Attribute::X => self.x.set(Some(parse("x", value, LengthDir::Horizontal, None)?)),
                Attribute::Y => self.y.set(Some(parse("y", value, LengthDir::Vertical, None)?)),
                Attribute::Width => self.width.set(Some(parse("width", value, LengthDir::Horizontal, None)?)),
                Attribute::Height => self.height.set(Some(parse("height", value, LengthDir::Vertical, None)?)),
                Attribute::Result => self.result.set(Some(value.to_string())),
                _ => (),
            }
        }

        Ok(())
    }

    #[inline]
    fn draw(&self, _: &RsvgNode, _: *mut RsvgDrawingCtx, _: &State, _: i32, _: bool) {
        // Nothing; filters are drawn in rsvg-cairo-draw.c.
    }

    #[inline]
    fn get_c_impl(&self) -> *const RsvgCNodeImpl {
        // At least for now we have to return a *const RsvgFilterPrimitive.
        &self.c_struct as *const RsvgFilterPrimitive as *const RsvgCNodeImpl
    }
}

impl Parse for Input {
    type Data = ();
    type Err = AttributeError;

    fn parse(s: &str, _data: Self::Data) -> Result<Self, Self::Err> {
        match s {
            "SourceGraphic" => Ok(Input::SourceGraphic),
            "SourceAlpha" => Ok(Input::SourceAlpha),
            "BackgroundImage" => Ok(Input::BackgroundImage),
            "BackgroundAlpha" => Ok(Input::BackgroundAlpha),
            "FillPaint" => Ok(Input::FillPaint),
            "StrokePaint" => Ok(Input::StrokePaint),
            s => Ok(Input::FilterResult(s.to_string())),
        }
    }
}

impl PrimitiveWithInput {
    /// Constructs a new `PrimitiveWithInput` with empty properties.
    #[inline]
    fn new<T: Filter>() -> PrimitiveWithInput {
        PrimitiveWithInput {
            base: Primitive::new(),
            in_: RefCell::new(None),
        }
    }
}

impl NodeTrait for PrimitiveWithInput {
    fn set_atts(
        &self,
        node: &RsvgNode,
        handle: *const RsvgHandle,
        pbag: &PropertyBag,
    ) -> NodeResult {
        self.base.set_atts(node, handle, pbag)?;

        for (_key, attr, value) in pbag.iter() {
            match attr {
                Attribute::In => drop(self.in_.replace(Some(parse("in", value, (), None)?))),
                _ => (),
            }
        }

        Ok(())
    }

    #[inline]
    fn draw(&self, _: &RsvgNode, _: *mut RsvgDrawingCtx, _: &State, _: i32, _: bool) {
        // Nothing; filters are drawn in rsvg-cairo-draw.c.
    }

    #[inline]
    fn get_c_impl(&self) -> *const RsvgCNodeImpl {
        self.base.get_c_impl()
    }
}
<|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.

//! A module for working with borrowed data.

#![stable(feature = "rust1", since = "1.0.0")]

use core::clone::Clone;
use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
use core::convert::AsRef;
use core::hash::{Hash, Hasher};
use core::marker::Sized;
use core::ops::Deref;
use core::option::Option;

use fmt;
use alloc::{boxed, rc, arc};

use self::Cow::*;

/// A trait for borrowing data.
///
/// In general, there may be several ways to "borrow" a piece of data.  The
/// typical ways of borrowing a type `T` are `&T` (a shared borrow) and `&mut T`
/// (a mutable borrow). But types like `Vec<T>` provide additional kinds of
/// borrows: the borrowed slices `&[T]` and `&mut [T]`.
///
/// When writing generic code, it is often desirable to abstract over all ways
/// of borrowing data from a given type. That is the role of the `Borrow`
/// trait: if `T: Borrow<U>`, then `&U` can be borrowed from `&T`.  A given
/// type can be borrowed as multiple different types. In particular, `Vec<T>:
/// Borrow<Vec<T>>` and `Vec<T>: Borrow<[T]>`.
///
/// `Borrow` is very similar to, but different than, `AsRef`. See
/// [the book][book] for more.
///
/// [book]: ../../book/borrow-and-asref.html
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Borrow<Borrowed: ?Sized> {
    /// Immutably borrows from an owned value.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::Borrow;
    ///
    /// fn check<T: Borrow<str>>(s: T) {
    ///     assert_eq!("Hello", s.borrow());
    /// }
    ///
    /// let s = "Hello".to_string();
    ///
    /// check(s);
    ///
    /// let s = "Hello";
    ///
    /// check(s);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn borrow(&self) -> &Borrowed;
}

/// A trait for mutably borrowing data.
///
/// Similar to `Borrow`, but for mutable borrows.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait BorrowMut<Borrowed: ?Sized> : Borrow<Borrowed> {
    /// Mutably borrows from an owned value.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::BorrowMut;
    ///
    /// fn check<T: BorrowMut<[i32]>>(mut v: T) {
    ///     assert_eq!(&mut [1, 2, 3], v.borrow_mut());
    /// }
    ///
    /// let v = vec![1, 2, 3];
    ///
    /// check(v);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn borrow_mut(&mut self) -> &mut Borrowed;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Borrow<T> for T {
    fn borrow(&self) -> &T { self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> BorrowMut<T> for T {
    fn borrow_mut(&mut self) -> &mut T { self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Borrow<T> for &'a T {
    fn borrow(&self) -> &T { &**self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Borrow<T> for &'a mut T {
    fn borrow(&self) -> &T { &**self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> BorrowMut<T> for &'a mut T {
    fn borrow_mut(&mut self) -> &mut T { &mut **self }
}

impl<T: ?Sized> Borrow<T> for boxed::Box<T> {
    fn borrow(&self) -> &T { &**self }
}

impl<T: ?Sized> BorrowMut<T> for boxed::Box<T> {
    fn borrow_mut(&mut self) -> &mut T { &mut **self }
}

impl<T: ?Sized> Borrow<T> for rc::Rc<T> {
    fn borrow(&self) -> &T { &**self }
}

impl<T: ?Sized> Borrow<T> for arc::Arc<T> {
    fn borrow(&self) -> &T { &**self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Borrow<B> for Cow<'a, B> where B: ToOwned, <B as ToOwned>::Owned: 'a {
    fn borrow(&self) -> &B {
        &**self
    }
}

/// A generalization of `Clone` to borrowed data.
///
/// Some types make it possible to go from borrowed to owned, usually by
/// implementing the `Clone` trait. But `Clone` works only for going from `&T`
/// to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data
/// from any borrow of a given type.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait ToOwned {
    #[stable(feature = "rust1", since = "1.0.0")]
    type Owned: Borrow<Self>;

    /// Creates owned data from borrowed data, usually by cloning.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn to_owned(&self) -> Self::Owned;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> ToOwned for T where T: Clone {
    type Owned = T;
    fn to_owned(&self) -> T { self.clone() }
}

/// A clone-on-write smart pointer.
///
/// The type `Cow` is a smart pointer providing clone-on-write functionality: it
/// can enclose and provide immutable access to borrowed data, and clone the
/// data lazily when mutation or ownership is required. The type is designed to
/// work with general borrowed data via the `Borrow` trait.
///
/// `Cow` implements `Deref`, which means that you can call
/// non-mutating methods directly on the data it encloses. If mutation
/// is desired, `to_mut` will obtain a mutable reference to an owned
/// value, cloning if necessary.
///
/// # Examples
///
/// ```
/// use std::borrow::Cow;
///
/// fn abs_all(input: &mut Cow<[i32]>) {
///     for i in 0..input.len() {
///         let v = input[i];
///         if v < 0 {
///             // clones into a vector the first time (if not already owned)
///             input.to_mut()[i] = -v;
///         }
///     }
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub enum Cow<'a, B: ?Sized + 'a> where B: ToOwned {
    /// Borrowed data.
    #[stable(feature = "rust1", since = "1.0.0")]
    Borrowed(&'a B),

    /// Owned data.
    #[stable(feature = "rust1", since = "1.0.0")]
    Owned(<B as ToOwned>::Owned)
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Clone for Cow<'a, B> where B: ToOwned {
    fn clone(&self) -> Cow<'a, B> {
        match *self {
            Borrowed(b) => Borrowed(b),
            Owned(ref o) => {
                let b: &B = o.borrow();
                Owned(b.to_owned())
            },
        }
    }
}

impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned {
    /// Acquires a mutable reference to the owned form of the data.
    ///
    /// Copies the data if it is not already owned.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::Cow;
    ///
    /// let mut cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]);
    ///
    /// let hello = cow.to_mut();
    ///
    /// assert_eq!(hello, &[1, 2, 3]);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn to_mut(&mut self) -> &mut <B as ToOwned>::Owned {
        match *self {
            Borrowed(borrowed) => {
                *self = Owned(borrowed.to_owned());
                self.to_mut()
            }
            Owned(ref mut owned) => owned
        }
    }

    /// Extracts the owned data.
    ///
    /// Copies the data if it is not already owned.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::Cow;
    ///
    /// let cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]);
    ///
    /// let hello = cow.into_owned();
    ///
    /// assert_eq!(vec![1, 2, 3], hello);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn into_owned(self) -> <B as ToOwned>::Owned {
        match self {
            Borrowed(borrowed) => borrowed.to_owned(),
            Owned(owned) => owned
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Deref for Cow<'a, B> where B: ToOwned {
    type Target = B;

    fn deref(&self) -> &B {
        match *self {
            Borrowed(borrowed) => borrowed,
            Owned(ref owned) => owned.borrow()
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Eq for Cow<'a, B> where B: Eq + ToOwned {}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Ord for Cow<'a, B> where B: Ord + ToOwned {
    #[inline]
    fn cmp(&self, other: &Cow<'a, B>) -> Ordering {
        Ord::cmp(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, 'b, B: ?Sized, C: ?Sized> PartialEq<Cow<'b, C>> for Cow<'a, B> where
    B: PartialEq<C> + ToOwned, C: ToOwned,
{
    #[inline]
    fn eq(&self, other: &Cow<'b, C>) -> bool {
        PartialEq::eq(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> PartialOrd for Cow<'a, B> where B: PartialOrd + ToOwned,
{
    #[inline]
    fn partial_cmp(&self, other: &Cow<'a, B>) -> Option<Ordering> {
        PartialOrd::partial_cmp(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> fmt::Debug for Cow<'a, B> where
    B: fmt::Debug + ToOwned,
    <B as ToOwned>::Owned: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Borrowed(ref b) => fmt::Debug::fmt(b, f),
            Owned(ref o) => fmt::Debug::fmt(o, f),
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> fmt::Display for Cow<'a, B> where
    B: fmt::Display + ToOwned,
    <B as ToOwned>::Owned: fmt::Display,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Borrowed(ref b) => fmt::Display::fmt(b, f),
            Owned(ref o) => fmt::Display::fmt(o, f),
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Hash for Cow<'a, B> where B: Hash + ToOwned
{
    #[inline]
    fn hash<H: Hasher>(&self, state: &mut H) {
        Hash::hash(&**self, state)
    }
}

/// Trait for moving into a `Cow`.
#[unstable(feature = "into_cow", reason = "may be replaced by `convert::Into`")]
pub trait IntoCow<'a, B: ?Sized> where B: ToOwned {
    /// Moves `self` into `Cow`
    fn into_cow(self) -> Cow<'a, B>;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a,  B: ?Sized> IntoCow<'a, B> for Cow<'a, B> where B: ToOwned {
    fn into_cow(self) -> Cow<'a, B> {
        self
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized + ToOwned> AsRef<T> for Cow<'a, T> {
    fn as_ref(&self) -> &T {
        self
    }
}
<commit_msg>Auto merge of #27122 - nham:tweak-cow-docs, r=Gankro<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.

//! A module for working with borrowed data.

#![stable(feature = "rust1", since = "1.0.0")]

use core::clone::Clone;
use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
use core::convert::AsRef;
use core::hash::{Hash, Hasher};
use core::marker::Sized;
use core::ops::Deref;
use core::option::Option;

use fmt;
use alloc::{boxed, rc, arc};

use self::Cow::*;

/// A trait for borrowing data.
///
/// In general, there may be several ways to "borrow" a piece of data.  The
/// typical ways of borrowing a type `T` are `&T` (a shared borrow) and `&mut T`
/// (a mutable borrow). But types like `Vec<T>` provide additional kinds of
/// borrows: the borrowed slices `&[T]` and `&mut [T]`.
///
/// When writing generic code, it is often desirable to abstract over all ways
/// of borrowing data from a given type. That is the role of the `Borrow`
/// trait: if `T: Borrow<U>`, then `&U` can be borrowed from `&T`.  A given
/// type can be borrowed as multiple different types. In particular, `Vec<T>:
/// Borrow<Vec<T>>` and `Vec<T>: Borrow<[T]>`.
///
/// `Borrow` is very similar to, but different than, `AsRef`. See
/// [the book][book] for more.
///
/// [book]: ../../book/borrow-and-asref.html
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Borrow<Borrowed: ?Sized> {
    /// Immutably borrows from an owned value.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::Borrow;
    ///
    /// fn check<T: Borrow<str>>(s: T) {
    ///     assert_eq!("Hello", s.borrow());
    /// }
    ///
    /// let s = "Hello".to_string();
    ///
    /// check(s);
    ///
    /// let s = "Hello";
    ///
    /// check(s);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn borrow(&self) -> &Borrowed;
}

/// A trait for mutably borrowing data.
///
/// Similar to `Borrow`, but for mutable borrows.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait BorrowMut<Borrowed: ?Sized> : Borrow<Borrowed> {
    /// Mutably borrows from an owned value.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::BorrowMut;
    ///
    /// fn check<T: BorrowMut<[i32]>>(mut v: T) {
    ///     assert_eq!(&mut [1, 2, 3], v.borrow_mut());
    /// }
    ///
    /// let v = vec![1, 2, 3];
    ///
    /// check(v);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn borrow_mut(&mut self) -> &mut Borrowed;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Borrow<T> for T {
    fn borrow(&self) -> &T { self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> BorrowMut<T> for T {
    fn borrow_mut(&mut self) -> &mut T { self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Borrow<T> for &'a T {
    fn borrow(&self) -> &T { &**self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Borrow<T> for &'a mut T {
    fn borrow(&self) -> &T { &**self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> BorrowMut<T> for &'a mut T {
    fn borrow_mut(&mut self) -> &mut T { &mut **self }
}

impl<T: ?Sized> Borrow<T> for boxed::Box<T> {
    fn borrow(&self) -> &T { &**self }
}

impl<T: ?Sized> BorrowMut<T> for boxed::Box<T> {
    fn borrow_mut(&mut self) -> &mut T { &mut **self }
}

impl<T: ?Sized> Borrow<T> for rc::Rc<T> {
    fn borrow(&self) -> &T { &**self }
}

impl<T: ?Sized> Borrow<T> for arc::Arc<T> {
    fn borrow(&self) -> &T { &**self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Borrow<B> for Cow<'a, B> where B: ToOwned, <B as ToOwned>::Owned: 'a {
    fn borrow(&self) -> &B {
        &**self
    }
}

/// A generalization of `Clone` to borrowed data.
///
/// Some types make it possible to go from borrowed to owned, usually by
/// implementing the `Clone` trait. But `Clone` works only for going from `&T`
/// to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data
/// from any borrow of a given type.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait ToOwned {
    #[stable(feature = "rust1", since = "1.0.0")]
    type Owned: Borrow<Self>;

    /// Creates owned data from borrowed data, usually by cloning.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn to_owned(&self) -> Self::Owned;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> ToOwned for T where T: Clone {
    type Owned = T;
    fn to_owned(&self) -> T { self.clone() }
}

/// A clone-on-write smart pointer.
///
/// The type `Cow` is a smart pointer providing clone-on-write functionality: it
/// can enclose and provide immutable access to borrowed data, and clone the
/// data lazily when mutation or ownership is required. The type is designed to
/// work with general borrowed data via the `Borrow` trait.
///
/// `Cow` implements `Deref`, which means that you can call
/// non-mutating methods directly on the data it encloses. If mutation
/// is desired, `to_mut` will obtain a mutable reference to an owned
/// value, cloning if necessary.
///
/// # Examples
///
/// ```
/// use std::borrow::Cow;
///
/// fn abs_all(input: &mut Cow<[i32]>) {
///     for i in 0..input.len() {
///         let v = input[i];
///         if v < 0 {
///             // clones into a vector the first time (if not already owned)
///             input.to_mut()[i] = -v;
///         }
///     }
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub enum Cow<'a, B: ?Sized + 'a> where B: ToOwned {
    /// Borrowed data.
    #[stable(feature = "rust1", since = "1.0.0")]
    Borrowed(&'a B),

    /// Owned data.
    #[stable(feature = "rust1", since = "1.0.0")]
    Owned(<B as ToOwned>::Owned)
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Clone for Cow<'a, B> where B: ToOwned {
    fn clone(&self) -> Cow<'a, B> {
        match *self {
            Borrowed(b) => Borrowed(b),
            Owned(ref o) => {
                let b: &B = o.borrow();
                Owned(b.to_owned())
            },
        }
    }
}

impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned {
    /// Acquires a mutable reference to the owned form of the data.
    ///
    /// Clones the data if it is not already owned.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::Cow;
    ///
    /// let mut cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]);
    ///
    /// let hello = cow.to_mut();
    ///
    /// assert_eq!(hello, &[1, 2, 3]);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn to_mut(&mut self) -> &mut <B as ToOwned>::Owned {
        match *self {
            Borrowed(borrowed) => {
                *self = Owned(borrowed.to_owned());
                self.to_mut()
            }
            Owned(ref mut owned) => owned
        }
    }

    /// Extracts the owned data.
    ///
    /// Clones the data if it is not already owned.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::Cow;
    ///
    /// let cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]);
    ///
    /// let hello = cow.into_owned();
    ///
    /// assert_eq!(vec![1, 2, 3], hello);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn into_owned(self) -> <B as ToOwned>::Owned {
        match self {
            Borrowed(borrowed) => borrowed.to_owned(),
            Owned(owned) => owned
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Deref for Cow<'a, B> where B: ToOwned {
    type Target = B;

    fn deref(&self) -> &B {
        match *self {
            Borrowed(borrowed) => borrowed,
            Owned(ref owned) => owned.borrow()
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Eq for Cow<'a, B> where B: Eq + ToOwned {}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Ord for Cow<'a, B> where B: Ord + ToOwned {
    #[inline]
    fn cmp(&self, other: &Cow<'a, B>) -> Ordering {
        Ord::cmp(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, 'b, B: ?Sized, C: ?Sized> PartialEq<Cow<'b, C>> for Cow<'a, B> where
    B: PartialEq<C> + ToOwned, C: ToOwned,
{
    #[inline]
    fn eq(&self, other: &Cow<'b, C>) -> bool {
        PartialEq::eq(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> PartialOrd for Cow<'a, B> where B: PartialOrd + ToOwned,
{
    #[inline]
    fn partial_cmp(&self, other: &Cow<'a, B>) -> Option<Ordering> {
        PartialOrd::partial_cmp(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> fmt::Debug for Cow<'a, B> where
    B: fmt::Debug + ToOwned,
    <B as ToOwned>::Owned: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Borrowed(ref b) => fmt::Debug::fmt(b, f),
            Owned(ref o) => fmt::Debug::fmt(o, f),
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> fmt::Display for Cow<'a, B> where
    B: fmt::Display + ToOwned,
    <B as ToOwned>::Owned: fmt::Display,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Borrowed(ref b) => fmt::Display::fmt(b, f),
            Owned(ref o) => fmt::Display::fmt(o, f),
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Hash for Cow<'a, B> where B: Hash + ToOwned
{
    #[inline]
    fn hash<H: Hasher>(&self, state: &mut H) {
        Hash::hash(&**self, state)
    }
}

/// Trait for moving into a `Cow`.
#[unstable(feature = "into_cow", reason = "may be replaced by `convert::Into`")]
pub trait IntoCow<'a, B: ?Sized> where B: ToOwned {
    /// Moves `self` into `Cow`
    fn into_cow(self) -> Cow<'a, B>;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a,  B: ?Sized> IntoCow<'a, B> for Cow<'a, B> where B: ToOwned {
    fn into_cow(self) -> Cow<'a, B> {
        self
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized + ToOwned> AsRef<T> for Cow<'a, T> {
    fn as_ref(&self) -> &T {
        self
    }
}
<|endoftext|>


<commit_before>// Copyright 2012 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.

//! Handles translation of callees as well as other call-related
//! things.  Callees are a superset of normal rust values and sometimes
//! have different representations.  In particular, top-level fn items
//! and methods are represented as just a fn ptr and not a full
//! closure.

use attributes;
use common::{self, CrateContext};
use consts;
use declare;
use llvm::{self, ValueRef};
use monomorphize::Instance;
use rustc::hir::def_id::DefId;
use rustc::ty::{self, TypeFoldable};
use rustc::traits;
use rustc::ty::subst::Substs;
use type_of;

/// Translates a reference to a fn/method item, monomorphizing and
/// inlining as it goes.
///
/// # Parameters
///
/// - `ccx`: the crate context
/// - `instance`: the instance to be instantiated
pub fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                        instance: Instance<'tcx>)
                        -> ValueRef
{
    let tcx = ccx.tcx();

    debug!("get_fn(instance={:?})", instance);

    assert!(!instance.substs.needs_infer());
    assert!(!instance.substs.has_escaping_regions());
    assert!(!instance.substs.has_param_types());

    let fn_ty = common::instance_ty(ccx.tcx(), &instance);
    if let Some(&llfn) = ccx.instances().borrow().get(&instance) {
        return llfn;
    }

    let sym = tcx.symbol_name(instance);
    debug!("get_fn({:?}: {:?}) => {}", instance, fn_ty, sym);

    // Create a fn pointer with the substituted signature.
    let fn_ptr_ty = tcx.mk_fn_ptr(common::ty_fn_sig(ccx, fn_ty));
    let llptrty = type_of::type_of(ccx, fn_ptr_ty);

    let llfn = if let Some(llfn) = declare::get_declared_value(ccx, &sym) {
        // This is subtle and surprising, but sometimes we have to bitcast
        // the resulting fn pointer.  The reason has to do with external
        // functions.  If you have two crates that both bind the same C
        // library, they may not use precisely the same types: for
        // example, they will probably each declare their own structs,
        // which are distinct types from LLVM's point of view (nominal
        // types).
        //
        // Now, if those two crates are linked into an application, and
        // they contain inlined code, you can wind up with a situation
        // where both of those functions wind up being loaded into this
        // application simultaneously. In that case, the same function
        // (from LLVM's point of view) requires two types. But of course
        // LLVM won't allow one function to have two types.
        //
        // What we currently do, therefore, is declare the function with
        // one of the two types (whichever happens to come first) and then
        // bitcast as needed when the function is referenced to make sure
        // it has the type we expect.
        //
        // This can occur on either a crate-local or crate-external
        // reference. It also occurs when testing libcore and in some
        // other weird situations. Annoying.
        if common::val_ty(llfn) != llptrty {
            debug!("get_fn: casting {:?} to {:?}", llfn, llptrty);
            consts::ptrcast(llfn, llptrty)
        } else {
            debug!("get_fn: not casting pointer!");
            llfn
        }
    } else {
        let llfn = declare::declare_fn(ccx, &sym, fn_ty);
        assert_eq!(common::val_ty(llfn), llptrty);
        debug!("get_fn: not casting pointer!");

        if common::is_inline_instance(tcx, &instance) {
            attributes::inline(llfn, attributes::InlineAttr::Hint);
        }
        let attrs = instance.def.attrs(ccx.tcx());
        attributes::from_fn_attrs(ccx, &attrs, llfn);

        let instance_def_id = instance.def_id();

        // Perhaps questionable, but we assume that anything defined
        // *in Rust code* may unwind. Foreign items like `extern "C" {
        // fn foo(); }` are assumed not to unwind **unless** they have
        // a `#[unwind]` attribute.
        if !tcx.is_foreign_item(instance_def_id) {
            attributes::unwind(llfn, true);
        }

        // Apply an appropriate linkage/visibility value to our item that we
        // just declared.
        //
        // This is sort of subtle. Inside our codegen unit we started off
        // compilation by predefining all our own `TransItem` instances. That
        // is, everything we're translating ourselves is already defined. That
        // means that anything we're actually translating ourselves will have
        // hit the above branch in `get_declared_value`. As a result, we're
        // guaranteed here that we're declaring a symbol that won't get defined,
        // or in other words we're referencing a foreign value.
        //
        // So because this is a foreign value we blanket apply an external
        // linkage directive because it's coming from a different object file.
        // The visibility here is where it gets tricky. This symbol could be
        // referencing some foreign crate or foreign library (an `extern`
        // block) in which case we want to leave the default visibility. We may
        // also, though, have multiple codegen units.
        //
        // In the situation of multiple codegen units this function may be
        // referencing a function from another codegen unit. If we're
        // indeed referencing a symbol in another codegen unit then we're in one
        // of two cases:
        //
        //  * This is a symbol defined in a foreign crate and we're just
        //    monomorphizing in another codegen unit. In this case this symbols
        //    is for sure not exported, so both codegen units will be using
        //    hidden visibility. Hence, we apply a hidden visibility here.
        //
        //  * This is a symbol defined in our local crate. If the symbol in the
        //    other codegen unit is also not exported then like with the foreign
        //    case we apply a hidden visibility. If the symbol is exported from
        //    the foreign object file, however, then we leave this at the
        //    default visibility as we'll just import it naturally.
        unsafe {
            llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::ExternalLinkage);

            if ccx.tcx().is_translated_function(instance_def_id) {
                if instance_def_id.is_local() {
                    if !ccx.tcx().is_exported_symbol(instance_def_id) {
                        llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
                    }
                } else {
                    llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
                }
            }
        }

        // FIXME(#42293) we should actually track this, but fails too many tests
        // today.
        tcx.dep_graph.with_ignore(|| {
            if ccx.use_dll_storage_attrs() &&
                tcx.is_dllimport_foreign_item(instance_def_id)
            {
                unsafe {
                    llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport);
                }
            }
        });
        llfn
    };

    ccx.instances().borrow_mut().insert(instance, llfn);

    llfn
}

pub fn resolve_and_get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                    def_id: DefId,
                                    substs: &'tcx Substs<'tcx>)
                                    -> ValueRef
{
    get_fn(ccx, ty::Instance::resolve(ccx.tcx(),
           ty::ParamEnv::empty(traits::Reveal::All),
           def_id,
           substs).unwrap())
}
<commit_msg>fix formatting<commit_after>// Copyright 2012 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.

//! Handles translation of callees as well as other call-related
//! things.  Callees are a superset of normal rust values and sometimes
//! have different representations.  In particular, top-level fn items
//! and methods are represented as just a fn ptr and not a full
//! closure.

use attributes;
use common::{self, CrateContext};
use consts;
use declare;
use llvm::{self, ValueRef};
use monomorphize::Instance;
use rustc::hir::def_id::DefId;
use rustc::ty::{self, TypeFoldable};
use rustc::traits;
use rustc::ty::subst::Substs;
use type_of;

/// Translates a reference to a fn/method item, monomorphizing and
/// inlining as it goes.
///
/// # Parameters
///
/// - `ccx`: the crate context
/// - `instance`: the instance to be instantiated
pub fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                        instance: Instance<'tcx>)
                        -> ValueRef
{
    let tcx = ccx.tcx();

    debug!("get_fn(instance={:?})", instance);

    assert!(!instance.substs.needs_infer());
    assert!(!instance.substs.has_escaping_regions());
    assert!(!instance.substs.has_param_types());

    let fn_ty = common::instance_ty(ccx.tcx(), &instance);
    if let Some(&llfn) = ccx.instances().borrow().get(&instance) {
        return llfn;
    }

    let sym = tcx.symbol_name(instance);
    debug!("get_fn({:?}: {:?}) => {}", instance, fn_ty, sym);

    // Create a fn pointer with the substituted signature.
    let fn_ptr_ty = tcx.mk_fn_ptr(common::ty_fn_sig(ccx, fn_ty));
    let llptrty = type_of::type_of(ccx, fn_ptr_ty);

    let llfn = if let Some(llfn) = declare::get_declared_value(ccx, &sym) {
        // This is subtle and surprising, but sometimes we have to bitcast
        // the resulting fn pointer.  The reason has to do with external
        // functions.  If you have two crates that both bind the same C
        // library, they may not use precisely the same types: for
        // example, they will probably each declare their own structs,
        // which are distinct types from LLVM's point of view (nominal
        // types).
        //
        // Now, if those two crates are linked into an application, and
        // they contain inlined code, you can wind up with a situation
        // where both of those functions wind up being loaded into this
        // application simultaneously. In that case, the same function
        // (from LLVM's point of view) requires two types. But of course
        // LLVM won't allow one function to have two types.
        //
        // What we currently do, therefore, is declare the function with
        // one of the two types (whichever happens to come first) and then
        // bitcast as needed when the function is referenced to make sure
        // it has the type we expect.
        //
        // This can occur on either a crate-local or crate-external
        // reference. It also occurs when testing libcore and in some
        // other weird situations. Annoying.
        if common::val_ty(llfn) != llptrty {
            debug!("get_fn: casting {:?} to {:?}", llfn, llptrty);
            consts::ptrcast(llfn, llptrty)
        } else {
            debug!("get_fn: not casting pointer!");
            llfn
        }
    } else {
        let llfn = declare::declare_fn(ccx, &sym, fn_ty);
        assert_eq!(common::val_ty(llfn), llptrty);
        debug!("get_fn: not casting pointer!");

        if common::is_inline_instance(tcx, &instance) {
            attributes::inline(llfn, attributes::InlineAttr::Hint);
        }
        let attrs = instance.def.attrs(ccx.tcx());
        attributes::from_fn_attrs(ccx, &attrs, llfn);

        let instance_def_id = instance.def_id();

        // Perhaps questionable, but we assume that anything defined
        // *in Rust code* may unwind. Foreign items like `extern "C" {
        // fn foo(); }` are assumed not to unwind **unless** they have
        // a `#[unwind]` attribute.
        if !tcx.is_foreign_item(instance_def_id) {
            attributes::unwind(llfn, true);
        }

        // Apply an appropriate linkage/visibility value to our item that we
        // just declared.
        //
        // This is sort of subtle. Inside our codegen unit we started off
        // compilation by predefining all our own `TransItem` instances. That
        // is, everything we're translating ourselves is already defined. That
        // means that anything we're actually translating ourselves will have
        // hit the above branch in `get_declared_value`. As a result, we're
        // guaranteed here that we're declaring a symbol that won't get defined,
        // or in other words we're referencing a foreign value.
        //
        // So because this is a foreign value we blanket apply an external
        // linkage directive because it's coming from a different object file.
        // The visibility here is where it gets tricky. This symbol could be
        // referencing some foreign crate or foreign library (an `extern`
        // block) in which case we want to leave the default visibility. We may
        // also, though, have multiple codegen units.
        //
        // In the situation of multiple codegen units this function may be
        // referencing a function from another codegen unit. If we're
        // indeed referencing a symbol in another codegen unit then we're in one
        // of two cases:
        //
        //  * This is a symbol defined in a foreign crate and we're just
        //    monomorphizing in another codegen unit. In this case this symbols
        //    is for sure not exported, so both codegen units will be using
        //    hidden visibility. Hence, we apply a hidden visibility here.
        //
        //  * This is a symbol defined in our local crate. If the symbol in the
        //    other codegen unit is also not exported then like with the foreign
        //    case we apply a hidden visibility. If the symbol is exported from
        //    the foreign object file, however, then we leave this at the
        //    default visibility as we'll just import it naturally.
        unsafe {
            llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::ExternalLinkage);

            if ccx.tcx().is_translated_function(instance_def_id) {
                if instance_def_id.is_local() {
                    if !ccx.tcx().is_exported_symbol(instance_def_id) {
                        llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
                    }
                } else {
                    llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
                }
            }
        }

        // FIXME(#42293) we should actually track this, but fails too many tests
        // today.
        tcx.dep_graph.with_ignore(|| {
            if ccx.use_dll_storage_attrs() &&
                tcx.is_dllimport_foreign_item(instance_def_id)
            {
                unsafe {
                    llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport);
                }
            }
        });
        llfn
    };

    ccx.instances().borrow_mut().insert(instance, llfn);

    llfn
}

pub fn resolve_and_get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                    def_id: DefId,
                                    substs: &'tcx Substs<'tcx>)
                                    -> ValueRef
{
    get_fn(
        ccx,
        ty::Instance::resolve(
            ccx.tcx(),
            ty::ParamEnv::empty(traits::Reveal::All),
            def_id,
            substs,)
        .unwrap()
    )
}
<|endoftext|>


<commit_before>use std::sync::Arc;
use std::collections::{HashSet, HashMap};

use rustc_serialize::json::Json;
use futures::sync::mpsc::{UnboundedSender as Sender};

use chat::Cid;
use intern::{Topic, SessionId, Lattice as Namespace, LatticeKey};
use super::ConnectionMessage;
use super::lattice;

pub struct NewConnection {
    pub cid: Cid,
    pub topics: HashSet<Topic>,
    pub lattices: HashSet<Namespace>,
    pub message_buffer: Vec<(Topic, Arc<Json>)>,
    pub channel: Sender<ConnectionMessage>,
}

pub struct Connection {
    pub cid: Cid,
    pub session_id: SessionId,
    pub topics: HashSet<Topic>,
    pub lattices: HashSet<Namespace>,
    pub channel: Sender<ConnectionMessage>,
}

impl NewConnection {
    pub fn new(conn_id: Cid, channel: Sender<ConnectionMessage>)
        -> NewConnection
    {
        NewConnection {
            cid: conn_id,
            topics: HashSet::new(),
            lattices: HashSet::new(),
            message_buffer: Vec::new(),
            channel: channel,
        }
    }
    pub fn associate(self, session_id: SessionId) -> Connection {
        let mut conn = Connection {
            cid: self.cid,
            session_id: session_id,
            topics: self.topics,
            lattices: self.lattices,
            channel: self.channel,
        };
        for (t, m) in self.message_buffer {
            conn.message(t, m);
        }
        return conn;
    }
    pub fn message(&mut self, topic: Topic, data: Arc<Json>) {
        self.message_buffer.push((topic, data));
    }
}

impl Connection {

    pub fn message(&mut self, topic: Topic, data: Arc<Json>) {
        self.channel.send(ConnectionMessage::Publish(topic, data))
            .expect("send connection message");
    }

    pub fn lattice(&mut self, namespace: &Namespace,
        update: &Arc<HashMap<LatticeKey, lattice::Values>>)
    {
        let msg = ConnectionMessage::Lattice(
            namespace.clone(), update.clone());
        self.channel.send(msg)
            .map_err(|e| info!("Error sending lattice: {}", e)).ok();
    }
}
<commit_msg>Fix crash on non-existent connection<commit_after>use std::sync::Arc;
use std::collections::{HashSet, HashMap};

use rustc_serialize::json::Json;
use futures::sync::mpsc::{UnboundedSender as Sender};

use chat::Cid;
use intern::{Topic, SessionId, Lattice as Namespace, LatticeKey};
use super::ConnectionMessage;
use super::lattice;

pub struct NewConnection {
    pub cid: Cid,
    pub topics: HashSet<Topic>,
    pub lattices: HashSet<Namespace>,
    pub message_buffer: Vec<(Topic, Arc<Json>)>,
    pub channel: Sender<ConnectionMessage>,
}

pub struct Connection {
    pub cid: Cid,
    pub session_id: SessionId,
    pub topics: HashSet<Topic>,
    pub lattices: HashSet<Namespace>,
    pub channel: Sender<ConnectionMessage>,
}

impl NewConnection {
    pub fn new(conn_id: Cid, channel: Sender<ConnectionMessage>)
        -> NewConnection
    {
        NewConnection {
            cid: conn_id,
            topics: HashSet::new(),
            lattices: HashSet::new(),
            message_buffer: Vec::new(),
            channel: channel,
        }
    }
    pub fn associate(self, session_id: SessionId) -> Connection {
        let mut conn = Connection {
            cid: self.cid,
            session_id: session_id,
            topics: self.topics,
            lattices: self.lattices,
            channel: self.channel,
        };
        for (t, m) in self.message_buffer {
            conn.message(t, m);
        }
        return conn;
    }
    pub fn message(&mut self, topic: Topic, data: Arc<Json>) {
        self.message_buffer.push((topic, data));
    }
}

impl Connection {

    pub fn message(&mut self, topic: Topic, data: Arc<Json>) {
        self.channel.send(ConnectionMessage::Publish(topic, data))
            .map_err(|e| info!("Error sending message: {}", e)).ok();
    }

    pub fn lattice(&mut self, namespace: &Namespace,
        update: &Arc<HashMap<LatticeKey, lattice::Values>>)
    {
        let msg = ConnectionMessage::Lattice(
            namespace.clone(), update.clone());
        self.channel.send(msg)
            .map_err(|e| info!("Error sending lattice: {}", e)).ok();
    }
}
<|endoftext|>


<commit_before>//! Tidy check to ensure `#[test]` is not used directly inside `libcore`.
//!
//! `#![no_core]` libraries cannot be tested directly due to duplicating lang
//! item. All tests must be written externally in `libcore/tests`.

use std::path::Path;

pub fn check(path: &Path, bad: &mut bool) {
    let libcore_path = path.join("libcore");
    super::walk(
        &libcore_path,
        &mut |subpath| t!(subpath.strip_prefix(&libcore_path)).starts_with("tests"),
        &mut |entry, contents| {
            let subpath = entry.path();
            if let Some("rs") = subpath.extension().and_then(|e| e.to_str()) {
                let contents = contents.trim();
                if !contents.starts_with("//") && contents.contains("#[test]") {
                    tidy_error!(
                        bad,
                        "`{}` contains `#[test]`; libcore tests must be placed inside \
                        `src/libcore/tests/`",
                        subpath.display()
                    );
                }
            }
        },
    );
}
<commit_msg>tidy: Fix a regression in `#[test]` detection in libcore<commit_after>//! Tidy check to ensure `#[test]` is not used directly inside `libcore`.
//!
//! `#![no_core]` libraries cannot be tested directly due to duplicating lang
//! item. All tests must be written externally in `libcore/tests`.

use std::path::Path;

pub fn check(path: &Path, bad: &mut bool) {
    let libcore_path = path.join("libcore");
    super::walk(
        &libcore_path,
        &mut |subpath| t!(subpath.strip_prefix(&libcore_path)).starts_with("tests"),
        &mut |entry, contents| {
            let subpath = entry.path();
            if let Some("rs") = subpath.extension().and_then(|e| e.to_str()) {
                for line in contents.lines() {
                    let line = line.trim();
                    if !line.starts_with("//") && line.contains("#[test]") {
                        tidy_error!(
                            bad,
                            "`{}` contains `#[test]`; libcore tests must be placed inside \
                            `src/libcore/tests/`",
                            subpath.display()
                        );
                    }
                }
            }
        },
    );
}
<|endoftext|>


<commit_before>use std::path;
use std::process;

use clap::{App, Arg, SubCommand, AppSettings};

use config;
use models;
use web;
use utils;

macro_rules! clap_dispatch {
    (
        $matches:expr;
        // FIXME: $matches_name absolutely requires a trailing comma, couldn't get it to work under
        // stable rust:
        //
        // foo(_) => ()   // Errors
        // foo(_,) => ()  // Works
        {
            $( $name:ident ($matches_name:pat, $($arg_name:ident as $varname:ident),*) => $callback:expr ),*
        }
    ) => {
        match $matches.subcommand_name() {
            $(
                Some(stringify!($name)) => {
                    let matches = $matches.subcommand_matches(stringify!($name)).unwrap();
                    $(
                        let $varname = matches.value_of(stringify!($arg_name)).unwrap();
                    )*
                    let $matches_name = matches;
                    $callback;
                }
            )*
            Some(x) => {
                panic!("Internal error: Command not covered: {}", x);
            },
            None => {
                println!("Subcommand required. See --help for help.");
                process::exit(1);
            }
        }
    }
}

pub fn main() {
    let matches =
        App::new("mysteryshack")
        .version(env!("CARGO_PKG_VERSION"))
        .author("Markus Unterwaditzer & contributors")
        .about("A remoteStorage server.")
        .args_from_usage("-c, --config=[FILE] 'Use specified config file, defaults to ./config'")
        .setting(AppSettings::SubcommandRequired)
        .subcommand(SubCommand::with_name("serve")
                    .about("Start server"))
        .subcommand(SubCommand::with_name("user")
                    .about("User management")
                    .setting(AppSettings::SubcommandRequired)
                    .subcommand(SubCommand::with_name("create")
                                .about("Create a new user")
                                .arg(Arg::with_name("USERNAME")
                                     .help("The username")
                                     .required(true)
                                     .index(1)))
                    .subcommand(SubCommand::with_name("setpass")
                                .about("Change password for user")
                                .arg(Arg::with_name("USERNAME")
                                     .help("The username")
                                     .required(true)
                                     .index(1)))
                    .subcommand(SubCommand::with_name("delete")
                                .about("Delete a user")
                                .arg(Arg::with_name("USERNAME")
                                     .help("The username")
                                     .required(true)
                                     .index(1))))
        .get_matches();

    let config_path = path::Path::new(matches.value_of("config").unwrap_or("./config"));

    let config = match config::Config::read_file(config_path) {
        Ok(x) => x,
        Err(e) => {
            println!("Failed to parse config: {}", e);
            process::exit(1);
        }
    };

    clap_dispatch!(matches; {
        serve(_,) => web::run_server(config),
        user(user_matches,) => clap_dispatch!(user_matches; {
            create(_, USERNAME as username) => {
                let password_hash = match models::PasswordHash::from_password(
                    utils::double_prompt("Password for new user: ")) {
                    Ok(x) => x,
                    Err(e) => {
                        println!("Failed to hash password: {}", e);
                        process::exit(1);
                    }
                };

                match models::User::create(&config.data_path, username).map(|user| {
                    user.set_password_hash(password_hash)
                }) {
                    Ok(_) => (),
                    Err(e) => {
                        println!("Failed to create user {}: {}", username, e);
                        process::exit(1);
                    }
                };

                println!("Successfully created user {}", username);
            },
            setpass(_, USERNAME as username) => {
                let user = match models::User::get(&config.data_path, username) {
                    Some(x) => x,
                    None => {
                        println!("User does not exist: {}", username);
                        process::exit(1);
                    }
                };

                let password_hash = match models::PasswordHash::from_password(
                    utils::double_prompt("New password: ")) {
                    Ok(x) => x,
                    Err(e) => {
                        println!("Failed to hash password: {}", e);
                        process::exit(1);
                    }
                };

                match user.set_password_hash(password_hash) {
                    Ok(_) => (),
                    Err(e) => {
                        println!("Failed to set password for user {}: {}", username, e);
                        process::exit(1);
                    }
                };

                println!("Changed password for user {}", username);
            },
            delete(_, USERNAME as username) => {
                let user = match models::User::get(&config.data_path, username) {
                    Some(x) => x,
                    None => {
                        println!("User does not exist: {}", username);
                        process::exit(1);
                    }
                };

                println!("You are about to delete the user {} and ALL the user's user data. This
                         process is irreversible.", username);
                if !utils::prompt_confirm(format!("Do you want to delete the user {}?", username), false) {
                    println!("Aborted!");
                    process::exit(1);
                }

                match user.delete() {
                    Ok(_) => println!("Successfully deleted user {}.", username),
                    Err(e) => {
                        println!("Failed to delete user: {:?}", e);
                        process::exit(1);
                    }
                };
            }
        })
    });
}
<commit_msg>Improve clap_dispatch re trailing comma<commit_after>use std::path;
use std::process;

use clap::{App, Arg, SubCommand, AppSettings};

use config;
use models;
use web;
use utils;

macro_rules! clap_dispatch {
    // Transform `foo(_) => ()` into `foo(_,) => ()` such that it actually can be parsed.
    // Using a single rule is only possible in nightly.
    ($matches:expr; { $( $name:ident ( $matches_name:pat ) => $callback:expr ),* }) => (clap_dispatch!($matches; { $( $name($matches_name,) => $callback ),* }));

    ($matches:expr; { $( $name:ident ($matches_name:pat, $($arg_name:ident as $varname:ident),*) => $callback:expr ),* }) => {
        match $matches.subcommand_name() {
            $(
                Some(stringify!($name)) => {
                    let matches = $matches.subcommand_matches(stringify!($name)).unwrap();
                    $(
                        let $varname = matches.value_of(stringify!($arg_name)).unwrap();
                    )*
                    let $matches_name = matches;
                    $callback;
                }
            )*
            Some(x) => {
                panic!("Internal error: Command not covered: {}", x);
            },
            None => {
                println!("Subcommand required. See --help for help.");
                process::exit(1);
            }
        }
    };
}

pub fn main() {
    let matches =
        App::new("mysteryshack")
        .version(env!("CARGO_PKG_VERSION"))
        .author("Markus Unterwaditzer & contributors")
        .about("A remoteStorage server.")
        .args_from_usage("-c, --config=[FILE] 'Use specified config file, defaults to ./config'")
        .setting(AppSettings::SubcommandRequired)
        .subcommand(SubCommand::with_name("serve")
                    .about("Start server"))
        .subcommand(SubCommand::with_name("user")
                    .about("User management")
                    .setting(AppSettings::SubcommandRequired)
                    .subcommand(SubCommand::with_name("create")
                                .about("Create a new user")
                                .arg(Arg::with_name("USERNAME")
                                     .help("The username")
                                     .required(true)
                                     .index(1)))
                    .subcommand(SubCommand::with_name("setpass")
                                .about("Change password for user")
                                .arg(Arg::with_name("USERNAME")
                                     .help("The username")
                                     .required(true)
                                     .index(1)))
                    .subcommand(SubCommand::with_name("delete")
                                .about("Delete a user")
                                .arg(Arg::with_name("USERNAME")
                                     .help("The username")
                                     .required(true)
                                     .index(1))))
        .get_matches();

    let config_path = path::Path::new(matches.value_of("config").unwrap_or("./config"));

    let config = match config::Config::read_file(config_path) {
        Ok(x) => x,
        Err(e) => {
            println!("Failed to parse config: {}", e);
            process::exit(1);
        }
    };

    clap_dispatch!(matches; {
        serve(_) => web::run_server(config),
        user(user_matches) => clap_dispatch!(user_matches; {
            create(_, USERNAME as username) => {
                let password_hash = match models::PasswordHash::from_password(
                    utils::double_prompt("Password for new user: ")) {
                    Ok(x) => x,
                    Err(e) => {
                        println!("Failed to hash password: {}", e);
                        process::exit(1);
                    }
                };

                match models::User::create(&config.data_path, username).map(|user| {
                    user.set_password_hash(password_hash)
                }) {
                    Ok(_) => (),
                    Err(e) => {
                        println!("Failed to create user {}: {}", username, e);
                        process::exit(1);
                    }
                };

                println!("Successfully created user {}", username);
            },
            setpass(_, USERNAME as username) => {
                let user = match models::User::get(&config.data_path, username) {
                    Some(x) => x,
                    None => {
                        println!("User does not exist: {}", username);
                        process::exit(1);
                    }
                };

                let password_hash = match models::PasswordHash::from_password(
                    utils::double_prompt("New password: ")) {
                    Ok(x) => x,
                    Err(e) => {
                        println!("Failed to hash password: {}", e);
                        process::exit(1);
                    }
                };

                match user.set_password_hash(password_hash) {
                    Ok(_) => (),
                    Err(e) => {
                        println!("Failed to set password for user {}: {}", username, e);
                        process::exit(1);
                    }
                };

                println!("Changed password for user {}", username);
            },
            delete(_, USERNAME as username) => {
                let user = match models::User::get(&config.data_path, username) {
                    Some(x) => x,
                    None => {
                        println!("User does not exist: {}", username);
                        process::exit(1);
                    }
                };

                println!("You are about to delete the user {} and ALL the user's user data. This
                         process is irreversible.", username);
                if !utils::prompt_confirm(format!("Do you want to delete the user {}?", username), false) {
                    println!("Aborted!");
                    process::exit(1);
                }

                match user.delete() {
                    Ok(_) => println!("Successfully deleted user {}.", username),
                    Err(e) => {
                        println!("Failed to delete user: {:?}", e);
                        process::exit(1);
                    }
                };
            }
        })
    });
}
<|endoftext|>