<commit_before>use std::ops::Range;
use std::sync::Arc;

use super::ast::{self, Assignment, Ast, AstKind, Identifier, Int, Struct, Symbol, Text};
use super::cst::{self, CstDb};
use super::cst_to_ast::CstToAst;
use super::error::CompilerError;
use super::hir::{self, Body, Expression, Lambda};
use crate::builtin_functions;
use crate::input::Input;
use im::HashMap;

#[salsa::query_group(AstToHirStorage)]
pub trait AstToHir: CstDb + CstToAst {
    fn hir_to_ast_id(&self, id: hir::Id) -> Option<ast::Id>;
    fn hir_to_cst_id(&self, id: hir::Id) -> Option<cst::Id>;
    fn hir_id_to_span(&self, id: hir::Id) -> Option<Range<usize>>;
    fn hir_id_to_display_span(&self, id: hir::Id) -> Option<Range<usize>>;

    fn ast_to_hir_id(&self, id: ast::Id) -> Option<hir::Id>;
    fn cst_to_hir_id(&self, input: Input, id: cst::Id) -> Option<hir::Id>;

    fn hir(&self, input: Input) -> Option<(Arc<Body>, HashMap<hir::Id, ast::Id>)>;
    fn hir_raw(
        &self,
        input: Input,
    ) -> Option<(Arc<Body>, HashMap<hir::Id, ast::Id>, Vec<CompilerError>)>;
}

fn hir_to_ast_id(db: &dyn AstToHir, id: hir::Id) -> Option<ast::Id> {
    let (_, hir_to_ast_id_mapping) = db.hir(id.input.clone()).unwrap();
    hir_to_ast_id_mapping.get(&id).cloned()
}
fn hir_to_cst_id(db: &dyn AstToHir, id: hir::Id) -> Option<cst::Id> {
    db.ast_to_cst_id(db.hir_to_ast_id(id.clone())?)
}
fn hir_id_to_span(db: &dyn AstToHir, id: hir::Id) -> Option<Range<usize>> {
    db.ast_id_to_span(db.hir_to_ast_id(id.clone())?)
}
fn hir_id_to_display_span(db: &dyn AstToHir, id: hir::Id) -> Option<Range<usize>> {
    let cst_id = db.hir_to_cst_id(id.clone())?;
    Some(db.find_cst(id.input, cst_id).display_span())
}

fn ast_to_hir_id(db: &dyn AstToHir, id: ast::Id) -> Option<hir::Id> {
    let (_, hir_to_ast_id_mapping) = db.hir(id.input.clone()).unwrap();
    hir_to_ast_id_mapping
        .iter()
        .find_map(|(key, value)| if value == &id { Some(key) } else { None })
        .cloned()
}
fn cst_to_hir_id(db: &dyn AstToHir, input: Input, id: cst::Id) -> Option<hir::Id> {
    let id = db.cst_to_ast_id(input, id)?;
    db.ast_to_hir_id(id)
}

fn hir(db: &dyn AstToHir, input: Input) -> Option<(Arc<Body>, HashMap<hir::Id, ast::Id>)> {
    db.hir_raw(input)
        .map(|(hir, id_mapping, _)| (hir, id_mapping))
}
fn hir_raw(
    db: &dyn AstToHir,
    input: Input,
) -> Option<(Arc<Body>, HashMap<hir::Id, ast::Id>, Vec<CompilerError>)> {
    let (ast, _) = db.ast(input.clone())?;

    let mut context = Context {
        db,
        input: input.clone(),
    };
    let mut compiler = Compiler::new(&mut context);
    compiler.compile(&ast);
    Some((
        Arc::new(compiler.body),
        compiler.output.id_mapping,
        compiler.output.errors,
    ))
}

struct Context<'c> {
    db: &'c dyn AstToHir,
    input: Input,
}

#[derive(Clone)]
struct Output {
    id_mapping: HashMap<hir::Id, ast::Id>,
    errors: Vec<CompilerError>,
}

struct Compiler<'c> {
    context: &'c Context<'c>,
    output: Output,
    body: Body,
    parent_ids: Vec<usize>,
    next_id: usize,
    identifiers: HashMap<String, hir::Id>,
}
impl<'c> Compiler<'c> {
    fn new(context: &'c Context<'c>) -> Self {
        let builtin_identifiers = builtin_functions::VALUES
            .iter()
            .enumerate()
            .map(|(index, builtin_function)| {
                let string = format!("builtin{:?}", builtin_function);
                (string, hir::Id::new(context.input.clone(), vec![index]))
            })
            .collect::<HashMap<_, _>>();

        let mut compiler = Compiler {
            context,
            output: Output {
                id_mapping: HashMap::new(),
                errors: vec![],
            },
            parent_ids: vec![],
            next_id: builtin_identifiers.len(),
            body: Body::new(),
            identifiers: builtin_identifiers,
        };
        compiler.generate_use();
        compiler
    }

    fn generate_use(&mut self) {
        let mut assignment_inner = Compiler::<'c> {
            context: &mut self.context,
            output: self.output.clone(),
            body: Body::new(),
            parent_ids: add_ids(&self.parent_ids, self.next_id),
            next_id: 0,
            identifiers: self.identifiers.clone(),
        };

        let lambda_id = add_ids(&assignment_inner.parent_ids, assignment_inner.next_id);
        let lambda_parameter_id = hir::Id::new(
            assignment_inner.context.input.clone(),
            add_ids(&lambda_id[..], 0),
        );
        let mut lambda_inner = Compiler::<'c> {
            context: &mut assignment_inner.context,
            output: assignment_inner.output.clone(),
            body: Body::new(),
            parent_ids: lambda_id.clone(),
            next_id: 1, // one parameter
            identifiers: assignment_inner.identifiers.clone(),
        };

        let panic_id = lambda_inner.identifiers["builtinPanic"].clone();
        match &lambda_inner.context.input {
            Input::File(path) => {
                let current_path_content = path
                    .iter()
                    .enumerate()
                    .map(|(index, it)| {
                        (
                            lambda_inner
                                .push_without_ast_mapping(Expression::Int(index as u64), None),
                            lambda_inner
                                .push_without_ast_mapping(Expression::Text(it.to_owned()), None),
                        )
                    })
                    .collect();
                let current_path = lambda_inner
                    .push_without_ast_mapping(Expression::Struct(current_path_content), None);
                lambda_inner.push_without_ast_mapping(
                    Expression::Call {
                        function: lambda_inner.identifiers["builtinUse"].clone(),
                        arguments: vec![current_path, lambda_parameter_id.clone()],
                    },
                    None,
                );
            }
            Input::ExternalFile(_) => {
                let message_id = lambda_inner.push_without_ast_mapping(
                    Expression::Text(
                        "File doesn't belong to the currently opened project.".to_owned(),
                    ),
                    None,
                );
                lambda_inner.push_without_ast_mapping(
                    Expression::Call {
                        function: panic_id,
                        arguments: vec![message_id],
                    },
                    None,
                );
            }
            Input::Untitled(_) => {
                let message_id = lambda_inner.push_without_ast_mapping(
                    Expression::Text("Untitled files can't call `use`.".to_owned()),
                    None,
                );
                lambda_inner.push_without_ast_mapping(
                    Expression::Call {
                        function: panic_id,
                        arguments: vec![message_id],
                    },
                    None,
                );
            }
        }

        assignment_inner.output = lambda_inner.output;
        assignment_inner.push_without_ast_mapping(
            Expression::Lambda(Lambda {
                first_id: lambda_parameter_id,
                parameters: vec!["target".to_owned()],
                body: lambda_inner.body,
            }),
            None,
        );

        self.output = assignment_inner.output;

        self.push_without_ast_mapping(
            Expression::Body(assignment_inner.body),
            Some("use".to_owned()),
        );
    }

    fn compile(&mut self, asts: &[Ast]) {
        if asts.is_empty() {
            self.push_without_ast_mapping(Expression::nothing(), None);
        } else {
            for ast in asts.into_iter() {
                self.compile_single(ast);
            }
        }
    }
    fn compile_single(&mut self, ast: &Ast) -> hir::Id {
        match &ast.kind {
            AstKind::Int(Int(int)) => {
                self.push(ast.id.clone(), Expression::Int(int.to_owned()), None)
            }
            AstKind::Text(Text(string)) => self.push(
                ast.id.clone(),
                Expression::Text(string.value.to_owned()),
                None,
            ),
            AstKind::Identifier(Identifier(symbol)) => {
                let reference = match self.identifiers.get(&symbol.value) {
                    Some(reference) => reference.to_owned(),
                    None => {
                        self.output.errors.push(CompilerError {
                            message: format!("Unknown reference: {}", symbol.value),
                            span: self.context.db.ast_id_to_span(symbol.id.clone()).unwrap(),
                        });
                        return self.push(symbol.id.clone(), Expression::Error, None);
                    }
                };
                self.push(
                    ast.id.clone(),
                    Expression::Reference(reference.to_owned()),
                    None,
                )
            }
            AstKind::Symbol(Symbol(symbol)) => self.push(
                ast.id.clone(),
                Expression::Symbol(symbol.value.to_owned()),
                None,
            ),
            AstKind::Struct(Struct { entries }) => {
                let entries = entries
                    .iter()
                    .map(|(key, value)| (self.compile_single(key), self.compile_single(value)))
                    .collect();
                self.push(ast.id.clone(), Expression::Struct(entries), None)
            }
            AstKind::Lambda(ast::Lambda {
                parameters,
                body: body_asts,
            }) => {
                let mut body = Body::new();
                let lambda_id = add_ids(&self.parent_ids, self.next_id);
                let mut identifiers = self.identifiers.clone();

                for (parameter_index, parameter) in parameters.iter().enumerate() {
                    let id = hir::Id::new(
                        self.context.input.clone(),
                        add_ids(&lambda_id, parameter_index),
                    );
                    self.output
                        .id_mapping
                        .insert(id.clone(), parameter.id.clone());
                    body.identifiers
                        .insert(id.to_owned(), parameter.value.to_owned());
                    identifiers.insert(parameter.value.to_owned(), id);
                }
                let mut inner = Compiler::<'c> {
                    context: &mut self.context,
                    output: self.output.clone(),
                    body,
                    parent_ids: lambda_id.to_owned(),
                    next_id: parameters.len(),
                    identifiers,
                };

                inner.compile(&body_asts);
                self.output = inner.output;
                self.push(
                    ast.id.clone(),
                    Expression::Lambda(Lambda {
                        first_id: hir::Id::new(
                            self.context.input.clone(),
                            add_ids(&lambda_id[..], 0),
                        ),
                        parameters: parameters.iter().map(|it| it.value.to_owned()).collect(),
                        body: inner.body,
                    }),
                    None,
                )
            }
            AstKind::Call(ast::Call { name, arguments }) => {
                let arguments = arguments
                    .iter()
                    .map(|argument| self.compile_single(argument))
                    .collect();

                let function = match self.identifiers.get(&name.value) {
                    Some(function) => function.to_owned(),
                    None => {
                        self.output.errors.push(CompilerError {
                            message: format!("Unknown function: {}", name.value),
                            span: self.context.db.ast_id_to_span(name.id.clone()).unwrap(),
                        });
                        return self.push(name.id.clone(), Expression::Error, None);
                    }
                };
                self.push(
                    ast.id.clone(),
                    Expression::Call {
                        function,
                        arguments,
                    },
                    None,
                )
            }
            AstKind::Assignment(Assignment { name, body }) => {
                let mut inner = Compiler::<'c> {
                    context: &mut self.context,
                    output: self.output.clone(),
                    body: Body::new(),
                    parent_ids: add_ids(&self.parent_ids, self.next_id),
                    next_id: 0,
                    identifiers: self.identifiers.clone(),
                };
                inner.compile(&body);
                self.output = inner.output;
                self.push(
                    ast.id.clone(),
                    Expression::Body(inner.body),
                    Some(name.value.to_owned()),
                )
            }
            AstKind::Error => self.push(ast.id.clone(), Expression::Error, None),
        }
    }

    fn push(
        &mut self,
        ast_id: ast::Id,
        expression: Expression,
        identifier: Option<String>,
    ) -> hir::Id {
        let id = self.create_next_id(ast_id);
        self.body.push(id.clone(), expression, identifier.clone());
        if let Some(identifier) = identifier {
            self.identifiers.insert(identifier, id.clone());
        }
        id
    }
    fn push_without_ast_mapping(
        &mut self,
        expression: Expression,
        identifier: Option<String>,
    ) -> hir::Id {
        let id = self.create_next_id_without_ast_mapping();
        self.body.push(id.to_owned(), expression, None);
        if let Some(identifier) = identifier {
            self.identifiers.insert(identifier, id.clone());
        }
        id
    }

    fn create_next_id(&mut self, ast_id: ast::Id) -> hir::Id {
        let id = self.create_next_id_without_ast_mapping();
        assert!(matches!(
            self.output.id_mapping.insert(id.to_owned(), ast_id),
            None
        ));
        id
    }
    fn create_next_id_without_ast_mapping(&mut self) -> hir::Id {
        let id = hir::Id::new(
            self.context.input.clone(),
            add_ids(&self.parent_ids, self.next_id),
        );
        self.next_id += 1;
        id
    }
}

fn add_ids(parents: &[usize], id: usize) -> Vec<usize> {
    parents.iter().map(|it| *it).chain(vec![id]).collect()
}
<commit_msg>fix(compiler): use Ast Id i/o AstString ID when looking up unknown reference span<commit_after>use std::ops::Range;
use std::sync::Arc;

use super::ast::{self, Assignment, Ast, AstKind, Identifier, Int, Struct, Symbol, Text};
use super::cst::{self, CstDb};
use super::cst_to_ast::CstToAst;
use super::error::CompilerError;
use super::hir::{self, Body, Expression, Lambda};
use crate::builtin_functions;
use crate::input::Input;
use im::HashMap;

#[salsa::query_group(AstToHirStorage)]
pub trait AstToHir: CstDb + CstToAst {
    fn hir_to_ast_id(&self, id: hir::Id) -> Option<ast::Id>;
    fn hir_to_cst_id(&self, id: hir::Id) -> Option<cst::Id>;
    fn hir_id_to_span(&self, id: hir::Id) -> Option<Range<usize>>;
    fn hir_id_to_display_span(&self, id: hir::Id) -> Option<Range<usize>>;

    fn ast_to_hir_id(&self, id: ast::Id) -> Option<hir::Id>;
    fn cst_to_hir_id(&self, input: Input, id: cst::Id) -> Option<hir::Id>;

    fn hir(&self, input: Input) -> Option<(Arc<Body>, HashMap<hir::Id, ast::Id>)>;
    fn hir_raw(
        &self,
        input: Input,
    ) -> Option<(Arc<Body>, HashMap<hir::Id, ast::Id>, Vec<CompilerError>)>;
}

fn hir_to_ast_id(db: &dyn AstToHir, id: hir::Id) -> Option<ast::Id> {
    let (_, hir_to_ast_id_mapping) = db.hir(id.input.clone()).unwrap();
    hir_to_ast_id_mapping.get(&id).cloned()
}
fn hir_to_cst_id(db: &dyn AstToHir, id: hir::Id) -> Option<cst::Id> {
    db.ast_to_cst_id(db.hir_to_ast_id(id.clone())?)
}
fn hir_id_to_span(db: &dyn AstToHir, id: hir::Id) -> Option<Range<usize>> {
    db.ast_id_to_span(db.hir_to_ast_id(id.clone())?)
}
fn hir_id_to_display_span(db: &dyn AstToHir, id: hir::Id) -> Option<Range<usize>> {
    let cst_id = db.hir_to_cst_id(id.clone())?;
    Some(db.find_cst(id.input, cst_id).display_span())
}

fn ast_to_hir_id(db: &dyn AstToHir, id: ast::Id) -> Option<hir::Id> {
    let (_, hir_to_ast_id_mapping) = db.hir(id.input.clone()).unwrap();
    hir_to_ast_id_mapping
        .iter()
        .find_map(|(key, value)| if value == &id { Some(key) } else { None })
        .cloned()
}
fn cst_to_hir_id(db: &dyn AstToHir, input: Input, id: cst::Id) -> Option<hir::Id> {
    let id = db.cst_to_ast_id(input, id)?;
    db.ast_to_hir_id(id)
}

fn hir(db: &dyn AstToHir, input: Input) -> Option<(Arc<Body>, HashMap<hir::Id, ast::Id>)> {
    db.hir_raw(input)
        .map(|(hir, id_mapping, _)| (hir, id_mapping))
}
fn hir_raw(
    db: &dyn AstToHir,
    input: Input,
) -> Option<(Arc<Body>, HashMap<hir::Id, ast::Id>, Vec<CompilerError>)> {
    let (ast, _) = db.ast(input.clone())?;

    let mut context = Context {
        db,
        input: input.clone(),
    };
    let mut compiler = Compiler::new(&mut context);
    compiler.compile(&ast);
    Some((
        Arc::new(compiler.body),
        compiler.output.id_mapping,
        compiler.output.errors,
    ))
}

struct Context<'c> {
    db: &'c dyn AstToHir,
    input: Input,
}

#[derive(Clone)]
struct Output {
    id_mapping: HashMap<hir::Id, ast::Id>,
    errors: Vec<CompilerError>,
}

struct Compiler<'c> {
    context: &'c Context<'c>,
    output: Output,
    body: Body,
    parent_ids: Vec<usize>,
    next_id: usize,
    identifiers: HashMap<String, hir::Id>,
}
impl<'c> Compiler<'c> {
    fn new(context: &'c Context<'c>) -> Self {
        let builtin_identifiers = builtin_functions::VALUES
            .iter()
            .enumerate()
            .map(|(index, builtin_function)| {
                let string = format!("builtin{:?}", builtin_function);
                (string, hir::Id::new(context.input.clone(), vec![index]))
            })
            .collect::<HashMap<_, _>>();

        let mut compiler = Compiler {
            context,
            output: Output {
                id_mapping: HashMap::new(),
                errors: vec![],
            },
            parent_ids: vec![],
            next_id: builtin_identifiers.len(),
            body: Body::new(),
            identifiers: builtin_identifiers,
        };
        compiler.generate_use();
        compiler
    }

    fn generate_use(&mut self) {
        let mut assignment_inner = Compiler::<'c> {
            context: &mut self.context,
            output: self.output.clone(),
            body: Body::new(),
            parent_ids: add_ids(&self.parent_ids, self.next_id),
            next_id: 0,
            identifiers: self.identifiers.clone(),
        };

        let lambda_id = add_ids(&assignment_inner.parent_ids, assignment_inner.next_id);
        let lambda_parameter_id = hir::Id::new(
            assignment_inner.context.input.clone(),
            add_ids(&lambda_id[..], 0),
        );
        let mut lambda_inner = Compiler::<'c> {
            context: &mut assignment_inner.context,
            output: assignment_inner.output.clone(),
            body: Body::new(),
            parent_ids: lambda_id.clone(),
            next_id: 1, // one parameter
            identifiers: assignment_inner.identifiers.clone(),
        };

        let panic_id = lambda_inner.identifiers["builtinPanic"].clone();
        match &lambda_inner.context.input {
            Input::File(path) => {
                let current_path_content = path
                    .iter()
                    .enumerate()
                    .map(|(index, it)| {
                        (
                            lambda_inner
                                .push_without_ast_mapping(Expression::Int(index as u64), None),
                            lambda_inner
                                .push_without_ast_mapping(Expression::Text(it.to_owned()), None),
                        )
                    })
                    .collect();
                let current_path = lambda_inner
                    .push_without_ast_mapping(Expression::Struct(current_path_content), None);
                lambda_inner.push_without_ast_mapping(
                    Expression::Call {
                        function: lambda_inner.identifiers["builtinUse"].clone(),
                        arguments: vec![current_path, lambda_parameter_id.clone()],
                    },
                    None,
                );
            }
            Input::ExternalFile(_) => {
                let message_id = lambda_inner.push_without_ast_mapping(
                    Expression::Text(
                        "File doesn't belong to the currently opened project.".to_owned(),
                    ),
                    None,
                );
                lambda_inner.push_without_ast_mapping(
                    Expression::Call {
                        function: panic_id,
                        arguments: vec![message_id],
                    },
                    None,
                );
            }
            Input::Untitled(_) => {
                let message_id = lambda_inner.push_without_ast_mapping(
                    Expression::Text("Untitled files can't call `use`.".to_owned()),
                    None,
                );
                lambda_inner.push_without_ast_mapping(
                    Expression::Call {
                        function: panic_id,
                        arguments: vec![message_id],
                    },
                    None,
                );
            }
        }

        assignment_inner.output = lambda_inner.output;
        assignment_inner.push_without_ast_mapping(
            Expression::Lambda(Lambda {
                first_id: lambda_parameter_id,
                parameters: vec!["target".to_owned()],
                body: lambda_inner.body,
            }),
            None,
        );

        self.output = assignment_inner.output;

        self.push_without_ast_mapping(
            Expression::Body(assignment_inner.body),
            Some("use".to_owned()),
        );
    }

    fn compile(&mut self, asts: &[Ast]) {
        if asts.is_empty() {
            self.push_without_ast_mapping(Expression::nothing(), None);
        } else {
            for ast in asts.into_iter() {
                self.compile_single(ast);
            }
        }
    }
    fn compile_single(&mut self, ast: &Ast) -> hir::Id {
        match &ast.kind {
            AstKind::Int(Int(int)) => {
                self.push(ast.id.clone(), Expression::Int(int.to_owned()), None)
            }
            AstKind::Text(Text(string)) => self.push(
                ast.id.clone(),
                Expression::Text(string.value.to_owned()),
                None,
            ),
            AstKind::Identifier(Identifier(symbol)) => {
                let reference = match self.identifiers.get(&symbol.value) {
                    Some(reference) => reference.to_owned(),
                    None => {
                        self.output.errors.push(CompilerError {
                            message: format!("Unknown reference: {}", symbol.value),
                            span: self.context.db.ast_id_to_span(ast.id.clone()).unwrap(),
                        });
                        return self.push(symbol.id.clone(), Expression::Error, None);
                    }
                };
                self.push(
                    ast.id.clone(),
                    Expression::Reference(reference.to_owned()),
                    None,
                )
            }
            AstKind::Symbol(Symbol(symbol)) => self.push(
                ast.id.clone(),
                Expression::Symbol(symbol.value.to_owned()),
                None,
            ),
            AstKind::Struct(Struct { entries }) => {
                let entries = entries
                    .iter()
                    .map(|(key, value)| (self.compile_single(key), self.compile_single(value)))
                    .collect();
                self.push(ast.id.clone(), Expression::Struct(entries), None)
            }
            AstKind::Lambda(ast::Lambda {
                parameters,
                body: body_asts,
            }) => {
                let mut body = Body::new();
                let lambda_id = add_ids(&self.parent_ids, self.next_id);
                let mut identifiers = self.identifiers.clone();

                for (parameter_index, parameter) in parameters.iter().enumerate() {
                    let id = hir::Id::new(
                        self.context.input.clone(),
                        add_ids(&lambda_id, parameter_index),
                    );
                    self.output
                        .id_mapping
                        .insert(id.clone(), parameter.id.clone());
                    body.identifiers
                        .insert(id.to_owned(), parameter.value.to_owned());
                    identifiers.insert(parameter.value.to_owned(), id);
                }
                let mut inner = Compiler::<'c> {
                    context: &mut self.context,
                    output: self.output.clone(),
                    body,
                    parent_ids: lambda_id.to_owned(),
                    next_id: parameters.len(),
                    identifiers,
                };

                inner.compile(&body_asts);
                self.output = inner.output;
                self.push(
                    ast.id.clone(),
                    Expression::Lambda(Lambda {
                        first_id: hir::Id::new(
                            self.context.input.clone(),
                            add_ids(&lambda_id[..], 0),
                        ),
                        parameters: parameters.iter().map(|it| it.value.to_owned()).collect(),
                        body: inner.body,
                    }),
                    None,
                )
            }
            AstKind::Call(ast::Call { name, arguments }) => {
                let arguments = arguments
                    .iter()
                    .map(|argument| self.compile_single(argument))
                    .collect();

                let function = match self.identifiers.get(&name.value) {
                    Some(function) => function.to_owned(),
                    None => {
                        self.output.errors.push(CompilerError {
                            message: format!("Unknown function: {}", name.value),
                            span: self.context.db.ast_id_to_span(name.id.clone()).unwrap(),
                        });
                        return self.push(name.id.clone(), Expression::Error, None);
                    }
                };
                self.push(
                    ast.id.clone(),
                    Expression::Call {
                        function,
                        arguments,
                    },
                    None,
                )
            }
            AstKind::Assignment(Assignment { name, body }) => {
                let mut inner = Compiler::<'c> {
                    context: &mut self.context,
                    output: self.output.clone(),
                    body: Body::new(),
                    parent_ids: add_ids(&self.parent_ids, self.next_id),
                    next_id: 0,
                    identifiers: self.identifiers.clone(),
                };
                inner.compile(&body);
                self.output = inner.output;
                self.push(
                    ast.id.clone(),
                    Expression::Body(inner.body),
                    Some(name.value.to_owned()),
                )
            }
            AstKind::Error => self.push(ast.id.clone(), Expression::Error, None),
        }
    }

    fn push(
        &mut self,
        ast_id: ast::Id,
        expression: Expression,
        identifier: Option<String>,
    ) -> hir::Id {
        let id = self.create_next_id(ast_id);
        self.body.push(id.clone(), expression, identifier.clone());
        if let Some(identifier) = identifier {
            self.identifiers.insert(identifier, id.clone());
        }
        id
    }
    fn push_without_ast_mapping(
        &mut self,
        expression: Expression,
        identifier: Option<String>,
    ) -> hir::Id {
        let id = self.create_next_id_without_ast_mapping();
        self.body.push(id.to_owned(), expression, None);
        if let Some(identifier) = identifier {
            self.identifiers.insert(identifier, id.clone());
        }
        id
    }

    fn create_next_id(&mut self, ast_id: ast::Id) -> hir::Id {
        let id = self.create_next_id_without_ast_mapping();
        assert!(matches!(
            self.output.id_mapping.insert(id.to_owned(), ast_id),
            None
        ));
        id
    }
    fn create_next_id_without_ast_mapping(&mut self) -> hir::Id {
        let id = hir::Id::new(
            self.context.input.clone(),
            add_ids(&self.parent_ids, self.next_id),
        );
        self.next_id += 1;
        id
    }
}

fn add_ids(parents: &[usize], id: usize) -> Vec<usize> {
    parents.iter().map(|it| *it).chain(vec![id]).collect()
}
<|endoftext|>


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

// aux-build:issue-13560-1.rs
// aux-build:issue-13560-2.rs
// aux-build:issue-13560-3.rs
// ignore-stage1

// Regression test for issue #13560, the test itself is all in the dependent
// libraries. The fail which previously failed to compile is the one numbered 3.

extern crate "issue-13560-2" as t2;
extern crate "issue-13560-3" as t3;

fn main() {}
<commit_msg>test: Ignore issue-19501 pretty for now<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// aux-build:issue-13560-1.rs
// aux-build:issue-13560-2.rs
// aux-build:issue-13560-3.rs
// ignore-pretty FIXME #19501
// ignore-stage1

// Regression test for issue #13560, the test itself is all in the dependent
// libraries. The fail which previously failed to compile is the one numbered 3.

extern crate "issue-13560-2" as t2;
extern crate "issue-13560-3" as t3;

fn main() {}
<|endoftext|>


<commit_before>use super::{RollingHash64, Rabin64};

pub struct Separator {
    pub index: u64,
    pub hash: u64,
}

pub struct SeparatorIter<InputIter> {
    iter: InputIter,
    rabin: Rabin64,
    bitmask: u64,
    masked_value: u64,
    index: u64,
}

impl<InputIter: Iterator<Item=u8>> SeparatorIter<InputIter> {
    pub fn new(iter: InputIter) -> SeparatorIter<InputIter> {
        // window_size: 1 << 6 == 64 bytes
        Self::custom_new(iter, 6, (1u64 << 13) - 1, (1u64 << 13) - 1)
    }

    pub fn custom_new(mut iter: InputIter,
        separator_size_nb_bits: u32,
        bitmask: u64,
        masked_value: u64) -> SeparatorIter<InputIter> {

        let mut rabin = Rabin64::new(separator_size_nb_bits);
        let index = rabin.prefill_window(&mut iter) as u64;

        SeparatorIter {
            iter: iter,
            rabin: rabin,
            bitmask: bitmask,
            masked_value: masked_value,
            index: index,
        }

    }
}

impl<InputIter: Iterator<Item=u8>> Iterator for SeparatorIter<InputIter> {
    type Item = Separator;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        while let Some(v) = self.iter.next() {
            self.rabin.slide(&v);
            self.index += 1;
            if self.rabin.hash & self.bitmask == self.masked_value {
                let separator = Some(Separator {index: self.index, hash: self.rabin.hash});

                // Note: We skip consequent separators which may overlap the current one.
                self.rabin.reset();
                self.index += self.rabin.prefill_window(&mut self.iter) as u64;

                return separator;
            }
        }

        None
    }

}
<commit_msg>Improved the API for separators.<commit_after>use super::{RollingHash64, Rabin64};

pub struct Separator {
    pub index: u64,
    pub hash: u64,
}

pub struct SeparatorIter<I, F> {
    iter: I,
    predicate: F,
    rabin: Rabin64,
    index: u64,
}

impl<I> SeparatorIter<I, fn(u64) -> bool> where I: Iterator<Item=u8> {
    pub fn new(iter: I) -> SeparatorIter<I, fn(u64) -> bool> {
        // window_size: 1 << 6 == 64 bytes
        let separator_size_nb_bits = 6;

        #[inline]
        fn default_predicate(x: u64) -> bool {
            const BITMASK: u64 = (1u64 << 13) - 1;
            x & BITMASK == BITMASK
        }

        Self::custom_new(iter, separator_size_nb_bits, default_predicate)
    }
}

impl<I, F> SeparatorIter<I, F> where I: Iterator<Item=u8>, F: Fn(u64) -> bool {
    pub fn custom_new(mut iter: I,
        separator_size_nb_bits: u32,
        predicate: F) -> SeparatorIter<I, F> {
        let mut rabin = Rabin64::new(separator_size_nb_bits);
        let index = rabin.prefill_window(&mut iter) as u64;

        SeparatorIter {
            iter: iter,
            predicate: predicate,
            rabin: rabin,
            index: index,
        }
    }
}

impl<I, F> Iterator for SeparatorIter<I, F> where I: Iterator<Item=u8>, F: Fn(u64) -> bool {
    type Item = Separator;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        while let Some(v) = self.iter.next() {
            self.rabin.slide(&v);
            self.index += 1;
            if (self.predicate)(self.rabin.hash) {
                let separator = Some(Separator {index: self.index, hash: self.rabin.hash});

                // Note: We skip subsequent separators which may overlap the current one.
                self.rabin.reset();
                self.index += self.rabin.prefill_window(&mut self.iter) as u64;

                return separator;
            }
        }

        None
    }

}
<|endoftext|>


<commit_before>//! A general purpose signaling mechanism
//!
//! This mechanism allows inter-module communication, by letting your modules
//! register callbacks to listen for events generated by other modules. This
//! signaling mechanism is synchronous and non-threadsafe. If you need
//! ascynchronous threadsafe communication, instead consider relying on channels.
//!
//! The whole mechanism is built on the [`Signaler`](./struct.Signaler.html) type.
//! It serves both as a message sending facility and a way to register new callbacks
//! for these messages. It can be cloned and passed around between your modules with
//! `Rc`-like semantics.
//!
//! When sending a new signal with `Signaler::signal`, the provided value `E` will
//! be made accessible as a reference `&E` to all registered callback.
//!
//! Sending a signal or registering a new callback from within a callback is supported.
//! These will however take effect after the current signal is completely delivered.
//! Ordering of sent signals and callback registration is preserved.

use std::{
    any::Any,
    cell::RefCell,
    collections::VecDeque,
    rc::{Rc, Weak},
};

/// A signaler, main type for signaling
pub struct Signaler<S> {
    inner: Rc<SignalInner<S>>,
}

// Manual clone impl because of type parameters
impl<S> Clone for Signaler<S> {
    fn clone(&self) -> Signaler<S> {
        Signaler {
            inner: self.inner.clone(),
        }
    }
}

impl<S> Signaler<S> {
    /// Create a new signaler for given signal type
    pub fn new() -> Signaler<S> {
        Signaler {
            inner: Rc::new(SignalInner::new()),
        }
    }

    /// Register a new callback to this signaler
    ///
    /// This method returns a `SignalToken`, which you must keep as long
    /// as you need your callback to remain in place. Dropping it will
    /// disable and free your callback. If you don't plan to ever disable
    /// your callback, see [`SignalToken::leak()`](./struct.SignalToken.html).
    ///
    /// If you register a callback from within a callback of the same Signaler,
    /// the new callback will only be inserted *after* the current signal is
    /// completely delivered, and thus will not receive it.
    #[must_use]
    pub fn register<F: FnMut(&S) + 'static>(&self, f: F) -> SignalToken {
        let rc = Rc::new(RefCell::new(f));
        let weak = Rc::downgrade(&rc) as Weak<RefCell<dyn FnMut(&S)>>;
        self.inner.insert(weak);
        SignalToken { signal: rc }
    }

    /// Signal the callbacks
    ///
    /// All registered callbacks will be invoked with a reference to the value
    /// you provide here, after which that value will be dropped.
    ///
    /// If this method is invoked from within a callback of the same Signaler,
    /// its signalling will be delayed until the current signal is completely
    /// delivered and this method will return immediately.
    pub fn signal(&self, signal: S) {
        self.inner.send(signal);
    }
}

impl<S> Default for Signaler<S> {
    fn default() -> Self {
        Self::new()
    }
}

/// A token associated with a callback registered to a Signaler
///
/// Dropping it will disable and drop the callback it is associated to.
/// If you don't plan to ever disable the callback, you can use the `leak`
/// method to safely get rid of this value.
pub struct SignalToken {
    signal: Rc<dyn Any>,
}

impl SignalToken {
    /// Destroy the token without disabling the associated callback
    pub fn leak(self) {
        // leak the Rc, so that it is never deallocated
        let _ = Rc::into_raw(self.signal);
    }
}

type WeakCallback<S> = Weak<RefCell<dyn FnMut(&S)>>;

struct SignalInner<S> {
    callbacks: RefCell<Vec<WeakCallback<S>>>,
    pending_callbacks: RefCell<Vec<WeakCallback<S>>>,
    pending_events: RefCell<VecDeque<S>>,
}

impl<S> SignalInner<S> {
    fn new() -> SignalInner<S> {
        SignalInner {
            callbacks: RefCell::new(Vec::new()),
            pending_callbacks: RefCell::new(Vec::new()),
            pending_events: RefCell::new(VecDeque::new()),
        }
    }

    fn insert(&self, weak: WeakCallback<S>) {
        // attempt to insert the new callback
        if let Ok(mut guard) = self.callbacks.try_borrow_mut() {
            // success, insert it
            guard.push(weak);
        } else {
            // The callback list is already borrowed, this means that this insertion is
            // done from within a callback.
            // In that case, insert the callback into the pending list, `send`
            // will insert it in the callback list when it is finished dispatching
            // the current event.
            self.pending_callbacks.borrow_mut().push(weak);
        }
    }

    fn send(&self, event: S) {
        // insert the new event into the pending list
        self.pending_events.borrow_mut().push_back(event);
        // now try to dispatch the events from the pending list
        // new events might be added by other callbacks in the process
        // so we try to completely drain it before returning
        //
        // If we cannot get the guard, that means an other dispatching is
        // already in progress. It'll empty the pending list, so there is
        // nothing more we need to do.
        if let Ok(mut guard) = self.callbacks.try_borrow_mut() {
            // We cannot just use `while let` because this would keep the
            // borrow of self.pending_events alive during the whole loop, rather
            // than just the evaluation of the condition. :/
            loop {
                let next_event = self.pending_events.borrow_mut().pop_front();
                if let Some(event) = next_event {
                    // Send the message, cleaning up defunct callbacks in the process
                    guard.retain(|weak| {
                        if let Some(cb) = Weak::upgrade(weak) {
                            (&mut *cb.borrow_mut())(&event);
                            true
                        } else {
                            false
                        }
                    });
                    // integrate any pending callbacks resulting from the dispatching
                    // of this event
                    guard.extend(self.pending_callbacks.borrow_mut().drain(..));
                } else {
                    break;
                }
            }
        }
    }
}

/// Trait representing the capability of an object to listen for some signals
///
/// It is provided so that the signaling system can play nicely into generic
/// constructs.
pub trait Linkable<S> {
    /// Make this object listen for signals from given signaler
    fn link(&mut self, signaler: Signaler<S>);
}

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

    use std::{cell::Cell, rc::Rc};

    #[test]
    fn basic_signal() {
        let signaler = Signaler::<u32>::new();

        let signaled = Rc::new(Cell::new(false));
        let signaled2 = signaled.clone();

        let _token = signaler.register(move |_| signaled2.set(true));

        signaler.signal(0);

        assert!(signaled.get());
    }

    #[test]
    fn remove_callback() {
        let signaler = Signaler::<u32>::new();

        let token = signaler.register(|&i| assert_eq!(i, 42));

        signaler.signal(42);

        ::std::mem::drop(token);

        signaler.signal(41);

        let _token = signaler.register(|&i| assert_eq!(i, 39));

        signaler.signal(39);
    }

    #[test]
    fn delayed_signal() {
        let signaler = Signaler::<u32>::new();

        let mut signaled = false;
        let sign2 = signaler.clone();
        let _token = signaler.register(move |&i| {
            if !signaled {
                sign2.signal(42);
                signaled = true;
            } else {
                assert_eq!(i, 42);
            }
        });

        signaler.signal(0);
    }

    #[test]
    fn delayed_register() {
        let signaler = Signaler::<bool>::new();

        let signaled = Rc::new(Cell::new(0u32));
        let signaled2 = signaled.clone();
        let sign2 = signaler.clone();

        let _token1 = signaler.register(move |&original| {
            signaled2.set(signaled2.get() + 1);
            if original {
                let signaled3 = signaled2.clone();
                sign2.register(move |_| signaled3.set(signaled3.get() + 1)).leak();
                sign2.signal(false);
            }
        });

        signaler.signal(true);

        // Two rounds of signals, the first triggers 1 callback, the second triggers 2
        assert_eq!(signaled.get(), 3);
    }
}
<commit_msg>[Debug Trait] signaling.rs<commit_after>//! A general purpose signaling mechanism
//!
//! This mechanism allows inter-module communication, by letting your modules
//! register callbacks to listen for events generated by other modules. This
//! signaling mechanism is synchronous and non-threadsafe. If you need
//! ascynchronous threadsafe communication, instead consider relying on channels.
//!
//! The whole mechanism is built on the [`Signaler`](./struct.Signaler.html) type.
//! It serves both as a message sending facility and a way to register new callbacks
//! for these messages. It can be cloned and passed around between your modules with
//! `Rc`-like semantics.
//!
//! When sending a new signal with `Signaler::signal`, the provided value `E` will
//! be made accessible as a reference `&E` to all registered callback.
//!
//! Sending a signal or registering a new callback from within a callback is supported.
//! These will however take effect after the current signal is completely delivered.
//! Ordering of sent signals and callback registration is preserved.

use std::{
    any::Any,
    cell::RefCell,
    collections::VecDeque,
    fmt,
    rc::{Rc, Weak},
};

/// A signaler, main type for signaling
#[derive(Debug)]
pub struct Signaler<S> {
    inner: Rc<SignalInner<S>>,
}

// Manual clone impl because of type parameters
impl<S> Clone for Signaler<S> {
    fn clone(&self) -> Signaler<S> {
        Signaler {
            inner: self.inner.clone(),
        }
    }
}

impl<S> Signaler<S> {
    /// Create a new signaler for given signal type
    pub fn new() -> Signaler<S> {
        Signaler {
            inner: Rc::new(SignalInner::new()),
        }
    }

    /// Register a new callback to this signaler
    ///
    /// This method returns a `SignalToken`, which you must keep as long
    /// as you need your callback to remain in place. Dropping it will
    /// disable and free your callback. If you don't plan to ever disable
    /// your callback, see [`SignalToken::leak()`](./struct.SignalToken.html).
    ///
    /// If you register a callback from within a callback of the same Signaler,
    /// the new callback will only be inserted *after* the current signal is
    /// completely delivered, and thus will not receive it.
    #[must_use]
    pub fn register<F: FnMut(&S) + 'static>(&self, f: F) -> SignalToken {
        let rc = Rc::new(RefCell::new(f));
        let weak = Rc::downgrade(&rc) as Weak<RefCell<dyn FnMut(&S)>>;
        self.inner.insert(weak);
        SignalToken { signal: rc }
    }

    /// Signal the callbacks
    ///
    /// All registered callbacks will be invoked with a reference to the value
    /// you provide here, after which that value will be dropped.
    ///
    /// If this method is invoked from within a callback of the same Signaler,
    /// its signalling will be delayed until the current signal is completely
    /// delivered and this method will return immediately.
    pub fn signal(&self, signal: S) {
        self.inner.send(signal);
    }
}

impl<S> Default for Signaler<S> {
    fn default() -> Self {
        Self::new()
    }
}

/// A token associated with a callback registered to a Signaler
///
/// Dropping it will disable and drop the callback it is associated to.
/// If you don't plan to ever disable the callback, you can use the `leak`
/// method to safely get rid of this value.
#[derive(Debug)]
pub struct SignalToken {
    signal: Rc<dyn Any>,
}

impl SignalToken {
    /// Destroy the token without disabling the associated callback
    pub fn leak(self) {
        // leak the Rc, so that it is never deallocated
        let _ = Rc::into_raw(self.signal);
    }
}

type WeakCallback<S> = Weak<RefCell<dyn FnMut(&S)>>;

struct SignalInner<S> {
    callbacks: RefCell<Vec<WeakCallback<S>>>,
    pending_callbacks: RefCell<Vec<WeakCallback<S>>>,
    pending_events: RefCell<VecDeque<S>>,
}

impl<S: fmt::Debug> fmt::Debug for SignalInner<S> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("SignalInner")
            .field("callbacks::len()", &self.callbacks.borrow().len())
            .field("pending_callbacks::len()", &self.pending_callbacks.borrow().len())
            .field("pending_events", &self.pending_events)
            .finish()
    }
}

impl<S> SignalInner<S> {
    fn new() -> SignalInner<S> {
        SignalInner {
            callbacks: RefCell::new(Vec::new()),
            pending_callbacks: RefCell::new(Vec::new()),
            pending_events: RefCell::new(VecDeque::new()),
        }
    }

    fn insert(&self, weak: WeakCallback<S>) {
        // attempt to insert the new callback
        if let Ok(mut guard) = self.callbacks.try_borrow_mut() {
            // success, insert it
            guard.push(weak);
        } else {
            // The callback list is already borrowed, this means that this insertion is
            // done from within a callback.
            // In that case, insert the callback into the pending list, `send`
            // will insert it in the callback list when it is finished dispatching
            // the current event.
            self.pending_callbacks.borrow_mut().push(weak);
        }
    }

    fn send(&self, event: S) {
        // insert the new event into the pending list
        self.pending_events.borrow_mut().push_back(event);
        // now try to dispatch the events from the pending list
        // new events might be added by other callbacks in the process
        // so we try to completely drain it before returning
        //
        // If we cannot get the guard, that means an other dispatching is
        // already in progress. It'll empty the pending list, so there is
        // nothing more we need to do.
        if let Ok(mut guard) = self.callbacks.try_borrow_mut() {
            // We cannot just use `while let` because this would keep the
            // borrow of self.pending_events alive during the whole loop, rather
            // than just the evaluation of the condition. :/
            loop {
                let next_event = self.pending_events.borrow_mut().pop_front();
                if let Some(event) = next_event {
                    // Send the message, cleaning up defunct callbacks in the process
                    guard.retain(|weak| {
                        if let Some(cb) = Weak::upgrade(weak) {
                            (&mut *cb.borrow_mut())(&event);
                            true
                        } else {
                            false
                        }
                    });
                    // integrate any pending callbacks resulting from the dispatching
                    // of this event
                    guard.extend(self.pending_callbacks.borrow_mut().drain(..));
                } else {
                    break;
                }
            }
        }
    }
}

/// Trait representing the capability of an object to listen for some signals
///
/// It is provided so that the signaling system can play nicely into generic
/// constructs.
pub trait Linkable<S> {
    /// Make this object listen for signals from given signaler
    fn link(&mut self, signaler: Signaler<S>);
}

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

    use std::{cell::Cell, rc::Rc};

    #[test]
    fn basic_signal() {
        let signaler = Signaler::<u32>::new();

        let signaled = Rc::new(Cell::new(false));
        let signaled2 = signaled.clone();

        let _token = signaler.register(move |_| signaled2.set(true));

        signaler.signal(0);

        assert!(signaled.get());
    }

    #[test]
    fn remove_callback() {
        let signaler = Signaler::<u32>::new();

        let token = signaler.register(|&i| assert_eq!(i, 42));

        signaler.signal(42);

        ::std::mem::drop(token);

        signaler.signal(41);

        let _token = signaler.register(|&i| assert_eq!(i, 39));

        signaler.signal(39);
    }

    #[test]
    fn delayed_signal() {
        let signaler = Signaler::<u32>::new();

        let mut signaled = false;
        let sign2 = signaler.clone();
        let _token = signaler.register(move |&i| {
            if !signaled {
                sign2.signal(42);
                signaled = true;
            } else {
                assert_eq!(i, 42);
            }
        });

        signaler.signal(0);
    }

    #[test]
    fn delayed_register() {
        let signaler = Signaler::<bool>::new();

        let signaled = Rc::new(Cell::new(0u32));
        let signaled2 = signaled.clone();
        let sign2 = signaler.clone();

        let _token1 = signaler.register(move |&original| {
            signaled2.set(signaled2.get() + 1);
            if original {
                let signaled3 = signaled2.clone();
                sign2.register(move |_| signaled3.set(signaled3.get() + 1)).leak();
                sign2.signal(false);
            }
        });

        signaler.signal(true);

        // Two rounds of signals, the first triggers 1 callback, the second triggers 2
        assert_eq!(signaled.get(), 3);
    }
}
<|endoftext|>


<commit_before>use std::sync::Arc;
use rustc_hash::FxHashMap;

use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap};
use ra_syntax::{
    AstPtr, SourceFile, TreeArc,
ast::{self, AstNode}};

use crate::{
    Const, Type, Function, HirFileId,
    HirDatabase, PersistentHirDatabase,
    ModuleDef, Trait, Resolution,
    type_ref::TypeRef,
    ids::LocationCtx,
    resolve::Resolver,
    ty::Ty, generics::GenericParams
};

use crate::code_model_api::{Module, ModuleSource};

#[derive(Debug, Default, PartialEq, Eq)]
pub struct ImplSourceMap {
    map: ArenaMap<ImplId, AstPtr<ast::ImplBlock>>,
}

impl ImplSourceMap {
    fn insert(&mut self, impl_id: ImplId, impl_block: &ast::ImplBlock) {
        self.map.insert(impl_id, AstPtr::new(impl_block))
    }

    pub fn get(&self, source: &ModuleSource, impl_id: ImplId) -> TreeArc<ast::ImplBlock> {
        let file = match source {
            ModuleSource::SourceFile(file) => &*file,
            ModuleSource::Module(m) => m.syntax().ancestors().find_map(SourceFile::cast).unwrap(),
        };

        self.map[impl_id].to_node(file).to_owned()
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ImplBlock {
    module: Module,
    impl_id: ImplId,
}

impl ImplBlock {
    pub(crate) fn containing(
        module_impl_blocks: Arc<ModuleImplBlocks>,
        item: ImplItem,
    ) -> Option<ImplBlock> {
        let impl_id = *module_impl_blocks.impls_by_def.get(&item)?;
        Some(ImplBlock { module: module_impl_blocks.module, impl_id })
    }

    pub(crate) fn from_id(module: Module, impl_id: ImplId) -> ImplBlock {
        ImplBlock { module, impl_id }
    }

    /// Returns the syntax of the impl block
    pub fn source(&self, db: &impl PersistentHirDatabase) -> (HirFileId, TreeArc<ast::ImplBlock>) {
        let source_map = db.impls_in_module_source_map(self.module);
        let (file_id, source) = self.module.definition_source(db);
        (file_id, source_map.get(&source, self.impl_id))
    }

    pub fn id(&self) -> ImplId {
        self.impl_id
    }

    pub fn module(&self) -> Module {
        self.module
    }

    pub fn target_trait_ref(&self, db: &impl PersistentHirDatabase) -> Option<TypeRef> {
        db.impls_in_module(self.module).impls[self.impl_id].target_trait().cloned()
    }

    pub fn target_type(&self, db: &impl PersistentHirDatabase) -> TypeRef {
        db.impls_in_module(self.module).impls[self.impl_id].target_type().clone()
    }

    pub fn target_ty(&self, db: &impl HirDatabase) -> Ty {
        Ty::from_hir(db, &self.resolver(db), &self.target_type(db))
    }

    pub fn target_trait(&self, db: &impl HirDatabase) -> Option<Trait> {
        if let Some(TypeRef::Path(path)) = self.target_trait_ref(db) {
            let resolver = self.resolver(db);
            if let Some(Resolution::Def(ModuleDef::Trait(tr))) =
                resolver.resolve_path(db, &path).take_types()
            {
                return Some(tr);
            }
        }
        None
    }

    pub fn items(&self, db: &impl PersistentHirDatabase) -> Vec<ImplItem> {
        db.impls_in_module(self.module).impls[self.impl_id].items().to_vec()
    }

    pub fn generic_params(&self, db: &impl PersistentHirDatabase) -> Arc<GenericParams> {
        db.generic_params((*self).into())
    }

    pub fn resolver(&self, db: &impl HirDatabase) -> Resolver {
        let r = self.module().resolver(db);
        // TODO: add generics
        let r = r.push_impl_block_scope(self.clone());
        r
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ImplData {
    target_trait: Option<TypeRef>,
    target_type: TypeRef,
    items: Vec<ImplItem>,
}

impl ImplData {
    pub(crate) fn from_ast(
        db: &impl PersistentHirDatabase,
        file_id: HirFileId,
        module: Module,
        node: &ast::ImplBlock,
    ) -> Self {
        let target_trait = node.target_trait().map(TypeRef::from_ast);
        let target_type = TypeRef::from_ast_opt(node.target_type());
        let ctx = LocationCtx::new(db, module, file_id);
        let items = if let Some(item_list) = node.item_list() {
            item_list
                .impl_items()
                .map(|item_node| match item_node.kind() {
                    ast::ImplItemKind::FnDef(it) => {
                        ImplItem::Method(Function { id: ctx.to_def(it) })
                    }
                    ast::ImplItemKind::ConstDef(it) => {
                        ImplItem::Const(Const { id: ctx.to_def(it) })
                    }
                    ast::ImplItemKind::TypeDef(it) => ImplItem::Type(Type { id: ctx.to_def(it) }),
                })
                .collect()
        } else {
            Vec::new()
        };
        ImplData { target_trait, target_type, items }
    }

    pub fn target_trait(&self) -> Option<&TypeRef> {
        self.target_trait.as_ref()
    }

    pub fn target_type(&self) -> &TypeRef {
        &self.target_type
    }

    pub fn items(&self) -> &[ImplItem] {
        &self.items
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
//TODO: rename to ImplDef?
pub enum ImplItem {
    Method(Function),
    Const(Const),
    Type(Type),
    // Existential
}
impl_froms!(ImplItem: Const, Type);

impl From<Function> for ImplItem {
    fn from(func: Function) -> ImplItem {
        ImplItem::Method(func)
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ImplId(pub RawId);
impl_arena_id!(ImplId);

/// The collection of impl blocks is a two-step process: first we collect the
/// blocks per-module; then we build an index of all impl blocks in the crate.
/// This way, we avoid having to do this process for the whole crate whenever
/// a file is changed; as long as the impl blocks in the file don't change,
/// we don't need to do the second step again.
#[derive(Debug, PartialEq, Eq)]
pub struct ModuleImplBlocks {
    pub(crate) module: Module,
    pub(crate) impls: Arena<ImplId, ImplData>,
    impls_by_def: FxHashMap<ImplItem, ImplId>,
}

impl ModuleImplBlocks {
    fn collect(
        db: &impl PersistentHirDatabase,
        module: Module,
        source_map: &mut ImplSourceMap,
    ) -> Self {
        let mut m = ModuleImplBlocks {
            module,
            impls: Arena::default(),
            impls_by_def: FxHashMap::default(),
        };

        let (file_id, module_source) = m.module.definition_source(db);
        let file_id: HirFileId = file_id.into();
        let node = match &module_source {
            ModuleSource::SourceFile(node) => node.syntax(),
            ModuleSource::Module(node) => {
                node.item_list().expect("inline module should have item list").syntax()
            }
        };

        for impl_block_ast in node.children().filter_map(ast::ImplBlock::cast) {
            let impl_block = ImplData::from_ast(db, file_id, m.module, impl_block_ast);
            let id = m.impls.alloc(impl_block);
            for &impl_item in &m.impls[id].items {
                m.impls_by_def.insert(impl_item, id);
            }

            source_map.insert(id, impl_block_ast);
        }

        m
    }
}

pub(crate) fn impls_in_module_with_source_map_query(
    db: &impl PersistentHirDatabase,
    module: Module,
) -> (Arc<ModuleImplBlocks>, Arc<ImplSourceMap>) {
    let mut source_map = ImplSourceMap::default();

    let result = ModuleImplBlocks::collect(db, module, &mut source_map);

    (Arc::new(result), Arc::new(source_map))
}

pub(crate) fn impls_in_module(
    db: &impl PersistentHirDatabase,
    module: Module,
) -> Arc<ModuleImplBlocks> {
    db.impls_in_module_with_source_map(module).0
}

pub(crate) fn impls_in_module_source_map_query(
    db: &impl PersistentHirDatabase,
    module: Module,
) -> Arc<ImplSourceMap> {
    db.impls_in_module_with_source_map(module).1
}
<commit_msg>Resolve impl generic params<commit_after>use std::sync::Arc;
use rustc_hash::FxHashMap;

use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap};
use ra_syntax::{
    AstPtr, SourceFile, TreeArc,
ast::{self, AstNode}};

use crate::{
    Const, Type, Function, HirFileId,
    HirDatabase, PersistentHirDatabase,
    ModuleDef, Trait, Resolution,
    type_ref::TypeRef,
    ids::LocationCtx,
    resolve::Resolver,
    ty::Ty, generics::GenericParams
};

use crate::code_model_api::{Module, ModuleSource};

#[derive(Debug, Default, PartialEq, Eq)]
pub struct ImplSourceMap {
    map: ArenaMap<ImplId, AstPtr<ast::ImplBlock>>,
}

impl ImplSourceMap {
    fn insert(&mut self, impl_id: ImplId, impl_block: &ast::ImplBlock) {
        self.map.insert(impl_id, AstPtr::new(impl_block))
    }

    pub fn get(&self, source: &ModuleSource, impl_id: ImplId) -> TreeArc<ast::ImplBlock> {
        let file = match source {
            ModuleSource::SourceFile(file) => &*file,
            ModuleSource::Module(m) => m.syntax().ancestors().find_map(SourceFile::cast).unwrap(),
        };

        self.map[impl_id].to_node(file).to_owned()
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ImplBlock {
    module: Module,
    impl_id: ImplId,
}

impl ImplBlock {
    pub(crate) fn containing(
        module_impl_blocks: Arc<ModuleImplBlocks>,
        item: ImplItem,
    ) -> Option<ImplBlock> {
        let impl_id = *module_impl_blocks.impls_by_def.get(&item)?;
        Some(ImplBlock { module: module_impl_blocks.module, impl_id })
    }

    pub(crate) fn from_id(module: Module, impl_id: ImplId) -> ImplBlock {
        ImplBlock { module, impl_id }
    }

    /// Returns the syntax of the impl block
    pub fn source(&self, db: &impl PersistentHirDatabase) -> (HirFileId, TreeArc<ast::ImplBlock>) {
        let source_map = db.impls_in_module_source_map(self.module);
        let (file_id, source) = self.module.definition_source(db);
        (file_id, source_map.get(&source, self.impl_id))
    }

    pub fn id(&self) -> ImplId {
        self.impl_id
    }

    pub fn module(&self) -> Module {
        self.module
    }

    pub fn target_trait_ref(&self, db: &impl PersistentHirDatabase) -> Option<TypeRef> {
        db.impls_in_module(self.module).impls[self.impl_id].target_trait().cloned()
    }

    pub fn target_type(&self, db: &impl PersistentHirDatabase) -> TypeRef {
        db.impls_in_module(self.module).impls[self.impl_id].target_type().clone()
    }

    pub fn target_ty(&self, db: &impl HirDatabase) -> Ty {
        Ty::from_hir(db, &self.resolver(db), &self.target_type(db))
    }

    pub fn target_trait(&self, db: &impl HirDatabase) -> Option<Trait> {
        if let Some(TypeRef::Path(path)) = self.target_trait_ref(db) {
            let resolver = self.resolver(db);
            if let Some(Resolution::Def(ModuleDef::Trait(tr))) =
                resolver.resolve_path(db, &path).take_types()
            {
                return Some(tr);
            }
        }
        None
    }

    pub fn items(&self, db: &impl PersistentHirDatabase) -> Vec<ImplItem> {
        db.impls_in_module(self.module).impls[self.impl_id].items().to_vec()
    }

    pub fn generic_params(&self, db: &impl PersistentHirDatabase) -> Arc<GenericParams> {
        db.generic_params((*self).into())
    }

    pub fn resolver(&self, db: &impl HirDatabase) -> Resolver {
        let r = self.module().resolver(db);
        // add generic params, if present
        let p = self.generic_params(db);
        let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
        let r = r.push_impl_block_scope(self.clone());
        r
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ImplData {
    target_trait: Option<TypeRef>,
    target_type: TypeRef,
    items: Vec<ImplItem>,
}

impl ImplData {
    pub(crate) fn from_ast(
        db: &impl PersistentHirDatabase,
        file_id: HirFileId,
        module: Module,
        node: &ast::ImplBlock,
    ) -> Self {
        let target_trait = node.target_trait().map(TypeRef::from_ast);
        let target_type = TypeRef::from_ast_opt(node.target_type());
        let ctx = LocationCtx::new(db, module, file_id);
        let items = if let Some(item_list) = node.item_list() {
            item_list
                .impl_items()
                .map(|item_node| match item_node.kind() {
                    ast::ImplItemKind::FnDef(it) => {
                        ImplItem::Method(Function { id: ctx.to_def(it) })
                    }
                    ast::ImplItemKind::ConstDef(it) => {
                        ImplItem::Const(Const { id: ctx.to_def(it) })
                    }
                    ast::ImplItemKind::TypeDef(it) => ImplItem::Type(Type { id: ctx.to_def(it) }),
                })
                .collect()
        } else {
            Vec::new()
        };
        ImplData { target_trait, target_type, items }
    }

    pub fn target_trait(&self) -> Option<&TypeRef> {
        self.target_trait.as_ref()
    }

    pub fn target_type(&self) -> &TypeRef {
        &self.target_type
    }

    pub fn items(&self) -> &[ImplItem] {
        &self.items
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
//TODO: rename to ImplDef?
pub enum ImplItem {
    Method(Function),
    Const(Const),
    Type(Type),
    // Existential
}
impl_froms!(ImplItem: Const, Type);

impl From<Function> for ImplItem {
    fn from(func: Function) -> ImplItem {
        ImplItem::Method(func)
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ImplId(pub RawId);
impl_arena_id!(ImplId);

/// The collection of impl blocks is a two-step process: first we collect the
/// blocks per-module; then we build an index of all impl blocks in the crate.
/// This way, we avoid having to do this process for the whole crate whenever
/// a file is changed; as long as the impl blocks in the file don't change,
/// we don't need to do the second step again.
#[derive(Debug, PartialEq, Eq)]
pub struct ModuleImplBlocks {
    pub(crate) module: Module,
    pub(crate) impls: Arena<ImplId, ImplData>,
    impls_by_def: FxHashMap<ImplItem, ImplId>,
}

impl ModuleImplBlocks {
    fn collect(
        db: &impl PersistentHirDatabase,
        module: Module,
        source_map: &mut ImplSourceMap,
    ) -> Self {
        let mut m = ModuleImplBlocks {
            module,
            impls: Arena::default(),
            impls_by_def: FxHashMap::default(),
        };

        let (file_id, module_source) = m.module.definition_source(db);
        let file_id: HirFileId = file_id.into();
        let node = match &module_source {
            ModuleSource::SourceFile(node) => node.syntax(),
            ModuleSource::Module(node) => {
                node.item_list().expect("inline module should have item list").syntax()
            }
        };

        for impl_block_ast in node.children().filter_map(ast::ImplBlock::cast) {
            let impl_block = ImplData::from_ast(db, file_id, m.module, impl_block_ast);
            let id = m.impls.alloc(impl_block);
            for &impl_item in &m.impls[id].items {
                m.impls_by_def.insert(impl_item, id);
            }

            source_map.insert(id, impl_block_ast);
        }

        m
    }
}

pub(crate) fn impls_in_module_with_source_map_query(
    db: &impl PersistentHirDatabase,
    module: Module,
) -> (Arc<ModuleImplBlocks>, Arc<ImplSourceMap>) {
    let mut source_map = ImplSourceMap::default();

    let result = ModuleImplBlocks::collect(db, module, &mut source_map);

    (Arc::new(result), Arc::new(source_map))
}

pub(crate) fn impls_in_module(
    db: &impl PersistentHirDatabase,
    module: Module,
) -> Arc<ModuleImplBlocks> {
    db.impls_in_module_with_source_map(module).0
}

pub(crate) fn impls_in_module_source_map_query(
    db: &impl PersistentHirDatabase,
    module: Module,
) -> Arc<ImplSourceMap> {
    db.impls_in_module_with_source_map(module).1
}
<|endoftext|>


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

//! Internal module containing convenience utility functions mainly for testing

use crate::traits::Uniform;
use serde::{Deserialize, Serialize};

/// A deterministic seed for PRNGs related to keys
pub const TEST_SEED: [u8; 32] = [0u8; 32];

/// A keypair consisting of a private and public key
#[cfg_attr(feature = "cloneable-private-keys", derive(Clone))]
#[derive(Serialize, Deserialize, PartialEq, Eq)]
pub struct KeyPair<S, P>
where
    for<'a> P: From<&'a S>,
{
    /// the private key component
    pub private_key: S,
    /// the public key component
    pub public_key: P,
}

impl<S, P> From<S> for KeyPair<S, P>
where
    for<'a> P: From<&'a S>,
{
    fn from(private_key: S) -> Self {
        KeyPair {
            public_key: (&private_key).into(),
            private_key,
        }
    }
}

impl<S, P> Uniform for KeyPair<S, P>
where
    S: Uniform,
    for<'a> P: From<&'a S>,
{
    fn generate<R>(rng: &mut R) -> Self
    where
        R: ::rand::RngCore + ::rand::CryptoRng,
    {
        let private_key = S::generate(rng);
        private_key.into()
    }
}

/// A pair consisting of a private and public key
impl<S, P> Uniform for (S, P)
where
    S: Uniform,
    for<'a> P: From<&'a S>,
{
    fn generate<R>(rng: &mut R) -> Self
    where
        R: ::rand::RngCore + ::rand::CryptoRng,
    {
        let private_key = S::generate(rng);
        let public_key = (&private_key).into();
        (private_key, public_key)
    }
}

impl<Priv, Pub> std::fmt::Debug for KeyPair<Priv, Pub>
where
    Priv: Serialize,
    Pub: Serialize + for<'a> From<&'a Priv>,
{
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let mut v = lcs::to_bytes(&self.private_key).unwrap();
        v.extend(&lcs::to_bytes(&self.public_key).unwrap());
        write!(f, "{}", hex::encode(&v[..]))
    }
}

#[cfg(any(test, feature = "fuzzing"))]
use proptest::prelude::*;
#[cfg(any(test, feature = "fuzzing"))]
use rand::{rngs::StdRng, SeedableRng};

/// Produces a uniformly random keypair from a seed
#[cfg(any(test, feature = "fuzzing"))]
pub fn uniform_keypair_strategy<Priv, Pub>() -> impl Strategy<Value = KeyPair<Priv, Pub>>
where
    Pub: Serialize + for<'a> From<&'a Priv>,
    Priv: Serialize + Uniform,
{
    // The no_shrink is because keypairs should be fixed -- shrinking would cause a different
    // keypair to be generated, which appears to not be very useful.
    any::<[u8; 32]>()
        .prop_map(|seed| {
            let mut rng = StdRng::from_seed(seed);
            KeyPair::<Priv, Pub>::generate(&mut rng)
        })
        .no_shrink()
}

/// This struct provides a means of testing signing and verification through
/// LCS serialization and domain separation
#[cfg(any(test, feature = "fuzzing"))]
#[derive(Debug, Serialize, Deserialize)]
pub struct TestLibraCrypto(pub String);

// the following block is macro expanded from derive(CryptoHasher, LCSCryptoHash)

/// Cryptographic hasher for an LCS-serializable #item
#[cfg(any(test, feature = "fuzzing"))]
pub struct TestLibraCryptoHasher(crate::hash::DefaultHasher);
#[cfg(any(test, feature = "fuzzing"))]
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::clone::Clone for TestLibraCryptoHasher {
    #[inline]
    fn clone(&self) -> TestLibraCryptoHasher {
        match *self {
            TestLibraCryptoHasher(ref __self_0_0) => {
                TestLibraCryptoHasher(::core::clone::Clone::clone(&(*__self_0_0)))
            }
        }
    }
}
#[cfg(any(test, feature = "fuzzing"))]
static TEST_LIBRA_CRYPTO_SEED: crate::_once_cell::sync::OnceCell<[u8; 32]> =
    crate::_once_cell::sync::OnceCell::new();
#[cfg(any(test, feature = "fuzzing"))]
impl TestLibraCryptoHasher {
    fn new() -> Self {
        let name = crate::_serde_name::trace_name::<TestLibraCrypto>()
            .expect("The `CryptoHasher` macro only applies to structs and enums");
        TestLibraCryptoHasher(crate::hash::DefaultHasher::new(&name.as_bytes()))
    }
}
#[cfg(any(test, feature = "fuzzing"))]
static TEST_LIBRA_CRYPTO_HASHER: crate::_once_cell::sync::Lazy<TestLibraCryptoHasher> =
    crate::_once_cell::sync::Lazy::new(TestLibraCryptoHasher::new);
#[cfg(any(test, feature = "fuzzing"))]
impl std::default::Default for TestLibraCryptoHasher {
    fn default() -> Self {
        TEST_LIBRA_CRYPTO_HASHER.clone()
    }
}
#[cfg(any(test, feature = "fuzzing"))]
impl crate::hash::CryptoHasher for TestLibraCryptoHasher {
    fn seed() -> &'static [u8; 32] {
        TEST_LIBRA_CRYPTO_SEED.get_or_init(|| {
            let name = crate::_serde_name::trace_name::<TestLibraCrypto>()
                .expect("The `CryptoHasher` macro only applies to structs and enums.")
                .as_bytes();
            crate::hash::DefaultHasher::prefixed_hash(&name)
        })
    }
    fn update(&mut self, bytes: &[u8]) {
        self.0.update(bytes);
    }
    fn finish(self) -> crate::hash::HashValue {
        self.0.finish()
    }
}
#[cfg(any(test, feature = "fuzzing"))]
impl std::io::Write for TestLibraCryptoHasher {
    fn write(&mut self, bytes: &[u8]) -> std::io::Result<usize> {
        self.0.update(bytes);
        Ok(bytes.len())
    }
    fn flush(&mut self) -> std::io::Result<()> {
        Ok(())
    }
}
#[cfg(any(test, feature = "fuzzing"))]
impl crate::hash::CryptoHash for TestLibraCrypto {
    type Hasher = TestLibraCryptoHasher;
    fn hash(&self) -> crate::hash::HashValue {
        use crate::hash::CryptoHasher;
        let mut state = Self::Hasher::default();
        lcs::serialize_into(&mut state, &self)
            .expect("LCS serialization of TestLibraCrypto should not fail");
        state.finish()
    }
}

/// Produces a random TestLibraCrypto signable / verifiable struct.
#[cfg(any(test, feature = "fuzzing"))]
pub fn random_serializable_struct() -> impl Strategy<Value = TestLibraCrypto> {
    (String::arbitrary()).prop_map(TestLibraCrypto).no_shrink()
}
<commit_msg>[crypto] [lint] Cleanup leftovers of #5126<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

//! Internal module containing convenience utility functions mainly for testing

use crate::traits::Uniform;
use serde::{Deserialize, Serialize};

/// A deterministic seed for PRNGs related to keys
pub const TEST_SEED: [u8; 32] = [0u8; 32];

/// A keypair consisting of a private and public key
#[cfg_attr(feature = "cloneable-private-keys", derive(Clone))]
#[derive(Serialize, Deserialize, PartialEq, Eq)]
pub struct KeyPair<S, P>
where
    for<'a> P: From<&'a S>,
{
    /// the private key component
    pub private_key: S,
    /// the public key component
    pub public_key: P,
}

impl<S, P> From<S> for KeyPair<S, P>
where
    for<'a> P: From<&'a S>,
{
    fn from(private_key: S) -> Self {
        KeyPair {
            public_key: (&private_key).into(),
            private_key,
        }
    }
}

impl<S, P> Uniform for KeyPair<S, P>
where
    S: Uniform,
    for<'a> P: From<&'a S>,
{
    fn generate<R>(rng: &mut R) -> Self
    where
        R: ::rand::RngCore + ::rand::CryptoRng,
    {
        let private_key = S::generate(rng);
        private_key.into()
    }
}

/// A pair consisting of a private and public key
impl<S, P> Uniform for (S, P)
where
    S: Uniform,
    for<'a> P: From<&'a S>,
{
    fn generate<R>(rng: &mut R) -> Self
    where
        R: ::rand::RngCore + ::rand::CryptoRng,
    {
        let private_key = S::generate(rng);
        let public_key = (&private_key).into();
        (private_key, public_key)
    }
}

impl<Priv, Pub> std::fmt::Debug for KeyPair<Priv, Pub>
where
    Priv: Serialize,
    Pub: Serialize + for<'a> From<&'a Priv>,
{
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let mut v = lcs::to_bytes(&self.private_key).unwrap();
        v.extend(&lcs::to_bytes(&self.public_key).unwrap());
        write!(f, "{}", hex::encode(&v[..]))
    }
}

#[cfg(any(test, feature = "fuzzing"))]
use proptest::prelude::*;
#[cfg(any(test, feature = "fuzzing"))]
use rand::{rngs::StdRng, SeedableRng};

/// Produces a uniformly random keypair from a seed
#[cfg(any(test, feature = "fuzzing"))]
pub fn uniform_keypair_strategy<Priv, Pub>() -> impl Strategy<Value = KeyPair<Priv, Pub>>
where
    Pub: Serialize + for<'a> From<&'a Priv>,
    Priv: Serialize + Uniform,
{
    // The no_shrink is because keypairs should be fixed -- shrinking would cause a different
    // keypair to be generated, which appears to not be very useful.
    any::<[u8; 32]>()
        .prop_map(|seed| {
            let mut rng = StdRng::from_seed(seed);
            KeyPair::<Priv, Pub>::generate(&mut rng)
        })
        .no_shrink()
}

/// This struct provides a means of testing signing and verification through
/// LCS serialization and domain separation
#[cfg(any(test, feature = "fuzzing"))]
#[derive(Debug, Serialize, Deserialize)]
pub struct TestLibraCrypto(pub String);

// the following block is macro expanded from derive(CryptoHasher, LCSCryptoHash)

/// Cryptographic hasher for an LCS-serializable #item
#[cfg(any(test, feature = "fuzzing"))]
pub struct TestLibraCryptoHasher(crate::hash::DefaultHasher);
#[cfg(any(test, feature = "fuzzing"))]
impl ::core::clone::Clone for TestLibraCryptoHasher {
    #[inline]
    fn clone(&self) -> TestLibraCryptoHasher {
        match *self {
            TestLibraCryptoHasher(ref __self_0_0) => {
                TestLibraCryptoHasher(::core::clone::Clone::clone(&(*__self_0_0)))
            }
        }
    }
}
#[cfg(any(test, feature = "fuzzing"))]
static TEST_LIBRA_CRYPTO_SEED: crate::_once_cell::sync::OnceCell<[u8; 32]> =
    crate::_once_cell::sync::OnceCell::new();
#[cfg(any(test, feature = "fuzzing"))]
impl TestLibraCryptoHasher {
    fn new() -> Self {
        let name = crate::_serde_name::trace_name::<TestLibraCrypto>()
            .expect("The `CryptoHasher` macro only applies to structs and enums");
        TestLibraCryptoHasher(crate::hash::DefaultHasher::new(&name.as_bytes()))
    }
}
#[cfg(any(test, feature = "fuzzing"))]
static TEST_LIBRA_CRYPTO_HASHER: crate::_once_cell::sync::Lazy<TestLibraCryptoHasher> =
    crate::_once_cell::sync::Lazy::new(TestLibraCryptoHasher::new);
#[cfg(any(test, feature = "fuzzing"))]
impl std::default::Default for TestLibraCryptoHasher {
    fn default() -> Self {
        TEST_LIBRA_CRYPTO_HASHER.clone()
    }
}
#[cfg(any(test, feature = "fuzzing"))]
impl crate::hash::CryptoHasher for TestLibraCryptoHasher {
    fn seed() -> &'static [u8; 32] {
        TEST_LIBRA_CRYPTO_SEED.get_or_init(|| {
            let name = crate::_serde_name::trace_name::<TestLibraCrypto>()
                .expect("The `CryptoHasher` macro only applies to structs and enums.")
                .as_bytes();
            crate::hash::DefaultHasher::prefixed_hash(&name)
        })
    }
    fn update(&mut self, bytes: &[u8]) {
        self.0.update(bytes);
    }
    fn finish(self) -> crate::hash::HashValue {
        self.0.finish()
    }
}
#[cfg(any(test, feature = "fuzzing"))]
impl std::io::Write for TestLibraCryptoHasher {
    fn write(&mut self, bytes: &[u8]) -> std::io::Result<usize> {
        self.0.update(bytes);
        Ok(bytes.len())
    }
    fn flush(&mut self) -> std::io::Result<()> {
        Ok(())
    }
}
#[cfg(any(test, feature = "fuzzing"))]
impl crate::hash::CryptoHash for TestLibraCrypto {
    type Hasher = TestLibraCryptoHasher;
    fn hash(&self) -> crate::hash::HashValue {
        use crate::hash::CryptoHasher;
        let mut state = Self::Hasher::default();
        lcs::serialize_into(&mut state, &self)
            .expect("LCS serialization of TestLibraCrypto should not fail");
        state.finish()
    }
}

/// Produces a random TestLibraCrypto signable / verifiable struct.
#[cfg(any(test, feature = "fuzzing"))]
pub fn random_serializable_struct() -> impl Strategy<Value = TestLibraCrypto> {
    (String::arbitrary()).prop_map(TestLibraCrypto).no_shrink()
}
<|endoftext|>


<commit_before>use std::{
    env,
    path::{Path, PathBuf},
};

pub static BACKUP_CONTROL_VALUES: &[&str] = &[
    "simple", "never", "numbered", "t", "existing", "nil", "none", "off",
];

pub static BACKUP_CONTROL_LONG_HELP: &str =
"The backup suffix is '~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX.
The version control method may be selected via the --backup option or through
the VERSION_CONTROL environment variable.  Here are the values:

  none, off       never make backups (even if --backup is given)
  numbered, t     make numbered backups
  existing, nil   numbered if numbered backups exist, simple otherwise
  simple, never   always make simple backups";

#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum BackupMode {
    NoBackup,
    SimpleBackup,
    NumberedBackup,
    ExistingBackup,
}

pub fn determine_backup_suffix(supplied_suffix: Option<&str>) -> String {
    if let Some(suffix) = supplied_suffix {
        String::from(suffix)
    } else {
        env::var("SIMPLE_BACKUP_SUFFIX").unwrap_or_else(|_| "~".to_owned())
    }
}

/// # TODO
///
/// This function currently deviates slightly from how the [manual][1] describes
/// that it should work. In particular, the current implementation:
///
/// 1. Doesn't strictly respect the order in which to determine the backup type,
///    which is (in order of precedence)
///     1. Take a valid value to the '--backup' option
///     2. Take the value of the `VERSION_CONTROL` env var
///     3. default to 'existing'
/// 2. Doesn't accept abbreviations to the 'backup_option' parameter
///
/// [1]: https://www.gnu.org/software/coreutils/manual/html_node/Backup-options.html
pub fn determine_backup_mode(backup_opt_exists: bool, backup_opt: Option<&str>) -> BackupMode {
    if backup_opt_exists {
        match backup_opt.map(String::from) {
            // default is existing, see:
            // https://www.gnu.org/software/coreutils/manual/html_node/Backup-options.html
            None => BackupMode::ExistingBackup,
            Some(mode) => match &mode[..] {
                "simple" | "never" => BackupMode::SimpleBackup,
                "numbered" | "t" => BackupMode::NumberedBackup,
                "existing" | "nil" => BackupMode::ExistingBackup,
                "none" | "off" => BackupMode::NoBackup,
                _ => panic!(), // cannot happen as it is managed by clap
            },
        }
    } else {
        BackupMode::NoBackup
    }
}

/// Match a backup option string to a `BackupMode`.
///
/// The GNU manual specifies that abbreviations to options are valid as long as
/// they aren't ambiguous. This function matches the given `method` argument
/// against all valid backup options (via `starts_with`), and returns a valid
/// [`BackupMode`] if exactly one backup option matches the `method` given.
///
/// `origin` is required in order to format the generated error message
/// properly, when an error occurs.
///
///
/// # Errors
///
/// If `method` is ambiguous (i.e. may resolve to multiple backup modes) or
/// invalid, an error is returned. The error contains the formatted error string
/// which may then be passed to the [`show_usage_error`] macro.
fn match_method(method: &str, origin: &str) -> Result<BackupMode, String> {
    let x = vec!["simple", "never", "numbered", "t",
                 "existing", "nil", "none", "off"];

    let matches: Vec<&&str> = x.iter()
        .filter(|val| val.starts_with(method))
        .collect();
    if matches.len() == 1 {
        match *matches[0] {
            "simple" | "never" => Ok(BackupMode::SimpleBackup),
            "numbered" | "t" => Ok(BackupMode::NumberedBackup),
            "existing" | "nil" => Ok(BackupMode::ExistingBackup),
            "none" | "off" => Ok(BackupMode::NoBackup),
            _ => panic!(),  // cannot happen as we must have exactly one match
                            // from the list above.
        }
    } else {
        let error_type = if matches.len() == 0 { "invalid" } else { "ambiguous" };
        Err(format!(
"{0} argument ‘{1}’ for ‘{2}’
Valid arguments are:
  - ‘none’, ‘off’
  - ‘simple’, ‘never’
  - ‘existing’, ‘nil’
  - ‘numbered’, ‘t’", error_type, method, origin))
    }
}

pub fn get_backup_path(
    backup_mode: BackupMode,
    backup_path: &Path,
    suffix: &str,
) -> Option<PathBuf> {
    match backup_mode {
        BackupMode::NoBackup => None,
        BackupMode::SimpleBackup => Some(simple_backup_path(backup_path, suffix)),
        BackupMode::NumberedBackup => Some(numbered_backup_path(backup_path)),
        BackupMode::ExistingBackup => Some(existing_backup_path(backup_path, suffix)),
    }
}

pub fn simple_backup_path(path: &Path, suffix: &str) -> PathBuf {
    let mut p = path.to_string_lossy().into_owned();
    p.push_str(suffix);
    PathBuf::from(p)
}

pub fn numbered_backup_path(path: &Path) -> PathBuf {
    for i in 1_u64.. {
        let path_str = &format!("{}.~{}~", path.to_string_lossy(), i);
        let path = Path::new(path_str);
        if !path.exists() {
            return path.to_path_buf();
        }
    }
    panic!("cannot create backup")
}

pub fn existing_backup_path(path: &Path, suffix: &str) -> PathBuf {
    let test_path_str = &format!("{}.~1~", path.to_string_lossy());
    let test_path = Path::new(test_path_str);
    if test_path.exists() {
        numbered_backup_path(path)
    } else {
        simple_backup_path(path, suffix)
    }
}
<commit_msg>backup_control: Make utility functions private<commit_after>use std::{
    env,
    path::{Path, PathBuf},
};

pub static BACKUP_CONTROL_VALUES: &[&str] = &[
    "simple", "never", "numbered", "t", "existing", "nil", "none", "off",
];

pub static BACKUP_CONTROL_LONG_HELP: &str =
"The backup suffix is '~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX.
The version control method may be selected via the --backup option or through
the VERSION_CONTROL environment variable.  Here are the values:

  none, off       never make backups (even if --backup is given)
  numbered, t     make numbered backups
  existing, nil   numbered if numbered backups exist, simple otherwise
  simple, never   always make simple backups";

#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum BackupMode {
    NoBackup,
    SimpleBackup,
    NumberedBackup,
    ExistingBackup,
}

pub fn determine_backup_suffix(supplied_suffix: Option<&str>) -> String {
    if let Some(suffix) = supplied_suffix {
        String::from(suffix)
    } else {
        env::var("SIMPLE_BACKUP_SUFFIX").unwrap_or_else(|_| "~".to_owned())
    }
}

/// # TODO
///
/// This function currently deviates slightly from how the [manual][1] describes
/// that it should work. In particular, the current implementation:
///
/// 1. Doesn't strictly respect the order in which to determine the backup type,
///    which is (in order of precedence)
///     1. Take a valid value to the '--backup' option
///     2. Take the value of the `VERSION_CONTROL` env var
///     3. default to 'existing'
/// 2. Doesn't accept abbreviations to the 'backup_option' parameter
///
/// [1]: https://www.gnu.org/software/coreutils/manual/html_node/Backup-options.html
pub fn determine_backup_mode(backup_opt_exists: bool, backup_opt: Option<&str>) -> BackupMode {
    if backup_opt_exists {
        match backup_opt.map(String::from) {
            // default is existing, see:
            // https://www.gnu.org/software/coreutils/manual/html_node/Backup-options.html
            None => BackupMode::ExistingBackup,
            Some(mode) => match &mode[..] {
                "simple" | "never" => BackupMode::SimpleBackup,
                "numbered" | "t" => BackupMode::NumberedBackup,
                "existing" | "nil" => BackupMode::ExistingBackup,
                "none" | "off" => BackupMode::NoBackup,
                _ => panic!(), // cannot happen as it is managed by clap
            },
        }
    } else {
        BackupMode::NoBackup
    }
}

/// Match a backup option string to a `BackupMode`.
///
/// The GNU manual specifies that abbreviations to options are valid as long as
/// they aren't ambiguous. This function matches the given `method` argument
/// against all valid backup options (via `starts_with`), and returns a valid
/// [`BackupMode`] if exactly one backup option matches the `method` given.
///
/// `origin` is required in order to format the generated error message
/// properly, when an error occurs.
///
///
/// # Errors
///
/// If `method` is ambiguous (i.e. may resolve to multiple backup modes) or
/// invalid, an error is returned. The error contains the formatted error string
/// which may then be passed to the [`show_usage_error`] macro.
fn match_method(method: &str, origin: &str) -> Result<BackupMode, String> {
    let x = vec!["simple", "never", "numbered", "t",
                 "existing", "nil", "none", "off"];

    let matches: Vec<&&str> = x.iter()
        .filter(|val| val.starts_with(method))
        .collect();
    if matches.len() == 1 {
        match *matches[0] {
            "simple" | "never" => Ok(BackupMode::SimpleBackup),
            "numbered" | "t" => Ok(BackupMode::NumberedBackup),
            "existing" | "nil" => Ok(BackupMode::ExistingBackup),
            "none" | "off" => Ok(BackupMode::NoBackup),
            _ => panic!(),  // cannot happen as we must have exactly one match
                            // from the list above.
        }
    } else {
        let error_type = if matches.len() == 0 { "invalid" } else { "ambiguous" };
        Err(format!(
"{0} argument ‘{1}’ for ‘{2}’
Valid arguments are:
  - ‘none’, ‘off’
  - ‘simple’, ‘never’
  - ‘existing’, ‘nil’
  - ‘numbered’, ‘t’", error_type, method, origin))
    }
}

pub fn get_backup_path(
    backup_mode: BackupMode,
    backup_path: &Path,
    suffix: &str,
) -> Option<PathBuf> {
    match backup_mode {
        BackupMode::NoBackup => None,
        BackupMode::SimpleBackup => Some(simple_backup_path(backup_path, suffix)),
        BackupMode::NumberedBackup => Some(numbered_backup_path(backup_path)),
        BackupMode::ExistingBackup => Some(existing_backup_path(backup_path, suffix)),
    }
}

fn simple_backup_path(path: &Path, suffix: &str) -> PathBuf {
    let mut p = path.to_string_lossy().into_owned();
    p.push_str(suffix);
    PathBuf::from(p)
}

fn numbered_backup_path(path: &Path) -> PathBuf {
    for i in 1_u64.. {
        let path_str = &format!("{}.~{}~", path.to_string_lossy(), i);
        let path = Path::new(path_str);
        if !path.exists() {
            return path.to_path_buf();
        }
    }
    panic!("cannot create backup")
}

fn existing_backup_path(path: &Path, suffix: &str) -> PathBuf {
    let test_path_str = &format!("{}.~1~", path.to_string_lossy());
    let test_path = Path::new(test_path_str);
    if test_path.exists() {
        numbered_backup_path(path)
    } else {
        simple_backup_path(path, suffix)
    }
}
<|endoftext|>


<commit_before>fn main() {
    println!("Hello, world!");
}
<commit_msg>Set up fakemain.<commit_after>fn main() {
    // Fake-main technique. This allows the main() function to return an int (i32) status code.
    std::process::exit(fake_main());
}

fn fake_main() -> i32 {
    println!("Hello from fakemain.");
    return 0;
}
<|endoftext|>