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

use super::FunctionDebugContext;
use super::metadata::file_metadata;
use super::utils::{DIB, span_start};

use llvm;
use llvm::debuginfo::{DIScope, DISubprogram};
use common::{CrateContext, FunctionContext};
use rustc::mir::{Mir, VisibilityScope};

use libc::c_uint;
use std::ptr;

use syntax_pos::Pos;

use rustc_data_structures::bitvec::BitVector;
use rustc_data_structures::indexed_vec::{Idx, IndexVec};

use syntax_pos::BytePos;

#[derive(Clone, Copy, Debug)]
pub struct MirDebugScope {
    pub scope_metadata: DIScope,
    // Start and end offsets of the file to which this DIScope belongs.
    // These are used to quickly determine whether some span refers to the same file.
    pub file_start_pos: BytePos,
    pub file_end_pos: BytePos,
}

impl MirDebugScope {
    pub fn is_valid(&self) -> bool {
        !self.scope_metadata.is_null()
    }
}

/// Produce DIScope DIEs for each MIR Scope which has variables defined in it.
/// If debuginfo is disabled, the returned vector is empty.
pub fn create_mir_scopes<'tcx>(
    fcx: &FunctionContext,
    mir: &'tcx Mir<'tcx>,
) -> IndexVec<VisibilityScope, MirDebugScope> {
    let null_scope = MirDebugScope {
        scope_metadata: ptr::null_mut(),
        file_start_pos: BytePos(0),
        file_end_pos: BytePos(0)
    };
    let mut scopes = IndexVec::from_elem(null_scope, &mir.visibility_scopes);

    let fn_metadata = match fcx.debug_context {
        FunctionDebugContext::RegularContext(ref data) => data.fn_metadata,
        FunctionDebugContext::DebugInfoDisabled |
        FunctionDebugContext::FunctionWithoutDebugInfo => {
            return scopes;
        }
    };

    // Find all the scopes with variables defined in them.
    let mut has_variables = BitVector::new(mir.visibility_scopes.len());
    for var in mir.vars_iter() {
        let decl = &mir.local_decls[var];
        has_variables.insert(decl.source_info.unwrap().scope.index());
    }

    // Instantiate all scopes.
    for idx in 0..mir.visibility_scopes.len() {
        let scope = VisibilityScope::new(idx);
        make_mir_scope(fcx.ccx, &mir, &has_variables, fn_metadata, scope, &mut scopes);
    }

    scopes
}

fn make_mir_scope(ccx: &CrateContext,
                  mir: &Mir,
                  has_variables: &BitVector,
                  fn_metadata: DISubprogram,
                  scope: VisibilityScope,
                  scopes: &mut IndexVec<VisibilityScope, MirDebugScope>) {
    if scopes[scope].is_valid() {
        return;
    }

    let scope_data = &mir.visibility_scopes[scope];
    let parent_scope = if let Some(parent) = scope_data.parent_scope {
        make_mir_scope(ccx, mir, has_variables, fn_metadata, parent, scopes);
        scopes[parent]
    } else {
        // The root is the function itself.
        let loc = span_start(ccx, mir.span);
        scopes[scope] = MirDebugScope {
            scope_metadata: fn_metadata,
            file_start_pos: loc.file.start_pos,
            file_end_pos: loc.file.end_pos,
        };
        return;
    };

    if !has_variables.contains(scope.index()) {
        // Do not create a DIScope if there are no variables
        // defined in this MIR Scope, to avoid debuginfo bloat.

        // However, we don't skip creating a nested scope if
        // our parent is the root, because we might want to
        // put arguments in the root and not have shadowing.
        if parent_scope.scope_metadata != fn_metadata {
            scopes[scope] = parent_scope;
            return;
        }
    }

    let loc = span_start(ccx, scope_data.span);
    let file_metadata = file_metadata(ccx, &loc.file.name, &loc.file.abs_path);
    let scope_metadata = unsafe {
        llvm::LLVMRustDIBuilderCreateLexicalBlock(
            DIB(ccx),
            parent_scope.scope_metadata,
            file_metadata,
            loc.line as c_uint,
            loc.col.to_usize() as c_uint)
    };
    scopes[scope] = MirDebugScope {
        scope_metadata: scope_metadata,
        file_start_pos: loc.file.start_pos,
        file_end_pos: loc.file.end_pos,
    };
}
<commit_msg>Remove lifetime parameter<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use super::FunctionDebugContext;
use super::metadata::file_metadata;
use super::utils::{DIB, span_start};

use llvm;
use llvm::debuginfo::{DIScope, DISubprogram};
use common::{CrateContext, FunctionContext};
use rustc::mir::{Mir, VisibilityScope};

use libc::c_uint;
use std::ptr;

use syntax_pos::Pos;

use rustc_data_structures::bitvec::BitVector;
use rustc_data_structures::indexed_vec::{Idx, IndexVec};

use syntax_pos::BytePos;

#[derive(Clone, Copy, Debug)]
pub struct MirDebugScope {
    pub scope_metadata: DIScope,
    // Start and end offsets of the file to which this DIScope belongs.
    // These are used to quickly determine whether some span refers to the same file.
    pub file_start_pos: BytePos,
    pub file_end_pos: BytePos,
}

impl MirDebugScope {
    pub fn is_valid(&self) -> bool {
        !self.scope_metadata.is_null()
    }
}

/// Produce DIScope DIEs for each MIR Scope which has variables defined in it.
/// If debuginfo is disabled, the returned vector is empty.
pub fn create_mir_scopes(fcx: &FunctionContext, mir: &Mir)
    -> IndexVec<VisibilityScope, MirDebugScope> {
    let null_scope = MirDebugScope {
        scope_metadata: ptr::null_mut(),
        file_start_pos: BytePos(0),
        file_end_pos: BytePos(0)
    };
    let mut scopes = IndexVec::from_elem(null_scope, &mir.visibility_scopes);

    let fn_metadata = match fcx.debug_context {
        FunctionDebugContext::RegularContext(ref data) => data.fn_metadata,
        FunctionDebugContext::DebugInfoDisabled |
        FunctionDebugContext::FunctionWithoutDebugInfo => {
            return scopes;
        }
    };

    // Find all the scopes with variables defined in them.
    let mut has_variables = BitVector::new(mir.visibility_scopes.len());
    for var in mir.vars_iter() {
        let decl = &mir.local_decls[var];
        has_variables.insert(decl.source_info.unwrap().scope.index());
    }

    // Instantiate all scopes.
    for idx in 0..mir.visibility_scopes.len() {
        let scope = VisibilityScope::new(idx);
        make_mir_scope(fcx.ccx, &mir, &has_variables, fn_metadata, scope, &mut scopes);
    }

    scopes
}

fn make_mir_scope(ccx: &CrateContext,
                  mir: &Mir,
                  has_variables: &BitVector,
                  fn_metadata: DISubprogram,
                  scope: VisibilityScope,
                  scopes: &mut IndexVec<VisibilityScope, MirDebugScope>) {
    if scopes[scope].is_valid() {
        return;
    }

    let scope_data = &mir.visibility_scopes[scope];
    let parent_scope = if let Some(parent) = scope_data.parent_scope {
        make_mir_scope(ccx, mir, has_variables, fn_metadata, parent, scopes);
        scopes[parent]
    } else {
        // The root is the function itself.
        let loc = span_start(ccx, mir.span);
        scopes[scope] = MirDebugScope {
            scope_metadata: fn_metadata,
            file_start_pos: loc.file.start_pos,
            file_end_pos: loc.file.end_pos,
        };
        return;
    };

    if !has_variables.contains(scope.index()) {
        // Do not create a DIScope if there are no variables
        // defined in this MIR Scope, to avoid debuginfo bloat.

        // However, we don't skip creating a nested scope if
        // our parent is the root, because we might want to
        // put arguments in the root and not have shadowing.
        if parent_scope.scope_metadata != fn_metadata {
            scopes[scope] = parent_scope;
            return;
        }
    }

    let loc = span_start(ccx, scope_data.span);
    let file_metadata = file_metadata(ccx, &loc.file.name, &loc.file.abs_path);
    let scope_metadata = unsafe {
        llvm::LLVMRustDIBuilderCreateLexicalBlock(
            DIB(ccx),
            parent_scope.scope_metadata,
            file_metadata,
            loc.line as c_uint,
            loc.col.to_usize() as c_uint)
    };
    scopes[scope] = MirDebugScope {
        scope_metadata: scope_metadata,
        file_start_pos: loc.file.start_pos,
        file_end_pos: loc.file.end_pos,
    };
}
<|endoftext|>


<commit_before>use super::TheModule;
use TheModule::*;
use test_tools::*;

//

fn basic_test()
{
  // test.case( "basic" );
  let src = vec![ 1, 2, 3 ];
  let exp = ( vec![ 2, 3, 4 ], vec![ 0, 1, 2 ] );
  let got : ( Vec< _ >, Vec< _ > ) = src.iter().map( | e |
  {(
    e + 1,
    e - 1,
  )}).multiunzip();
  assert_eq!( got, exp );

}

//

test_suite!
{
  basic,
}
<commit_msg>Update tests of module `iter_tools`, use new test macroses<commit_after>use super::TheModule;
use TheModule::*;
use test_tools::*;

//

tests_impls!
{
  #[ test ]
  fn basic()
  {
    // test.case( "basic" );
    let src = vec![ 1, 2, 3 ];
    let exp = ( vec![ 2, 3, 4 ], vec![ 0, 1, 2 ] );
    let got : ( Vec< _ >, Vec< _ > ) = src.iter().map( | e |
    {(
      e + 1,
      e - 1,
    )}).multiunzip();
    assert_eq!( got, exp );

  }
}

//

tests_index!
{
  basic,
}
<|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/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

<% data.new_style_struct("Pointing", inherited=True, gecko_name="UserInterface") %>

${helpers.predefined_type("cursor",
                          "Cursor",
                          "computed::Cursor::auto()",
                          initial_specified_value="specified::Cursor::auto()",
                          animation_value_type="discrete",
                          spec="https://drafts.csswg.org/css-ui/#cursor")}

// NB: `pointer-events: auto` (and use of `pointer-events` in anything that isn't SVG, in fact)
// is nonstandard, slated for CSS4-UI.
// TODO(pcwalton): SVG-only values.
${helpers.single_keyword("pointer-events", "auto none", animation_value_type="discrete",
                         extra_gecko_values="visiblepainted visiblefill visiblestroke visible painted fill stroke all",
                         flags="APPLIES_TO_PLACEHOLDER",
                         spec="https://www.w3.org/TR/SVG11/interact.html#PointerEventsProperty")}

${helpers.single_keyword("-moz-user-input", "auto none enabled disabled",
                         products="gecko", gecko_ffi_name="mUserInput",
                         gecko_enum_prefix="StyleUserInput",
                         animation_value_type="discrete",
                         spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-user-input)")}

${helpers.single_keyword("-moz-user-modify", "read-only read-write write-only",
                         products="gecko", gecko_ffi_name="mUserModify",
                         gecko_enum_prefix="StyleUserModify",
                         needs_conversion=True,
                         animation_value_type="discrete",
                         spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-user-modify)")}

${helpers.single_keyword("-moz-user-focus",
                         "none ignore normal select-after select-before select-menu select-same select-all",
                         products="gecko", gecko_ffi_name="mUserFocus",
                         gecko_enum_prefix="StyleUserFocus",
                         animation_value_type="discrete",
                         spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-user-focus)")}

${helpers.predefined_type(
    "caret-color",
    "ColorOrAuto",
    "Either::Second(Auto)",
    spec="https://drafts.csswg.org/css-ui/#caret-color",
    animation_value_type="Either<AnimatedColor, Auto>",
    boxed=not RUSTC_HAS_PR45225,
    ignored_when_colors_disabled=True,
    products="gecko",
)}
<commit_msg>style: Nix -moz-user-input: disabled.<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/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

<% data.new_style_struct("Pointing", inherited=True, gecko_name="UserInterface") %>

${helpers.predefined_type("cursor",
                          "Cursor",
                          "computed::Cursor::auto()",
                          initial_specified_value="specified::Cursor::auto()",
                          animation_value_type="discrete",
                          spec="https://drafts.csswg.org/css-ui/#cursor")}

// NB: `pointer-events: auto` (and use of `pointer-events` in anything that isn't SVG, in fact)
// is nonstandard, slated for CSS4-UI.
// TODO(pcwalton): SVG-only values.
${helpers.single_keyword("pointer-events", "auto none", animation_value_type="discrete",
                         extra_gecko_values="visiblepainted visiblefill visiblestroke visible painted fill stroke all",
                         flags="APPLIES_TO_PLACEHOLDER",
                         spec="https://www.w3.org/TR/SVG11/interact.html#PointerEventsProperty")}

${helpers.single_keyword("-moz-user-input", "auto none enabled",
                         products="gecko", gecko_ffi_name="mUserInput",
                         gecko_enum_prefix="StyleUserInput",
                         animation_value_type="discrete",
                         spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-user-input)")}

${helpers.single_keyword("-moz-user-modify", "read-only read-write write-only",
                         products="gecko", gecko_ffi_name="mUserModify",
                         gecko_enum_prefix="StyleUserModify",
                         needs_conversion=True,
                         animation_value_type="discrete",
                         spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-user-modify)")}

${helpers.single_keyword("-moz-user-focus",
                         "none ignore normal select-after select-before select-menu select-same select-all",
                         products="gecko", gecko_ffi_name="mUserFocus",
                         gecko_enum_prefix="StyleUserFocus",
                         animation_value_type="discrete",
                         spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-user-focus)")}

${helpers.predefined_type(
    "caret-color",
    "ColorOrAuto",
    "Either::Second(Auto)",
    spec="https://drafts.csswg.org/css-ui/#caret-color",
    animation_value_type="Either<AnimatedColor, Auto>",
    boxed=not RUSTC_HAS_PR45225,
    ignored_when_colors_disabled=True,
    products="gecko",
)}
<|endoftext|>


<commit_before>use either::Either;
use hir::{db::AstDatabase, InFile};
use ide_db::{assists::Assist, source_change::SourceChange};
use rustc_hash::FxHashMap;
use stdx::format_to;
use syntax::{algo, ast::make, AstNode, SyntaxNodePtr};
use text_edit::TextEdit;

use crate::{fix, Diagnostic, DiagnosticsContext};

// Diagnostic: missing-fields
//
// This diagnostic is triggered if record lacks some fields that exist in the corresponding structure.
//
// Example:
//
// ```rust
// struct A { a: u8, b: u8 }
//
// let a = A { a: 10 };
// ```
pub(crate) fn missing_fields(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Diagnostic {
    let mut message = String::from("missing structure fields:\n");
    for field in &d.missed_fields {
        format_to!(message, "- {}\n", field);
    }

    let ptr = InFile::new(
        d.file,
        d.field_list_parent_path
            .clone()
            .map(SyntaxNodePtr::from)
            .unwrap_or_else(|| d.field_list_parent.clone().either(|it| it.into(), |it| it.into())),
    );

    Diagnostic::new("missing-fields", message, ctx.sema.diagnostics_display_range(ptr).range)
        .with_fixes(fixes(ctx, d))
}

fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Assist>> {
    // Note that although we could add a diagnostics to
    // fill the missing tuple field, e.g :
    // `struct A(usize);`
    // `let a = A { 0: () }`
    // but it is uncommon usage and it should not be encouraged.
    if d.missed_fields.iter().any(|it| it.as_tuple_index().is_some()) {
        return None;
    }

    let root = ctx.sema.db.parse_or_expand(d.file)?;
    let field_list_parent = match &d.field_list_parent {
        Either::Left(record_expr) => record_expr.to_node(&root),
        // FIXE: patterns should be fixable as well.
        Either::Right(_) => return None,
    };
    let old_field_list = field_list_parent.record_expr_field_list()?;
    let new_field_list = old_field_list.clone_for_update();
    let mut locals = FxHashMap::default();
    ctx.sema.scope(field_list_parent.syntax()).process_all_names(&mut |name, def| {
        if let hir::ScopeDef::Local(local) = def {
            locals.insert(name, local);
        }
    });
    let missing_fields = ctx.sema.record_literal_missing_fields(&field_list_parent);
    for (f, ty) in missing_fields.iter() {
        let field_expr = if let Some(local_candidate) = locals.get(&f.name(ctx.sema.db)) {
            cov_mark::hit!(field_shorthand);
            let candidate_ty = local_candidate.ty(ctx.sema.db);
            if ty.could_unify_with(ctx.sema.db, &candidate_ty) {
                None
            } else {
                Some(make::ext::expr_todo())
            }
        } else {
            Some(make::ext::expr_todo())
        };
        let field =
            make::record_expr_field(make::name_ref(&f.name(ctx.sema.db).to_string()), field_expr)
                .clone_for_update();
        new_field_list.add_field(field);
    }

    let edit = {
        let mut builder = TextEdit::builder();
        algo::diff(old_field_list.syntax(), new_field_list.syntax()).into_text_edit(&mut builder);
        builder.finish()
    };
    Some(vec![fix(
        "fill_missing_fields",
        "Fill struct fields",
        SourceChange::from_text_edit(d.file.original_file(ctx.sema.db), edit),
        ctx.sema.original_range(field_list_parent.syntax()).range,
    )])
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_diagnostics, check_fix};

    #[test]
    fn missing_record_pat_field_diagnostic() {
        check_diagnostics(
            r#"
struct S { foo: i32, bar: () }
fn baz(s: S) {
    let S { foo: _ } = s;
      //^ error: missing structure fields:
      //| - bar
}
"#,
        );
    }

    #[test]
    fn missing_record_pat_field_no_diagnostic_if_not_exhaustive() {
        check_diagnostics(
            r"
struct S { foo: i32, bar: () }
fn baz(s: S) -> i32 {
    match s {
        S { foo, .. } => foo,
    }
}
",
        )
    }

    #[test]
    fn missing_record_pat_field_box() {
        check_diagnostics(
            r"
struct S { s: Box<u32> }
fn x(a: S) {
    let S { box s } = a;
}
",
        )
    }

    #[test]
    fn missing_record_pat_field_ref() {
        check_diagnostics(
            r"
struct S { s: u32 }
fn x(a: S) {
    let S { ref s } = a;
}
",
        )
    }

    #[test]
    fn range_mapping_out_of_macros() {
        // FIXME: this is very wrong, but somewhat tricky to fix.
        check_fix(
            r#"
fn some() {}
fn items() {}
fn here() {}

macro_rules! id { ($($tt:tt)*) => { $($tt)*}; }

fn main() {
    let _x = id![Foo { a: $042 }];
}

pub struct Foo { pub a: i32, pub b: i32 }
"#,
            r#"
fn some(, b: todo!() ) {}
fn items() {}
fn here() {}

macro_rules! id { ($($tt:tt)*) => { $($tt)*}; }

fn main() {
    let _x = id![Foo { a: 42 }];
}

pub struct Foo { pub a: i32, pub b: i32 }
"#,
        );
    }

    #[test]
    fn test_fill_struct_fields_empty() {
        check_fix(
            r#"
struct TestStruct { one: i32, two: i64 }

fn test_fn() {
    let s = TestStruct {$0};
}
"#,
            r#"
struct TestStruct { one: i32, two: i64 }

fn test_fn() {
    let s = TestStruct { one: todo!(), two: todo!() };
}
"#,
        );
    }

    #[test]
    fn test_fill_struct_fields_self() {
        check_fix(
            r#"
struct TestStruct { one: i32 }

impl TestStruct {
    fn test_fn() { let s = Self {$0}; }
}
"#,
            r#"
struct TestStruct { one: i32 }

impl TestStruct {
    fn test_fn() { let s = Self { one: todo!() }; }
}
"#,
        );
    }

    #[test]
    fn test_fill_struct_fields_enum() {
        check_fix(
            r#"
enum Expr {
    Bin { lhs: Box<Expr>, rhs: Box<Expr> }
}

impl Expr {
    fn new_bin(lhs: Box<Expr>, rhs: Box<Expr>) -> Expr {
        Expr::Bin {$0 }
    }
}
"#,
            r#"
enum Expr {
    Bin { lhs: Box<Expr>, rhs: Box<Expr> }
}

impl Expr {
    fn new_bin(lhs: Box<Expr>, rhs: Box<Expr>) -> Expr {
        Expr::Bin { lhs, rhs }
    }
}
"#,
        );
    }

    #[test]
    fn test_fill_struct_fields_partial() {
        check_fix(
            r#"
struct TestStruct { one: i32, two: i64 }

fn test_fn() {
    let s = TestStruct{ two: 2$0 };
}
"#,
            r"
struct TestStruct { one: i32, two: i64 }

fn test_fn() {
    let s = TestStruct{ two: 2, one: todo!() };
}
",
        );
    }

    #[test]
    fn test_fill_struct_fields_raw_ident() {
        check_fix(
            r#"
struct TestStruct { r#type: u8 }

fn test_fn() {
    TestStruct { $0 };
}
"#,
            r"
struct TestStruct { r#type: u8 }

fn test_fn() {
    TestStruct { r#type: todo!()  };
}
",
        );
    }

    #[test]
    fn test_fill_struct_fields_no_diagnostic() {
        check_diagnostics(
            r#"
struct TestStruct { one: i32, two: i64 }

fn test_fn() {
    let one = 1;
    let s = TestStruct{ one, two: 2 };
}
        "#,
        );
    }

    #[test]
    fn test_fill_struct_fields_no_diagnostic_on_spread() {
        check_diagnostics(
            r#"
struct TestStruct { one: i32, two: i64 }

fn test_fn() {
    let one = 1;
    let s = TestStruct{ ..a };
}
"#,
        );
    }

    #[test]
    fn test_fill_struct_fields_blank_line() {
        check_fix(
            r#"
struct S { a: (), b: () }

fn f() {
    S {
        $0
    };
}
"#,
            r#"
struct S { a: (), b: () }

fn f() {
    S {
        a: todo!(),
        b: todo!(),
    };
}
"#,
        );
    }

    #[test]
    fn test_fill_struct_fields_shorthand() {
        cov_mark::check!(field_shorthand);
        check_fix(
            r#"
struct S { a: &'static str, b: i32 }

fn f() {
    let a = "hello";
    let b = 1i32;
    S {
        $0
    };
}
"#,
            r#"
struct S { a: &'static str, b: i32 }

fn f() {
    let a = "hello";
    let b = 1i32;
    S {
        a,
        b,
    };
}
"#,
        );
    }

    #[test]
    fn test_fill_struct_fields_shorthand_ty_mismatch() {
        check_fix(
            r#"
struct S { a: &'static str, b: i32 }

fn f() {
    let a = "hello";
    let b = 1usize;
    S {
        $0
    };
}
"#,
            r#"
struct S { a: &'static str, b: i32 }

fn f() {
    let a = "hello";
    let b = 1usize;
    S {
        a,
        b: todo!(),
    };
}
"#,
        );
    }

    #[test]
    fn test_fill_struct_fields_shorthand_unifies() {
        check_fix(
            r#"
struct S<T> { a: &'static str, b: T }

fn f() {
    let a = "hello";
    let b = 1i32;
    S {
        $0
    };
}
"#,
            r#"
struct S<T> { a: &'static str, b: T }

fn f() {
    let a = "hello";
    let b = 1i32;
    S {
        a,
        b,
    };
}
"#,
        );
    }

    #[test]
    fn import_extern_crate_clash_with_inner_item() {
        // This is more of a resolver test, but doesn't really work with the hir_def testsuite.

        check_diagnostics(
            r#"
//- /lib.rs crate:lib deps:jwt
mod permissions;

use permissions::jwt;

fn f() {
    fn inner() {}
    jwt::Claims {}; // should resolve to the local one with 0 fields, and not get a diagnostic
}

//- /permissions.rs
pub mod jwt  {
    pub struct Claims {}
}

//- /jwt/lib.rs crate:jwt
pub struct Claims {
    field: u8,
}
        "#,
        );
    }
}
<commit_msg>Fix missing_fields diagnostic fix replacing wrong text ranges<commit_after>use either::Either;
use hir::{db::AstDatabase, InFile};
use ide_db::{assists::Assist, source_change::SourceChange};
use rustc_hash::FxHashMap;
use stdx::format_to;
use syntax::{algo, ast::make, AstNode, SyntaxNodePtr};
use text_edit::TextEdit;

use crate::{fix, Diagnostic, DiagnosticsContext};

// Diagnostic: missing-fields
//
// This diagnostic is triggered if record lacks some fields that exist in the corresponding structure.
//
// Example:
//
// ```rust
// struct A { a: u8, b: u8 }
//
// let a = A { a: 10 };
// ```
pub(crate) fn missing_fields(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Diagnostic {
    let mut message = String::from("missing structure fields:\n");
    for field in &d.missed_fields {
        format_to!(message, "- {}\n", field);
    }

    let ptr = InFile::new(
        d.file,
        d.field_list_parent_path
            .clone()
            .map(SyntaxNodePtr::from)
            .unwrap_or_else(|| d.field_list_parent.clone().either(|it| it.into(), |it| it.into())),
    );

    Diagnostic::new("missing-fields", message, ctx.sema.diagnostics_display_range(ptr).range)
        .with_fixes(fixes(ctx, d))
}

fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Assist>> {
    // Note that although we could add a diagnostics to
    // fill the missing tuple field, e.g :
    // `struct A(usize);`
    // `let a = A { 0: () }`
    // but it is uncommon usage and it should not be encouraged.
    if d.missed_fields.iter().any(|it| it.as_tuple_index().is_some()) {
        return None;
    }

    let root = ctx.sema.db.parse_or_expand(d.file)?;
    let field_list_parent = match &d.field_list_parent {
        Either::Left(record_expr) => record_expr.to_node(&root),
        // FIXE: patterns should be fixable as well.
        Either::Right(_) => return None,
    };
    let old_field_list = field_list_parent.record_expr_field_list()?;

    let new_field_list = old_field_list.clone_for_update();
    let mut locals = FxHashMap::default();
    ctx.sema.scope(field_list_parent.syntax()).process_all_names(&mut |name, def| {
        if let hir::ScopeDef::Local(local) = def {
            locals.insert(name, local);
        }
    });
    let missing_fields = ctx.sema.record_literal_missing_fields(&field_list_parent);
    for (f, ty) in missing_fields.iter() {
        let field_expr = if let Some(local_candidate) = locals.get(&f.name(ctx.sema.db)) {
            cov_mark::hit!(field_shorthand);
            let candidate_ty = local_candidate.ty(ctx.sema.db);
            if ty.could_unify_with(ctx.sema.db, &candidate_ty) {
                None
            } else {
                Some(make::ext::expr_todo())
            }
        } else {
            Some(make::ext::expr_todo())
        };
        let field =
            make::record_expr_field(make::name_ref(&f.name(ctx.sema.db).to_string()), field_expr)
                .clone_for_update();
        new_field_list.add_field(field);
    }

    let mut builder = TextEdit::builder();
    if d.file.is_macro() {
        // we can't map the diff up into the macro input unfortunately, as the macro loses all
        // whitespace information so the diff wouldn't be applicable no matter what
        // This has the downside that the cursor will be moved in macros by doing it without a diff
        // but that is a trade off we can make.
        // FIXE: this also currently discards a lot of whitespace in the input... we really need a formatter here
        let range = ctx.sema.original_range_opt(old_field_list.syntax())?;
        builder.replace(range.range, new_field_list.to_string());
    } else {
        algo::diff(old_field_list.syntax(), new_field_list.syntax()).into_text_edit(&mut builder);
    }
    let edit = builder.finish();
    Some(vec![fix(
        "fill_missing_fields",
        "Fill struct fields",
        SourceChange::from_text_edit(d.file.original_file(ctx.sema.db), edit),
        ctx.sema.original_range(field_list_parent.syntax()).range,
    )])
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_diagnostics, check_fix};

    #[test]
    fn missing_record_pat_field_diagnostic() {
        check_diagnostics(
            r#"
struct S { foo: i32, bar: () }
fn baz(s: S) {
    let S { foo: _ } = s;
      //^ error: missing structure fields:
      //| - bar
}
"#,
        );
    }

    #[test]
    fn missing_record_pat_field_no_diagnostic_if_not_exhaustive() {
        check_diagnostics(
            r"
struct S { foo: i32, bar: () }
fn baz(s: S) -> i32 {
    match s {
        S { foo, .. } => foo,
    }
}
",
        )
    }

    #[test]
    fn missing_record_pat_field_box() {
        check_diagnostics(
            r"
struct S { s: Box<u32> }
fn x(a: S) {
    let S { box s } = a;
}
",
        )
    }

    #[test]
    fn missing_record_pat_field_ref() {
        check_diagnostics(
            r"
struct S { s: u32 }
fn x(a: S) {
    let S { ref s } = a;
}
",
        )
    }

    #[test]
    fn range_mapping_out_of_macros() {
        check_fix(
            r#"
fn some() {}
fn items() {}
fn here() {}

macro_rules! id { ($($tt:tt)*) => { $($tt)*}; }

fn main() {
    let _x = id![Foo { a: $042 }];
}

pub struct Foo { pub a: i32, pub b: i32 }
"#,
            r#"
fn some() {}
fn items() {}
fn here() {}

macro_rules! id { ($($tt:tt)*) => { $($tt)*}; }

fn main() {
    let _x = id![Foo {a:42, b: todo!() }];
}

pub struct Foo { pub a: i32, pub b: i32 }
"#,
        );
    }

    #[test]
    fn test_fill_struct_fields_empty() {
        check_fix(
            r#"
struct TestStruct { one: i32, two: i64 }

fn test_fn() {
    let s = TestStruct {$0};
}
"#,
            r#"
struct TestStruct { one: i32, two: i64 }

fn test_fn() {
    let s = TestStruct { one: todo!(), two: todo!() };
}
"#,
        );
    }

    #[test]
    fn test_fill_struct_fields_self() {
        check_fix(
            r#"
struct TestStruct { one: i32 }

impl TestStruct {
    fn test_fn() { let s = Self {$0}; }
}
"#,
            r#"
struct TestStruct { one: i32 }

impl TestStruct {
    fn test_fn() { let s = Self { one: todo!() }; }
}
"#,
        );
    }

    #[test]
    fn test_fill_struct_fields_enum() {
        check_fix(
            r#"
enum Expr {
    Bin { lhs: Box<Expr>, rhs: Box<Expr> }
}

impl Expr {
    fn new_bin(lhs: Box<Expr>, rhs: Box<Expr>) -> Expr {
        Expr::Bin {$0 }
    }
}
"#,
            r#"
enum Expr {
    Bin { lhs: Box<Expr>, rhs: Box<Expr> }
}

impl Expr {
    fn new_bin(lhs: Box<Expr>, rhs: Box<Expr>) -> Expr {
        Expr::Bin { lhs, rhs }
    }
}
"#,
        );
    }

    #[test]
    fn test_fill_struct_fields_partial() {
        check_fix(
            r#"
struct TestStruct { one: i32, two: i64 }

fn test_fn() {
    let s = TestStruct{ two: 2$0 };
}
"#,
            r"
struct TestStruct { one: i32, two: i64 }

fn test_fn() {
    let s = TestStruct{ two: 2, one: todo!() };
}
",
        );
    }

    #[test]
    fn test_fill_struct_fields_raw_ident() {
        check_fix(
            r#"
struct TestStruct { r#type: u8 }

fn test_fn() {
    TestStruct { $0 };
}
"#,
            r"
struct TestStruct { r#type: u8 }

fn test_fn() {
    TestStruct { r#type: todo!()  };
}
",
        );
    }

    #[test]
    fn test_fill_struct_fields_no_diagnostic() {
        check_diagnostics(
            r#"
struct TestStruct { one: i32, two: i64 }

fn test_fn() {
    let one = 1;
    let s = TestStruct{ one, two: 2 };
}
        "#,
        );
    }

    #[test]
    fn test_fill_struct_fields_no_diagnostic_on_spread() {
        check_diagnostics(
            r#"
struct TestStruct { one: i32, two: i64 }

fn test_fn() {
    let one = 1;
    let s = TestStruct{ ..a };
}
"#,
        );
    }

    #[test]
    fn test_fill_struct_fields_blank_line() {
        check_fix(
            r#"
struct S { a: (), b: () }

fn f() {
    S {
        $0
    };
}
"#,
            r#"
struct S { a: (), b: () }

fn f() {
    S {
        a: todo!(),
        b: todo!(),
    };
}
"#,
        );
    }

    #[test]
    fn test_fill_struct_fields_shorthand() {
        cov_mark::check!(field_shorthand);
        check_fix(
            r#"
struct S { a: &'static str, b: i32 }

fn f() {
    let a = "hello";
    let b = 1i32;
    S {
        $0
    };
}
"#,
            r#"
struct S { a: &'static str, b: i32 }

fn f() {
    let a = "hello";
    let b = 1i32;
    S {
        a,
        b,
    };
}
"#,
        );
    }

    #[test]
    fn test_fill_struct_fields_shorthand_ty_mismatch() {
        check_fix(
            r#"
struct S { a: &'static str, b: i32 }

fn f() {
    let a = "hello";
    let b = 1usize;
    S {
        $0
    };
}
"#,
            r#"
struct S { a: &'static str, b: i32 }

fn f() {
    let a = "hello";
    let b = 1usize;
    S {
        a,
        b: todo!(),
    };
}
"#,
        );
    }

    #[test]
    fn test_fill_struct_fields_shorthand_unifies() {
        check_fix(
            r#"
struct S<T> { a: &'static str, b: T }

fn f() {
    let a = "hello";
    let b = 1i32;
    S {
        $0
    };
}
"#,
            r#"
struct S<T> { a: &'static str, b: T }

fn f() {
    let a = "hello";
    let b = 1i32;
    S {
        a,
        b,
    };
}
"#,
        );
    }

    #[test]
    fn import_extern_crate_clash_with_inner_item() {
        // This is more of a resolver test, but doesn't really work with the hir_def testsuite.

        check_diagnostics(
            r#"
//- /lib.rs crate:lib deps:jwt
mod permissions;

use permissions::jwt;

fn f() {
    fn inner() {}
    jwt::Claims {}; // should resolve to the local one with 0 fields, and not get a diagnostic
}

//- /permissions.rs
pub mod jwt  {
    pub struct Claims {}
}

//- /jwt/lib.rs crate:jwt
pub struct Claims {
    field: u8,
}
        "#,
        );
    }
}
<|endoftext|>


<commit_before>use crate::error::Error;

pub fn validate(server_name: &str) -> Result<(), Error> {
    use std::net::Ipv6Addr;

    if server_name.is_empty() {
        return Err(Error::InvalidServerName);
    }

    let end_of_host = if server_name.starts_with('[') {
        let end_of_ipv6 = match server_name.find(']') {
            Some(idx) => idx,
            None => return Err(Error::InvalidServerName),
        };

        if server_name[1..end_of_ipv6].parse::<Ipv6Addr>().is_err() {
            return Err(Error::InvalidServerName);
        }

        end_of_ipv6 + 1
    } else {
        let end_of_host = server_name.find(':').unwrap_or_else(|| server_name.len());

        if server_name[..end_of_host]
            .bytes()
            .any(|byte| !(byte.is_ascii_alphanumeric() || byte == b'-' || byte == b'.'))
        {
            return Err(Error::InvalidServerName);
        }

        end_of_host
    };

    if server_name.len() != end_of_host
        && (
            // hostname is followed by something other than ":port"
            server_name.as_bytes()[end_of_host] != b':'
            // the remaining characters after ':' are not a valid port
            || server_name[end_of_host + 1..].parse::<u16>().is_err()
        )
    {
        Err(Error::InvalidServerName)
    } else {
        Ok(())
    }
}
<commit_msg>Silence buggy clippy lint<commit_after>use crate::error::Error;

// Clippy lint is buggy, should be fixed within the next week (as of 2021-10-29)
#[allow(clippy::question_mark)]
pub fn validate(server_name: &str) -> Result<(), Error> {
    use std::net::Ipv6Addr;

    if server_name.is_empty() {
        return Err(Error::InvalidServerName);
    }

    let end_of_host = if server_name.starts_with('[') {
        let end_of_ipv6 = match server_name.find(']') {
            Some(idx) => idx,
            None => return Err(Error::InvalidServerName),
        };

        if server_name[1..end_of_ipv6].parse::<Ipv6Addr>().is_err() {
            return Err(Error::InvalidServerName);
        }

        end_of_ipv6 + 1
    } else {
        let end_of_host = server_name.find(':').unwrap_or_else(|| server_name.len());

        if server_name[..end_of_host]
            .bytes()
            .any(|byte| !(byte.is_ascii_alphanumeric() || byte == b'-' || byte == b'.'))
        {
            return Err(Error::InvalidServerName);
        }

        end_of_host
    };

    if server_name.len() != end_of_host
        && (
            // hostname is followed by something other than ":port"
            server_name.as_bytes()[end_of_host] != b':'
            // the remaining characters after ':' are not a valid port
            || server_name[end_of_host + 1..].parse::<u16>().is_err()
        )
    {
        Err(Error::InvalidServerName)
    } else {
        Ok(())
    }
}
<|endoftext|>


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

use crate::{
    errors::Error,
    scheduler::{Incarnation, TxnIndex, Version},
    task::{ExecutionStatus, ModulePath, Transaction, TransactionOutput},
};
use aptos_types::access_path::AccessPath;
use arc_swap::ArcSwapOption;
use crossbeam::utils::CachePadded;
use dashmap::DashSet;
use std::{
    collections::HashSet,
    sync::{
        atomic::{AtomicBool, Ordering},
        Arc,
    },
};

type TxnInput<K> = Vec<ReadDescriptor<K>>;
type TxnOutput<T, E> = ExecutionStatus<T, Error<E>>;

// If an entry was read from the multi-version data-structure, then kind is
// MVHashMap(txn_idx, incarnation), with transaction index and incarnation number
// of the execution associated with the write of the entry. Otherwise, if the read
// occured from storage, and kind is set to Storage.
#[derive(Clone, PartialEq)]
enum ReadKind {
    MVHashMap(TxnIndex, Incarnation),
    Storage,
}

#[derive(Clone)]
pub struct ReadDescriptor<K> {
    access_path: K,

    kind: ReadKind,
}

impl<K: ModulePath> ReadDescriptor<K> {
    pub fn from(access_path: K, txn_idx: TxnIndex, incarnation: Incarnation) -> Self {
        Self {
            access_path,
            kind: ReadKind::MVHashMap(txn_idx, incarnation),
        }
    }

    pub fn from_storage(access_path: K) -> Self {
        Self {
            access_path,
            kind: ReadKind::Storage,
        }
    }

    fn module_path(&self) -> Option<AccessPath> {
        self.access_path.module_path()
    }

    pub fn path(&self) -> &K {
        &self.access_path
    }

    // Does the read descriptor describe a read from MVHashMap w. a specified version.
    pub fn validate_version(&self, version: Version) -> bool {
        let (txn_idx, incarnation) = version;
        self.kind == ReadKind::MVHashMap(txn_idx, incarnation)
    }

    // Does the read descriptor describe a read from storage.
    pub fn validate_storage(&self) -> bool {
        self.kind == ReadKind::Storage
    }
}

pub struct TxnLastInputOutput<K, T, E> {
    inputs: Vec<CachePadded<ArcSwapOption<TxnInput<K>>>>, // txn_idx -> input.

    outputs: Vec<CachePadded<ArcSwapOption<TxnOutput<T, E>>>>, // txn_idx -> output.

    // Record all writes and reads to access paths corresponding to modules (code) in any
    // (speculative) executions. Used to avoid a potential race with module publishing and
    // Move-VM loader cache - see 'record' function comment for more information.
    module_writes: DashSet<AccessPath>,
    module_reads: DashSet<AccessPath>,

    module_read_write_intersection: AtomicBool,
}

impl<K: ModulePath, T: TransactionOutput, E: Send + Clone> TxnLastInputOutput<K, T, E> {
    pub fn new(num_txns: usize) -> Self {
        Self {
            inputs: (0..num_txns)
                .map(|_| CachePadded::new(ArcSwapOption::empty()))
                .collect(),
            outputs: (0..num_txns)
                .map(|_| CachePadded::new(ArcSwapOption::empty()))
                .collect(),
            module_writes: DashSet::new(),
            module_reads: DashSet::new(),
            module_read_write_intersection: AtomicBool::new(false),
        }
    }

    fn append_and_check(
        paths: Vec<AccessPath>,
        set_to_append: &DashSet<AccessPath>,
        set_to_check: &DashSet<AccessPath>,
    ) -> bool {
        for path in paths {
            // Standard flags, first show, then look.
            set_to_append.insert(path.clone());

            if set_to_check.contains(&path) {
                return true;
            }
        }
        false
    }

    /// Returns an error if a module path that was read was previously written to, and vice versa.
    /// Since parallel executor is instantiated per block, any module that is in the Move-VM loader
    /// cache must previously be read and would be recorded in the 'module_reads' set. Any module
    /// that is written (published or re-published) goes through transaction output write-set and
    /// gets recorded in the 'module_writes' set. If these sets have an intersection, it is currently
    /// possible that Move-VM loader cache loads a module and incorrectly uses it for another
    /// transaction (e.g. a smaller transaction, or if the speculative execution of the publishing
    /// transaction later aborts). The intersection is guaranteed to be found because we first
    /// record the paths then check the other set (flags principle), and in this case we return an
    /// error that ensures a fallback to a correct sequential execution.
    /// When the sets do not have an intersection, it is impossible for the race to occur as any
    /// module in the loader cache may not be published by a transaction in the ongoing block.
    pub fn record(
        &self,
        txn_idx: TxnIndex,
        input: Vec<ReadDescriptor<K>>,
        output: ExecutionStatus<T, Error<E>>,
    ) {
        let read_modules: Vec<AccessPath> =
            input.iter().filter_map(|desc| desc.module_path()).collect();
        let written_modules: Vec<AccessPath> = match &output {
            ExecutionStatus::Success(output) | ExecutionStatus::SkipRest(output) => output
                .get_writes()
                .into_iter()
                .filter_map(|(k, _)| k.module_path())
                .collect(),
            ExecutionStatus::Abort(_) => Vec::new(),
        };

        if !self.module_read_write_intersection.load(Ordering::Relaxed) {
            self.module_read_write_intersection.store(
                Self::append_and_check(read_modules, &self.module_reads, &self.module_writes)
                    || Self::append_and_check(
                        written_modules,
                        &self.module_writes,
                        &self.module_reads,
                    ),
                Ordering::Release,
            );
        }

        self.inputs[txn_idx].store(Some(Arc::new(input)));
        self.outputs[txn_idx].store(Some(Arc::new(output)));
    }

    pub fn module_publishing_may_race(&self) -> bool {
        self.module_read_write_intersection.load(Ordering::Acquire)
    }

    pub fn read_set(&self, txn_idx: TxnIndex) -> Option<Arc<Vec<ReadDescriptor<K>>>> {
        self.inputs[txn_idx].load_full()
    }

    // Extracts a set of paths written during execution from transaction output.
    pub fn write_set(
        &self,
        txn_idx: TxnIndex,
    ) -> HashSet<<<T as TransactionOutput>::T as Transaction>::Key> {
        match &self.outputs[txn_idx].load_full() {
            None => HashSet::new(),
            Some(txn_output) => match txn_output.as_ref() {
                ExecutionStatus::Success(t) | ExecutionStatus::SkipRest(t) => {
                    t.get_writes().into_iter().map(|(k, _)| k).collect()
                }
                ExecutionStatus::Abort(_) => HashSet::new(),
            },
        }
    }

    // Must be executed after parallel execution is done, grabs outputs. Will panic if
    // other outstanding references to the recorded outputs exist.
    pub fn take_output(&self, txn_idx: TxnIndex) -> ExecutionStatus<T, Error<E>> {
        let owning_ptr = self.outputs[txn_idx]
            .swap(None)
            .expect("Output must be recorded after execution");

        if let Ok(output) = Arc::try_unwrap(owning_ptr) {
            output
        } else {
            unreachable!("Output should be uniquely owned after execution");
        }
    }
}
<commit_msg>eliminate possible race, overwriting with false (#2916)<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use crate::{
    errors::Error,
    scheduler::{Incarnation, TxnIndex, Version},
    task::{ExecutionStatus, ModulePath, Transaction, TransactionOutput},
};
use aptos_types::access_path::AccessPath;
use arc_swap::ArcSwapOption;
use crossbeam::utils::CachePadded;
use dashmap::DashSet;
use std::{
    collections::HashSet,
    sync::{
        atomic::{AtomicBool, Ordering},
        Arc,
    },
};

type TxnInput<K> = Vec<ReadDescriptor<K>>;
type TxnOutput<T, E> = ExecutionStatus<T, Error<E>>;

// If an entry was read from the multi-version data-structure, then kind is
// MVHashMap(txn_idx, incarnation), with transaction index and incarnation number
// of the execution associated with the write of the entry. Otherwise, if the read
// occured from storage, and kind is set to Storage.
#[derive(Clone, PartialEq)]
enum ReadKind {
    MVHashMap(TxnIndex, Incarnation),
    Storage,
}

#[derive(Clone)]
pub struct ReadDescriptor<K> {
    access_path: K,

    kind: ReadKind,
}

impl<K: ModulePath> ReadDescriptor<K> {
    pub fn from(access_path: K, txn_idx: TxnIndex, incarnation: Incarnation) -> Self {
        Self {
            access_path,
            kind: ReadKind::MVHashMap(txn_idx, incarnation),
        }
    }

    pub fn from_storage(access_path: K) -> Self {
        Self {
            access_path,
            kind: ReadKind::Storage,
        }
    }

    fn module_path(&self) -> Option<AccessPath> {
        self.access_path.module_path()
    }

    pub fn path(&self) -> &K {
        &self.access_path
    }

    // Does the read descriptor describe a read from MVHashMap w. a specified version.
    pub fn validate_version(&self, version: Version) -> bool {
        let (txn_idx, incarnation) = version;
        self.kind == ReadKind::MVHashMap(txn_idx, incarnation)
    }

    // Does the read descriptor describe a read from storage.
    pub fn validate_storage(&self) -> bool {
        self.kind == ReadKind::Storage
    }
}

pub struct TxnLastInputOutput<K, T, E> {
    inputs: Vec<CachePadded<ArcSwapOption<TxnInput<K>>>>, // txn_idx -> input.

    outputs: Vec<CachePadded<ArcSwapOption<TxnOutput<T, E>>>>, // txn_idx -> output.

    // Record all writes and reads to access paths corresponding to modules (code) in any
    // (speculative) executions. Used to avoid a potential race with module publishing and
    // Move-VM loader cache - see 'record' function comment for more information.
    module_writes: DashSet<AccessPath>,
    module_reads: DashSet<AccessPath>,

    module_read_write_intersection: AtomicBool,
}

impl<K: ModulePath, T: TransactionOutput, E: Send + Clone> TxnLastInputOutput<K, T, E> {
    pub fn new(num_txns: usize) -> Self {
        Self {
            inputs: (0..num_txns)
                .map(|_| CachePadded::new(ArcSwapOption::empty()))
                .collect(),
            outputs: (0..num_txns)
                .map(|_| CachePadded::new(ArcSwapOption::empty()))
                .collect(),
            module_writes: DashSet::new(),
            module_reads: DashSet::new(),
            module_read_write_intersection: AtomicBool::new(false),
        }
    }

    fn append_and_check(
        paths: Vec<AccessPath>,
        set_to_append: &DashSet<AccessPath>,
        set_to_check: &DashSet<AccessPath>,
    ) -> bool {
        for path in paths {
            // Standard flags, first show, then look.
            set_to_append.insert(path.clone());

            if set_to_check.contains(&path) {
                return true;
            }
        }
        false
    }

    /// Returns an error if a module path that was read was previously written to, and vice versa.
    /// Since parallel executor is instantiated per block, any module that is in the Move-VM loader
    /// cache must previously be read and would be recorded in the 'module_reads' set. Any module
    /// that is written (published or re-published) goes through transaction output write-set and
    /// gets recorded in the 'module_writes' set. If these sets have an intersection, it is currently
    /// possible that Move-VM loader cache loads a module and incorrectly uses it for another
    /// transaction (e.g. a smaller transaction, or if the speculative execution of the publishing
    /// transaction later aborts). The intersection is guaranteed to be found because we first
    /// record the paths then check the other set (flags principle), and in this case we return an
    /// error that ensures a fallback to a correct sequential execution.
    /// When the sets do not have an intersection, it is impossible for the race to occur as any
    /// module in the loader cache may not be published by a transaction in the ongoing block.
    pub fn record(
        &self,
        txn_idx: TxnIndex,
        input: Vec<ReadDescriptor<K>>,
        output: ExecutionStatus<T, Error<E>>,
    ) {
        let read_modules: Vec<AccessPath> =
            input.iter().filter_map(|desc| desc.module_path()).collect();
        let written_modules: Vec<AccessPath> = match &output {
            ExecutionStatus::Success(output) | ExecutionStatus::SkipRest(output) => output
                .get_writes()
                .into_iter()
                .filter_map(|(k, _)| k.module_path())
                .collect(),
            ExecutionStatus::Abort(_) => Vec::new(),
        };

        if !self.module_read_write_intersection.load(Ordering::Relaxed) {
            // Check if adding new read & write modules leads to intersections.
            if Self::append_and_check(read_modules, &self.module_reads, &self.module_writes)
                || Self::append_and_check(written_modules, &self.module_writes, &self.module_reads)
            {
                self.module_read_write_intersection
                    .store(true, Ordering::Release);
            }
        }

        self.inputs[txn_idx].store(Some(Arc::new(input)));
        self.outputs[txn_idx].store(Some(Arc::new(output)));
    }

    pub fn module_publishing_may_race(&self) -> bool {
        self.module_read_write_intersection.load(Ordering::Acquire)
    }

    pub fn read_set(&self, txn_idx: TxnIndex) -> Option<Arc<Vec<ReadDescriptor<K>>>> {
        self.inputs[txn_idx].load_full()
    }

    // Extracts a set of paths written during execution from transaction output.
    pub fn write_set(
        &self,
        txn_idx: TxnIndex,
    ) -> HashSet<<<T as TransactionOutput>::T as Transaction>::Key> {
        match &self.outputs[txn_idx].load_full() {
            None => HashSet::new(),
            Some(txn_output) => match txn_output.as_ref() {
                ExecutionStatus::Success(t) | ExecutionStatus::SkipRest(t) => {
                    t.get_writes().into_iter().map(|(k, _)| k).collect()
                }
                ExecutionStatus::Abort(_) => HashSet::new(),
            },
        }
    }

    // Must be executed after parallel execution is done, grabs outputs. Will panic if
    // other outstanding references to the recorded outputs exist.
    pub fn take_output(&self, txn_idx: TxnIndex) -> ExecutionStatus<T, Error<E>> {
        let owning_ptr = self.outputs[txn_idx]
            .swap(None)
            .expect("Output must be recorded after execution");

        if let Ok(output) = Arc::try_unwrap(owning_ptr) {
            output
        } else {
            unreachable!("Output should be uniquely owned after execution");
        }
    }
}
<|endoftext|>


<commit_before>use hir::{MacroDef, ModuleDef, Name, PathResolution, ScopeDef, SemanticsScope};
use ra_ide_db::{
    defs::{classify_name_ref, Definition, NameRefClass},
    RootDatabase,
};
use ra_syntax::{ast, match_ast, AstNode, SyntaxNode, SyntaxToken, T};

use crate::{
    assist_context::{AssistBuilder, AssistContext, Assists},
    AssistId, AssistKind,
};

// Assist: expand_glob_import
//
// Expands glob imports.
//
// ```
// mod foo {
//     pub struct Bar;
//     pub struct Baz;
// }
//
// use foo::*<|>;
//
// fn qux(bar: Bar, baz: Baz) {}
// ```
// ->
// ```
// mod foo {
//     pub struct Bar;
//     pub struct Baz;
// }
//
// use foo::{Baz, Bar};
//
// fn qux(bar: Bar, baz: Baz) {}
// ```
pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let star = ctx.find_token_at_offset(T![*])?;
    let mod_path = find_mod_path(&star)?;

    let source_file = ctx.source_file();
    let scope = ctx.sema.scope_at_offset(source_file.syntax(), ctx.offset());

    let defs_in_mod = find_defs_in_mod(ctx, scope, &mod_path)?;
    let name_refs_in_source_file =
        source_file.syntax().descendants().filter_map(ast::NameRef::cast).collect();
    let used_names = find_used_names(ctx, defs_in_mod, name_refs_in_source_file);

    let parent = star.parent().parent()?;
    acc.add(
        AssistId("expand_glob_import", AssistKind::RefactorRewrite),
        "Expand glob import",
        parent.text_range(),
        |builder| {
            replace_ast(builder, &parent, mod_path, used_names);
        },
    )
}

fn find_mod_path(star: &SyntaxToken) -> Option<ast::Path> {
    let mut node = star.parent();

    loop {
        match_ast! {
            match node {
                ast::UseTree(use_tree) => {
                    if let Some(path) = use_tree.path() {
                        return Some(path);
                    }
                },
                ast::UseTreeList(_use_tree_list) => {},
                _ => return None,
            }
        }

        node = match node.parent() {
            Some(node) => node,
            None => return None,
        }
    }
}

#[derive(PartialEq)]
enum Def {
    ModuleDef(ModuleDef),
    MacroDef(MacroDef),
}

impl Def {
    fn name(&self, db: &RootDatabase) -> Option<Name> {
        match self {
            Def::ModuleDef(def) => def.name(db),
            Def::MacroDef(def) => def.name(db),
        }
    }
}

fn find_defs_in_mod(
    ctx: &AssistContext,
    from: SemanticsScope<'_>,
    path: &ast::Path,
) -> Option<Vec<Def>> {
    let hir_path = ctx.sema.lower_path(&path)?;
    let module = if let Some(PathResolution::Def(ModuleDef::Module(module))) =
        from.resolve_hir_path_qualifier(&hir_path)
    {
        module
    } else {
        return None;
    };

    let module_scope = module.scope(ctx.db(), from.module());

    let mut defs = vec![];
    for (_, def) in module_scope {
        match def {
            ScopeDef::ModuleDef(def) => defs.push(Def::ModuleDef(def)),
            ScopeDef::MacroDef(def) => defs.push(Def::MacroDef(def)),
            _ => continue,
        }
    }

    Some(defs)
}

fn find_used_names(
    ctx: &AssistContext,
    defs_in_mod: Vec<Def>,
    name_refs_in_source_file: Vec<ast::NameRef>,
) -> Vec<Name> {
    let defs_in_source_file = name_refs_in_source_file
        .iter()
        .filter_map(|r| classify_name_ref(&ctx.sema, r))
        .filter_map(|rc| match rc {
            NameRefClass::Definition(Definition::ModuleDef(def)) => Some(Def::ModuleDef(def)),
            NameRefClass::Definition(Definition::Macro(def)) => Some(Def::MacroDef(def)),
            _ => None,
        })
        .collect::<Vec<Def>>();

    defs_in_mod
        .iter()
        .filter(|d| defs_in_source_file.contains(d))
        .filter_map(|d| d.name(ctx.db()))
        .collect()
}

fn replace_ast(
    builder: &mut AssistBuilder,
    node: &SyntaxNode,
    path: ast::Path,
    used_names: Vec<Name>,
) {
    let new_use_tree_list = ast::make::use_tree_list(used_names.iter().map(|n| {
        ast::make::use_tree(ast::make::path_from_text(&n.to_string()), None, None, false)
    }));

    match_ast! {
        match node {
            ast::UseTree(use_tree) => {
                builder.replace_ast(use_tree, make_use_tree(path, new_use_tree_list));
            },
            ast::UseTreeList(use_tree_list) => {
                builder.replace_ast(use_tree_list, new_use_tree_list);
            },
            ast::Use(use_item) => {
                builder.replace_ast(use_item, ast::make::use_item(make_use_tree(path, new_use_tree_list)));
            },
            _ => {},
        }
    }

    fn make_use_tree(path: ast::Path, use_tree_list: ast::UseTreeList) -> ast::UseTree {
        ast::make::use_tree(path, Some(use_tree_list), None, false)
    }
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    #[test]
    fn expanding_glob_import() {
        check_assist(
            expand_glob_import,
            r"
mod foo {
    pub struct Bar;
    pub struct Baz;
    pub struct Qux;

    pub fn f() {}
}

use foo::*<|>;

fn qux(bar: Bar, baz: Baz) {
    f();
}
",
            r"
mod foo {
    pub struct Bar;
    pub struct Baz;
    pub struct Qux;

    pub fn f() {}
}

use foo::{Baz, Bar, f};

fn qux(bar: Bar, baz: Baz) {
    f();
}
",
        )
    }

    #[test]
    fn expanding_glob_import_with_existing_explicit_names() {
        check_assist(
            expand_glob_import,
            r"
mod foo {
    pub struct Bar;
    pub struct Baz;
    pub struct Qux;

    pub fn f() {}
}

use foo::{*<|>, f};

fn qux(bar: Bar, baz: Baz) {
    f();
}
",
            r"
mod foo {
    pub struct Bar;
    pub struct Baz;
    pub struct Qux;

    pub fn f() {}
}

use foo::{Baz, Bar, f};

fn qux(bar: Bar, baz: Baz) {
    f();
}
",
        )
    }

    #[test]
    fn expanding_nested_glob_import() {
        check_assist(
            expand_glob_import,
            r"
mod foo {
    mod bar {
        pub struct Bar;
        pub struct Baz;
        pub struct Qux;

        pub fn f() {}
    }

    mod baz {
        pub fn g() {}
    }
}

use foo::{bar::{*<|>, f}, baz::*};

fn qux(bar: Bar, baz: Baz) {
    f();
    g();
}
",
            r"
mod foo {
    mod bar {
        pub struct Bar;
        pub struct Baz;
        pub struct Qux;

        pub fn f() {}
    }

    mod baz {
        pub fn g() {}
    }
}

use foo::{bar::{Baz, Bar, f}, baz::*};

fn qux(bar: Bar, baz: Baz) {
    f();
    g();
}
",
        )
    }

    #[test]
    fn expanding_glob_import_with_macro_defs() {
        check_assist(
            expand_glob_import,
            r"
//- /lib.rs crate:foo
#[macro_export]
macro_rules! bar {
    () => ()
}

pub fn baz() {}

//- /main.rs crate:main deps:foo
use foo::*<|>;

fn main() {
    bar!();
    baz();
}
",
            r"
use foo::{bar, baz};

fn main() {
    bar!();
    baz();
}
",
        )
    }

    #[test]
    fn expanding_is_not_applicable_if_cursor_is_not_in_star_token() {
        check_assist_not_applicable(
            expand_glob_import,
            r"
    mod foo {
        pub struct Bar;
        pub struct Baz;
        pub struct Qux;
    }

    use foo::Bar<|>;

    fn qux(bar: Bar, baz: Baz) {}
    ",
        )
    }
}
<commit_msg>Simplify `find_mod_path` with use of `node.ancestors`<commit_after>use hir::{MacroDef, ModuleDef, Name, PathResolution, ScopeDef, SemanticsScope};
use ra_ide_db::{
    defs::{classify_name_ref, Definition, NameRefClass},
    RootDatabase,
};
use ra_syntax::{ast, match_ast, AstNode, SyntaxNode, SyntaxToken, T};

use crate::{
    assist_context::{AssistBuilder, AssistContext, Assists},
    AssistId, AssistKind,
};

// Assist: expand_glob_import
//
// Expands glob imports.
//
// ```
// mod foo {
//     pub struct Bar;
//     pub struct Baz;
// }
//
// use foo::*<|>;
//
// fn qux(bar: Bar, baz: Baz) {}
// ```
// ->
// ```
// mod foo {
//     pub struct Bar;
//     pub struct Baz;
// }
//
// use foo::{Baz, Bar};
//
// fn qux(bar: Bar, baz: Baz) {}
// ```
pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let star = ctx.find_token_at_offset(T![*])?;
    let mod_path = find_mod_path(&star)?;

    let source_file = ctx.source_file();
    let scope = ctx.sema.scope_at_offset(source_file.syntax(), ctx.offset());

    let defs_in_mod = find_defs_in_mod(ctx, scope, &mod_path)?;
    let name_refs_in_source_file =
        source_file.syntax().descendants().filter_map(ast::NameRef::cast).collect();
    let used_names = find_used_names(ctx, defs_in_mod, name_refs_in_source_file);

    let parent = star.parent().parent()?;
    acc.add(
        AssistId("expand_glob_import", AssistKind::RefactorRewrite),
        "Expand glob import",
        parent.text_range(),
        |builder| {
            replace_ast(builder, &parent, mod_path, used_names);
        },
    )
}

fn find_mod_path(star: &SyntaxToken) -> Option<ast::Path> {
    star.ancestors().find_map(|n| ast::UseTree::cast(n).and_then(|u| u.path()))
}

#[derive(PartialEq)]
enum Def {
    ModuleDef(ModuleDef),
    MacroDef(MacroDef),
}

impl Def {
    fn name(&self, db: &RootDatabase) -> Option<Name> {
        match self {
            Def::ModuleDef(def) => def.name(db),
            Def::MacroDef(def) => def.name(db),
        }
    }
}

fn find_defs_in_mod(
    ctx: &AssistContext,
    from: SemanticsScope<'_>,
    path: &ast::Path,
) -> Option<Vec<Def>> {
    let hir_path = ctx.sema.lower_path(&path)?;
    let module = if let Some(PathResolution::Def(ModuleDef::Module(module))) =
        from.resolve_hir_path_qualifier(&hir_path)
    {
        module
    } else {
        return None;
    };

    let module_scope = module.scope(ctx.db(), from.module());

    let mut defs = vec![];
    for (_, def) in module_scope {
        match def {
            ScopeDef::ModuleDef(def) => defs.push(Def::ModuleDef(def)),
            ScopeDef::MacroDef(def) => defs.push(Def::MacroDef(def)),
            _ => continue,
        }
    }

    Some(defs)
}

fn find_used_names(
    ctx: &AssistContext,
    defs_in_mod: Vec<Def>,
    name_refs_in_source_file: Vec<ast::NameRef>,
) -> Vec<Name> {
    let defs_in_source_file = name_refs_in_source_file
        .iter()
        .filter_map(|r| classify_name_ref(&ctx.sema, r))
        .filter_map(|rc| match rc {
            NameRefClass::Definition(Definition::ModuleDef(def)) => Some(Def::ModuleDef(def)),
            NameRefClass::Definition(Definition::Macro(def)) => Some(Def::MacroDef(def)),
            _ => None,
        })
        .collect::<Vec<Def>>();

    defs_in_mod
        .iter()
        .filter(|d| defs_in_source_file.contains(d))
        .filter_map(|d| d.name(ctx.db()))
        .collect()
}

fn replace_ast(
    builder: &mut AssistBuilder,
    node: &SyntaxNode,
    path: ast::Path,
    used_names: Vec<Name>,
) {
    let new_use_tree_list = ast::make::use_tree_list(used_names.iter().map(|n| {
        ast::make::use_tree(ast::make::path_from_text(&n.to_string()), None, None, false)
    }));

    match_ast! {
        match node {
            ast::UseTree(use_tree) => {
                builder.replace_ast(use_tree, make_use_tree(path, new_use_tree_list));
            },
            ast::UseTreeList(use_tree_list) => {
                builder.replace_ast(use_tree_list, new_use_tree_list);
            },
            ast::Use(use_item) => {
                builder.replace_ast(use_item, ast::make::use_item(make_use_tree(path, new_use_tree_list)));
            },
            _ => {},
        }
    }

    fn make_use_tree(path: ast::Path, use_tree_list: ast::UseTreeList) -> ast::UseTree {
        ast::make::use_tree(path, Some(use_tree_list), None, false)
    }
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    #[test]
    fn expanding_glob_import() {
        check_assist(
            expand_glob_import,
            r"
mod foo {
    pub struct Bar;
    pub struct Baz;
    pub struct Qux;

    pub fn f() {}
}

use foo::*<|>;

fn qux(bar: Bar, baz: Baz) {
    f();
}
",
            r"
mod foo {
    pub struct Bar;
    pub struct Baz;
    pub struct Qux;

    pub fn f() {}
}

use foo::{Baz, Bar, f};

fn qux(bar: Bar, baz: Baz) {
    f();
}
",
        )
    }

    #[test]
    fn expanding_glob_import_with_existing_explicit_names() {
        check_assist(
            expand_glob_import,
            r"
mod foo {
    pub struct Bar;
    pub struct Baz;
    pub struct Qux;

    pub fn f() {}
}

use foo::{*<|>, f};

fn qux(bar: Bar, baz: Baz) {
    f();
}
",
            r"
mod foo {
    pub struct Bar;
    pub struct Baz;
    pub struct Qux;

    pub fn f() {}
}

use foo::{Baz, Bar, f};

fn qux(bar: Bar, baz: Baz) {
    f();
}
",
        )
    }

    #[test]
    fn expanding_nested_glob_import() {
        check_assist(
            expand_glob_import,
            r"
mod foo {
    mod bar {
        pub struct Bar;
        pub struct Baz;
        pub struct Qux;

        pub fn f() {}
    }

    mod baz {
        pub fn g() {}
    }
}

use foo::{bar::{*<|>, f}, baz::*};

fn qux(bar: Bar, baz: Baz) {
    f();
    g();
}
",
            r"
mod foo {
    mod bar {
        pub struct Bar;
        pub struct Baz;
        pub struct Qux;

        pub fn f() {}
    }

    mod baz {
        pub fn g() {}
    }
}

use foo::{bar::{Baz, Bar, f}, baz::*};

fn qux(bar: Bar, baz: Baz) {
    f();
    g();
}
",
        )
    }

    #[test]
    fn expanding_glob_import_with_macro_defs() {
        check_assist(
            expand_glob_import,
            r"
//- /lib.rs crate:foo
#[macro_export]
macro_rules! bar {
    () => ()
}

pub fn baz() {}

//- /main.rs crate:main deps:foo
use foo::*<|>;

fn main() {
    bar!();
    baz();
}
",
            r"
use foo::{bar, baz};

fn main() {
    bar!();
    baz();
}
",
        )
    }

    #[test]
    fn expanding_is_not_applicable_if_cursor_is_not_in_star_token() {
        check_assist_not_applicable(
            expand_glob_import,
            r"
    mod foo {
        pub struct Bar;
        pub struct Baz;
        pub struct Qux;
    }

    use foo::Bar<|>;

    fn qux(bar: Bar, baz: Baz) {}
    ",
        )
    }
}
<|endoftext|>


<commit_before>use std::cmp;

use card;
use types;
use calculator::utility;

pub fn test(cards: Vec<card::Card>) -> Option<types::Combination> {
  if cards.len() < 3 {
    return None;
  }

  let hash_map = utility::get_count_hash_map(&cards[..]);

  let mut largest_set: Option<types::Rank> = None;

  for (&rank_value, &count) in &hash_map {
    if count == 3 {
      // if count == 4 we have a four of a kind, do not consider this.
      if let Some(current_set_rank) = largest_set {
        largest_set = Some(cmp::max(current_set_rank, rank_value));
      } else {
        largest_set = Some(rank_value);
      }
    }
  }

  if let Some(current_set_rank) = largest_set {
    return Some(types::Combination::ThreeOfAKind(current_set_rank));
  }

  None
}
<commit_msg>add tests for three of a kind<commit_after>use std::cmp;

use card::Card;
use types;
use calculator::utility;

pub fn test(cards: Vec<Card>) -> Option<types::Combination> {
  if cards.len() < 3 {
    return None;
  }

  let hash_map = utility::get_count_hash_map(&cards[..]);

  let mut largest_set: Option<types::Rank> = None;

  for (&rank_value, &count) in &hash_map {
    if count == 3 {
      // if count == 4 we have a four of a kind, do not consider this.
      if let Some(current_set_rank) = largest_set {
        largest_set = Some(cmp::max(current_set_rank, rank_value));
      } else {
        largest_set = Some(rank_value);
      }
    }
  }

  if let Some(current_set_rank) = largest_set {
    return Some(types::Combination::ThreeOfAKind(current_set_rank));
  }

  None
}
#[cfg(test)]
mod tests {
  use super::*;

  #[test]
  fn none_for_empty() {
    assert_eq!(None, test(vec![]));
  }

  #[test]
  fn none_for_seven_cards_without_three_of_a_kind() {
    assert_eq!(
      None,
      test(vec![
        Card {
          rank: types::Rank::Four,
          suit: types::Suit::Spades,
        },
        Card {
          rank: types::Rank::Two,
          suit: types::Suit::Hearts,
        },
        Card {
          rank: types::Rank::Six,
          suit: types::Suit::Spades,
        },
        Card {
          rank: types::Rank::Two,
          suit: types::Suit::Hearts,
        },
        Card {
          rank: types::Rank::King,
          suit: types::Suit::Clubs,
        },
        Card {
          rank: types::Rank::Ace,
          suit: types::Suit::Diamonds,
        },
        Card {
          rank: types::Rank::Ace,
          suit: types::Suit::Hearts,
        },
      ])
    );
  }

  #[test]
  fn none_for_seven_cards_with_four_of_a_kind() {
    // because of impl specifics
    assert_eq!(
      None,
      test(vec![
        Card {
          rank: types::Rank::Four,
          suit: types::Suit::Spades,
        },
        Card {
          rank: types::Rank::Two,
          suit: types::Suit::Hearts,
        },
        Card {
          rank: types::Rank::Six,
          suit: types::Suit::Spades,
        },
        Card {
          rank: types::Rank::Four,
          suit: types::Suit::Hearts,
        },
        Card {
          rank: types::Rank::Four,
          suit: types::Suit::Clubs,
        },
        Card {
          rank: types::Rank::Four,
          suit: types::Suit::Diamonds,
        },
        Card {
          rank: types::Rank::Ace,
          suit: types::Suit::Hearts,
        },
      ])
    );
  }

  #[test]
  fn option_for_seven_cards_with_three_of_a_kind() {
    // because of impl specifics
    assert_eq!(
      Some(types::Combination::ThreeOfAKind(types::Rank::Four)),
      test(vec![
        Card {
          rank: types::Rank::Jack,
          suit: types::Suit::Spades,
        },
        Card {
          rank: types::Rank::Two,
          suit: types::Suit::Hearts,
        },
        Card {
          rank: types::Rank::Six,
          suit: types::Suit::Spades,
        },
        Card {
          rank: types::Rank::Four,
          suit: types::Suit::Hearts,
        },
        Card {
          rank: types::Rank::Four,
          suit: types::Suit::Clubs,
        },
        Card {
          rank: types::Rank::Four,
          suit: types::Suit::Diamonds,
        },
        Card {
          rank: types::Rank::Ace,
          suit: types::Suit::Hearts,
        },
      ])
    );
  }

  #[test]
  fn option_for_seven_cards_chooses_highest_with_three_of_a_kind() {
    // because of impl specifics
    assert_eq!(
      Some(types::Combination::ThreeOfAKind(types::Rank::Jack)),
      test(vec![
        Card {
          rank: types::Rank::Four,
          suit: types::Suit::Spades,
        },
        Card {
          rank: types::Rank::Four,
          suit: types::Suit::Hearts,
        },
        Card {
          rank: types::Rank::Jack,
          suit: types::Suit::Spades,
        },
        Card {
          rank: types::Rank::Four,
          suit: types::Suit::Hearts,
        },
        Card {
          rank: types::Rank::Ace,
          suit: types::Suit::Clubs,
        },
        Card {
          rank: types::Rank::Jack,
          suit: types::Suit::Diamonds,
        },
        Card {
          rank: types::Rank::Jack,
          suit: types::Suit::Hearts,
        },
      ])
    );
  }
}
<|endoftext|>


<commit_before>#![allow(unstable)]
extern crate num;
extern crate rustfft;

use num::complex::Complex;
use std::rand;
use std::rand::distributions::{Normal, IndependentSample};
use rustfft::{FFT, dft};

fn compare_vectors(vec1: &[Complex<f32>], vec2: &[Complex<f32>]) -> bool {
    let mut sse = 0f32;
    for (&a, &b) in vec1.iter().zip(vec2.iter()) {
        sse = sse + (a - b).norm();
    }
    return (sse / vec1.len() as f32) < 0.1f32;
}

fn test_dft_correct(signal: &[Complex<f32>], spectrum: &[Complex<f32>]) -> bool {
    assert_eq!(signal.len(), spectrum.len());
    let mut fft = FFT::new(signal.len());
    let mut test_spectrum = signal.to_vec();
    fft.process(signal, test_spectrum.as_mut_slice());
    println!("our spectrum: {:?}", test_spectrum);
    println!("yes spectrum: {:?}", spectrum);
    return compare_vectors(spectrum, test_spectrum.as_slice());
}

/*
    Tests against some known signal <-> spectrum relationships.
*/
#[test]
fn dft_test() {

    let signal = vec![Complex{re: 1f32, im: 0f32},
                      Complex{re:-1f32, im: 0f32}];
    let spectrum = vec![Complex{re: 0f32, im: 0f32},
                        Complex{re: 2f32, im: 0f32}];
    assert!(test_dft_correct(signal.as_slice(), spectrum.as_slice()));

    let signal = vec![Complex{re: 1f32, im: 1f32},
                      Complex{re: 2f32, im:-3f32},
                      Complex{re:-1f32, im: 4f32}];
    let spectrum = vec![Complex{re: 2f32, im: 2f32},
                        Complex{re: -5.562177f32, im: -2.098076f32},
                        Complex{re: 6.562178f32, im: 3.09807f32}];
    assert!(test_dft_correct(signal.as_slice(), spectrum.as_slice()));

    let signal = vec![Complex{re: 1f32, im: 1f32},
                      Complex{re: 2f32, im: 2f32},
                      Complex{re: 3f32, im: 3f32},
                      Complex{re: 4f32, im: 4f32},
                      Complex{re: 5f32, im: 5f32},
                      Complex{re: 6f32, im: 6f32}];
    let spectrum = vec![Complex{re: 21f32, im: 21f32},
                        Complex{re: -8.16f32, im: 2.16f32},
                        Complex{re: -4.76f32, im: -1.24f32},
                        Complex{re: -3f32, im: -3f32},
                        Complex{re: -1.24f32, im: -4.76f32},
                        Complex{re: 2.16f32, im: -8.16f32}];
    assert!(test_dft_correct(signal.as_slice(), spectrum.as_slice()));

    let signal = vec![Complex{re: 0f32, im: 1f32},
                      Complex{re: 2.5f32, im:-3f32},
                      Complex{re:-1f32, im: -1f32},
                      Complex{re: 4f32, im: 0f32}];
    let spectrum = vec![Complex{re: 5.5f32, im: -3f32},
                        Complex{re: -2f32, im: 3.5f32},
                        Complex{re: -7.5f32, im: 3f32},
                        Complex{re: 4f32, im: 0.5f32}];
    assert!(test_dft_correct(signal.as_slice(), spectrum.as_slice()));

}

fn ct_matches_dft(signal: &[Complex<f32>]) -> bool {
    let mut spectrum_dft = signal.to_vec();
    let mut spectrum_ct = signal.to_vec();
    dft(signal.iter(), spectrum_dft.iter_mut());
    test_dft_correct(signal, spectrum_dft.as_slice())
}

fn random_signal(length: usize) -> Vec<Complex<f32>> {
    let mut sig = Vec::with_capacity(length);
    let normal_dist = Normal::new(0.0, 10.0);
    let mut rng = rand::thread_rng();
    for _ in range(0, length)
    {
        sig.push(Complex{re: (normal_dist.ind_sample(&mut rng) as f32),
                         im: (normal_dist.ind_sample(&mut rng) as f32)});
    }
    return sig;
}

#[test]
fn test_cooley_tukey() {
    for len in range(2us, 100) {
        let signal = random_signal(len);
        assert!(ct_matches_dft(signal.as_slice()), "length = {}", len);
    }
}
<commit_msg>Use a const seed for deterministic randomness. Fixes #14<commit_after>#![allow(unstable)]
extern crate num;
extern crate rustfft;

use num::complex::Complex;
use std::rand::{StdRng, SeedableRng};
use std::rand::distributions::{Normal, IndependentSample};
use rustfft::{FFT, dft};

/// The seed for the random number generator used to generate
/// random signals. It's defined here so that we have deterministic
/// tests
const RNG_SEED: [usize; 5] = [1910, 11431, 4984, 14828, 12226];

fn compare_vectors(vec1: &[Complex<f32>], vec2: &[Complex<f32>]) -> bool {
    let mut sse = 0f32;
    for (&a, &b) in vec1.iter().zip(vec2.iter()) {
        sse = sse + (a - b).norm();
    }
    return (sse / vec1.len() as f32) < 0.1f32;
}

fn test_dft_correct(signal: &[Complex<f32>], spectrum: &[Complex<f32>]) -> bool {
    assert_eq!(signal.len(), spectrum.len());
    let mut fft = FFT::new(signal.len());
    let mut test_spectrum = signal.to_vec();
    fft.process(signal, test_spectrum.as_mut_slice());
    println!("our spectrum: {:?}", test_spectrum);
    println!("yes spectrum: {:?}", spectrum);
    return compare_vectors(spectrum, test_spectrum.as_slice());
}

/*
    Tests against some known signal <-> spectrum relationships.
*/
#[test]
fn dft_test() {

    let signal = vec![Complex{re: 1f32, im: 0f32},
                      Complex{re:-1f32, im: 0f32}];
    let spectrum = vec![Complex{re: 0f32, im: 0f32},
                        Complex{re: 2f32, im: 0f32}];
    assert!(test_dft_correct(signal.as_slice(), spectrum.as_slice()));

    let signal = vec![Complex{re: 1f32, im: 1f32},
                      Complex{re: 2f32, im:-3f32},
                      Complex{re:-1f32, im: 4f32}];
    let spectrum = vec![Complex{re: 2f32, im: 2f32},
                        Complex{re: -5.562177f32, im: -2.098076f32},
                        Complex{re: 6.562178f32, im: 3.09807f32}];
    assert!(test_dft_correct(signal.as_slice(), spectrum.as_slice()));

    let signal = vec![Complex{re: 1f32, im: 1f32},
                      Complex{re: 2f32, im: 2f32},
                      Complex{re: 3f32, im: 3f32},
                      Complex{re: 4f32, im: 4f32},
                      Complex{re: 5f32, im: 5f32},
                      Complex{re: 6f32, im: 6f32}];
    let spectrum = vec![Complex{re: 21f32, im: 21f32},
                        Complex{re: -8.16f32, im: 2.16f32},
                        Complex{re: -4.76f32, im: -1.24f32},
                        Complex{re: -3f32, im: -3f32},
                        Complex{re: -1.24f32, im: -4.76f32},
                        Complex{re: 2.16f32, im: -8.16f32}];
    assert!(test_dft_correct(signal.as_slice(), spectrum.as_slice()));

    let signal = vec![Complex{re: 0f32, im: 1f32},
                      Complex{re: 2.5f32, im:-3f32},
                      Complex{re:-1f32, im: -1f32},
                      Complex{re: 4f32, im: 0f32}];
    let spectrum = vec![Complex{re: 5.5f32, im: -3f32},
                        Complex{re: -2f32, im: 3.5f32},
                        Complex{re: -7.5f32, im: 3f32},
                        Complex{re: 4f32, im: 0.5f32}];
    assert!(test_dft_correct(signal.as_slice(), spectrum.as_slice()));

}

fn ct_matches_dft(signal: &[Complex<f32>]) -> bool {
    let mut spectrum_dft = signal.to_vec();
    let mut spectrum_ct = signal.to_vec();
    dft(signal.iter(), spectrum_dft.iter_mut());
    test_dft_correct(signal, spectrum_dft.as_slice())
}

fn random_signal(length: usize) -> Vec<Complex<f32>> {
    let mut sig = Vec::with_capacity(length);
    let normal_dist = Normal::new(0.0, 10.0);
    let mut rng: StdRng = SeedableRng::from_seed(RNG_SEED.as_slice());
    for _ in range(0, length) {
        sig.push(Complex{re: (normal_dist.ind_sample(&mut rng) as f32),
                         im: (normal_dist.ind_sample(&mut rng) as f32)});
    }
    return sig;
}

#[test]
fn test_cooley_tukey() {
    for len in range(2us, 100) {
        let signal = random_signal(len);
        assert!(ct_matches_dft(signal.as_slice()), "length = {}", len);
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 tokio-jsonrpc Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://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.

extern crate tokio_jsonrpc;
extern crate tokio_core;
extern crate futures;
#[macro_use]
extern crate serde_json;

use std::time::Duration;
use std::io::{Error as IoError, ErrorKind};

use tokio_jsonrpc::{Endpoint, LineCodec, Server, ServerCtl, ServerError};

use futures::{Future, Stream};
use tokio_core::reactor::{Core, Timeout};
use tokio_core::net::{TcpListener, TcpStream};
use tokio_core::io::{Io, Framed};
use serde_json::Value;

struct AnswerServer;

/// A test server
///
/// It expects no parameters and the method to be `"test"` and returns 42 on RPC. It expects
/// `"notif"` as a notification. Both `rpc` and `notification` terminate the server.
impl Server for AnswerServer {
    type Success = u32;
    type RPCCallResult = Result<u32, ServerError>;
    type NotificationResult = Result<(), ()>;
    fn rpc(&self, ctl: &ServerCtl, method: &str, params: &Option<Value>) -> Option<Self::RPCCallResult> {
        ctl.terminate();
        assert_eq!(method, "test");
        assert!(params.is_none());
        Some(Ok(42))
    }
    fn notification(&self, ctl: &ServerCtl, method: &str, params: &Option<Value>) -> Option<Self::NotificationResult> {
        ctl.terminate();
        assert_eq!(method, "notif");
        assert!(params.is_none());
        Some(Ok(()))
    }
}

/// Set up a client and a server
///
/// Create a reactor, set a safety timeout (if the test doesn't finish in 15 seconds, panic) and
/// provide two connected TCP streams. We could use unix socket pair, but that wouldn't work on
/// windows, so we just connect on 127.0.0.1.
fn prepare() -> (Core, Framed<TcpStream, LineCodec>, Framed<TcpStream, LineCodec>) {
    let mut reactor = Core::new().unwrap();
    let handle = reactor.handle();
    // Kill the test if it gets stuck
    let timeout = Timeout::new(Duration::new(15, 0), &handle)
        .unwrap()
        .then(|_| -> Result<(), ()> {
            panic!("Timeout happened")
        });
    handle.spawn(timeout);
    // Build two connected TCP streams
    let listener = TcpListener::bind(&"127.0.0.1:0".parse().unwrap(), &handle).unwrap();
    let address = listener.local_addr().unwrap();
    let server_finished = listener.incoming()
        .into_future()
        .then(|result| match result {
            Ok((result, _incoming)) => Ok(result.unwrap().0),
            Err((err, _incoming)) => Err(err),
        });
    let client_finished = TcpStream::connect(&address, &handle);
    // Wait for both of them to be connected
    let (s1, s2) = reactor.run(server_finished.join(client_finished))
        .unwrap();
    // And return everything
    (reactor, s1.framed(LineCodec::new()), s2.framed(LineCodec::new()))
}

/// Single RPC call
///
/// Run both the server and client, send a request and wait for the answer. The server terminates
/// after the first request, so we can wait for both to terminate.
#[test]
fn rpc_answer() {
    let (mut reactor, s1, s2) = prepare();
    let both = {
        // Run in a sub-block, so we drop all the clients, etc.
        let handle = reactor.handle();
        let (_client, _ctl, server_finished) = Endpoint::new(s1, AnswerServer).start(&handle);
        let (client, _ctl, _finished) = Endpoint::client_only(s2).start(&handle);
        let client_finished = client.call("test".to_owned(), None, None)
            .and_then(|(_client, answered)| answered)
            .map(|response| assert_eq!(json!(42), response.unwrap().result.unwrap()));
        let both = server_finished.map_err(|_| IoError::new(ErrorKind::Other, "Canceled"))
            .join(client_finished)
            .map(|_| ())
            .map_err(|e| panic!("{:?}", e));
        both
    };
    reactor.run(both).unwrap();
}

/// Send a notification to the server.
#[test]
fn notification() {
    let (mut reactor, s1, s2) = prepare();
    let both = {
        // Run in a sub-block, so we drop all the clients, etc.
        let handle = reactor.handle();
        let (_client, _ctl, server_finished) = Endpoint::new(s1, AnswerServer).start(&handle);
        let (client, _ctl, _finished) = Endpoint::client_only(s2).start(&handle);
        let client_finished = client.notify("notif".to_owned(), None)
            .and_then(|_client| Ok(()));
        let both = server_finished.map_err(|_| IoError::new(ErrorKind::Other, "Canceled"))
            .join(client_finished)
            .map(|_| ())
            .map_err(|e| panic!("{:?}", e));
        both
    };
    reactor.run(both).unwrap();
}
<commit_msg>Style cleanups<commit_after>// Copyright 2017 tokio-jsonrpc Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://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.

extern crate tokio_jsonrpc;
extern crate tokio_core;
extern crate futures;
#[macro_use]
extern crate serde_json;

use std::time::Duration;
use std::io::{Error as IoError, ErrorKind};

use tokio_jsonrpc::{Endpoint, LineCodec, Server, ServerCtl, ServerError};

use futures::{Future, Stream};
use tokio_core::reactor::{Core, Timeout};
use tokio_core::net::{TcpListener, TcpStream};
use tokio_core::io::{Io, Framed};
use serde_json::Value;

struct AnswerServer;

/// A test server
///
/// It expects no parameters and the method to be `"test"` and returns 42 on RPC. It expects
/// `"notif"` as a notification. Both `rpc` and `notification` terminate the server.
impl Server for AnswerServer {
    type Success = u32;
    type RPCCallResult = Result<u32, ServerError>;
    type NotificationResult = Result<(), ()>;
    fn rpc(&self, ctl: &ServerCtl, method: &str, params: &Option<Value>) -> Option<Self::RPCCallResult> {
        ctl.terminate();
        assert_eq!(method, "test");
        assert!(params.is_none());
        Some(Ok(42))
    }
    fn notification(&self, ctl: &ServerCtl, method: &str, params: &Option<Value>) -> Option<Self::NotificationResult> {
        ctl.terminate();
        assert_eq!(method, "notif");
        assert!(params.is_none());
        Some(Ok(()))
    }
}

/// Set up a client and a server
///
/// Create a reactor, set a safety timeout (if the test doesn't finish in 15 seconds, panic) and
/// provide two connected TCP streams. We could use unix socket pair, but that wouldn't work on
/// windows, so we just connect on 127.0.0.1.
fn prepare() -> (Core, Framed<TcpStream, LineCodec>, Framed<TcpStream, LineCodec>) {
    let mut reactor = Core::new().unwrap();
    let handle = reactor.handle();
    // Kill the test if it gets stuck
    let timeout = Timeout::new(Duration::new(15, 0), &handle)
        .unwrap()
        .then(|_| -> Result<(), ()> { panic!("Timeout happened") });
    handle.spawn(timeout);
    // Build two connected TCP streams
    let listener = TcpListener::bind(&"127.0.0.1:0".parse().unwrap(), &handle).unwrap();
    let address = listener.local_addr().unwrap();
    let server_finished = listener.incoming()
        .into_future()
        .then(|result| match result {
            Ok((result, _incoming)) => Ok(result.unwrap().0),
            Err((err, _incoming)) => Err(err),
        });
    let client_finished = TcpStream::connect(&address, &handle);
    // Wait for both of them to be connected
    let (s1, s2) = reactor.run(server_finished.join(client_finished))
        .unwrap();
    // And return everything
    (reactor, s1.framed(LineCodec::new()), s2.framed(LineCodec::new()))
}

/// Single RPC call
///
/// Run both the server and client, send a request and wait for the answer. The server terminates
/// after the first request, so we can wait for both to terminate.
#[test]
fn rpc_answer() {
    let (mut reactor, s1, s2) = prepare();
    let both = {
        // Run in a sub-block, so we drop all the clients, etc.
        let handle = reactor.handle();
        let (_client, _ctl, server_finished) = Endpoint::new(s1, AnswerServer).start(&handle);
        let (client, _ctl, _finished) = Endpoint::client_only(s2).start(&handle);
        let client_finished = client.call("test".to_owned(), None, None)
            .and_then(|(_client, answered)| answered)
            .map(|response| assert_eq!(json!(42), response.unwrap().result.unwrap()));
        server_finished.map_err(|_| IoError::new(ErrorKind::Other, "Canceled"))
            .join(client_finished)
            .map(|_| ())
            .map_err(|e| panic!("{:?}", e))
    };
    reactor.run(both).unwrap();
}

/// Send a notification to the server.
#[test]
fn notification() {
    let (mut reactor, s1, s2) = prepare();
    let both = {
        // Run in a sub-block, so we drop all the clients, etc.
        let handle = reactor.handle();
        let (_client, _ctl, server_finished) = Endpoint::new(s1, AnswerServer).start(&handle);
        let (client, _ctl, _finished) = Endpoint::client_only(s2).start(&handle);
        let client_finished = client.notify("notif".to_owned(), None)
            .and_then(|_client| Ok(()));
        server_finished.map_err(|_| IoError::new(ErrorKind::Other, "Canceled"))
            .join(client_finished)
            .map(|_| ())
            .map_err(|e| panic!("{:?}", e))
    };
    reactor.run(both).unwrap();
}
<|endoftext|>


<commit_before>// (c) 2017 Productize SPRL <joost@productize.be>

extern crate symbolic_expressions;
#[macro_use]
extern crate error_chain;

mod error {
    use symbolic_expressions;

    error_chain! {

        links {
            SymbolicExpression(symbolic_expressions::Error, symbolic_expressions::ErrorKind) #[doc = "symbolic expression library error"];
        }
    }
}

use error::*;
use symbolic_expressions::iteratom::*;

fn test_int() -> Result<()> {
    let s = "(a (b c) (d 42))";
    let s= symbolic_expressions::parser::parse_str(s)?;
    let mut i = IterAtom::new(&s, "a")?;
    let c = i.s_in_list("b")?;
    assert_eq!(&c, "c");
    let e = i.maybe_i_in_list("d").unwrap();
    assert_eq!(e, 42);
    Ok(())
}

#[test]
fn test_iteratom() {
    test_int().unwrap();
}
<commit_msg>test that error handling works when used from other lib<commit_after>// (c) 2017 Productize SPRL <joost@productize.be>

extern crate symbolic_expressions;
#[macro_use]
extern crate error_chain;

mod error {
    use symbolic_expressions;

    error_chain! {

        links {
            SymbolicExpression(symbolic_expressions::Error, symbolic_expressions::ErrorKind) #[doc = "symbolic expression library error"];
        }
    }
}

use error::*;
use symbolic_expressions::iteratom::*;
use symbolic_expressions::Sexp;
use symbolic_expressions::Result as SResult;

struct Qq(i64);

impl FromSexp for Qq {
    fn from_sexp(s:&Sexp) -> SResult<Self> {
        let i = s.named_value_i("d")?;
        Ok(Qq(i))
    }
}

fn test_int() -> Result<()> {
    let s = "(a (b c) (d 42))";
    let s= symbolic_expressions::parser::parse_str(s)?;
    let mut i = IterAtom::new(&s, "a")?;
    let c = i.s_in_list("b")?;
    assert_eq!(&c, "c");
    let e:Qq = i.t("d")?;
    assert_eq!(e.0, 42);
    Ok(())
}

#[test]
fn test_iteratom() {
    test_int().unwrap();
}
<|endoftext|>