<commit_before>extern crate bus;

use std::sync::mpsc;
use std::time;

#[test]
fn it_works() {
    let mut c = bus::Bus::new(10);
    let mut r1 = c.add_rx();
    let mut r2 = c.add_rx();
    assert_eq!(c.try_broadcast(true), Ok(()));
    assert_eq!(r1.try_recv(), Ok(true));
    assert_eq!(r2.try_recv(), Ok(true));
}

#[test]
fn it_fails_when_full() {
    let mut c = bus::Bus::new(1);
    let r1 = c.add_rx();
    assert_eq!(c.try_broadcast(true), Ok(()));
    assert_eq!(c.try_broadcast(false), Err(false));
    drop(r1);
}

#[test]
fn it_succeeds_when_not_full() {
    let mut c = bus::Bus::new(1);
    let mut r1 = c.add_rx();
    assert_eq!(c.try_broadcast(true), Ok(()));
    assert_eq!(c.try_broadcast(false), Err(false));
    assert_eq!(r1.try_recv(), Ok(true));
    assert_eq!(c.try_broadcast(true), Ok(()));
}

#[test]
fn it_fails_when_empty() {
    let mut c = bus::Bus::<bool>::new(10);
    let mut r1 = c.add_rx();
    assert_eq!(r1.try_recv(), Err(mpsc::TryRecvError::Empty));
}

#[test]
fn it_reads_when_full() {
    let mut c = bus::Bus::new(1);
    let mut r1 = c.add_rx();
    assert_eq!(c.try_broadcast(true), Ok(()));
    assert_eq!(r1.try_recv(), Ok(true));
}

#[test]
fn it_iterates() {
    use std::thread;

    let mut tx = bus::Bus::new(2);
    let mut rx = tx.add_rx();
    let j = thread::spawn(move || {
        for i in 0..1_000 {
            tx.broadcast(i);
        }
    });

    let mut ii = 0;
    for i in rx.iter() {
        assert_eq!(i, ii);
        ii += 1;
    }

    j.join().unwrap();
    assert_eq!(ii, 1_000);
    assert_eq!(rx.try_recv(), Err(mpsc::TryRecvError::Disconnected));
}

#[test]
fn aggressive_iteration() {
    for _ in 0..10_000 {
        use std::thread;

        let mut tx = bus::Bus::new(2);
        let mut rx = tx.add_rx();
        let j = thread::spawn(move || {
            for i in 0..1_000 {
                tx.broadcast(i);
            }
        });

        let mut ii = 0;
        for i in rx.iter() {
            assert_eq!(i, ii);
            ii += 1;
        }

        j.join().unwrap();
        assert_eq!(ii, 1_000);
        assert_eq!(rx.try_recv(), Err(mpsc::TryRecvError::Disconnected));
    }
}

#[test]
fn it_detects_closure() {
    let mut tx = bus::Bus::new(1);
    let mut rx = tx.add_rx();
    assert_eq!(tx.try_broadcast(true), Ok(()));
    assert_eq!(rx.try_recv(), Ok(true));
    assert_eq!(rx.try_recv(), Err(mpsc::TryRecvError::Empty));
    drop(tx);
    assert_eq!(rx.try_recv(), Err(mpsc::TryRecvError::Disconnected));
}

#[test]
fn it_recvs_after_close() {
    let mut tx = bus::Bus::new(1);
    let mut rx = tx.add_rx();
    assert_eq!(tx.try_broadcast(true), Ok(()));
    drop(tx);
    assert_eq!(rx.try_recv(), Ok(true));
    assert_eq!(rx.try_recv(), Err(mpsc::TryRecvError::Disconnected));
}

#[test]
fn it_handles_leaves() {
    let mut c = bus::Bus::new(1);
    let mut r1 = c.add_rx();
    let r2 = c.add_rx();
    assert_eq!(c.try_broadcast(true), Ok(()));
    drop(r2);
    assert_eq!(r1.try_recv(), Ok(true));
    assert_eq!(c.try_broadcast(true), Ok(()));
}

#[test]
fn it_runs_blocked_writes() {
    use std::thread;

    let mut c = Box::new(bus::Bus::new(1));
    let mut r1 = c.add_rx();
    c.broadcast(true); // this is fine

    // buffer is now full
    assert_eq!(c.try_broadcast(false), Err(false));
    // start other thread that blocks
    let c = thread::spawn(move || {
        c.broadcast(false);
    });
    // unblock sender by receiving
    assert_eq!(r1.try_recv(), Ok(true));
    // drop r1 to release other thread and safely drop c
    drop(r1);
    c.join().unwrap();
}

#[test]
fn it_runs_blocked_reads() {
    use std::sync::mpsc;
    use std::thread;

    let mut tx = Box::new(bus::Bus::new(1));
    let mut rx = tx.add_rx();
    // buffer is now empty
    assert_eq!(rx.try_recv(), Err(mpsc::TryRecvError::Empty));
    // start other thread that blocks
    let c = thread::spawn(move || {
        rx.recv().unwrap();
    });
    // unblock receiver by broadcasting
    tx.broadcast(true);
    // check that thread now finished
    c.join().unwrap();
}

#[test]
fn it_can_count_to_10000() {
    use std::thread;

    let mut c = bus::Bus::new(2);
    let mut r1 = c.add_rx();
    let j = thread::spawn(move || {
        for i in 0..10_000 {
            c.broadcast(i);
        }
    });

    for i in 0..10_000 {
        assert_eq!(r1.recv(), Ok(i));
    }

    j.join().unwrap();
    assert_eq!(r1.try_recv(), Err(mpsc::TryRecvError::Disconnected));
}

#[test]
fn test_busy() {
    use std::thread;

    // start a bus with limited space
    let mut bus = bus::Bus::new(1);

    // first receiver only receives 5 items
    let mut rx1 = bus.add_rx();
    let t1 = thread::spawn(move || {
        for _ in 0..5 {
            rx1.recv().unwrap();
        }
        drop(rx1);
    });

    // second receiver receives 10 items
    let mut rx2 = bus.add_rx();
    let t2 = thread::spawn(move || {
        for _ in 0..10 {
            rx2.recv().unwrap();
        }
        drop(rx2);
    });

    // let receivers start
    std::thread::sleep(time::Duration::from_millis(500));

    // try to send 25 items -- should work fine
    for i in 0..25 {
        std::thread::sleep(time::Duration::from_millis(100));
        match bus.try_broadcast(i) {
            Ok(_) => (),
            Err(e) => println!("Broadcast failed {}", e),
        }
    }

    // done sending -- wait for receivers (which should already be done)
    t1.join().unwrap();
    t2.join().unwrap();
    assert!(true);
}
<commit_msg>Make aggressive test run in sane time<commit_after>extern crate bus;

use std::sync::mpsc;
use std::time;

#[test]
fn it_works() {
    let mut c = bus::Bus::new(10);
    let mut r1 = c.add_rx();
    let mut r2 = c.add_rx();
    assert_eq!(c.try_broadcast(true), Ok(()));
    assert_eq!(r1.try_recv(), Ok(true));
    assert_eq!(r2.try_recv(), Ok(true));
}

#[test]
fn it_fails_when_full() {
    let mut c = bus::Bus::new(1);
    let r1 = c.add_rx();
    assert_eq!(c.try_broadcast(true), Ok(()));
    assert_eq!(c.try_broadcast(false), Err(false));
    drop(r1);
}

#[test]
fn it_succeeds_when_not_full() {
    let mut c = bus::Bus::new(1);
    let mut r1 = c.add_rx();
    assert_eq!(c.try_broadcast(true), Ok(()));
    assert_eq!(c.try_broadcast(false), Err(false));
    assert_eq!(r1.try_recv(), Ok(true));
    assert_eq!(c.try_broadcast(true), Ok(()));
}

#[test]
fn it_fails_when_empty() {
    let mut c = bus::Bus::<bool>::new(10);
    let mut r1 = c.add_rx();
    assert_eq!(r1.try_recv(), Err(mpsc::TryRecvError::Empty));
}

#[test]
fn it_reads_when_full() {
    let mut c = bus::Bus::new(1);
    let mut r1 = c.add_rx();
    assert_eq!(c.try_broadcast(true), Ok(()));
    assert_eq!(r1.try_recv(), Ok(true));
}

#[test]
fn it_iterates() {
    use std::thread;

    let mut tx = bus::Bus::new(2);
    let mut rx = tx.add_rx();
    let j = thread::spawn(move || {
        for i in 0..1_000 {
            tx.broadcast(i);
        }
    });

    let mut ii = 0;
    for i in rx.iter() {
        assert_eq!(i, ii);
        ii += 1;
    }

    j.join().unwrap();
    assert_eq!(ii, 1_000);
    assert_eq!(rx.try_recv(), Err(mpsc::TryRecvError::Disconnected));
}

#[test]
fn aggressive_iteration() {
    for _ in 0..1_000 {
        use std::thread;

        let mut tx = bus::Bus::new(2);
        let mut rx = tx.add_rx();
        let j = thread::spawn(move || {
            for i in 0..1_000 {
                tx.broadcast(i);
            }
        });

        let mut ii = 0;
        for i in rx.iter() {
            assert_eq!(i, ii);
            ii += 1;
        }

        j.join().unwrap();
        assert_eq!(ii, 1_000);
        assert_eq!(rx.try_recv(), Err(mpsc::TryRecvError::Disconnected));
    }
}

#[test]
fn it_detects_closure() {
    let mut tx = bus::Bus::new(1);
    let mut rx = tx.add_rx();
    assert_eq!(tx.try_broadcast(true), Ok(()));
    assert_eq!(rx.try_recv(), Ok(true));
    assert_eq!(rx.try_recv(), Err(mpsc::TryRecvError::Empty));
    drop(tx);
    assert_eq!(rx.try_recv(), Err(mpsc::TryRecvError::Disconnected));
}

#[test]
fn it_recvs_after_close() {
    let mut tx = bus::Bus::new(1);
    let mut rx = tx.add_rx();
    assert_eq!(tx.try_broadcast(true), Ok(()));
    drop(tx);
    assert_eq!(rx.try_recv(), Ok(true));
    assert_eq!(rx.try_recv(), Err(mpsc::TryRecvError::Disconnected));
}

#[test]
fn it_handles_leaves() {
    let mut c = bus::Bus::new(1);
    let mut r1 = c.add_rx();
    let r2 = c.add_rx();
    assert_eq!(c.try_broadcast(true), Ok(()));
    drop(r2);
    assert_eq!(r1.try_recv(), Ok(true));
    assert_eq!(c.try_broadcast(true), Ok(()));
}

#[test]
fn it_runs_blocked_writes() {
    use std::thread;

    let mut c = Box::new(bus::Bus::new(1));
    let mut r1 = c.add_rx();
    c.broadcast(true); // this is fine

    // buffer is now full
    assert_eq!(c.try_broadcast(false), Err(false));
    // start other thread that blocks
    let c = thread::spawn(move || {
        c.broadcast(false);
    });
    // unblock sender by receiving
    assert_eq!(r1.try_recv(), Ok(true));
    // drop r1 to release other thread and safely drop c
    drop(r1);
    c.join().unwrap();
}

#[test]
fn it_runs_blocked_reads() {
    use std::sync::mpsc;
    use std::thread;

    let mut tx = Box::new(bus::Bus::new(1));
    let mut rx = tx.add_rx();
    // buffer is now empty
    assert_eq!(rx.try_recv(), Err(mpsc::TryRecvError::Empty));
    // start other thread that blocks
    let c = thread::spawn(move || {
        rx.recv().unwrap();
    });
    // unblock receiver by broadcasting
    tx.broadcast(true);
    // check that thread now finished
    c.join().unwrap();
}

#[test]
fn it_can_count_to_10000() {
    use std::thread;

    let mut c = bus::Bus::new(2);
    let mut r1 = c.add_rx();
    let j = thread::spawn(move || {
        for i in 0..10_000 {
            c.broadcast(i);
        }
    });

    for i in 0..10_000 {
        assert_eq!(r1.recv(), Ok(i));
    }

    j.join().unwrap();
    assert_eq!(r1.try_recv(), Err(mpsc::TryRecvError::Disconnected));
}

#[test]
fn test_busy() {
    use std::thread;

    // start a bus with limited space
    let mut bus = bus::Bus::new(1);

    // first receiver only receives 5 items
    let mut rx1 = bus.add_rx();
    let t1 = thread::spawn(move || {
        for _ in 0..5 {
            rx1.recv().unwrap();
        }
        drop(rx1);
    });

    // second receiver receives 10 items
    let mut rx2 = bus.add_rx();
    let t2 = thread::spawn(move || {
        for _ in 0..10 {
            rx2.recv().unwrap();
        }
        drop(rx2);
    });

    // let receivers start
    std::thread::sleep(time::Duration::from_millis(500));

    // try to send 25 items -- should work fine
    for i in 0..25 {
        std::thread::sleep(time::Duration::from_millis(100));
        match bus.try_broadcast(i) {
            Ok(_) => (),
            Err(e) => println!("Broadcast failed {}", e),
        }
    }

    // done sending -- wait for receivers (which should already be done)
    t1.join().unwrap();
    t2.join().unwrap();
    assert!(true);
}
<|endoftext|>


<commit_before>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use anyhow::{anyhow, Result};
use std::{collections::BTreeMap, str::FromStr};
use structopt::StructOpt;

use bytecode::function_target_pipeline::{FunctionVariant, VerificationFlavor};
use move_model::ast::SpecBlockTarget;

mod ast_print;
mod workflow;

// spec simplification pass
mod exp_inlining;
mod exp_trimming;

use ast_print::SpecPrinter;
use workflow::WorkflowOptions;

/// List of simplification passes available
#[derive(Clone, Debug)]
pub enum SimplificationPass {
    Inline,
    TrimAbortsIf,
}

impl FromStr for SimplificationPass {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let r = match s {
            "inline" => SimplificationPass::Inline,
            "trim_aborts_if" => SimplificationPass::TrimAbortsIf,
            _ => return Err(s.to_string()),
        };
        Ok(r)
    }
}

/// Options passed into the specification flattening tool.
#[derive(StructOpt, Clone)]
pub struct FlattenOptions {
    /// Options common and shared by the proving workflow and all passes
    #[structopt(flatten)]
    pub workflow: WorkflowOptions,

    /// Simplification processing pipeline
    #[structopt(short, long)]
    pub pipeline: Vec<SimplificationPass>,

    /// Dump stepwise result
    #[structopt(long)]
    pub dump: bool,
}

//**************************************************************************************************
// Entrypoint
//**************************************************************************************************

pub fn run(options: &FlattenOptions) -> Result<()> {
    let workflow_options = &options.workflow;
    let (env, targets) = workflow::prepare(workflow_options)?;

    // make sure the original verification works
    let proved = workflow::prove(workflow_options, &env, &targets)?;
    if !proved {
        return Err(anyhow!("Original proof is not successful"));
    }

    // flatten spec in target modules
    let mut simplified_specs = BTreeMap::new();
    for (fun_id, variant) in targets.get_funs_and_variants() {
        if !matches!(
            variant,
            FunctionVariant::Verification(VerificationFlavor::Regular)
        ) {
            // only care for functions that have the regular verification variant
            continue;
        }

        let fun_env = env.get_function(fun_id);
        if !fun_env.module_env.is_target() {
            // only run on specs in target module
            continue;
        }
        match &workflow_options.target {
            None => {
                if !fun_env.has_unknown_callers() {
                    // only run on specs for external-facing functions
                    continue;
                }
            }
            Some(target) => {
                if fun_env.get_simple_name_string().as_ref() != target {
                    // only run on matched function name
                    continue;
                }
            }
        }

        // get a copy of the original spec
        let fun_target = targets.get_target(&fun_env, &variant);
        let mut fun_spec = Some(fun_target.get_spec().clone());

        // prepare for stepwise result printing
        let fun_scope = SpecBlockTarget::Function(fun_id.module_id, fun_id.id);
        let printer = SpecPrinter::new(&env, &fun_scope);
        if options.dump {
            println!(
                "================ fun {} ================",
                fun_env.get_full_name_str()
            );
        }

        // pass the spec through the simplification pipeline
        for (i, pass) in options.pipeline.iter().enumerate() {
            let target = fun_target.clone();
            let old_spec = fun_spec.take().unwrap();
            let new_spec = match pass {
                SimplificationPass::Inline => {
                    exp_inlining::inline_all_exp_in_spec(workflow_options, target, old_spec)
                }
                SimplificationPass::TrimAbortsIf => {
                    exp_trimming::trim_aborts_ifs(workflow_options, target, old_spec)
                }
            }?;

            // dump stepwise results if requested
            if options.dump {
                println!("step {} - {:?} {{", i, pass);
                for cond in &new_spec.conditions {
                    println!("\t{}", SpecPrinter::convert(printer.print_condition(cond)));
                }
                println!("}}");
            }

            fun_spec = Some(new_spec);
        }

        simplified_specs.insert(fun_id, fun_spec.unwrap());
    }

    // dump the final result
    for (fun_id, spec) in simplified_specs {
        let fun_env = env.get_function(fun_id);
        let fun_scope = SpecBlockTarget::Function(fun_id.module_id, fun_id.id);
        let printer = SpecPrinter::new(&env, &fun_scope);
        if !spec.conditions.is_empty() {
            println!("fun {}{{", fun_env.get_full_name_str());
            for cond in &spec.conditions {
                println!("\t{}", SpecPrinter::convert(printer.print_condition(cond)));
            }
            println!("}}");
        }
    }

    // everything is OK
    Ok(())
}
<commit_msg>[move-prover][spec-flatten] add an option to use ExpDisplay for debug<commit_after>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use anyhow::{anyhow, Result};
use std::{collections::BTreeMap, str::FromStr};
use structopt::StructOpt;

use bytecode::function_target_pipeline::{FunctionVariant, VerificationFlavor};
use move_model::ast::SpecBlockTarget;

mod ast_print;
mod workflow;

// spec simplification pass
mod exp_inlining;
mod exp_trimming;

use ast_print::SpecPrinter;
use workflow::WorkflowOptions;

/// List of simplification passes available
#[derive(Clone, Debug)]
pub enum SimplificationPass {
    Inline,
    TrimAbortsIf,
}

impl FromStr for SimplificationPass {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let r = match s {
            "inline" => SimplificationPass::Inline,
            "trim_aborts_if" => SimplificationPass::TrimAbortsIf,
            _ => return Err(s.to_string()),
        };
        Ok(r)
    }
}

/// Options passed into the specification flattening tool.
#[derive(StructOpt, Clone)]
pub struct FlattenOptions {
    /// Options common and shared by the proving workflow and all passes
    #[structopt(flatten)]
    pub workflow: WorkflowOptions,

    /// Simplification processing pipeline
    #[structopt(short, long)]
    pub pipeline: Vec<SimplificationPass>,

    /// Dump stepwise result
    #[structopt(long = "dump-stepwise")]
    pub dump_stepwise: bool,

    /// Dump stepwise result in raw exp printing format
    #[structopt(long = "dump-stepwise-raw", requires = "dump-stepwise")]
    pub dump_stepwise_raw: bool,
}

//**************************************************************************************************
// Entrypoint
//**************************************************************************************************

pub fn run(options: &FlattenOptions) -> Result<()> {
    let workflow_options = &options.workflow;
    let (env, targets) = workflow::prepare(workflow_options)?;

    // make sure the original verification works
    let proved = workflow::prove(workflow_options, &env, &targets)?;
    if !proved {
        return Err(anyhow!("Original proof is not successful"));
    }

    // flatten spec in target modules
    let mut simplified_specs = BTreeMap::new();
    for (fun_id, variant) in targets.get_funs_and_variants() {
        if !matches!(
            variant,
            FunctionVariant::Verification(VerificationFlavor::Regular)
        ) {
            // only care for functions that have the regular verification variant
            continue;
        }

        let fun_env = env.get_function(fun_id);
        if !fun_env.module_env.is_target() {
            // only run on specs in target module
            continue;
        }
        match &workflow_options.target {
            None => {
                if !fun_env.has_unknown_callers() {
                    // only run on specs for external-facing functions
                    continue;
                }
            }
            Some(target) => {
                if fun_env.get_simple_name_string().as_ref() != target {
                    // only run on matched function name
                    continue;
                }
            }
        }

        // get a copy of the original spec
        let fun_target = targets.get_target(&fun_env, &variant);
        let mut fun_spec = Some(fun_target.get_spec().clone());

        // prepare for stepwise result printing
        let fun_scope = SpecBlockTarget::Function(fun_id.module_id, fun_id.id);
        let printer = SpecPrinter::new(&env, &fun_scope);
        if options.dump_stepwise {
            println!(
                "================ fun {} ================",
                fun_env.get_full_name_str()
            );
        }

        // pass the spec through the simplification pipeline
        for (i, pass) in options.pipeline.iter().enumerate() {
            let target = fun_target.clone();
            let old_spec = fun_spec.take().unwrap();
            let new_spec = match pass {
                SimplificationPass::Inline => {
                    exp_inlining::inline_all_exp_in_spec(workflow_options, target, old_spec)
                }
                SimplificationPass::TrimAbortsIf => {
                    exp_trimming::trim_aborts_ifs(workflow_options, target, old_spec)
                }
            }?;

            // dump stepwise results if requested
            if options.dump_stepwise {
                println!("step {} - {:?} {{", i, pass);
                for cond in &new_spec.conditions {
                    if options.dump_stepwise_raw {
                        println!("\t{:?} {}", cond.kind, cond.exp.display(&env));
                    } else {
                        println!("\t{}", SpecPrinter::convert(printer.print_condition(cond)));
                    }
                }
                println!("}}");
            }

            fun_spec = Some(new_spec);
        }

        simplified_specs.insert(fun_id, fun_spec.unwrap());
    }

    // dump the final result
    for (fun_id, spec) in simplified_specs {
        let fun_env = env.get_function(fun_id);
        let fun_scope = SpecBlockTarget::Function(fun_id.module_id, fun_id.id);
        let printer = SpecPrinter::new(&env, &fun_scope);
        if !spec.conditions.is_empty() {
            println!("fun {}{{", fun_env.get_full_name_str());
            for cond in &spec.conditions {
                println!("\t{}", SpecPrinter::convert(printer.print_condition(cond)));
            }
            println!("}}");
        }
    }

    // everything is OK
    Ok(())
}
<|endoftext|>


<commit_before>//! `AstTransformer`s are functions that replace nodes in an AST and can be easily combined.
use rustc_hash::FxHashMap;

use hir::{HirDisplay, PathResolution, SemanticsScope};
use ra_ide_db::RootDatabase;
use ra_syntax::{
    algo::SyntaxRewriter,
    ast::{self, AstNode},
};

pub trait AstTransform<'a> {
    fn get_substitution(&self, node: &ra_syntax::SyntaxNode) -> Option<ra_syntax::SyntaxNode>;

    fn chain_before(self, other: Box<dyn AstTransform<'a> + 'a>) -> Box<dyn AstTransform<'a> + 'a>;
    fn or<T: AstTransform<'a> + 'a>(self, other: T) -> Box<dyn AstTransform<'a> + 'a>
    where
        Self: Sized + 'a,
    {
        self.chain_before(Box::new(other))
    }
}

struct NullTransformer;

impl<'a> AstTransform<'a> for NullTransformer {
    fn get_substitution(&self, _node: &ra_syntax::SyntaxNode) -> Option<ra_syntax::SyntaxNode> {
        None
    }
    fn chain_before(self, other: Box<dyn AstTransform<'a> + 'a>) -> Box<dyn AstTransform<'a> + 'a> {
        other
    }
}

pub struct SubstituteTypeParams<'a> {
    source_scope: &'a SemanticsScope<'a, RootDatabase>,
    substs: FxHashMap<hir::TypeParam, ast::TypeRef>,
    previous: Box<dyn AstTransform<'a> + 'a>,
}

impl<'a> SubstituteTypeParams<'a> {
    pub fn for_trait_impl(
        source_scope: &'a SemanticsScope<'a, RootDatabase>,
        // FIXME: there's implicit invariant that `trait_` and  `source_scope` match...
        trait_: hir::Trait,
        impl_def: ast::ImplDef,
    ) -> SubstituteTypeParams<'a> {
        let substs = get_syntactic_substs(impl_def).unwrap_or_default();
        let generic_def: hir::GenericDef = trait_.into();
        let substs_by_param: FxHashMap<_, _> = generic_def
            .params(source_scope.db)
            .into_iter()
            // this is a trait impl, so we need to skip the first type parameter -- this is a bit hacky
            .skip(1)
            // The actual list of trait type parameters may be longer than the one
            // used in the `impl` block due to trailing default type parametrs.
            // For that case we extend the `substs` with an empty iterator so we
            // can still hit those trailing values and check if they actually have
            // a default type. If they do, go for that type from `hir` to `ast` so
            // the resulting change can be applied correctly.
            .zip(substs.into_iter().map(Some).chain(std::iter::repeat(None)))
            .filter_map(|(k, v)| match v {
                Some(v) => Some((k, v)),
                None => {
                    let default = k.default(source_scope.db)?;
                    Some((
                        k,
                        ast::make::type_ref(
                            &default
                                .display_source_code(source_scope.db, source_scope.module()?.into())
                                .ok()?,
                        )
                    ))
                }
            })
            .collect();
        return SubstituteTypeParams {
            source_scope,
            substs: substs_by_param,
            previous: Box::new(NullTransformer),
        };

        // FIXME: It would probably be nicer if we could get this via HIR (i.e. get the
        // trait ref, and then go from the types in the substs back to the syntax)
        fn get_syntactic_substs(impl_def: ast::ImplDef) -> Option<Vec<ast::TypeRef>> {
            let target_trait = impl_def.target_trait()?;
            let path_type = match target_trait {
                ast::TypeRef::PathType(path) => path,
                _ => return None,
            };
            let type_arg_list = path_type.path()?.segment()?.type_arg_list()?;
            let mut result = Vec::new();
            for type_arg in type_arg_list.type_args() {
                let type_arg: ast::TypeArg = type_arg;
                result.push(type_arg.type_ref()?);
            }
            Some(result)
        }
    }
    fn get_substitution_inner(
        &self,
        node: &ra_syntax::SyntaxNode,
    ) -> Option<ra_syntax::SyntaxNode> {
        let type_ref = ast::TypeRef::cast(node.clone())?;
        let path = match &type_ref {
            ast::TypeRef::PathType(path_type) => path_type.path()?,
            _ => return None,
        };
        // FIXME: use `hir::Path::from_src` instead.
        let path = hir::Path::from_ast(path)?;
        let resolution = self.source_scope.resolve_hir_path(&path)?;
        match resolution {
            hir::PathResolution::TypeParam(tp) => Some(self.substs.get(&tp)?.syntax().clone()),
            _ => None,
        }
    }
}

impl<'a> AstTransform<'a> for SubstituteTypeParams<'a> {
    fn get_substitution(&self, node: &ra_syntax::SyntaxNode) -> Option<ra_syntax::SyntaxNode> {
        self.get_substitution_inner(node).or_else(|| self.previous.get_substitution(node))
    }
    fn chain_before(self, other: Box<dyn AstTransform<'a> + 'a>) -> Box<dyn AstTransform<'a> + 'a> {
        Box::new(SubstituteTypeParams { previous: other, ..self })
    }
}

pub struct QualifyPaths<'a> {
    target_scope: &'a SemanticsScope<'a, RootDatabase>,
    source_scope: &'a SemanticsScope<'a, RootDatabase>,
    previous: Box<dyn AstTransform<'a> + 'a>,
}

impl<'a> QualifyPaths<'a> {
    pub fn new(
        target_scope: &'a SemanticsScope<'a, RootDatabase>,
        source_scope: &'a SemanticsScope<'a, RootDatabase>,
    ) -> Self {
        Self { target_scope, source_scope, previous: Box::new(NullTransformer) }
    }

    fn get_substitution_inner(
        &self,
        node: &ra_syntax::SyntaxNode,
    ) -> Option<ra_syntax::SyntaxNode> {
        // FIXME handle value ns?
        let from = self.target_scope.module()?;
        let p = ast::Path::cast(node.clone())?;
        if p.segment().and_then(|s| s.param_list()).is_some() {
            // don't try to qualify `Fn(Foo) -> Bar` paths, they are in prelude anyway
            return None;
        }
        // FIXME: use `hir::Path::from_src` instead.
        let hir_path = hir::Path::from_ast(p.clone());
        let resolution = self.source_scope.resolve_hir_path(&hir_path?)?;
        match resolution {
            PathResolution::Def(def) => {
                let found_path = from.find_use_path(self.source_scope.db, def)?;
                let mut path = path_to_ast(found_path);

                let type_args = p
                    .segment()
                    .and_then(|s| s.type_arg_list())
                    .map(|arg_list| apply(self, arg_list));
                if let Some(type_args) = type_args {
                    let last_segment = path.segment().unwrap();
                    path = path.with_segment(last_segment.with_type_args(type_args))
                }

                Some(path.syntax().clone())
            }
            PathResolution::Local(_)
            | PathResolution::TypeParam(_)
            | PathResolution::SelfType(_) => None,
            PathResolution::Macro(_) => None,
            PathResolution::AssocItem(_) => None,
        }
    }
}

pub fn apply<'a, N: AstNode>(transformer: &dyn AstTransform<'a>, node: N) -> N {
    SyntaxRewriter::from_fn(|element| match element {
        ra_syntax::SyntaxElement::Node(n) => {
            let replacement = transformer.get_substitution(&n)?;
            Some(replacement.into())
        }
        _ => None,
    })
    .rewrite_ast(&node)
}

impl<'a> AstTransform<'a> for QualifyPaths<'a> {
    fn get_substitution(&self, node: &ra_syntax::SyntaxNode) -> Option<ra_syntax::SyntaxNode> {
        self.get_substitution_inner(node).or_else(|| self.previous.get_substitution(node))
    }
    fn chain_before(self, other: Box<dyn AstTransform<'a> + 'a>) -> Box<dyn AstTransform<'a> + 'a> {
        Box::new(QualifyPaths { previous: other, ..self })
    }
}

pub(crate) fn path_to_ast(path: hir::ModPath) -> ast::Path {
    let parse = ast::SourceFile::parse(&path.to_string());
    parse
        .tree()
        .syntax()
        .descendants()
        .find_map(ast::Path::cast)
        .unwrap_or_else(|| panic!("failed to parse path {:?}, `{}`", path, path))
}
<commit_msg>Fix formatting<commit_after>//! `AstTransformer`s are functions that replace nodes in an AST and can be easily combined.
use rustc_hash::FxHashMap;

use hir::{HirDisplay, PathResolution, SemanticsScope};
use ra_ide_db::RootDatabase;
use ra_syntax::{
    algo::SyntaxRewriter,
    ast::{self, AstNode},
};

pub trait AstTransform<'a> {
    fn get_substitution(&self, node: &ra_syntax::SyntaxNode) -> Option<ra_syntax::SyntaxNode>;

    fn chain_before(self, other: Box<dyn AstTransform<'a> + 'a>) -> Box<dyn AstTransform<'a> + 'a>;
    fn or<T: AstTransform<'a> + 'a>(self, other: T) -> Box<dyn AstTransform<'a> + 'a>
    where
        Self: Sized + 'a,
    {
        self.chain_before(Box::new(other))
    }
}

struct NullTransformer;

impl<'a> AstTransform<'a> for NullTransformer {
    fn get_substitution(&self, _node: &ra_syntax::SyntaxNode) -> Option<ra_syntax::SyntaxNode> {
        None
    }
    fn chain_before(self, other: Box<dyn AstTransform<'a> + 'a>) -> Box<dyn AstTransform<'a> + 'a> {
        other
    }
}

pub struct SubstituteTypeParams<'a> {
    source_scope: &'a SemanticsScope<'a, RootDatabase>,
    substs: FxHashMap<hir::TypeParam, ast::TypeRef>,
    previous: Box<dyn AstTransform<'a> + 'a>,
}

impl<'a> SubstituteTypeParams<'a> {
    pub fn for_trait_impl(
        source_scope: &'a SemanticsScope<'a, RootDatabase>,
        // FIXME: there's implicit invariant that `trait_` and  `source_scope` match...
        trait_: hir::Trait,
        impl_def: ast::ImplDef,
    ) -> SubstituteTypeParams<'a> {
        let substs = get_syntactic_substs(impl_def).unwrap_or_default();
        let generic_def: hir::GenericDef = trait_.into();
        let substs_by_param: FxHashMap<_, _> = generic_def
            .params(source_scope.db)
            .into_iter()
            // this is a trait impl, so we need to skip the first type parameter -- this is a bit hacky
            .skip(1)
            // The actual list of trait type parameters may be longer than the one
            // used in the `impl` block due to trailing default type parametrs.
            // For that case we extend the `substs` with an empty iterator so we
            // can still hit those trailing values and check if they actually have
            // a default type. If they do, go for that type from `hir` to `ast` so
            // the resulting change can be applied correctly.
            .zip(substs.into_iter().map(Some).chain(std::iter::repeat(None)))
            .filter_map(|(k, v)| match v {
                Some(v) => Some((k, v)),
                None => {
                    let default = k.default(source_scope.db)?;
                    Some((
                        k,
                        ast::make::type_ref(
                            &default
                                .display_source_code(source_scope.db, source_scope.module()?.into())
                                .ok()?,
                        ),
                    ))
                }
            })
            .collect();
        return SubstituteTypeParams {
            source_scope,
            substs: substs_by_param,
            previous: Box::new(NullTransformer),
        };

        // FIXME: It would probably be nicer if we could get this via HIR (i.e. get the
        // trait ref, and then go from the types in the substs back to the syntax)
        fn get_syntactic_substs(impl_def: ast::ImplDef) -> Option<Vec<ast::TypeRef>> {
            let target_trait = impl_def.target_trait()?;
            let path_type = match target_trait {
                ast::TypeRef::PathType(path) => path,
                _ => return None,
            };
            let type_arg_list = path_type.path()?.segment()?.type_arg_list()?;
            let mut result = Vec::new();
            for type_arg in type_arg_list.type_args() {
                let type_arg: ast::TypeArg = type_arg;
                result.push(type_arg.type_ref()?);
            }
            Some(result)
        }
    }
    fn get_substitution_inner(
        &self,
        node: &ra_syntax::SyntaxNode,
    ) -> Option<ra_syntax::SyntaxNode> {
        let type_ref = ast::TypeRef::cast(node.clone())?;
        let path = match &type_ref {
            ast::TypeRef::PathType(path_type) => path_type.path()?,
            _ => return None,
        };
        // FIXME: use `hir::Path::from_src` instead.
        let path = hir::Path::from_ast(path)?;
        let resolution = self.source_scope.resolve_hir_path(&path)?;
        match resolution {
            hir::PathResolution::TypeParam(tp) => Some(self.substs.get(&tp)?.syntax().clone()),
            _ => None,
        }
    }
}

impl<'a> AstTransform<'a> for SubstituteTypeParams<'a> {
    fn get_substitution(&self, node: &ra_syntax::SyntaxNode) -> Option<ra_syntax::SyntaxNode> {
        self.get_substitution_inner(node).or_else(|| self.previous.get_substitution(node))
    }
    fn chain_before(self, other: Box<dyn AstTransform<'a> + 'a>) -> Box<dyn AstTransform<'a> + 'a> {
        Box::new(SubstituteTypeParams { previous: other, ..self })
    }
}

pub struct QualifyPaths<'a> {
    target_scope: &'a SemanticsScope<'a, RootDatabase>,
    source_scope: &'a SemanticsScope<'a, RootDatabase>,
    previous: Box<dyn AstTransform<'a> + 'a>,
}

impl<'a> QualifyPaths<'a> {
    pub fn new(
        target_scope: &'a SemanticsScope<'a, RootDatabase>,
        source_scope: &'a SemanticsScope<'a, RootDatabase>,
    ) -> Self {
        Self { target_scope, source_scope, previous: Box::new(NullTransformer) }
    }

    fn get_substitution_inner(
        &self,
        node: &ra_syntax::SyntaxNode,
    ) -> Option<ra_syntax::SyntaxNode> {
        // FIXME handle value ns?
        let from = self.target_scope.module()?;
        let p = ast::Path::cast(node.clone())?;
        if p.segment().and_then(|s| s.param_list()).is_some() {
            // don't try to qualify `Fn(Foo) -> Bar` paths, they are in prelude anyway
            return None;
        }
        // FIXME: use `hir::Path::from_src` instead.
        let hir_path = hir::Path::from_ast(p.clone());
        let resolution = self.source_scope.resolve_hir_path(&hir_path?)?;
        match resolution {
            PathResolution::Def(def) => {
                let found_path = from.find_use_path(self.source_scope.db, def)?;
                let mut path = path_to_ast(found_path);

                let type_args = p
                    .segment()
                    .and_then(|s| s.type_arg_list())
                    .map(|arg_list| apply(self, arg_list));
                if let Some(type_args) = type_args {
                    let last_segment = path.segment().unwrap();
                    path = path.with_segment(last_segment.with_type_args(type_args))
                }

                Some(path.syntax().clone())
            }
            PathResolution::Local(_)
            | PathResolution::TypeParam(_)
            | PathResolution::SelfType(_) => None,
            PathResolution::Macro(_) => None,
            PathResolution::AssocItem(_) => None,
        }
    }
}

pub fn apply<'a, N: AstNode>(transformer: &dyn AstTransform<'a>, node: N) -> N {
    SyntaxRewriter::from_fn(|element| match element {
        ra_syntax::SyntaxElement::Node(n) => {
            let replacement = transformer.get_substitution(&n)?;
            Some(replacement.into())
        }
        _ => None,
    })
    .rewrite_ast(&node)
}

impl<'a> AstTransform<'a> for QualifyPaths<'a> {
    fn get_substitution(&self, node: &ra_syntax::SyntaxNode) -> Option<ra_syntax::SyntaxNode> {
        self.get_substitution_inner(node).or_else(|| self.previous.get_substitution(node))
    }
    fn chain_before(self, other: Box<dyn AstTransform<'a> + 'a>) -> Box<dyn AstTransform<'a> + 'a> {
        Box::new(QualifyPaths { previous: other, ..self })
    }
}

pub(crate) fn path_to_ast(path: hir::ModPath) -> ast::Path {
    let parse = ast::SourceFile::parse(&path.to_string());
    parse
        .tree()
        .syntax()
        .descendants()
        .find_map(ast::Path::cast)
        .unwrap_or_else(|| panic!("failed to parse path {:?}, `{}`", path, path))
}
<|endoftext|>


<commit_before>macro_rules! unimpl {
    () => (return Err(io::Error::new(io::ErrorKind::Other, "No networking available on L4Re."));)
}

pub mod net {
    #![allow(warnings)]
    use crate::fmt;
    use crate::io::{self, IoVec, IoVecMut};
    use crate::net::{SocketAddr, Shutdown, Ipv4Addr, Ipv6Addr};
    use crate::sys_common::{AsInner, FromInner, IntoInner};
    use crate::sys::fd::FileDesc;
    use crate::time::Duration;
    use crate::convert::TryFrom;

    #[allow(unused_extern_crates)]
    pub extern crate libc as netc;

    pub struct Socket(FileDesc);
    impl Socket {
        pub fn new(_: &SocketAddr, _: libc::c_int) -> io::Result<Socket> {
            unimpl!();
        }

        pub fn new_raw(_: libc::c_int, _: libc::c_int) -> io::Result<Socket> {
            unimpl!();
        }

        pub fn new_pair(_: libc::c_int, _: libc::c_int) -> io::Result<(Socket, Socket)> {
            unimpl!();
        }

        pub fn connect_timeout(&self, _: &SocketAddr, _: Duration) -> io::Result<()> {
            unimpl!();
        }

        pub fn accept(&self, _: *mut libc::sockaddr, _: *mut libc::socklen_t)
                  -> io::Result<Socket> {
            unimpl!();
        }

        pub fn duplicate(&self) -> io::Result<Socket> {
            unimpl!();
        }

        pub fn read(&self, _: &mut [u8]) -> io::Result<usize> {
            unimpl!();
        }

        pub fn read_vectored(&self, _: &mut [IoVecMut<'_>]) -> io::Result<usize> {
            unimpl!();
        }

        pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
            unimpl!();
        }

        pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
            unimpl!();
        }

        pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
            unimpl!();
        }

        pub fn write(&self, _: &[u8]) -> io::Result<usize> {
            unimpl!();
        }

        pub fn write_vectored(&self, _: &[IoVec<'_>]) -> io::Result<usize> {
            unimpl!();
        }

        pub fn set_timeout(&self, _: Option<Duration>, _: libc::c_int) -> io::Result<()> {
            unimpl!();
        }

        pub fn timeout(&self, _: libc::c_int) -> io::Result<Option<Duration>> {
            unimpl!();
        }

        pub fn shutdown(&self, _: Shutdown) -> io::Result<()> {
            unimpl!();
        }

        pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
            unimpl!();
        }

        pub fn nodelay(&self) -> io::Result<bool> {
            unimpl!();
        }

        pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
            unimpl!();
        }

        pub fn take_error(&self) -> io::Result<Option<io::Error>> {
            unimpl!();
        }
    }

    impl AsInner<libc::c_int> for Socket {
        fn as_inner(&self) -> &libc::c_int { self.0.as_inner() }
    }

    impl FromInner<libc::c_int> for Socket {
        fn from_inner(fd: libc::c_int) -> Socket { Socket(FileDesc::new(fd)) }
    }

    impl IntoInner<libc::c_int> for Socket {
        fn into_inner(self) -> libc::c_int { self.0.into_raw() }
    }

    pub struct TcpStream {
        inner: Socket,
    }

    impl TcpStream {
        pub fn connect(_: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
            unimpl!();
        }

        pub fn connect_timeout(_: &SocketAddr, _: Duration) -> io::Result<TcpStream> {
            unimpl!();
        }

        pub fn socket(&self) -> &Socket { &self.inner }

        pub fn into_socket(self) -> Socket { self.inner }

        pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
            unimpl!();
        }

        pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
            unimpl!();
        }

        pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
            unimpl!();
        }

        pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
            unimpl!();
        }

        pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
            unimpl!();
        }

        pub fn read(&self, _: &mut [u8]) -> io::Result<usize> {
            unimpl!();
        }

        pub fn read_vectored(&self, _: &mut [IoVecMut<'_>]) -> io::Result<usize> {
            unimpl!();
        }

        pub fn write(&self, _: &[u8]) -> io::Result<usize> {
            unimpl!();
        }

        pub fn write_vectored(&self, _: &[IoVec<'_>]) -> io::Result<usize> {
            unimpl!();
        }

        pub fn peer_addr(&self) -> io::Result<SocketAddr> {
            unimpl!();
        }

        pub fn socket_addr(&self) -> io::Result<SocketAddr> {
            unimpl!();
        }

        pub fn shutdown(&self, _: Shutdown) -> io::Result<()> {
            unimpl!();
        }

        pub fn duplicate(&self) -> io::Result<TcpStream> {
            unimpl!();
        }

        pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
            unimpl!();
        }

        pub fn nodelay(&self) -> io::Result<bool> {
            unimpl!();
        }

        pub fn set_ttl(&self, _: u32) -> io::Result<()> {
            unimpl!();
        }

        pub fn ttl(&self) -> io::Result<u32> {
            unimpl!();
        }

        pub fn take_error(&self) -> io::Result<Option<io::Error>> {
            unimpl!();
        }

        pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
            unimpl!();
        }
    }

    impl FromInner<Socket> for TcpStream {
        fn from_inner(socket: Socket) -> TcpStream {
            TcpStream { inner: socket }
        }
    }

    impl fmt::Debug for TcpStream {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "No networking support available on L4Re")
        }
    }

    pub struct TcpListener {
        inner: Socket,
    }

    impl TcpListener {
        pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
            unimpl!();
        }

        pub fn socket(&self) -> &Socket { &self.inner }

        pub fn into_socket(self) -> Socket { self.inner }

        pub fn socket_addr(&self) -> io::Result<SocketAddr> {
            unimpl!();
        }

        pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
            unimpl!();
        }

        pub fn duplicate(&self) -> io::Result<TcpListener> {
            unimpl!();
        }

        pub fn set_ttl(&self, _: u32) -> io::Result<()> {
            unimpl!();
        }

        pub fn ttl(&self) -> io::Result<u32> {
            unimpl!();
        }

        pub fn set_only_v6(&self, _: bool) -> io::Result<()> {
            unimpl!();
        }

        pub fn only_v6(&self) -> io::Result<bool> {
            unimpl!();
        }

        pub fn take_error(&self) -> io::Result<Option<io::Error>> {
            unimpl!();
        }

        pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
            unimpl!();
        }
    }

    impl FromInner<Socket> for TcpListener {
        fn from_inner(socket: Socket) -> TcpListener {
            TcpListener { inner: socket }
        }
    }

    impl fmt::Debug for TcpListener {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "No networking support available on L4Re.")
        }
    }

    pub struct UdpSocket {
        inner: Socket,
    }

    impl UdpSocket {
        pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
            unimpl!();
        }

        pub fn socket(&self) -> &Socket { &self.inner }

        pub fn into_socket(self) -> Socket { self.inner }

        pub fn socket_addr(&self) -> io::Result<SocketAddr> {
            unimpl!();
        }

        pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
            unimpl!();
        }

        pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
            unimpl!();
        }

        pub fn send_to(&self, _: &[u8], _: &SocketAddr) -> io::Result<usize> {
            unimpl!();
        }

        pub fn duplicate(&self) -> io::Result<UdpSocket> {
            unimpl!();
        }

        pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
            unimpl!();
        }

        pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
            unimpl!();
        }

        pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
            unimpl!();
        }

        pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
            unimpl!();
        }

        pub fn set_broadcast(&self, _: bool) -> io::Result<()> {
            unimpl!();
        }

        pub fn broadcast(&self) -> io::Result<bool> {
            unimpl!();
        }

        pub fn set_multicast_loop_v4(&self, _: bool) -> io::Result<()> {
            unimpl!();
        }

        pub fn multicast_loop_v4(&self) -> io::Result<bool> {
            unimpl!();
        }

        pub fn set_multicast_ttl_v4(&self, _: u32) -> io::Result<()> {
            unimpl!();
        }

        pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
            unimpl!();
        }

        pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> {
            unimpl!();
        }

        pub fn multicast_loop_v6(&self) -> io::Result<bool> {
            unimpl!();
        }

        pub fn join_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr)
                             -> io::Result<()> {
                                 unimpl!();
        }

        pub fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32)
                             -> io::Result<()> {
                                 unimpl!();
        }

        pub fn leave_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr)
                              -> io::Result<()> {
                                  unimpl!();
        }

        pub fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32)
                              -> io::Result<()> {
                                  unimpl!();
        }

        pub fn set_ttl(&self, _: u32) -> io::Result<()> {
            unimpl!();
        }

        pub fn ttl(&self) -> io::Result<u32> {
            unimpl!();
        }

        pub fn take_error(&self) -> io::Result<Option<io::Error>> {
            unimpl!();
        }

        pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
            unimpl!();
        }

        pub fn recv(&self, _: &mut [u8]) -> io::Result<usize> {
            unimpl!();
        }

        pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
            unimpl!();
        }

        pub fn send(&self, _: &[u8]) -> io::Result<usize> {
            unimpl!();
        }

        pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> {
            unimpl!();
        }
    }

    impl FromInner<Socket> for UdpSocket {
        fn from_inner(socket: Socket) -> UdpSocket {
            UdpSocket { inner: socket }
        }
    }

    impl fmt::Debug for UdpSocket {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "No networking support on L4Re available.")
        }
    }

    pub struct LookupHost {
        original: *mut libc::addrinfo,
        cur: *mut libc::addrinfo,
    }

    impl Iterator for LookupHost {
        type Item = SocketAddr;
        fn next(&mut self) -> Option<SocketAddr> {
            None
        }
    }

    impl LookupHost {
        pub fn port(&self) -> u16 {
            unimpl!();
        }
    }

    unsafe impl Sync for LookupHost {}
    unsafe impl Send for LookupHost {}

    impl TryFrom<&str> for LookupHost {
        type Error = io::Error;

        fn try_from(_v: &str) -> io::Result<LookupHost> {
            unimpl!();
        }
    }

    impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
        type Error = io::Error;

        fn try_from(_v: (&'a str, u16)) -> io::Result<LookupHost> {
            unimpl!();
        }
    }
}

<commit_msg>Add UdpSocket peer_addr implementation for L4Re<commit_after>macro_rules! unimpl {
    () => (return Err(io::Error::new(io::ErrorKind::Other, "No networking available on L4Re."));)
}

pub mod net {
    #![allow(warnings)]
    use crate::fmt;
    use crate::io::{self, IoVec, IoVecMut};
    use crate::net::{SocketAddr, Shutdown, Ipv4Addr, Ipv6Addr};
    use crate::sys_common::{AsInner, FromInner, IntoInner};
    use crate::sys::fd::FileDesc;
    use crate::time::Duration;
    use crate::convert::TryFrom;

    #[allow(unused_extern_crates)]
    pub extern crate libc as netc;

    pub struct Socket(FileDesc);
    impl Socket {
        pub fn new(_: &SocketAddr, _: libc::c_int) -> io::Result<Socket> {
            unimpl!();
        }

        pub fn new_raw(_: libc::c_int, _: libc::c_int) -> io::Result<Socket> {
            unimpl!();
        }

        pub fn new_pair(_: libc::c_int, _: libc::c_int) -> io::Result<(Socket, Socket)> {
            unimpl!();
        }

        pub fn connect_timeout(&self, _: &SocketAddr, _: Duration) -> io::Result<()> {
            unimpl!();
        }

        pub fn accept(&self, _: *mut libc::sockaddr, _: *mut libc::socklen_t)
                  -> io::Result<Socket> {
            unimpl!();
        }

        pub fn duplicate(&self) -> io::Result<Socket> {
            unimpl!();
        }

        pub fn read(&self, _: &mut [u8]) -> io::Result<usize> {
            unimpl!();
        }

        pub fn read_vectored(&self, _: &mut [IoVecMut<'_>]) -> io::Result<usize> {
            unimpl!();
        }

        pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
            unimpl!();
        }

        pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
            unimpl!();
        }

        pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
            unimpl!();
        }

        pub fn write(&self, _: &[u8]) -> io::Result<usize> {
            unimpl!();
        }

        pub fn write_vectored(&self, _: &[IoVec<'_>]) -> io::Result<usize> {
            unimpl!();
        }

        pub fn set_timeout(&self, _: Option<Duration>, _: libc::c_int) -> io::Result<()> {
            unimpl!();
        }

        pub fn timeout(&self, _: libc::c_int) -> io::Result<Option<Duration>> {
            unimpl!();
        }

        pub fn shutdown(&self, _: Shutdown) -> io::Result<()> {
            unimpl!();
        }

        pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
            unimpl!();
        }

        pub fn nodelay(&self) -> io::Result<bool> {
            unimpl!();
        }

        pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
            unimpl!();
        }

        pub fn take_error(&self) -> io::Result<Option<io::Error>> {
            unimpl!();
        }
    }

    impl AsInner<libc::c_int> for Socket {
        fn as_inner(&self) -> &libc::c_int { self.0.as_inner() }
    }

    impl FromInner<libc::c_int> for Socket {
        fn from_inner(fd: libc::c_int) -> Socket { Socket(FileDesc::new(fd)) }
    }

    impl IntoInner<libc::c_int> for Socket {
        fn into_inner(self) -> libc::c_int { self.0.into_raw() }
    }

    pub struct TcpStream {
        inner: Socket,
    }

    impl TcpStream {
        pub fn connect(_: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
            unimpl!();
        }

        pub fn connect_timeout(_: &SocketAddr, _: Duration) -> io::Result<TcpStream> {
            unimpl!();
        }

        pub fn socket(&self) -> &Socket { &self.inner }

        pub fn into_socket(self) -> Socket { self.inner }

        pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
            unimpl!();
        }

        pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
            unimpl!();
        }

        pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
            unimpl!();
        }

        pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
            unimpl!();
        }

        pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
            unimpl!();
        }

        pub fn read(&self, _: &mut [u8]) -> io::Result<usize> {
            unimpl!();
        }

        pub fn read_vectored(&self, _: &mut [IoVecMut<'_>]) -> io::Result<usize> {
            unimpl!();
        }

        pub fn write(&self, _: &[u8]) -> io::Result<usize> {
            unimpl!();
        }

        pub fn write_vectored(&self, _: &[IoVec<'_>]) -> io::Result<usize> {
            unimpl!();
        }

        pub fn peer_addr(&self) -> io::Result<SocketAddr> {
            unimpl!();
        }

        pub fn socket_addr(&self) -> io::Result<SocketAddr> {
            unimpl!();
        }

        pub fn shutdown(&self, _: Shutdown) -> io::Result<()> {
            unimpl!();
        }

        pub fn duplicate(&self) -> io::Result<TcpStream> {
            unimpl!();
        }

        pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
            unimpl!();
        }

        pub fn nodelay(&self) -> io::Result<bool> {
            unimpl!();
        }

        pub fn set_ttl(&self, _: u32) -> io::Result<()> {
            unimpl!();
        }

        pub fn ttl(&self) -> io::Result<u32> {
            unimpl!();
        }

        pub fn take_error(&self) -> io::Result<Option<io::Error>> {
            unimpl!();
        }

        pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
            unimpl!();
        }
    }

    impl FromInner<Socket> for TcpStream {
        fn from_inner(socket: Socket) -> TcpStream {
            TcpStream { inner: socket }
        }
    }

    impl fmt::Debug for TcpStream {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "No networking support available on L4Re")
        }
    }

    pub struct TcpListener {
        inner: Socket,
    }

    impl TcpListener {
        pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
            unimpl!();
        }

        pub fn socket(&self) -> &Socket { &self.inner }

        pub fn into_socket(self) -> Socket { self.inner }

        pub fn socket_addr(&self) -> io::Result<SocketAddr> {
            unimpl!();
        }

        pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
            unimpl!();
        }

        pub fn duplicate(&self) -> io::Result<TcpListener> {
            unimpl!();
        }

        pub fn set_ttl(&self, _: u32) -> io::Result<()> {
            unimpl!();
        }

        pub fn ttl(&self) -> io::Result<u32> {
            unimpl!();
        }

        pub fn set_only_v6(&self, _: bool) -> io::Result<()> {
            unimpl!();
        }

        pub fn only_v6(&self) -> io::Result<bool> {
            unimpl!();
        }

        pub fn take_error(&self) -> io::Result<Option<io::Error>> {
            unimpl!();
        }

        pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
            unimpl!();
        }
    }

    impl FromInner<Socket> for TcpListener {
        fn from_inner(socket: Socket) -> TcpListener {
            TcpListener { inner: socket }
        }
    }

    impl fmt::Debug for TcpListener {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "No networking support available on L4Re.")
        }
    }

    pub struct UdpSocket {
        inner: Socket,
    }

    impl UdpSocket {
        pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
            unimpl!();
        }

        pub fn socket(&self) -> &Socket { &self.inner }

        pub fn into_socket(self) -> Socket { self.inner }

        pub fn peer_addr(&self) -> io::Result<SocketAddr> {
            unimpl!();
        }

        pub fn socket_addr(&self) -> io::Result<SocketAddr> {
            unimpl!();
        }

        pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
            unimpl!();
        }

        pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
            unimpl!();
        }

        pub fn send_to(&self, _: &[u8], _: &SocketAddr) -> io::Result<usize> {
            unimpl!();
        }

        pub fn duplicate(&self) -> io::Result<UdpSocket> {
            unimpl!();
        }

        pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
            unimpl!();
        }

        pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
            unimpl!();
        }

        pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
            unimpl!();
        }

        pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
            unimpl!();
        }

        pub fn set_broadcast(&self, _: bool) -> io::Result<()> {
            unimpl!();
        }

        pub fn broadcast(&self) -> io::Result<bool> {
            unimpl!();
        }

        pub fn set_multicast_loop_v4(&self, _: bool) -> io::Result<()> {
            unimpl!();
        }

        pub fn multicast_loop_v4(&self) -> io::Result<bool> {
            unimpl!();
        }

        pub fn set_multicast_ttl_v4(&self, _: u32) -> io::Result<()> {
            unimpl!();
        }

        pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
            unimpl!();
        }

        pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> {
            unimpl!();
        }

        pub fn multicast_loop_v6(&self) -> io::Result<bool> {
            unimpl!();
        }

        pub fn join_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr)
                             -> io::Result<()> {
                                 unimpl!();
        }

        pub fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32)
                             -> io::Result<()> {
                                 unimpl!();
        }

        pub fn leave_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr)
                              -> io::Result<()> {
                                  unimpl!();
        }

        pub fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32)
                              -> io::Result<()> {
                                  unimpl!();
        }

        pub fn set_ttl(&self, _: u32) -> io::Result<()> {
            unimpl!();
        }

        pub fn ttl(&self) -> io::Result<u32> {
            unimpl!();
        }

        pub fn take_error(&self) -> io::Result<Option<io::Error>> {
            unimpl!();
        }

        pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
            unimpl!();
        }

        pub fn recv(&self, _: &mut [u8]) -> io::Result<usize> {
            unimpl!();
        }

        pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
            unimpl!();
        }

        pub fn send(&self, _: &[u8]) -> io::Result<usize> {
            unimpl!();
        }

        pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> {
            unimpl!();
        }
    }

    impl FromInner<Socket> for UdpSocket {
        fn from_inner(socket: Socket) -> UdpSocket {
            UdpSocket { inner: socket }
        }
    }

    impl fmt::Debug for UdpSocket {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "No networking support on L4Re available.")
        }
    }

    pub struct LookupHost {
        original: *mut libc::addrinfo,
        cur: *mut libc::addrinfo,
    }

    impl Iterator for LookupHost {
        type Item = SocketAddr;
        fn next(&mut self) -> Option<SocketAddr> {
            None
        }
    }

    impl LookupHost {
        pub fn port(&self) -> u16 {
            unimpl!();
        }
    }

    unsafe impl Sync for LookupHost {}
    unsafe impl Send for LookupHost {}

    impl TryFrom<&str> for LookupHost {
        type Error = io::Error;

        fn try_from(_v: &str) -> io::Result<LookupHost> {
            unimpl!();
        }
    }

    impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
        type Error = io::Error;

        fn try_from(_v: (&'a str, u16)) -> io::Result<LookupHost> {
            unimpl!();
        }
    }
}
<|endoftext|>


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

//! An "interner" is a data structure that associates values with usize tags and
//! allows bidirectional lookup; i.e. given a value, one can easily find the
//! type, and vice versa.

use hygiene::SyntaxContext;

use serialize::{Decodable, Decoder, Encodable, Encoder};
use std::cell::RefCell;
use std::collections::HashMap;
use std::fmt;

#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct Ident {
    pub name: Symbol,
    pub ctxt: SyntaxContext,
}

impl Ident {
    pub const fn with_empty_ctxt(name: Symbol) -> Ident {
        Ident { name: name, ctxt: SyntaxContext::empty() }
    }

    /// Maps a string to an identifier with an empty syntax context.
    pub fn from_str(string: &str) -> Ident {
        Ident::with_empty_ctxt(Symbol::intern(string))
    }

    pub fn modern(self) -> Ident {
        Ident { name: self.name, ctxt: self.ctxt.modern() }
    }
}

impl fmt::Debug for Ident {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}{:?}", self.name, self.ctxt)
    }
}

impl fmt::Display for Ident {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.name, f)
    }
}

impl Encodable for Ident {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        if self.ctxt.modern() == SyntaxContext::empty() {
            s.emit_str(&self.name.as_str())
        } else { // FIXME(jseyfried) intercrate hygiene
            let mut string = "#".to_owned();
            string.push_str(&self.name.as_str());
            s.emit_str(&string)
        }
    }
}

impl Decodable for Ident {
    fn decode<D: Decoder>(d: &mut D) -> Result<Ident, D::Error> {
        let string = d.read_str()?;
        Ok(if !string.starts_with('#') {
            Ident::from_str(&string)
        } else { // FIXME(jseyfried) intercrate hygiene
            Ident::with_empty_ctxt(Symbol::gensym(&string[1..]))
        })
    }
}

/// A symbol is an interned or gensymed string.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Symbol(u32);

// The interner in thread-local, so `Symbol` shouldn't move between threads.
impl !Send for Symbol { }
impl !Sync for Symbol { }

impl Symbol {
    /// Maps a string to its interned representation.
    pub fn intern(string: &str) -> Self {
        with_interner(|interner| interner.intern(string))
    }

    pub fn interned(self) -> Self {
        with_interner(|interner| interner.interned(self))
    }

    /// gensym's a new usize, using the current interner.
    pub fn gensym(string: &str) -> Self {
        with_interner(|interner| interner.gensym(string))
    }

    pub fn gensymed(self) -> Self {
        with_interner(|interner| interner.gensymed(self))
    }

    pub fn as_str(self) -> InternedString {
        with_interner(|interner| unsafe {
            InternedString {
                string: ::std::mem::transmute::<&str, &str>(interner.get(self))
            }
        })
    }

    pub fn as_u32(self) -> u32 {
        self.0
    }
}

impl fmt::Debug for Symbol {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}({})", self, self.0)
    }
}

impl fmt::Display for Symbol {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.as_str(), f)
    }
}

impl Encodable for Symbol {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        s.emit_str(&self.as_str())
    }
}

impl Decodable for Symbol {
    fn decode<D: Decoder>(d: &mut D) -> Result<Symbol, D::Error> {
        Ok(Symbol::intern(&d.read_str()?))
    }
}

impl<T: ::std::ops::Deref<Target=str>> PartialEq<T> for Symbol {
    fn eq(&self, other: &T) -> bool {
        self.as_str() == other.deref()
    }
}

#[derive(Default)]
pub struct Interner {
    names: HashMap<Box<str>, Symbol>,
    strings: Vec<Box<str>>,
    gensyms: Vec<Symbol>,
}

impl Interner {
    pub fn new() -> Self {
        Interner::default()
    }

    fn prefill(init: &[&str]) -> Self {
        let mut this = Interner::new();
        for &string in init {
            this.intern(string);
        }
        this
    }

    pub fn intern(&mut self, string: &str) -> Symbol {
        if let Some(&name) = self.names.get(string) {
            return name;
        }

        let name = Symbol(self.strings.len() as u32);
        let string = string.to_string().into_boxed_str();
        self.strings.push(string.clone());
        self.names.insert(string, name);
        name
    }

    pub fn interned(&self, symbol: Symbol) -> Symbol {
        if (symbol.0 as usize) < self.strings.len() {
            symbol
        } else {
            self.interned(self.gensyms[(!0 - symbol.0) as usize])
        }
    }

    fn gensym(&mut self, string: &str) -> Symbol {
        let symbol = self.intern(string);
        self.gensymed(symbol)
    }

    fn gensymed(&mut self, symbol: Symbol) -> Symbol {
        self.gensyms.push(symbol);
        Symbol(!0 - self.gensyms.len() as u32 + 1)
    }

    pub fn get(&self, symbol: Symbol) -> &str {
        match self.strings.get(symbol.0 as usize) {
            Some(ref string) => string,
            None => self.get(self.gensyms[(!0 - symbol.0) as usize]),
        }
    }
}

// In this macro, there is the requirement that the name (the number) must be monotonically
// increasing by one in the special identifiers, starting at 0; the same holds for the keywords,
// except starting from the next number instead of zero.
macro_rules! declare_keywords {(
    $( ($index: expr, $konst: ident, $string: expr) )*
) => {
    pub mod keywords {
        use super::{Symbol, Ident};
        #[derive(Clone, Copy, PartialEq, Eq)]
        pub struct Keyword {
            ident: Ident,
        }
        impl Keyword {
            #[inline] pub fn ident(self) -> Ident { self.ident }
            #[inline] pub fn name(self) -> Symbol { self.ident.name }
        }
        $(
            #[allow(non_upper_case_globals)]
            pub const $konst: Keyword = Keyword {
                ident: Ident::with_empty_ctxt(super::Symbol($index))
            };
        )*
    }

    impl Interner {
        fn fresh() -> Self {
            Interner::prefill(&[$($string,)*])
        }
    }
}}

// NB: leaving holes in the ident table is bad! a different ident will get
// interned with the id from the hole, but it will be between the min and max
// of the reserved words, and thus tagged as "reserved".
// After modifying this list adjust `is_special_ident`, `is_used_keyword`/`is_unused_keyword`,
// this should be rarely necessary though if the keywords are kept in alphabetic order.
declare_keywords! {
    // Special reserved identifiers used internally for elided lifetimes,
    // unnamed method parameters, crate root module, error recovery etc.
    (0,  Invalid,        "")
    (1,  CrateRoot,      "{{root}}")
    (2,  DollarCrate,    "$crate")

    // Keywords used in the language.
    (3,  As,             "as")
    (4,  Box,            "box")
    (5,  Break,          "break")
    (6,  Const,          "const")
    (7,  Continue,       "continue")
    (8,  Crate,          "crate")
    (9,  Else,           "else")
    (10, Enum,           "enum")
    (11, Extern,         "extern")
    (12, False,          "false")
    (13, Fn,             "fn")
    (14, For,            "for")
    (15, If,             "if")
    (16, Impl,           "impl")
    (17, In,             "in")
    (18, Let,            "let")
    (19, Loop,           "loop")
    (20, Match,          "match")
    (21, Mod,            "mod")
    (22, Move,           "move")
    (23, Mut,            "mut")
    (24, Pub,            "pub")
    (25, Ref,            "ref")
    (26, Return,         "return")
    (27, SelfValue,      "self")
    (28, SelfType,       "Self")
    (29, Static,         "static")
    (30, Struct,         "struct")
    (31, Super,          "super")
    (32, Trait,          "trait")
    (33, True,           "true")
    (34, Type,           "type")
    (35, Unsafe,         "unsafe")
    (36, Use,            "use")
    (37, Where,          "where")
    (38, While,          "while")

    // Keywords reserved for future use.
    (39, Abstract,       "abstract")
    (40, Alignof,        "alignof")
    (41, Become,         "become")
    (42, Do,             "do")
    (43, Final,          "final")
    (44, Macro,          "macro")
    (45, Offsetof,       "offsetof")
    (46, Override,       "override")
    (47, Priv,           "priv")
    (48, Proc,           "proc")
    (49, Pure,           "pure")
    (50, Sizeof,         "sizeof")
    (51, Typeof,         "typeof")
    (52, Unsized,        "unsized")
    (53, Virtual,        "virtual")
    (54, Yield,          "yield")

    // Weak keywords, have special meaning only in specific contexts.
    (55, Default,        "default")
    (56, StaticLifetime, "'static")
    (57, Union,          "union")
    (58, Catch,          "catch")
}

// If an interner exists in TLS, return it. Otherwise, prepare a fresh one.
fn with_interner<T, F: FnOnce(&mut Interner) -> T>(f: F) -> T {
    thread_local!(static INTERNER: RefCell<Interner> = {
        RefCell::new(Interner::fresh())
    });
    INTERNER.with(|interner| f(&mut *interner.borrow_mut()))
}

/// Represents a string stored in the thread-local interner. Because the
/// interner lives for the life of the thread, this can be safely treated as an
/// immortal string, as long as it never crosses between threads.
///
/// FIXME(pcwalton): You must be careful about what you do in the destructors
/// of objects stored in TLS, because they may run after the interner is
/// destroyed. In particular, they must not access string contents. This can
/// be fixed in the future by just leaking all strings until thread death
/// somehow.
#[derive(Clone, Copy, Hash, PartialOrd, Eq, Ord)]
pub struct InternedString {
    string: &'static str,
}

impl<U: ?Sized> ::std::convert::AsRef<U> for InternedString where str: ::std::convert::AsRef<U> {
    fn as_ref(&self) -> &U {
        self.string.as_ref()
    }
}

impl<T: ::std::ops::Deref<Target = str>> ::std::cmp::PartialEq<T> for InternedString {
    fn eq(&self, other: &T) -> bool {
        self.string == other.deref()
    }
}

impl ::std::cmp::PartialEq<InternedString> for str {
    fn eq(&self, other: &InternedString) -> bool {
        self == other.string
    }
}

impl<'a> ::std::cmp::PartialEq<InternedString> for &'a str {
    fn eq(&self, other: &InternedString) -> bool {
        *self == other.string
    }
}

impl ::std::cmp::PartialEq<InternedString> for String {
    fn eq(&self, other: &InternedString) -> bool {
        self == other.string
    }
}

impl<'a> ::std::cmp::PartialEq<InternedString> for &'a String {
    fn eq(&self, other: &InternedString) -> bool {
        *self == other.string
    }
}

impl !Send for InternedString { }

impl ::std::ops::Deref for InternedString {
    type Target = str;
    fn deref(&self) -> &str { self.string }
}

impl fmt::Debug for InternedString {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(self.string, f)
    }
}

impl fmt::Display for InternedString {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(self.string, f)
    }
}

impl Decodable for InternedString {
    fn decode<D: Decoder>(d: &mut D) -> Result<InternedString, D::Error> {
        Ok(Symbol::intern(&d.read_str()?).as_str())
    }
}

impl Encodable for InternedString {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        s.emit_str(self.string)
    }
}

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

    #[test]
    fn interner_tests() {
        let mut i: Interner = Interner::new();
        // first one is zero:
        assert_eq!(i.intern("dog"), Symbol(0));
        // re-use gets the same entry:
        assert_eq!(i.intern ("dog"), Symbol(0));
        // different string gets a different #:
        assert_eq!(i.intern("cat"), Symbol(1));
        assert_eq!(i.intern("cat"), Symbol(1));
        // dog is still at zero
        assert_eq!(i.intern("dog"), Symbol(0));
        assert_eq!(i.gensym("zebra"), Symbol(4294967295));
        // gensym of same string gets new number :
        assert_eq!(i.gensym("zebra"), Symbol(4294967294));
        // gensym of *existing* string gets new number:
        assert_eq!(i.gensym("dog"), Symbol(4294967293));
    }
}
<commit_msg>Implement From<&str> for Symbol.<commit_after>// Copyright 2016 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.

//! An "interner" is a data structure that associates values with usize tags and
//! allows bidirectional lookup; i.e. given a value, one can easily find the
//! type, and vice versa.

use hygiene::SyntaxContext;

use serialize::{Decodable, Decoder, Encodable, Encoder};
use std::cell::RefCell;
use std::collections::HashMap;
use std::fmt;

#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct Ident {
    pub name: Symbol,
    pub ctxt: SyntaxContext,
}

impl Ident {
    pub const fn with_empty_ctxt(name: Symbol) -> Ident {
        Ident { name: name, ctxt: SyntaxContext::empty() }
    }

    /// Maps a string to an identifier with an empty syntax context.
    pub fn from_str(string: &str) -> Ident {
        Ident::with_empty_ctxt(Symbol::intern(string))
    }

    pub fn modern(self) -> Ident {
        Ident { name: self.name, ctxt: self.ctxt.modern() }
    }
}

impl fmt::Debug for Ident {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}{:?}", self.name, self.ctxt)
    }
}

impl fmt::Display for Ident {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.name, f)
    }
}

impl Encodable for Ident {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        if self.ctxt.modern() == SyntaxContext::empty() {
            s.emit_str(&self.name.as_str())
        } else { // FIXME(jseyfried) intercrate hygiene
            let mut string = "#".to_owned();
            string.push_str(&self.name.as_str());
            s.emit_str(&string)
        }
    }
}

impl Decodable for Ident {
    fn decode<D: Decoder>(d: &mut D) -> Result<Ident, D::Error> {
        let string = d.read_str()?;
        Ok(if !string.starts_with('#') {
            Ident::from_str(&string)
        } else { // FIXME(jseyfried) intercrate hygiene
            Ident::with_empty_ctxt(Symbol::gensym(&string[1..]))
        })
    }
}

/// A symbol is an interned or gensymed string.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Symbol(u32);

// The interner in thread-local, so `Symbol` shouldn't move between threads.
impl !Send for Symbol { }
impl !Sync for Symbol { }

impl Symbol {
    /// Maps a string to its interned representation.
    pub fn intern(string: &str) -> Self {
        with_interner(|interner| interner.intern(string))
    }

    pub fn interned(self) -> Self {
        with_interner(|interner| interner.interned(self))
    }

    /// gensym's a new usize, using the current interner.
    pub fn gensym(string: &str) -> Self {
        with_interner(|interner| interner.gensym(string))
    }

    pub fn gensymed(self) -> Self {
        with_interner(|interner| interner.gensymed(self))
    }

    pub fn as_str(self) -> InternedString {
        with_interner(|interner| unsafe {
            InternedString {
                string: ::std::mem::transmute::<&str, &str>(interner.get(self))
            }
        })
    }

    pub fn as_u32(self) -> u32 {
        self.0
    }
}

impl<'a> From<&'a str> for Symbol {
    fn from(string: &'a str) -> Symbol {
        Symbol::intern(string)
    }
}

impl fmt::Debug for Symbol {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}({})", self, self.0)
    }
}

impl fmt::Display for Symbol {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.as_str(), f)
    }
}

impl Encodable for Symbol {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        s.emit_str(&self.as_str())
    }
}

impl Decodable for Symbol {
    fn decode<D: Decoder>(d: &mut D) -> Result<Symbol, D::Error> {
        Ok(Symbol::intern(&d.read_str()?))
    }
}

impl<T: ::std::ops::Deref<Target=str>> PartialEq<T> for Symbol {
    fn eq(&self, other: &T) -> bool {
        self.as_str() == other.deref()
    }
}

#[derive(Default)]
pub struct Interner {
    names: HashMap<Box<str>, Symbol>,
    strings: Vec<Box<str>>,
    gensyms: Vec<Symbol>,
}

impl Interner {
    pub fn new() -> Self {
        Interner::default()
    }

    fn prefill(init: &[&str]) -> Self {
        let mut this = Interner::new();
        for &string in init {
            this.intern(string);
        }
        this
    }

    pub fn intern(&mut self, string: &str) -> Symbol {
        if let Some(&name) = self.names.get(string) {
            return name;
        }

        let name = Symbol(self.strings.len() as u32);
        let string = string.to_string().into_boxed_str();
        self.strings.push(string.clone());
        self.names.insert(string, name);
        name
    }

    pub fn interned(&self, symbol: Symbol) -> Symbol {
        if (symbol.0 as usize) < self.strings.len() {
            symbol
        } else {
            self.interned(self.gensyms[(!0 - symbol.0) as usize])
        }
    }

    fn gensym(&mut self, string: &str) -> Symbol {
        let symbol = self.intern(string);
        self.gensymed(symbol)
    }

    fn gensymed(&mut self, symbol: Symbol) -> Symbol {
        self.gensyms.push(symbol);
        Symbol(!0 - self.gensyms.len() as u32 + 1)
    }

    pub fn get(&self, symbol: Symbol) -> &str {
        match self.strings.get(symbol.0 as usize) {
            Some(ref string) => string,
            None => self.get(self.gensyms[(!0 - symbol.0) as usize]),
        }
    }
}

// In this macro, there is the requirement that the name (the number) must be monotonically
// increasing by one in the special identifiers, starting at 0; the same holds for the keywords,
// except starting from the next number instead of zero.
macro_rules! declare_keywords {(
    $( ($index: expr, $konst: ident, $string: expr) )*
) => {
    pub mod keywords {
        use super::{Symbol, Ident};
        #[derive(Clone, Copy, PartialEq, Eq)]
        pub struct Keyword {
            ident: Ident,
        }
        impl Keyword {
            #[inline] pub fn ident(self) -> Ident { self.ident }
            #[inline] pub fn name(self) -> Symbol { self.ident.name }
        }
        $(
            #[allow(non_upper_case_globals)]
            pub const $konst: Keyword = Keyword {
                ident: Ident::with_empty_ctxt(super::Symbol($index))
            };
        )*
    }

    impl Interner {
        fn fresh() -> Self {
            Interner::prefill(&[$($string,)*])
        }
    }
}}

// NB: leaving holes in the ident table is bad! a different ident will get
// interned with the id from the hole, but it will be between the min and max
// of the reserved words, and thus tagged as "reserved".
// After modifying this list adjust `is_special_ident`, `is_used_keyword`/`is_unused_keyword`,
// this should be rarely necessary though if the keywords are kept in alphabetic order.
declare_keywords! {
    // Special reserved identifiers used internally for elided lifetimes,
    // unnamed method parameters, crate root module, error recovery etc.
    (0,  Invalid,        "")
    (1,  CrateRoot,      "{{root}}")
    (2,  DollarCrate,    "$crate")

    // Keywords used in the language.
    (3,  As,             "as")
    (4,  Box,            "box")
    (5,  Break,          "break")
    (6,  Const,          "const")
    (7,  Continue,       "continue")
    (8,  Crate,          "crate")
    (9,  Else,           "else")
    (10, Enum,           "enum")
    (11, Extern,         "extern")
    (12, False,          "false")
    (13, Fn,             "fn")
    (14, For,            "for")
    (15, If,             "if")
    (16, Impl,           "impl")
    (17, In,             "in")
    (18, Let,            "let")
    (19, Loop,           "loop")
    (20, Match,          "match")
    (21, Mod,            "mod")
    (22, Move,           "move")
    (23, Mut,            "mut")
    (24, Pub,            "pub")
    (25, Ref,            "ref")
    (26, Return,         "return")
    (27, SelfValue,      "self")
    (28, SelfType,       "Self")
    (29, Static,         "static")
    (30, Struct,         "struct")
    (31, Super,          "super")
    (32, Trait,          "trait")
    (33, True,           "true")
    (34, Type,           "type")
    (35, Unsafe,         "unsafe")
    (36, Use,            "use")
    (37, Where,          "where")
    (38, While,          "while")

    // Keywords reserved for future use.
    (39, Abstract,       "abstract")
    (40, Alignof,        "alignof")
    (41, Become,         "become")
    (42, Do,             "do")
    (43, Final,          "final")
    (44, Macro,          "macro")
    (45, Offsetof,       "offsetof")
    (46, Override,       "override")
    (47, Priv,           "priv")
    (48, Proc,           "proc")
    (49, Pure,           "pure")
    (50, Sizeof,         "sizeof")
    (51, Typeof,         "typeof")
    (52, Unsized,        "unsized")
    (53, Virtual,        "virtual")
    (54, Yield,          "yield")

    // Weak keywords, have special meaning only in specific contexts.
    (55, Default,        "default")
    (56, StaticLifetime, "'static")
    (57, Union,          "union")
    (58, Catch,          "catch")
}

// If an interner exists in TLS, return it. Otherwise, prepare a fresh one.
fn with_interner<T, F: FnOnce(&mut Interner) -> T>(f: F) -> T {
    thread_local!(static INTERNER: RefCell<Interner> = {
        RefCell::new(Interner::fresh())
    });
    INTERNER.with(|interner| f(&mut *interner.borrow_mut()))
}

/// Represents a string stored in the thread-local interner. Because the
/// interner lives for the life of the thread, this can be safely treated as an
/// immortal string, as long as it never crosses between threads.
///
/// FIXME(pcwalton): You must be careful about what you do in the destructors
/// of objects stored in TLS, because they may run after the interner is
/// destroyed. In particular, they must not access string contents. This can
/// be fixed in the future by just leaking all strings until thread death
/// somehow.
#[derive(Clone, Copy, Hash, PartialOrd, Eq, Ord)]
pub struct InternedString {
    string: &'static str,
}

impl<U: ?Sized> ::std::convert::AsRef<U> for InternedString where str: ::std::convert::AsRef<U> {
    fn as_ref(&self) -> &U {
        self.string.as_ref()
    }
}

impl<T: ::std::ops::Deref<Target = str>> ::std::cmp::PartialEq<T> for InternedString {
    fn eq(&self, other: &T) -> bool {
        self.string == other.deref()
    }
}

impl ::std::cmp::PartialEq<InternedString> for str {
    fn eq(&self, other: &InternedString) -> bool {
        self == other.string
    }
}

impl<'a> ::std::cmp::PartialEq<InternedString> for &'a str {
    fn eq(&self, other: &InternedString) -> bool {
        *self == other.string
    }
}

impl ::std::cmp::PartialEq<InternedString> for String {
    fn eq(&self, other: &InternedString) -> bool {
        self == other.string
    }
}

impl<'a> ::std::cmp::PartialEq<InternedString> for &'a String {
    fn eq(&self, other: &InternedString) -> bool {
        *self == other.string
    }
}

impl !Send for InternedString { }

impl ::std::ops::Deref for InternedString {
    type Target = str;
    fn deref(&self) -> &str { self.string }
}

impl fmt::Debug for InternedString {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(self.string, f)
    }
}

impl fmt::Display for InternedString {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(self.string, f)
    }
}

impl Decodable for InternedString {
    fn decode<D: Decoder>(d: &mut D) -> Result<InternedString, D::Error> {
        Ok(Symbol::intern(&d.read_str()?).as_str())
    }
}

impl Encodable for InternedString {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        s.emit_str(self.string)
    }
}

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

    #[test]
    fn interner_tests() {
        let mut i: Interner = Interner::new();
        // first one is zero:
        assert_eq!(i.intern("dog"), Symbol(0));
        // re-use gets the same entry:
        assert_eq!(i.intern ("dog"), Symbol(0));
        // different string gets a different #:
        assert_eq!(i.intern("cat"), Symbol(1));
        assert_eq!(i.intern("cat"), Symbol(1));
        // dog is still at zero
        assert_eq!(i.intern("dog"), Symbol(0));
        assert_eq!(i.gensym("zebra"), Symbol(4294967295));
        // gensym of same string gets new number :
        assert_eq!(i.gensym("zebra"), Symbol(4294967294));
        // gensym of *existing* string gets new number:
        assert_eq!(i.gensym("dog"), Symbol(4294967293));
    }
}
<|endoftext|>