<commit_before>//! Polymorphization Analysis
//! =========================
//!
//! This module implements an analysis of functions, methods and closures to determine which
//! generic parameters are unused (and eventually, in what ways generic parameters are used - only
//! for their size, offset of a field, etc.).

use rustc_hir::{def::DefKind, def_id::DefId};
use rustc_index::bit_set::FiniteBitSet;
use rustc_middle::mir::{
    visit::{TyContext, Visitor},
    Local, LocalDecl, Location,
};
use rustc_middle::ty::{
    self,
    fold::{TypeFoldable, TypeVisitor},
    query::Providers,
    subst::SubstsRef,
    Const, Ty, TyCtxt,
};
use rustc_span::symbol::sym;
use std::convert::TryInto;
use std::ops::ControlFlow;

/// Provide implementations of queries relating to polymorphization analysis.
pub fn provide(providers: &mut Providers) {
    providers.unused_generic_params = unused_generic_params;
}

/// Determine which generic parameters are used by the function/method/closure represented by
/// `def_id`. Returns a bitset where bits representing unused parameters are set (`is_empty`
/// indicates all parameters are used).
fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> {
    debug!("unused_generic_params({:?})", def_id);

    if !tcx.sess.opts.debugging_opts.polymorphize {
        // If polymorphization disabled, then all parameters are used.
        return FiniteBitSet::new_empty();
    }

    // Polymorphization results are stored in cross-crate metadata only when there are unused
    // parameters, so assume that non-local items must have only used parameters (else this query
    // would not be invoked, and the cross-crate metadata used instead).
    if !def_id.is_local() {
        return FiniteBitSet::new_empty();
    }

    let generics = tcx.generics_of(def_id);
    debug!("unused_generic_params: generics={:?}", generics);

    // Exit early when there are no parameters to be unused.
    if generics.count() == 0 {
        return FiniteBitSet::new_empty();
    }

    // Exit early when there is no MIR available.
    let context = tcx.hir().body_const_context(def_id.expect_local());
    match context {
        None if !tcx.is_mir_available(def_id) => {
            debug!("unused_generic_params: (no mir available) def_id={:?}", def_id);
            return FiniteBitSet::new_empty();
        }
        Some(_) if !tcx.is_ctfe_mir_available(def_id) => {
            debug!("unused_generic_params: (no ctfe mir available) def_id={:?}", def_id);
            return FiniteBitSet::new_empty();
        }
        _ => {}
    }

    // Create a bitset with N rightmost ones for each parameter.
    let generics_count: u32 =
        generics.count().try_into().expect("more generic parameters than can fit into a `u32`");
    let mut unused_parameters = FiniteBitSet::<u32>::new_empty();
    unused_parameters.set_range(0..generics_count);
    debug!("unused_generic_params: (start) unused_parameters={:?}", unused_parameters);
    mark_used_by_default_parameters(tcx, def_id, generics, &mut unused_parameters);
    debug!("unused_generic_params: (after default) unused_parameters={:?}", unused_parameters);

    // Visit MIR and accumululate used generic parameters.
    let body = match context {
        None => tcx.optimized_mir(def_id),
        // FIXME(oli-obk): since this is solely used for codegen (I think?), should we keep using
        // the optimized MIR for `const fn`? Need to adjust the above `is_mir_available` check
        // in that case.
        Some(_) => tcx.mir_for_ctfe(def_id),
    };
    let mut vis = MarkUsedGenericParams { tcx, def_id, unused_parameters: &mut unused_parameters };
    vis.visit_body(body);
    debug!("unused_generic_params: (after visitor) unused_parameters={:?}", unused_parameters);

    mark_used_by_predicates(tcx, def_id, &mut unused_parameters);
    debug!("unused_generic_params: (end) unused_parameters={:?}", unused_parameters);

    // Emit errors for debugging and testing if enabled.
    if !unused_parameters.is_empty() {
        emit_unused_generic_params_error(tcx, def_id, generics, &unused_parameters);
    }

    unused_parameters
}

/// Some parameters are considered used-by-default, such as non-generic parameters and the dummy
/// generic parameters from closures, this function marks them as used. `leaf_is_closure` should
/// be `true` if the item that `unused_generic_params` was invoked on is a closure.
fn mark_used_by_default_parameters<'tcx>(
    tcx: TyCtxt<'tcx>,
    def_id: DefId,
    generics: &'tcx ty::Generics,
    unused_parameters: &mut FiniteBitSet<u32>,
) {
    if !tcx.is_trait(def_id) && (tcx.is_closure(def_id) || tcx.type_of(def_id).is_generator()) {
        for param in &generics.params {
            debug!("mark_used_by_default_parameters: (closure/gen) param={:?}", param);
            unused_parameters.clear(param.index);
        }
    } else {
        for param in &generics.params {
            debug!("mark_used_by_default_parameters: (other) param={:?}", param);
            if let ty::GenericParamDefKind::Lifetime = param.kind {
                unused_parameters.clear(param.index);
            }
        }
    }

    if let Some(parent) = generics.parent {
        mark_used_by_default_parameters(tcx, parent, tcx.generics_of(parent), unused_parameters);
    }
}

/// Search the predicates on used generic parameters for any unused generic parameters, and mark
/// those as used.
fn mark_used_by_predicates<'tcx>(
    tcx: TyCtxt<'tcx>,
    def_id: DefId,
    unused_parameters: &mut FiniteBitSet<u32>,
) {
    let def_id = tcx.closure_base_def_id(def_id);
    let predicates = tcx.explicit_predicates_of(def_id);
    debug!("mark_used_by_predicates: predicates_of={:?}", predicates);

    let mut current_unused_parameters = FiniteBitSet::new_empty();
    // Run to a fixed point to support `where T: Trait<U>, U: Trait<V>`, starting with an empty
    // bit set so that this is skipped if all parameters are already used.
    while current_unused_parameters != *unused_parameters {
        debug!(
            "mark_used_by_predicates: current_unused_parameters={:?} = unused_parameters={:?}",
            current_unused_parameters, unused_parameters
        );
        current_unused_parameters = *unused_parameters;

        for (predicate, _) in predicates.predicates {
            // Consider all generic params in a predicate as used if any other parameter in the
            // predicate is used.
            let any_param_used = {
                let mut vis = HasUsedGenericParams { unused_parameters };
                predicate.visit_with(&mut vis).is_break()
            };

            if any_param_used {
                let mut vis = MarkUsedGenericParams { tcx, def_id, unused_parameters };
                predicate.visit_with(&mut vis);
            }
        }
    }

    if let Some(parent) = predicates.parent {
        mark_used_by_predicates(tcx, parent, unused_parameters);
    }
}

/// Emit errors for the function annotated by `#[rustc_polymorphize_error]`, labelling each generic
/// parameter which was unused.
fn emit_unused_generic_params_error<'tcx>(
    tcx: TyCtxt<'tcx>,
    def_id: DefId,
    generics: &'tcx ty::Generics,
    unused_parameters: &FiniteBitSet<u32>,
) {
    debug!("emit_unused_generic_params_error: def_id={:?}", def_id);
    let base_def_id = tcx.closure_base_def_id(def_id);
    if !tcx
        .get_attrs(base_def_id)
        .iter()
        .any(|a| tcx.sess.check_name(a, sym::rustc_polymorphize_error))
    {
        return;
    }

    debug!("emit_unused_generic_params_error: unused_parameters={:?}", unused_parameters);
    let fn_span = match tcx.opt_item_name(def_id) {
        Some(ident) => ident.span,
        _ => tcx.def_span(def_id),
    };

    let mut err = tcx.sess.struct_span_err(fn_span, "item has unused generic parameters");

    let mut next_generics = Some(generics);
    while let Some(generics) = next_generics {
        for param in &generics.params {
            if unused_parameters.contains(param.index).unwrap_or(false) {
                debug!("emit_unused_generic_params_error: param={:?}", param);
                let def_span = tcx.def_span(param.def_id);
                err.span_label(def_span, &format!("generic parameter `{}` is unused", param.name));
            }
        }

        next_generics = generics.parent.map(|did| tcx.generics_of(did));
    }

    err.emit();
}

/// Visitor used to aggregate generic parameter uses.
struct MarkUsedGenericParams<'a, 'tcx> {
    tcx: TyCtxt<'tcx>,
    def_id: DefId,
    unused_parameters: &'a mut FiniteBitSet<u32>,
}

impl<'a, 'tcx> MarkUsedGenericParams<'a, 'tcx> {
    /// Invoke `unused_generic_params` on a body contained within the current item (e.g.
    /// a closure, generator or constant).
    fn visit_child_body(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) {
        let unused = self.tcx.unused_generic_params(def_id);
        debug!(
            "visit_child_body: unused_parameters={:?} unused={:?}",
            self.unused_parameters, unused
        );
        for (i, arg) in substs.iter().enumerate() {
            let i = i.try_into().unwrap();
            if !unused.contains(i).unwrap_or(false) {
                arg.visit_with(self);
            }
        }
        debug!("visit_child_body: unused_parameters={:?}", self.unused_parameters);
    }
}

impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
    fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
        debug!("visit_local_decl: local_decl={:?}", local_decl);
        if local == Local::from_usize(1) {
            let def_kind = self.tcx.def_kind(self.def_id);
            if matches!(def_kind, DefKind::Closure | DefKind::Generator) {
                // Skip visiting the closure/generator that is currently being processed. This only
                // happens because the first argument to the closure is a reference to itself and
                // that will call `visit_substs`, resulting in each generic parameter captured being
                // considered used by default.
                debug!("visit_local_decl: skipping closure substs");
                return;
            }
        }

        self.super_local_decl(local, local_decl);
    }

    fn visit_const(&mut self, c: &&'tcx Const<'tcx>, _: Location) {
        c.visit_with(self);
    }

    fn visit_ty(&mut self, ty: Ty<'tcx>, _: TyContext) {
        ty.visit_with(self);
    }
}

impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
    fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
        debug!("visit_const: c={:?}", c);
        if !c.has_param_types_or_consts() {
            return ControlFlow::CONTINUE;
        }

        match c.val {
            ty::ConstKind::Param(param) => {
                debug!("visit_const: param={:?}", param);
                self.unused_parameters.clear(param.index);
                ControlFlow::CONTINUE
            }
            ty::ConstKind::Unevaluated(def, _, Some(p))
                // Avoid considering `T` unused when constants are of the form:
                //   `<Self as Foo<T>>::foo::promoted[p]`
                if self.def_id == def.did && !self.tcx.generics_of(def.did).has_self =>
            {
                // If there is a promoted, don't look at the substs - since it will always contain
                // the generic parameters, instead, traverse the promoted MIR.
                let promoted = self.tcx.promoted_mir(def.did);
                self.visit_body(&promoted[p]);
                ControlFlow::CONTINUE
            }
            ty::ConstKind::Unevaluated(def, unevaluated_substs, None)
                if self.tcx.def_kind(def.did) == DefKind::AnonConst =>
            {
                self.visit_child_body(def.did, unevaluated_substs);
                ControlFlow::CONTINUE
            }
            _ => c.super_visit_with(self),
        }
    }

    fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
        debug!("visit_ty: ty={:?}", ty);
        if !ty.has_param_types_or_consts() {
            return ControlFlow::CONTINUE;
        }

        match *ty.kind() {
            ty::Closure(def_id, substs) | ty::Generator(def_id, substs, ..) => {
                debug!("visit_ty: def_id={:?}", def_id);
                // Avoid cycle errors with generators.
                if def_id == self.def_id {
                    return ControlFlow::CONTINUE;
                }

                // Consider any generic parameters used by any closures/generators as used in the
                // parent.
                self.visit_child_body(def_id, substs);
                ControlFlow::CONTINUE
            }
            ty::Param(param) => {
                debug!("visit_ty: param={:?}", param);
                self.unused_parameters.clear(param.index);
                ControlFlow::CONTINUE
            }
            _ => ty.super_visit_with(self),
        }
    }
}

/// Visitor used to check if a generic parameter is used.
struct HasUsedGenericParams<'a> {
    unused_parameters: &'a FiniteBitSet<u32>,
}

impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a> {
    type BreakTy = ();

    fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
        debug!("visit_const: c={:?}", c);
        if !c.has_param_types_or_consts() {
            return ControlFlow::CONTINUE;
        }

        match c.val {
            ty::ConstKind::Param(param) => {
                if self.unused_parameters.contains(param.index).unwrap_or(false) {
                    ControlFlow::CONTINUE
                } else {
                    ControlFlow::BREAK
                }
            }
            _ => c.super_visit_with(self),
        }
    }

    fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
        debug!("visit_ty: ty={:?}", ty);
        if !ty.has_param_types_or_consts() {
            return ControlFlow::CONTINUE;
        }

        match ty.kind() {
            ty::Param(param) => {
                if self.unused_parameters.contains(param.index).unwrap_or(false) {
                    ControlFlow::CONTINUE
                } else {
                    ControlFlow::BREAK
                }
            }
            _ => ty.super_visit_with(self),
        }
    }
}
<commit_msg>Polymorphization should look at the runtime MIR of `const fn`<commit_after>//! Polymorphization Analysis
//! =========================
//!
//! This module implements an analysis of functions, methods and closures to determine which
//! generic parameters are unused (and eventually, in what ways generic parameters are used - only
//! for their size, offset of a field, etc.).

use rustc_hir::{def::DefKind, def_id::DefId};
use rustc_index::bit_set::FiniteBitSet;
use rustc_middle::mir::{
    visit::{TyContext, Visitor},
    Local, LocalDecl, Location,
};
use rustc_middle::ty::{
    self,
    fold::{TypeFoldable, TypeVisitor},
    query::Providers,
    subst::SubstsRef,
    Const, Ty, TyCtxt,
};
use rustc_span::symbol::sym;
use std::convert::TryInto;
use std::ops::ControlFlow;

/// Provide implementations of queries relating to polymorphization analysis.
pub fn provide(providers: &mut Providers) {
    providers.unused_generic_params = unused_generic_params;
}

/// Determine which generic parameters are used by the function/method/closure represented by
/// `def_id`. Returns a bitset where bits representing unused parameters are set (`is_empty`
/// indicates all parameters are used).
fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> {
    debug!("unused_generic_params({:?})", def_id);

    if !tcx.sess.opts.debugging_opts.polymorphize {
        // If polymorphization disabled, then all parameters are used.
        return FiniteBitSet::new_empty();
    }

    // Polymorphization results are stored in cross-crate metadata only when there are unused
    // parameters, so assume that non-local items must have only used parameters (else this query
    // would not be invoked, and the cross-crate metadata used instead).
    if !def_id.is_local() {
        return FiniteBitSet::new_empty();
    }

    let generics = tcx.generics_of(def_id);
    debug!("unused_generic_params: generics={:?}", generics);

    // Exit early when there are no parameters to be unused.
    if generics.count() == 0 {
        return FiniteBitSet::new_empty();
    }

    // Exit early when there is no MIR available.
    let context = tcx.hir().body_const_context(def_id.expect_local());
    match context {
        Some(ConstContext::Fn) | None if !tcx.is_mir_available(def_id) => {
            debug!("unused_generic_params: (no mir available) def_id={:?}", def_id);
            return FiniteBitSet::new_empty();
        }
        Some(_) if !tcx.is_ctfe_mir_available(def_id) => {
            debug!("unused_generic_params: (no ctfe mir available) def_id={:?}", def_id);
            return FiniteBitSet::new_empty();
        }
        _ => {}
    }

    // Create a bitset with N rightmost ones for each parameter.
    let generics_count: u32 =
        generics.count().try_into().expect("more generic parameters than can fit into a `u32`");
    let mut unused_parameters = FiniteBitSet::<u32>::new_empty();
    unused_parameters.set_range(0..generics_count);
    debug!("unused_generic_params: (start) unused_parameters={:?}", unused_parameters);
    mark_used_by_default_parameters(tcx, def_id, generics, &mut unused_parameters);
    debug!("unused_generic_params: (after default) unused_parameters={:?}", unused_parameters);

    // Visit MIR and accumululate used generic parameters.
    let body = match context {
        // Const functions are actually called and should thus be considered for polymorphization
        // via their runtime MIR
        Some(ConstContext::Fn) | None => tcx.optimized_mir(def_id),
        Some(_) => tcx.mir_for_ctfe(def_id),
    };
    let mut vis = MarkUsedGenericParams { tcx, def_id, unused_parameters: &mut unused_parameters };
    vis.visit_body(body);
    debug!("unused_generic_params: (after visitor) unused_parameters={:?}", unused_parameters);

    mark_used_by_predicates(tcx, def_id, &mut unused_parameters);
    debug!("unused_generic_params: (end) unused_parameters={:?}", unused_parameters);

    // Emit errors for debugging and testing if enabled.
    if !unused_parameters.is_empty() {
        emit_unused_generic_params_error(tcx, def_id, generics, &unused_parameters);
    }

    unused_parameters
}

/// Some parameters are considered used-by-default, such as non-generic parameters and the dummy
/// generic parameters from closures, this function marks them as used. `leaf_is_closure` should
/// be `true` if the item that `unused_generic_params` was invoked on is a closure.
fn mark_used_by_default_parameters<'tcx>(
    tcx: TyCtxt<'tcx>,
    def_id: DefId,
    generics: &'tcx ty::Generics,
    unused_parameters: &mut FiniteBitSet<u32>,
) {
    if !tcx.is_trait(def_id) && (tcx.is_closure(def_id) || tcx.type_of(def_id).is_generator()) {
        for param in &generics.params {
            debug!("mark_used_by_default_parameters: (closure/gen) param={:?}", param);
            unused_parameters.clear(param.index);
        }
    } else {
        for param in &generics.params {
            debug!("mark_used_by_default_parameters: (other) param={:?}", param);
            if let ty::GenericParamDefKind::Lifetime = param.kind {
                unused_parameters.clear(param.index);
            }
        }
    }

    if let Some(parent) = generics.parent {
        mark_used_by_default_parameters(tcx, parent, tcx.generics_of(parent), unused_parameters);
    }
}

/// Search the predicates on used generic parameters for any unused generic parameters, and mark
/// those as used.
fn mark_used_by_predicates<'tcx>(
    tcx: TyCtxt<'tcx>,
    def_id: DefId,
    unused_parameters: &mut FiniteBitSet<u32>,
) {
    let def_id = tcx.closure_base_def_id(def_id);
    let predicates = tcx.explicit_predicates_of(def_id);
    debug!("mark_used_by_predicates: predicates_of={:?}", predicates);

    let mut current_unused_parameters = FiniteBitSet::new_empty();
    // Run to a fixed point to support `where T: Trait<U>, U: Trait<V>`, starting with an empty
    // bit set so that this is skipped if all parameters are already used.
    while current_unused_parameters != *unused_parameters {
        debug!(
            "mark_used_by_predicates: current_unused_parameters={:?} = unused_parameters={:?}",
            current_unused_parameters, unused_parameters
        );
        current_unused_parameters = *unused_parameters;

        for (predicate, _) in predicates.predicates {
            // Consider all generic params in a predicate as used if any other parameter in the
            // predicate is used.
            let any_param_used = {
                let mut vis = HasUsedGenericParams { unused_parameters };
                predicate.visit_with(&mut vis).is_break()
            };

            if any_param_used {
                let mut vis = MarkUsedGenericParams { tcx, def_id, unused_parameters };
                predicate.visit_with(&mut vis);
            }
        }
    }

    if let Some(parent) = predicates.parent {
        mark_used_by_predicates(tcx, parent, unused_parameters);
    }
}

/// Emit errors for the function annotated by `#[rustc_polymorphize_error]`, labelling each generic
/// parameter which was unused.
fn emit_unused_generic_params_error<'tcx>(
    tcx: TyCtxt<'tcx>,
    def_id: DefId,
    generics: &'tcx ty::Generics,
    unused_parameters: &FiniteBitSet<u32>,
) {
    debug!("emit_unused_generic_params_error: def_id={:?}", def_id);
    let base_def_id = tcx.closure_base_def_id(def_id);
    if !tcx
        .get_attrs(base_def_id)
        .iter()
        .any(|a| tcx.sess.check_name(a, sym::rustc_polymorphize_error))
    {
        return;
    }

    debug!("emit_unused_generic_params_error: unused_parameters={:?}", unused_parameters);
    let fn_span = match tcx.opt_item_name(def_id) {
        Some(ident) => ident.span,
        _ => tcx.def_span(def_id),
    };

    let mut err = tcx.sess.struct_span_err(fn_span, "item has unused generic parameters");

    let mut next_generics = Some(generics);
    while let Some(generics) = next_generics {
        for param in &generics.params {
            if unused_parameters.contains(param.index).unwrap_or(false) {
                debug!("emit_unused_generic_params_error: param={:?}", param);
                let def_span = tcx.def_span(param.def_id);
                err.span_label(def_span, &format!("generic parameter `{}` is unused", param.name));
            }
        }

        next_generics = generics.parent.map(|did| tcx.generics_of(did));
    }

    err.emit();
}

/// Visitor used to aggregate generic parameter uses.
struct MarkUsedGenericParams<'a, 'tcx> {
    tcx: TyCtxt<'tcx>,
    def_id: DefId,
    unused_parameters: &'a mut FiniteBitSet<u32>,
}

impl<'a, 'tcx> MarkUsedGenericParams<'a, 'tcx> {
    /// Invoke `unused_generic_params` on a body contained within the current item (e.g.
    /// a closure, generator or constant).
    fn visit_child_body(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) {
        let unused = self.tcx.unused_generic_params(def_id);
        debug!(
            "visit_child_body: unused_parameters={:?} unused={:?}",
            self.unused_parameters, unused
        );
        for (i, arg) in substs.iter().enumerate() {
            let i = i.try_into().unwrap();
            if !unused.contains(i).unwrap_or(false) {
                arg.visit_with(self);
            }
        }
        debug!("visit_child_body: unused_parameters={:?}", self.unused_parameters);
    }
}

impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
    fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
        debug!("visit_local_decl: local_decl={:?}", local_decl);
        if local == Local::from_usize(1) {
            let def_kind = self.tcx.def_kind(self.def_id);
            if matches!(def_kind, DefKind::Closure | DefKind::Generator) {
                // Skip visiting the closure/generator that is currently being processed. This only
                // happens because the first argument to the closure is a reference to itself and
                // that will call `visit_substs`, resulting in each generic parameter captured being
                // considered used by default.
                debug!("visit_local_decl: skipping closure substs");
                return;
            }
        }

        self.super_local_decl(local, local_decl);
    }

    fn visit_const(&mut self, c: &&'tcx Const<'tcx>, _: Location) {
        c.visit_with(self);
    }

    fn visit_ty(&mut self, ty: Ty<'tcx>, _: TyContext) {
        ty.visit_with(self);
    }
}

impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
    fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
        debug!("visit_const: c={:?}", c);
        if !c.has_param_types_or_consts() {
            return ControlFlow::CONTINUE;
        }

        match c.val {
            ty::ConstKind::Param(param) => {
                debug!("visit_const: param={:?}", param);
                self.unused_parameters.clear(param.index);
                ControlFlow::CONTINUE
            }
            ty::ConstKind::Unevaluated(def, _, Some(p))
                // Avoid considering `T` unused when constants are of the form:
                //   `<Self as Foo<T>>::foo::promoted[p]`
                if self.def_id == def.did && !self.tcx.generics_of(def.did).has_self =>
            {
                // If there is a promoted, don't look at the substs - since it will always contain
                // the generic parameters, instead, traverse the promoted MIR.
                let promoted = self.tcx.promoted_mir(def.did);
                self.visit_body(&promoted[p]);
                ControlFlow::CONTINUE
            }
            ty::ConstKind::Unevaluated(def, unevaluated_substs, None)
                if self.tcx.def_kind(def.did) == DefKind::AnonConst =>
            {
                self.visit_child_body(def.did, unevaluated_substs);
                ControlFlow::CONTINUE
            }
            _ => c.super_visit_with(self),
        }
    }

    fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
        debug!("visit_ty: ty={:?}", ty);
        if !ty.has_param_types_or_consts() {
            return ControlFlow::CONTINUE;
        }

        match *ty.kind() {
            ty::Closure(def_id, substs) | ty::Generator(def_id, substs, ..) => {
                debug!("visit_ty: def_id={:?}", def_id);
                // Avoid cycle errors with generators.
                if def_id == self.def_id {
                    return ControlFlow::CONTINUE;
                }

                // Consider any generic parameters used by any closures/generators as used in the
                // parent.
                self.visit_child_body(def_id, substs);
                ControlFlow::CONTINUE
            }
            ty::Param(param) => {
                debug!("visit_ty: param={:?}", param);
                self.unused_parameters.clear(param.index);
                ControlFlow::CONTINUE
            }
            _ => ty.super_visit_with(self),
        }
    }
}

/// Visitor used to check if a generic parameter is used.
struct HasUsedGenericParams<'a> {
    unused_parameters: &'a FiniteBitSet<u32>,
}

impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a> {
    type BreakTy = ();

    fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
        debug!("visit_const: c={:?}", c);
        if !c.has_param_types_or_consts() {
            return ControlFlow::CONTINUE;
        }

        match c.val {
            ty::ConstKind::Param(param) => {
                if self.unused_parameters.contains(param.index).unwrap_or(false) {
                    ControlFlow::CONTINUE
                } else {
                    ControlFlow::BREAK
                }
            }
            _ => c.super_visit_with(self),
        }
    }

    fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
        debug!("visit_ty: ty={:?}", ty);
        if !ty.has_param_types_or_consts() {
            return ControlFlow::CONTINUE;
        }

        match ty.kind() {
            ty::Param(param) => {
                if self.unused_parameters.contains(param.index).unwrap_or(false) {
                    ControlFlow::CONTINUE
                } else {
                    ControlFlow::BREAK
                }
            }
            _ => ty.super_visit_with(self),
        }
    }
}
<|endoftext|>


<commit_before>// error-pattern:static item is never used: `UNUSED`
#![deny(dead_code)]
#[macro_use]
extern crate lazy_static_compiletest as lazy_static;

lazy_static! {
    static ref UNUSED: () = ();
}

fn main() { }
<commit_msg>remove static_never_used test<commit_after><|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use controller::Controller;
use iron::{ AfterMiddleware, headers, IronResult, Request, Response };
use iron::headers::ContentType;
use iron::method::Method;
use iron::method::Method::*;
use iron::prelude::Chain;
use iron::status::Status;
use router::Router;
use unicase::UniCase;

type Endpoint = (&'static[Method], &'static[&'static str]);

struct CORS;

impl CORS {
    // Only endpoints listed here will allow CORS.
    // Endpoints containing a variable path part can use '*' like in:
    // &["bar", "*"] for a URL like https://foo.com/bar/123
    pub const ENDPOINTS: &'static[Endpoint] = &[
        (&[Method::Get], &["list.json"]),
        (&[Method::Get, Method::Post, Method::Put], &["*", "*"])
    ];
}

impl AfterMiddleware for CORS {
    fn after(&self, req: &mut Request, mut res: Response)
        -> IronResult<Response> {

        let mut is_cors_endpoint = false;
        for endpoint in CORS::ENDPOINTS {
            let (ref methods, path) = *endpoint;

            if !methods.contains(&req.method) &&
               req.method != Method::Options {
                continue;
            }

            if path.len() != req.url.path.len() {
                continue;
            }

            for (i, path) in path.iter().enumerate() {
                is_cors_endpoint = false;
                if req.url.path[i] != path.to_owned() &&
                   "*" != path.to_owned() {
                    break;
                }
                is_cors_endpoint = true;
            }
            if is_cors_endpoint {
                break;
            }
        }

        if !is_cors_endpoint {
            return Ok(res);
        }

        res.headers.set(headers::AccessControlAllowOrigin::Any);
        res.headers.set(headers::AccessControlAllowHeaders(
            vec![
                UniCase(String::from("accept")),
                UniCase(String::from("content-type"))
            ]
        ));
        res.headers.set(headers::AccessControlAllowMethods(
            vec![Get, Post, Put]
        ));
        res.status = Some(Status::Ok);
        Ok(res)
    }
}

pub fn create<T: Controller>(controller: T) -> Chain {
    let mut router = Router::new();

    let c1 = controller.clone();
    router.get("list.json", move |_: &mut Request| -> IronResult<Response> {
        // Build a json representation of the services.
        let serialized = itry!(c1.services_as_json());

        let mut response = Response::with(serialized);
        response.status = Some(Status::Ok);
        response.headers.set(ContentType::json());

        Ok(response)
    });

    let c2 = controller.clone();
    router.any(":service/:command", move |req: &mut Request| -> IronResult<Response> {
        // Call a function on a service.
        let id = req.extensions.get::<Router>().unwrap()
            .find("service").unwrap_or("").to_owned();
        c2.dispatch_service_request(id, req)
    });

    let mut chain = Chain::new(router);
    chain.link_after(CORS);

    chain
}

#[cfg(test)]
describe! service_router {
    before_each {
        use iron::Headers;
        use controller::FoxBox;
        use iron_test::request;

        let controller = FoxBox::new(false, Some("localhost".to_owned()), None, None);
        let service_router = create(controller.clone());
    }

    describe! services {
        before_each {
            use iron_test::response;
        }

        it "should create list.json" {
            let response = request::get("http://localhost:3000/list.json",
                            Headers::new(),
                            &service_router).unwrap();

            let result = response::extract_body_to_string(response);
            assert_eq!(result, "[]");
        }

        it "should make service available" {
            use controller::Controller;
            use stubs::service::ServiceStub;
            controller.add_service(Box::new(ServiceStub));
            let response = request::get("http://localhost:3000/1/a-command",
                            Headers::new(),
                            &service_router).unwrap();

            let result = response::extract_body_to_string(response);
            assert_eq!(result, "request processed");
        }

        it "should return an error if no service was found" {
            let response = request::get("http://localhost:3000/unknown-id/a-command",
                            Headers::new(),
                            &service_router).unwrap();

            let result = response::extract_body_to_string(response);
            assert_eq!(result, "No Such Service: unknown-id");
        }
    }

    describe! cors {
        before_each {
            use iron::headers;
            use super::super::CORS;
        }

        it "should get the appropriate CORS headers" {
            for endpoint in CORS::ENDPOINTS {
                let (_, path) = *endpoint;
                let path = "http://localhost:3000/".to_owned() +
                           &(path.join("/").replace("*", "foo"));
                let response = request::options(&path, Headers::new(), &service_router).unwrap();
                let headers = &response.headers;
                assert!(headers.has::<headers::AccessControlAllowOrigin>());
                assert!(headers.has::<headers::AccessControlAllowHeaders>());
                assert!(headers.has::<headers::AccessControlAllowMethods>());
            }
        }
    }
}
<commit_msg>Better way to define paths for CORS endpoints. r=fabrice<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use controller::Controller;
use iron::{ AfterMiddleware, headers, IronResult, Request, Response };
use iron::headers::ContentType;
use iron::method::Method;
use iron::method::Method::*;
use iron::prelude::Chain;
use iron::status::Status;
use router::Router;
use unicase::UniCase;

type Endpoint = (&'static[Method], &'static str);

struct CORS;

impl CORS {
    // Only endpoints listed here will allow CORS.
    // Endpoints containing a variable path part can use ':foo' like in:
    // "/foo/:bar" for a URL like https://domain.com/foo/123 where 123 is
    // variable.
    pub const ENDPOINTS: &'static[Endpoint] = &[
        (&[Method::Get], "list.json"),
        (&[Method::Get, Method::Post, Method::Put], ":service/:command")
    ];
}

impl AfterMiddleware for CORS {
    fn after(&self, req: &mut Request, mut res: Response)
        -> IronResult<Response> {

        let mut is_cors_endpoint = false;
        for endpoint in CORS::ENDPOINTS {
            let (ref methods, path) = *endpoint;

            if !methods.contains(&req.method) &&
               req.method != Method::Options {
                continue;
            }

            let path: Vec<&str> = if path.starts_with('/') {
                path[1..].split('/').collect()
            } else {
                path[0..].split('/').collect()
            };

            if path.len() != req.url.path.len() {
                continue;
            }

            for (i, req_path) in req.url.path.iter().enumerate() {
                is_cors_endpoint = false;
                if req_path != path[i] && !path[i].starts_with(':') {
                    break;
                }
                is_cors_endpoint = true;
            }
            if is_cors_endpoint {
                break;
            }
        }

        if !is_cors_endpoint {
            return Ok(res);
        }

        res.headers.set(headers::AccessControlAllowOrigin::Any);
        res.headers.set(headers::AccessControlAllowHeaders(
            vec![
                UniCase(String::from("accept")),
                UniCase(String::from("content-type"))
            ]
        ));
        res.headers.set(headers::AccessControlAllowMethods(
            vec![Get, Post, Put]
        ));
        res.status = Some(Status::Ok);
        Ok(res)
    }
}

pub fn create<T: Controller>(controller: T) -> Chain {
    let mut router = Router::new();

    let c1 = controller.clone();
    router.get("list.json", move |_: &mut Request| -> IronResult<Response> {
        // Build a json representation of the services.
        let serialized = itry!(c1.services_as_json());

        let mut response = Response::with(serialized);
        response.status = Some(Status::Ok);
        response.headers.set(ContentType::json());

        Ok(response)
    });

    let c2 = controller.clone();
    router.any(":service/:command", move |req: &mut Request| -> IronResult<Response> {
        // Call a function on a service.
        let id = req.extensions.get::<Router>().unwrap()
            .find("service").unwrap_or("").to_owned();
        c2.dispatch_service_request(id, req)
    });

    let mut chain = Chain::new(router);
    chain.link_after(CORS);

    chain
}

#[cfg(test)]
describe! service_router {
    before_each {
        use iron::Headers;
        use controller::FoxBox;
        use iron_test::request;

        let controller = FoxBox::new(false, Some("localhost".to_owned()), None, None);
        let service_router = create(controller.clone());
    }

    describe! services {
        before_each {
            use iron_test::response;
        }

        it "should create list.json" {
            let response = request::get("http://localhost:3000/list.json",
                            Headers::new(),
                            &service_router).unwrap();

            let result = response::extract_body_to_string(response);
            assert_eq!(result, "[]");
        }

        it "should make service available" {
            use controller::Controller;
            use stubs::service::ServiceStub;
            controller.add_service(Box::new(ServiceStub));
            let response = request::get("http://localhost:3000/1/a-command",
                            Headers::new(),
                            &service_router).unwrap();

            let result = response::extract_body_to_string(response);
            assert_eq!(result, "request processed");
        }

        it "should return an error if no service was found" {
            let response = request::get("http://localhost:3000/unknown-id/a-command",
                            Headers::new(),
                            &service_router).unwrap();

            let result = response::extract_body_to_string(response);
            assert_eq!(result, "No Such Service: unknown-id");
        }
    }

    describe! cors {
        before_each {
            use iron::headers;
            use super::super::CORS;
        }

        it "should get the appropriate CORS headers" {
            for endpoint in CORS::ENDPOINTS {
                let (_, path) = *endpoint;
                let path = "http://localhost:3000/".to_owned() +
                           &(path.replace(":", "foo"));
                let response = request::options(&path,
                                                Headers::new(),
                                                &service_router).unwrap();
                let headers = &response.headers;
                assert!(headers.has::<headers::AccessControlAllowOrigin>());
                assert!(headers.has::<headers::AccessControlAllowHeaders>());
                assert!(headers.has::<headers::AccessControlAllowMethods>());
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2013 The Lmath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

pub use self::frustum::Frustum;
pub use self::projection::{Projection, Ortho, Perspective, PerspectiveFOV};

pub mod frustum;
pub mod projection;
<commit_msg>Re-export FrustumPoints from world module<commit_after>// Copyright 2013 The Lmath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

pub use self::frustum::{Frustum, FrustumPoints};
pub use self::projection::{Projection, Perspective, PerspectiveFOV, Ortho};

pub mod frustum;
pub mod projection;
<|endoftext|>


<commit_before>// The file `built.rs` was placed there by cargo and `build.rs`
pub mod built_info {
    include!(concat!(env!("OUT_DIR"), "/built.rs"));
}

fn main() {
    // Print various information produced by `built`. See the docs for a full list.

    println!(
        "This is version {}{}, built for {} by {}.",
        built_info::PKG_VERSION,
        built_info::GIT_VERSION.map_or_else(|| "".to_owned(), |v| format!(" (git {})", v)),
        built_info::TARGET,
        built_info::RUSTC_VERSION
    );

    print!(
        "I was built for a {}-CPU, which is a {}-endian architecture. ",
        built_info::CFG_TARGET_ARCH,
        built_info::CFG_ENDIAN
    );

    println!(
        "I was compiled to run on {} (a {}-breed) and my runtime should be {}.",
        built_info::CFG_OS,
        built_info::CFG_FAMILY,
        built_info::CFG_ENV
    );

    match built_info::CI_PLATFORM {
        None => print!("It seems I've not been built on a continuous integration platform,"),
        Some(ci) => print!("I've been built on CI-platform {},", ci),
    }
    if built::util::detect_ci().is_some() {
        println!(" but I'm currently executing on one!");
    } else {
        println!(" and I'm currently not executing on one!");
    }

    let built_time = built::util::strptime(built_info::BUILT_TIME_UTC);
    println!(
        "I was built with profile \"{}\", features \"{}\" on {} ({} seconds ago) using {}",
        built_info::PROFILE,
        built_info::FEATURES_STR,
        built_time.with_timezone(&chrono::offset::Local),
        (chrono::offset::Utc::now() - built_time).num_seconds(),
        built_info::DEPENDENCIES_STR
    );

    let bad_dep =
        built::util::parse_versions(built_info::DEPENDENCIES.iter()).any(|(name, ver)| {
            name == "DeleteAllMyFiles" && ver < semver::Version::parse("1.1.4").unwrap()
        });
    if bad_dep {
        println!(
            "I was built with DeleteAllMyFiles < 1.1.4, which is known to sometimes not really delete all your files. Beware!"
        );
    }
}
<commit_msg>Update example<commit_after>// The file `built.rs` was placed there by cargo and `build.rs`
pub mod built_info {
    include!(concat!(env!("OUT_DIR"), "/built.rs"));
}

fn main() {
    // Print various information produced by `built`. See the docs for a full list.

    println!(
        "This is version {}, built for {} by {}.\n",
        built_info::PKG_VERSION,
        built_info::TARGET,
        built_info::RUSTC_VERSION
    );

    if let (Some(v), Some(hash)) = (built_info::GIT_VERSION, built_info::GIT_COMMIT_HASH) {
        print!("I was built from git `{}`, commit {}.", v, hash);
    }

    match built_info::GIT_HEAD_REF {
        Some(r) => println!(" The branch was `{}`.\n", r),
        None => println!("\n"),
    }

    print!(
        "I was built for a {}-CPU, which is a {}-endian architecture. ",
        built_info::CFG_TARGET_ARCH,
        built_info::CFG_ENDIAN
    );

    println!(
        "I was compiled to run on {} (a {}-breed) and my runtime should be {}.\n",
        built_info::CFG_OS,
        built_info::CFG_FAMILY,
        built_info::CFG_ENV
    );

    match built_info::CI_PLATFORM {
        None => print!("It seems I've not been built on a continuous integration platform,"),
        Some(ci) => print!("I've been built on CI-platform {},", ci),
    }
    if built::util::detect_ci().is_some() {
        println!(" but I'm currently executing on one!\n");
    } else {
        println!(" and I'm currently not executing on one!\n");
    }

    let built_time = built::util::strptime(built_info::BUILT_TIME_UTC);
    println!(
        "I was built with profile \"{}\", features \"{}\" on {} ({} seconds ago) using {}",
        built_info::PROFILE,
        built_info::FEATURES_STR,
        built_time.with_timezone(&chrono::offset::Local),
        (chrono::offset::Utc::now() - built_time).num_seconds(),
        built_info::DEPENDENCIES_STR
    );

    let bad_dep =
        built::util::parse_versions(built_info::DEPENDENCIES.iter()).any(|(name, ver)| {
            name == "DeleteAllMyFiles" && ver < semver::Version::parse("1.1.4").unwrap()
        });
    if bad_dep {
        println!(
            "I was built with DeleteAllMyFiles < 1.1.4, which is known to sometimes not really delete all your files. Beware!"
        );
    }
}
<|endoftext|>


<commit_before>//! Actix web diesel example
//!
//! Diesel does not support tokio, so we have to run it in separate threads.
//! Actix supports sync actors by default, so we going to create sync actor that will
//! use diesel. Technically sync actors are worker style actors, multiple of them
//! can run in parallel and process messages from same queue.
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate diesel;
extern crate uuid;
extern crate futures;
extern crate actix;
extern crate actix_web;
extern crate env_logger;

use actix::*;
use actix_web::*;

use diesel::prelude::*;
use futures::future::Future;

mod db;
mod models;
mod schema;

use db::{CreateUser, DbExecutor};

/// State with DbExecutor address
struct State {
    db: Addr<Syn, DbExecutor>,
}

/// Async request handler
fn index(req: HttpRequest<State>) -> Box<Future<Item=HttpResponse, Error=Error>> {
    let name = &req.match_info()["name"];

    req.state().db.send(CreateUser{name: name.to_owned()})
        .from_err()
        .and_then(|res| {
            match res {
                Ok(user) => Ok(httpcodes::HTTPOk.build().json(user)?),
                Err(_) => Ok(httpcodes::HTTPInternalServerError.into())
            }
        })
        .responder()
}

fn main() {
    ::std::env::set_var("RUST_LOG", "actix_web=info");
    let _ = env_logger::init();
    let sys = actix::System::new("diesel-example");

    // Start db executor actors
    let addr = SyncArbiter::start(3, || {
        DbExecutor(SqliteConnection::establish("test.db").unwrap())
    });

    // Start http server
    let _addr = HttpServer::new(move || {
        Application::with_state(State{db: addr.clone()})
            // enable logger
            .middleware(middleware::Logger::default())
            .resource("/{name}", |r| r.method(Method::GET).a(index))})
        .bind("127.0.0.1:8080").unwrap()
        .start();

    println!("Started http server: 127.0.0.1:8080");
    let _ = sys.run();
}
<commit_msg>add comments<commit_after>//! Actix web diesel example
//!
//! Diesel does not support tokio, so we have to run it in separate threads.
//! Actix supports sync actors by default, so we going to create sync actor that use diesel.
//! Technically sync actors are worker style actors, multiple of them
//! can run in parallel and process messages from same queue.
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate diesel;
extern crate uuid;
extern crate futures;
extern crate actix;
extern crate actix_web;
extern crate env_logger;

use actix::*;
use actix_web::*;

use diesel::prelude::*;
use futures::future::Future;

mod db;
mod models;
mod schema;

use db::{CreateUser, DbExecutor};

/// State with DbExecutor address
struct State {
    db: Addr<Syn, DbExecutor>,
}

/// Async request handler
fn index(req: HttpRequest<State>) -> Box<Future<Item=HttpResponse, Error=Error>> {
    let name = &req.match_info()["name"];

    // send async `CreateUser` message to a `DbExecutor`
    req.state().db.send(CreateUser{name: name.to_owned()})
        .from_err()
        .and_then(|res| {
            match res {
                Ok(user) => Ok(httpcodes::HTTPOk.build().json(user)?),
                Err(_) => Ok(httpcodes::HTTPInternalServerError.into())
            }
        })
        .responder()
}

fn main() {
    ::std::env::set_var("RUST_LOG", "actix_web=info");
    let _ = env_logger::init();
    let sys = actix::System::new("diesel-example");

    // Start 3 db executor actors
    let addr = SyncArbiter::start(3, || {
        DbExecutor(SqliteConnection::establish("test.db").unwrap())
    });

    // Start http server
    let _addr = HttpServer::new(move || {
        Application::with_state(State{db: addr.clone()})
            // enable logger
            .middleware(middleware::Logger::default())
            .resource("/{name}", |r| r.method(Method::GET).a(index))})
        .bind("127.0.0.1:8080").unwrap()
        .start();

    println!("Started http server: 127.0.0.1:8080");
    let _ = sys.run();
}
<|endoftext|>


<commit_before>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use crate::metrics::OTHER_TIMERS_SECONDS;
use crate::utils::stream::StreamX;
use crate::{
    backup_types::{
        epoch_ending::restore::EpochHistory, state_snapshot::manifest::StateSnapshotBackup,
    },
    metrics::{
        restore::{
            STATE_SNAPSHOT_LEAF_INDEX, STATE_SNAPSHOT_TARGET_LEAF_INDEX, STATE_SNAPSHOT_VERSION,
        },
        verify::{
            VERIFY_STATE_SNAPSHOT_LEAF_INDEX, VERIFY_STATE_SNAPSHOT_TARGET_LEAF_INDEX,
            VERIFY_STATE_SNAPSHOT_VERSION,
        },
    },
    storage::{BackupStorage, FileHandle},
    utils::{
        read_record_bytes::ReadRecordBytes, storage_ext::BackupStorageExt, GlobalRestoreOptions,
        RestoreRunMode,
    },
};
use anyhow::{anyhow, ensure, Result};
use aptos_infallible::Mutex;
use aptos_logger::prelude::*;
use aptos_types::{
    ledger_info::LedgerInfoWithSignatures,
    proof::TransactionInfoWithProof,
    state_store::{state_key::StateKey, state_value::StateValue},
    transaction::Version,
};
use clap::Parser;
use futures::{stream, TryStreamExt};
use std::sync::Arc;
use storage_interface::StateSnapshotReceiver;
use tokio::time::Instant;
use tokio::try_join;

#[derive(Parser)]
pub struct StateSnapshotRestoreOpt {
    #[clap(long = "state-manifest")]
    pub manifest_handle: FileHandle,
    #[clap(long = "state-into-version")]
    pub version: Version,
}

pub struct StateSnapshotRestoreController {
    storage: Arc<dyn BackupStorage>,
    run_mode: Arc<RestoreRunMode>,
    /// State snapshot restores to this version.
    version: Version,
    manifest_handle: FileHandle,
    /// Global "target_version" for the entire restore process, if `version` is newer than this,
    /// nothing will be done, otherwise, this has no effect.
    target_version: Version,
    epoch_history: Option<Arc<EpochHistory>>,
    concurrent_downloads: usize,
}

impl StateSnapshotRestoreController {
    pub fn new(
        opt: StateSnapshotRestoreOpt,
        global_opt: GlobalRestoreOptions,
        storage: Arc<dyn BackupStorage>,
        epoch_history: Option<Arc<EpochHistory>>,
    ) -> Self {
        Self {
            storage,
            run_mode: global_opt.run_mode,
            version: opt.version,
            manifest_handle: opt.manifest_handle,
            target_version: global_opt.target_version,
            epoch_history,
            concurrent_downloads: global_opt.concurrent_downloads,
        }
    }

    pub async fn run(self) -> Result<()> {
        let name = self.name();
        let start = Instant::now();
        info!("{} started. Manifest: {}", name, self.manifest_handle);
        self.run_impl()
            .await
            .map_err(|e| anyhow!("{} failed: {}", name, e))?;
        info!(time = start.elapsed().as_secs(), "{} succeeded.", name);
        Ok(())
    }
}

impl StateSnapshotRestoreController {
    fn name(&self) -> String {
        format!("state snapshot {}", self.run_mode.name())
    }

    async fn run_impl(self) -> Result<()> {
        if self.version > self.target_version {
            warn!(
                "Trying to restore state snapshot to version {}, which is newer than the target version {}, skipping.",
                self.version,
                self.target_version,
            );
            return Ok(());
        }

        let manifest: StateSnapshotBackup =
            self.storage.load_json_file(&self.manifest_handle).await?;
        let (txn_info_with_proof, li): (TransactionInfoWithProof, LedgerInfoWithSignatures) =
            self.storage.load_bcs_file(&manifest.proof).await?;
        txn_info_with_proof.verify(li.ledger_info(), manifest.version)?;
        let state_root_hash = txn_info_with_proof
            .transaction_info()
            .ensure_state_checkpoint_hash()?;
        ensure!(
            state_root_hash == manifest.root_hash,
            "Root hash mismatch with that in proof. root hash: {}, expected: {}",
            manifest.root_hash,
            state_root_hash,
        );
        if let Some(epoch_history) = self.epoch_history.as_ref() {
            epoch_history.verify_ledger_info(&li)?;
        }

        let receiver = Arc::new(Mutex::new(Some(
            self.run_mode
                .get_state_restore_receiver(self.version, manifest.root_hash)?,
        )));

        let (ver_gauge, tgt_leaf_idx, leaf_idx) = if self.run_mode.is_verify() {
            (
                &VERIFY_STATE_SNAPSHOT_VERSION,
                &VERIFY_STATE_SNAPSHOT_TARGET_LEAF_INDEX,
                &VERIFY_STATE_SNAPSHOT_LEAF_INDEX,
            )
        } else {
            (
                &STATE_SNAPSHOT_VERSION,
                &STATE_SNAPSHOT_TARGET_LEAF_INDEX,
                &STATE_SNAPSHOT_LEAF_INDEX,
            )
        };

        ver_gauge.set(self.version as i64);
        tgt_leaf_idx.set(manifest.chunks.last().map_or(0, |c| c.last_idx as i64));
        let total_chunks = manifest.chunks.len();

        let resume_point_opt = receiver.lock().as_mut().unwrap().previous_key_hash()?;
        let chunks = if let Some(resume_point) = resume_point_opt {
            manifest
                .chunks
                .into_iter()
                .skip_while(|chunk| chunk.last_key <= resume_point)
                .collect()
        } else {
            manifest.chunks
        };
        if chunks.len() < total_chunks {
            info!(
                chunks_to_add = chunks.len(),
                total_chunks = total_chunks,
                "Resumed state snapshot restore."
            )
        };
        let chunks_to_add = chunks.len();

        let start_idx = chunks.first().map_or(0, |chunk| chunk.first_idx);

        let storage = self.storage.clone();
        let futs_iter = chunks.into_iter().enumerate().map(|(chunk_idx, chunk)| {
            let storage = storage.clone();
            async move {
                let (blobs, proof) = try_join!(
                    Self::read_state_value(&storage, chunk.blobs.clone()),
                    storage.load_bcs_file(&chunk.proof)
                )?;
                Result::<_>::Ok((chunk_idx, chunk, blobs, proof))
            }
        });
        let con = self.concurrent_downloads;
        let mut futs_stream = stream::iter(futs_iter).buffered_x(con * 2, con);
        let mut start = None;
        while let Some((chunk_idx, chunk, blobs, proof)) = futs_stream.try_next().await? {
            start = start.or_else(|| Some(Instant::now()));
            let _timer = OTHER_TIMERS_SECONDS
                .with_label_values(&["add_state_chunk"])
                .start_timer();
            let receiver = receiver.clone();
            tokio::task::spawn_blocking(move || {
                receiver.lock().as_mut().unwrap().add_chunk(blobs, proof)
            })
            .await??;
            leaf_idx.set(chunk.last_idx as i64);
            info!(
                chunk = chunk_idx,
                chunks_to_add = chunks_to_add,
                last_idx = chunk.last_idx,
                values_per_second = ((chunk.last_idx + 1 - start_idx) as f64
                    / start.as_ref().unwrap().elapsed().as_secs_f64())
                    as u64,
                "State chunk added.",
            );
        }

        tokio::task::spawn_blocking(move || receiver.lock().take().unwrap().finish()).await??;
        self.run_mode.finish();
        Ok(())
    }

    async fn read_state_value(
        storage: &Arc<dyn BackupStorage>,
        file_handle: FileHandle,
    ) -> Result<Vec<(StateKey, StateValue)>> {
        let mut file = storage.open_for_read(&file_handle).await?;

        let mut chunk = vec![];

        while let Some(record_bytes) = file.read_record_bytes().await? {
            chunk.push(bcs::from_bytes(&record_bytes)?);
        }

        Ok(chunk)
    }
}
<commit_msg>[backup] state snapshot restore: deserialize in seperate task<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use crate::metrics::OTHER_TIMERS_SECONDS;
use crate::utils::stream::StreamX;
use crate::{
    backup_types::{
        epoch_ending::restore::EpochHistory, state_snapshot::manifest::StateSnapshotBackup,
    },
    metrics::{
        restore::{
            STATE_SNAPSHOT_LEAF_INDEX, STATE_SNAPSHOT_TARGET_LEAF_INDEX, STATE_SNAPSHOT_VERSION,
        },
        verify::{
            VERIFY_STATE_SNAPSHOT_LEAF_INDEX, VERIFY_STATE_SNAPSHOT_TARGET_LEAF_INDEX,
            VERIFY_STATE_SNAPSHOT_VERSION,
        },
    },
    storage::{BackupStorage, FileHandle},
    utils::{
        read_record_bytes::ReadRecordBytes, storage_ext::BackupStorageExt, GlobalRestoreOptions,
        RestoreRunMode,
    },
};
use anyhow::{anyhow, ensure, Result};
use aptos_infallible::Mutex;
use aptos_logger::prelude::*;
use aptos_types::{
    ledger_info::LedgerInfoWithSignatures,
    proof::TransactionInfoWithProof,
    state_store::{state_key::StateKey, state_value::StateValue},
    transaction::Version,
};
use clap::Parser;
use futures::{stream, TryStreamExt};
use std::sync::Arc;
use storage_interface::StateSnapshotReceiver;
use tokio::time::Instant;

#[derive(Parser)]
pub struct StateSnapshotRestoreOpt {
    #[clap(long = "state-manifest")]
    pub manifest_handle: FileHandle,
    #[clap(long = "state-into-version")]
    pub version: Version,
}

pub struct StateSnapshotRestoreController {
    storage: Arc<dyn BackupStorage>,
    run_mode: Arc<RestoreRunMode>,
    /// State snapshot restores to this version.
    version: Version,
    manifest_handle: FileHandle,
    /// Global "target_version" for the entire restore process, if `version` is newer than this,
    /// nothing will be done, otherwise, this has no effect.
    target_version: Version,
    epoch_history: Option<Arc<EpochHistory>>,
    concurrent_downloads: usize,
}

impl StateSnapshotRestoreController {
    pub fn new(
        opt: StateSnapshotRestoreOpt,
        global_opt: GlobalRestoreOptions,
        storage: Arc<dyn BackupStorage>,
        epoch_history: Option<Arc<EpochHistory>>,
    ) -> Self {
        Self {
            storage,
            run_mode: global_opt.run_mode,
            version: opt.version,
            manifest_handle: opt.manifest_handle,
            target_version: global_opt.target_version,
            epoch_history,
            concurrent_downloads: global_opt.concurrent_downloads,
        }
    }

    pub async fn run(self) -> Result<()> {
        let name = self.name();
        let start = Instant::now();
        info!("{} started. Manifest: {}", name, self.manifest_handle);
        self.run_impl()
            .await
            .map_err(|e| anyhow!("{} failed: {}", name, e))?;
        info!(time = start.elapsed().as_secs(), "{} succeeded.", name);
        Ok(())
    }
}

impl StateSnapshotRestoreController {
    fn name(&self) -> String {
        format!("state snapshot {}", self.run_mode.name())
    }

    async fn run_impl(self) -> Result<()> {
        if self.version > self.target_version {
            warn!(
                "Trying to restore state snapshot to version {}, which is newer than the target version {}, skipping.",
                self.version,
                self.target_version,
            );
            return Ok(());
        }

        let manifest: StateSnapshotBackup =
            self.storage.load_json_file(&self.manifest_handle).await?;
        let (txn_info_with_proof, li): (TransactionInfoWithProof, LedgerInfoWithSignatures) =
            self.storage.load_bcs_file(&manifest.proof).await?;
        txn_info_with_proof.verify(li.ledger_info(), manifest.version)?;
        let state_root_hash = txn_info_with_proof
            .transaction_info()
            .ensure_state_checkpoint_hash()?;
        ensure!(
            state_root_hash == manifest.root_hash,
            "Root hash mismatch with that in proof. root hash: {}, expected: {}",
            manifest.root_hash,
            state_root_hash,
        );
        if let Some(epoch_history) = self.epoch_history.as_ref() {
            epoch_history.verify_ledger_info(&li)?;
        }

        let receiver = Arc::new(Mutex::new(Some(
            self.run_mode
                .get_state_restore_receiver(self.version, manifest.root_hash)?,
        )));

        let (ver_gauge, tgt_leaf_idx, leaf_idx) = if self.run_mode.is_verify() {
            (
                &VERIFY_STATE_SNAPSHOT_VERSION,
                &VERIFY_STATE_SNAPSHOT_TARGET_LEAF_INDEX,
                &VERIFY_STATE_SNAPSHOT_LEAF_INDEX,
            )
        } else {
            (
                &STATE_SNAPSHOT_VERSION,
                &STATE_SNAPSHOT_TARGET_LEAF_INDEX,
                &STATE_SNAPSHOT_LEAF_INDEX,
            )
        };

        ver_gauge.set(self.version as i64);
        tgt_leaf_idx.set(manifest.chunks.last().map_or(0, |c| c.last_idx as i64));
        let total_chunks = manifest.chunks.len();

        let resume_point_opt = receiver.lock().as_mut().unwrap().previous_key_hash()?;
        let chunks = if let Some(resume_point) = resume_point_opt {
            manifest
                .chunks
                .into_iter()
                .skip_while(|chunk| chunk.last_key <= resume_point)
                .collect()
        } else {
            manifest.chunks
        };
        if chunks.len() < total_chunks {
            info!(
                chunks_to_add = chunks.len(),
                total_chunks = total_chunks,
                "Resumed state snapshot restore."
            )
        };
        let chunks_to_add = chunks.len();

        let start_idx = chunks.first().map_or(0, |chunk| chunk.first_idx);

        let storage = self.storage.clone();
        let futs_iter = chunks.into_iter().enumerate().map(|(chunk_idx, chunk)| {
            let storage = storage.clone();
            async move {
                tokio::spawn(async move {
                    let blobs = Self::read_state_value(&storage, chunk.blobs.clone()).await?;
                    let proof = storage.load_bcs_file(&chunk.proof).await?;
                    Result::<_>::Ok((chunk_idx, chunk, blobs, proof))
                })
                .await?
            }
        });
        let con = self.concurrent_downloads;
        let mut futs_stream = stream::iter(futs_iter).buffered_x(con * 2, con);
        let mut start = None;
        while let Some((chunk_idx, chunk, blobs, proof)) = futs_stream.try_next().await? {
            start = start.or_else(|| Some(Instant::now()));
            let _timer = OTHER_TIMERS_SECONDS
                .with_label_values(&["add_state_chunk"])
                .start_timer();
            let receiver = receiver.clone();
            tokio::task::spawn_blocking(move || {
                receiver.lock().as_mut().unwrap().add_chunk(blobs, proof)
            })
            .await??;
            leaf_idx.set(chunk.last_idx as i64);
            info!(
                chunk = chunk_idx,
                chunks_to_add = chunks_to_add,
                last_idx = chunk.last_idx,
                values_per_second = ((chunk.last_idx + 1 - start_idx) as f64
                    / start.as_ref().unwrap().elapsed().as_secs_f64())
                    as u64,
                "State chunk added.",
            );
        }

        tokio::task::spawn_blocking(move || receiver.lock().take().unwrap().finish()).await??;
        self.run_mode.finish();
        Ok(())
    }

    async fn read_state_value(
        storage: &Arc<dyn BackupStorage>,
        file_handle: FileHandle,
    ) -> Result<Vec<(StateKey, StateValue)>> {
        let mut file = storage.open_for_read(&file_handle).await?;

        let mut chunk = vec![];

        while let Some(record_bytes) = file.read_record_bytes().await? {
            chunk.push(bcs::from_bytes(&record_bytes)?);
        }

        Ok(chunk)
    }
}
<|endoftext|>


<commit_before>struct Fibonacci {
    curr: u32,
    next: u32,
}

// 实现关于 `Fibonacci` （斐波那契）的 `Iterator`。
// `Iterator` trait 只需定义一个指向 `next`（下一个）元素的方法。
impl Iterator for Fibonacci {
    type Item = u32;

    // 我们在这里使用 `.curr` 和 `.next` 来定义数列（sequence）。
    // 返回类型为 `Option<T>`：
    //     * 当 `Iterator` 结束时，返回 `None`。
    //     * 其他情况，返回被 `Some` 包裹（wrapped）的下一个值。
    fn next(&mut self) -> Option<u32> {
        let new_next = self.curr + self.next;

        self.curr = self.next;
        self.next = new_next;

        // 既然斐波那契数列不存在不存在终点，那么 `Iterator` 将不可能
        // 返回 `None`，而总是返回 `Some`。
        Some(self.curr)
    }
}

// 返回一个斐波那契数列生存器（generator）
fn fibonacci() -> Fibonacci {
    Fibonacci { curr: 1, next: 1 }
}

fn main() {
    // `0..3` 是一个 `Iterator`，会产生：0，1 和 2。
    let mut sequence = 0..3;

    println!("Four consecutive `next` calls on 0..3");
    println!("> {:?}", sequence.next());
    println!("> {:?}", sequence.next());
    println!("> {:?}", sequence.next());
    println!("> {:?}", sequence.next());

    // `for` 通过 `Iterator` 进行工作，直到 `Iterator` 为 `None`。
    // 每个 `Some` 值都被解包（unwrap）且限定为一个变量（这里是 `i`）。
    println!("Iterate through 0..3 using `for`");
    for i in 0..3 {
        println!("> {}", i);
    }

    // `take(n)` 方法提取 `Iterator` 的前 `n` 项。
    println!("The first four terms of the Fibonacci sequence are: ");
    for i in fibonacci().take(4) {
        println!("> {}", i);
    }

    // `skip(n)` 方法通过跳过前 `n` 项缩短了 `Iterator` 。
    println!("The next four terms of the Fibonacci sequence are: ");
    for i in fibonacci().skip(4).take(4) {
        println!("> {}", i);
    }

    let array = [1u32, 3, 3, 7];

    // `iter` 方法对数组/slice 产生一个 `Iterator`。
    println!("Iterate the following array {:?}", &array);
    for i in array.iter() {
        println!("> {}", i);
    }
}
<commit_msg>Typo fix<commit_after>struct Fibonacci {
    curr: u32,
    next: u32,
}

// 实现关于 `Fibonacci` （斐波那契）的 `Iterator`。
// `Iterator` trait 只需定义一个指向 `next`（下一个）元素的方法。
impl Iterator for Fibonacci {
    type Item = u32;

    // 我们在这里使用 `.curr` 和 `.next` 来定义数列（sequence）。
    // 返回类型为 `Option<T>`：
    //     * 当 `Iterator` 结束时，返回 `None`。
    //     * 其他情况，返回被 `Some` 包裹（wrapped）的下一个值。
    fn next(&mut self) -> Option<u32> {
        let new_next = self.curr + self.next;

        self.curr = self.next;
        self.next = new_next;

        // 既然斐波那契数列不存在终点，那么 `Iterator` 将不可能
        // 返回 `None`，而总是返回 `Some`。
        Some(self.curr)
    }
}

// 返回一个斐波那契数列生成器（generator）
fn fibonacci() -> Fibonacci {
    Fibonacci { curr: 1, next: 1 }
}

fn main() {
    // `0..3` 是一个 `Iterator`，会产生：0，1 和 2。
    let mut sequence = 0..3;

    println!("Four consecutive `next` calls on 0..3");
    println!("> {:?}", sequence.next());
    println!("> {:?}", sequence.next());
    println!("> {:?}", sequence.next());
    println!("> {:?}", sequence.next());

    // `for` 通过 `Iterator` 进行工作，直到 `Iterator` 为 `None`。
    // 每个 `Some` 值都被解包（unwrap）且限定为一个变量（这里是 `i`）。
    println!("Iterate through 0..3 using `for`");
    for i in 0..3 {
        println!("> {}", i);
    }

    // `take(n)` 方法提取 `Iterator` 的前 `n` 项。
    println!("The first four terms of the Fibonacci sequence are: ");
    for i in fibonacci().take(4) {
        println!("> {}", i);
    }

    // `skip(n)` 方法通过跳过前 `n` 项缩短了 `Iterator` 。
    println!("The next four terms of the Fibonacci sequence are: ");
    for i in fibonacci().skip(4).take(4) {
        println!("> {}", i);
    }

    let array = [1u32, 3, 3, 7];

    // `iter` 方法对数组/slice 产生一个 `Iterator`。
    println!("Iterate the following array {:?}", &array);
    for i in array.iter() {
        println!("> {}", i);
    }
}
<|endoftext|>


<commit_before>use ra_syntax::{
    ast::{self, AstChildren},
    AstNode, SmolStr, SyntaxNode, SyntaxNodeRef,
};

pub struct ModuleScope {
    entries: Vec<Entry>,
}

pub struct Entry {
    node: SyntaxNode,
    kind: EntryKind,
}

enum EntryKind {
    Item,
    Import,
}

impl ModuleScope {
    pub fn new(items: AstChildren<ast::ModuleItem>) -> ModuleScope {
        let mut entries = Vec::new();
        for item in items {
            let entry = match item {
                ast::ModuleItem::StructDef(item) => Entry::new(item),
                ast::ModuleItem::EnumDef(item) => Entry::new(item),
                ast::ModuleItem::FnDef(item) => Entry::new(item),
                ast::ModuleItem::ConstDef(item) => Entry::new(item),
                ast::ModuleItem::StaticDef(item) => Entry::new(item),
                ast::ModuleItem::TraitDef(item) => Entry::new(item),
                ast::ModuleItem::TypeDef(item) => Entry::new(item),
                ast::ModuleItem::Module(item) => Entry::new(item),
                ast::ModuleItem::UseItem(item) => {
                    if let Some(tree) = item.use_tree() {
                        collect_imports(tree, &mut entries);
                    }
                    continue;
                }
                ast::ModuleItem::ExternCrateItem(_) | ast::ModuleItem::ImplItem(_) => continue,
            };
            entries.extend(entry)
        }

        ModuleScope { entries }
    }

    pub fn entries(&self) -> &[Entry] {
        self.entries.as_slice()
    }
}

impl Entry {
    fn new<'a>(item: impl ast::NameOwner<'a>) -> Option<Entry> {
        let name = item.name()?;
        Some(Entry {
            node: name.syntax().owned(),
            kind: EntryKind::Item,
        })
    }
    fn new_import(path: ast::Path) -> Option<Entry> {
        let name_ref = path.segment()?.name_ref()?;
        Some(Entry {
            node: name_ref.syntax().owned(),
            kind: EntryKind::Import,
        })
    }
    pub fn name(&self) -> SmolStr {
        match self.kind {
            EntryKind::Item => ast::Name::cast(self.node.borrowed()).unwrap().text(),
            EntryKind::Import => ast::NameRef::cast(self.node.borrowed()).unwrap().text(),
        }
    }
    pub fn syntax(&self) -> SyntaxNodeRef {
        self.node.borrowed()
    }
}

fn collect_imports(tree: ast::UseTree, acc: &mut Vec<Entry>) {
    if let Some(use_tree_list) = tree.use_tree_list() {
        return use_tree_list
            .use_trees()
            .for_each(|it| collect_imports(it, acc));
    }
    if let Some(path) = tree.path() {
        acc.extend(Entry::new_import(path));
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use ra_syntax::{ast::ModuleItemOwner, File};

    fn do_check(code: &str, expected: &[&str]) {
        let file = File::parse(&code);
        let scope = ModuleScope::new(file.ast().items());
        let actual = scope.entries.iter().map(|it| it.name()).collect::<Vec<_>>();
        assert_eq!(expected, actual.as_slice());
    }

    #[test]
    fn test_module_scope() {
        do_check(
            "
            struct Foo;
            enum Bar {}
            mod baz {}
            fn quux() {}
            use x::{
                y::z,
                t,
            };
            type T = ();
        ",
            &["Foo", "Bar", "baz", "quux", "z", "t", "T"],
        )
    }
}
<commit_msg>Rename new to new_item (to match new_impl)<commit_after>use ra_syntax::{
    ast::{self, AstChildren},
    AstNode, SmolStr, SyntaxNode, SyntaxNodeRef,
};

pub struct ModuleScope {
    entries: Vec<Entry>,
}

pub struct Entry {
    node: SyntaxNode,
    kind: EntryKind,
}

enum EntryKind {
    Item,
    Import,
}

impl ModuleScope {
    pub fn new(items: AstChildren<ast::ModuleItem>) -> ModuleScope {
        let mut entries = Vec::new();
        for item in items {
            let entry = match item {
                ast::ModuleItem::StructDef(item) => Entry::new_item(item),
                ast::ModuleItem::EnumDef(item) => Entry::new_item(item),
                ast::ModuleItem::FnDef(item) => Entry::new_item(item),
                ast::ModuleItem::ConstDef(item) => Entry::new_item(item),
                ast::ModuleItem::StaticDef(item) => Entry::new_item(item),
                ast::ModuleItem::TraitDef(item) => Entry::new_item(item),
                ast::ModuleItem::TypeDef(item) => Entry::new_item(item),
                ast::ModuleItem::Module(item) => Entry::new_item(item),
                ast::ModuleItem::UseItem(item) => {
                    if let Some(tree) = item.use_tree() {
                        collect_imports(tree, &mut entries);
                    }
                    continue;
                }
                ast::ModuleItem::ExternCrateItem(_) | ast::ModuleItem::ImplItem(_) => continue,
            };
            entries.extend(entry)
        }

        ModuleScope { entries }
    }

    pub fn entries(&self) -> &[Entry] {
        self.entries.as_slice()
    }
}

impl Entry {
    fn new_item<'a>(item: impl ast::NameOwner<'a>) -> Option<Entry> {
        let name = item.name()?;
        Some(Entry {
            node: name.syntax().owned(),
            kind: EntryKind::Item,
        })
    }
    fn new_import(path: ast::Path) -> Option<Entry> {
        let name_ref = path.segment()?.name_ref()?;
        Some(Entry {
            node: name_ref.syntax().owned(),
            kind: EntryKind::Import,
        })
    }
    pub fn name(&self) -> SmolStr {
        match self.kind {
            EntryKind::Item => ast::Name::cast(self.node.borrowed()).unwrap().text(),
            EntryKind::Import => ast::NameRef::cast(self.node.borrowed()).unwrap().text(),
        }
    }
    pub fn syntax(&self) -> SyntaxNodeRef {
        self.node.borrowed()
    }
}

fn collect_imports(tree: ast::UseTree, acc: &mut Vec<Entry>) {
    if let Some(use_tree_list) = tree.use_tree_list() {
        return use_tree_list
            .use_trees()
            .for_each(|it| collect_imports(it, acc));
    }
    if let Some(path) = tree.path() {
        acc.extend(Entry::new_import(path));
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use ra_syntax::{ast::ModuleItemOwner, File};

    fn do_check(code: &str, expected: &[&str]) {
        let file = File::parse(&code);
        let scope = ModuleScope::new(file.ast().items());
        let actual = scope.entries.iter().map(|it| it.name()).collect::<Vec<_>>();
        assert_eq!(expected, actual.as_slice());
    }

    #[test]
    fn test_module_scope() {
        do_check(
            "
            struct Foo;
            enum Bar {}
            mod baz {}
            fn quux() {}
            use x::{
                y::z,
                t,
            };
            type T = ();
        ",
            &["Foo", "Bar", "baz", "quux", "z", "t", "T"],
        )
    }
}
<|endoftext|>


<commit_before>#[derive(Debug)]
struct ListNode {
    Val: i32,
    Next: Option<Box<ListNode>>,
}

impl ListNode {
    fn new(i: i32) -> Self {
        ListNode { Val: i, Next: None }
    }

    fn addL(&mut self, l: &Vec<i32>) {
        let org: *mut ListNode = self as *mut ListNode;
        let mut p: *mut ListNode = org;
        for i in l {
            unsafe {
                println!("{:?}", *p);
                (*p).Next = Some(Box::new(ListNode::new(*i)));
                let temp_b = Box::from_raw(p);
                p = Box::into_raw(temp_b.Next.unwrap());
            };
        }
    }
    fn removeNthFromEnd(&self, n: i32) {}
}
fn main() {
    let mut a = ListNode::new(1);
    a.addL(&vec![2, 3, 4, 5]);
    println!("{:?}", a);
}
<commit_msg>a bit<commit_after>#[derive(Debug)]
struct ListNode {
    val: i32,
    next: Option<Box<ListNode>>,
}

impl ListNode {
    fn new(i: i32) -> Self {
        ListNode { val: i, next: None }
    }

    //:= DEBUG: self point changed
    //:= https://stackoverflow.com/questions/50957738/how-to-copy-a-raw-pointer-in-rust?noredirect=1#comment88913158_50957738
    fn add_l(&mut self, l: &Vec<i32>) {
        //let mut p: *mut ListNode = self as *mut ListNode;
        let org = self;
        let mut p: *mut ListNode = org as *mut ListNode;

        for i in l {
            unsafe {
                //println!("{:?}", *p);
                (*p).next = Some(Box::new(ListNode::new(*i)));
                let temp_b = Box::from_raw(p);
                p = Box::into_raw(temp_b.next.unwrap());
            };
        }
    }

    fn add(&mut self, i: &i32) {
        self.next = Some(Box::new(ListNode::new(*i)));
    }

    fn add_head(self, i: i32) -> Self {
        ListNode {
            val: i,
            next: Some(Box::new(self)),
        }
    }

    fn new_l(l: Vec<i32>) -> Self {
        let mut inner_l = l;
        let mut temp = Self::new(*&inner_l.pop().unwrap());
        for i in inner_l.into_iter().rev() {
            temp = temp.add_head(i)
        }
        temp
    }

    fn removeNthFromEnd(&self, n: i32) {}
}
fn main() {
    //let mut a = ListNode::new(1);
    //a.add_l(&vec![2, 3, 4, 5]);

    let a = ListNode::new_l(vec![1, 2, 3, 4, 5]);
    println!("{:?}", a);
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate diesel;

use diesel::*;
use diesel::sqlite::SqliteConnection;
use diesel::backend::Backend;
use diesel::types::{Integer, VarChar};

table! {
    users {
        id -> Integer,
        name -> VarChar,
    }
}

pub struct User {
    id: i32,
    name: String,
}

use diesel::types::FromSqlRow;

impl<DB: Backend> Queryable<(Integer, VarChar), DB> for User where
    (i32, String): FromSqlRow<(Integer, VarChar), DB>,
{
    type Row = (i32, String);

    fn build(row: Self::Row) -> Self {
        User {
            id: row.0,
            name: row.1,
        }
    }
}

pub struct NewUser(String);

fn main() {
    let connection = SqliteConnection::establish(":memory:").unwrap();

    insert_default_values()
        .into(users::table)
        .get_result::<User>(&connection);
    //~^ ERROR: no method named `get_result`

    insert_default_values()
        .into(users::table)
        .returning(users::name)
        .get_result::<String>(&connection);
    //~^ ERROR: SupportsReturningClause
}
<commit_msg>Remove redundant compile test<commit_after><|endoftext|>