<commit_before>use alloc::boxed::Box;

use collections::string::{String, ToString};
use collections::vec::Vec;

use core::cmp::{min, max};

/// ARP scheme
pub mod arp;
/// Context scheme
pub mod context;
/// Debug scheme
pub mod debug;
/// Display Scheme
pub mod display;
/// Ethernet scheme
pub mod ethernet;
/// File scheme
pub mod file;
/// IP scheme
pub mod ip;
/// Memory scheme
pub mod memory;
/// Pseudo random generation scheme
pub mod random;
/// Time scheme
pub mod time;
/// Window scheme
pub mod window;

#[allow(unused_variables)]
pub trait KScheme {
    fn on_irq(&mut self, irq: u8) {

    }

    fn on_poll(&mut self) {

    }

    fn scheme(&self) -> &str {
        ""
    }

    fn open(&mut self, url: &URL) -> Option<Box<Resource>> {
        None
    }
}

/// Resource seek
pub enum ResourceSeek {
    /// Start point
    Start(usize),
    /// Current point
    Current(isize),
    /// End point
    End(isize),
}

/// A system resource
#[allow(unused_variables)]
pub trait Resource {
    /// Duplicate the resource
    fn dup(&self) -> Option<Box<Resource>> {
        None
    }
    /// Return the url of this resource
    fn url(&self) -> URL;
    // TODO: Make use of Write and Read trait
    /// Read data to buffer
    fn read(&mut self, buf: &mut [u8]) -> Option<usize> {
        None
    }
    /// Write to resource
    fn write(&mut self, buf: &[u8]) -> Option<usize> {
        None
    }
    /// Seek
    fn seek(&mut self, pos: ResourceSeek) -> Option<usize> {
        None
    }
    /// Sync the resource
    fn sync(&mut self) -> bool {
        false
    }

    //Helper functions
    fn read_to_end(&mut self, vec: &mut Vec<u8>) -> Option<usize> {
        let mut read = 0;
        loop {
            let mut bytes = [0; 1024];
            match self.read(&mut bytes) {
                Some(0) => return Some(read),
                None => return None,
                Some(count) => {
                    vec.push_all(&bytes[0..count]);
                    read += count;
                }
            }
        }
    }
}

/// An URL, see wiki
pub struct URL {
    pub string: String,
}

impl URL {
    /// Create a new empty URL
    pub fn new() -> Self {
        URL { string: String::new() }
    }

    /// Create an URL from a string literal
    pub fn from_str(url_str: &'static str) -> Self {
        return URL::from_string(&url_str.to_string());
    }

    /// Create an URL from `String`
    pub fn from_string(url_string: &String) -> Self {
        URL { string: url_string.clone() }
    }

    /// Convert to string
    pub fn to_string(&self) -> String {
        self.string.clone()
    }

    /// Get the length of this URL
    pub fn len(&self) -> usize {
        self.string.len()
    }

    /// Open this URL (returns a resource)
    pub fn open(&self) -> Option<Box<Resource>> {
        unsafe {
            return (*::session_ptr).open(&self);
        }
    }

    /// Return the scheme of this url
    pub fn scheme(&self) -> &str {
        &self.string[..self.string.find(':').unwrap_or(self.string.len())]
    }

    /// Get the reference (after the ':') of the url
    pub fn reference(&self) -> &str {
        &self.string[(1 + self.string.find(':').unwrap_or(self.string.len()))..]
    }

}

impl Clone for URL {
    fn clone(&self) -> Self {
        URL { string: self.string.clone() }
    }
}

/// A vector resource
pub struct VecResource {
    url: URL,
    vec: Vec<u8>,
    seek: usize,
}

impl VecResource {
    pub fn new(url: URL, vec: Vec<u8>) -> Self {
        VecResource {
            url: url,
            vec: vec,
            seek: 0,
        }
    }

    pub fn inner(&self) -> &Vec<u8> {
        return &self.vec;
    }
}

impl Resource for VecResource {
    fn dup(&self) -> Option<Box<Resource>> {
        Some(box VecResource {
            url: self.url.clone(),
            vec: self.vec.clone(),
            seek: self.seek,
        })
    }

    fn url(&self) -> URL {
        return self.url.clone();
    }

    fn read(&mut self, buf: &mut [u8]) -> Option<usize> {
        let mut i = 0;
        while i < buf.len() && self.seek < self.vec.len() {
            match self.vec.get(self.seek) {
                Some(b) => buf[i] = *b,
                None => (),
            }
            self.seek += 1;
            i += 1;
        }
        return Some(i);
    }

    fn write(&mut self, buf: &[u8]) -> Option<usize> {
        let mut i = 0;
        while i < buf.len() && self.seek < self.vec.len() {
            self.vec[self.seek] = buf[i];
            self.seek += 1;
            i += 1;
        }
        while i < buf.len() {
            self.vec.push(buf[i]);
            self.seek += 1;
            i += 1;
        }
        return Some(i);
    }

    fn seek(&mut self, pos: ResourceSeek) -> Option<usize> {
        match pos {
            ResourceSeek::Start(offset) => self.seek = min(self.vec.len(), offset),
            ResourceSeek::Current(offset) =>
                self.seek = max(0, min(self.seek as isize, self.seek as isize + offset)) as usize,
            ResourceSeek::End(offset) =>
                self.seek =
                    max(0, min(self.seek as isize, self.vec.len() as isize + offset)) as usize,
        }
        return Some(self.seek);
    }

    fn sync(&mut self) -> bool {
        return true;
    }
}
<commit_msg>Have to explicitly match or will still `1 + string.len()`<commit_after>use alloc::boxed::Box;

use collections::string::{String, ToString};
use collections::vec::Vec;

use core::cmp::{min, max};

/// ARP scheme
pub mod arp;
/// Context scheme
pub mod context;
/// Debug scheme
pub mod debug;
/// Display Scheme
pub mod display;
/// Ethernet scheme
pub mod ethernet;
/// File scheme
pub mod file;
/// IP scheme
pub mod ip;
/// Memory scheme
pub mod memory;
/// Pseudo random generation scheme
pub mod random;
/// Time scheme
pub mod time;
/// Window scheme
pub mod window;

#[allow(unused_variables)]
pub trait KScheme {
    fn on_irq(&mut self, irq: u8) {

    }

    fn on_poll(&mut self) {

    }

    fn scheme(&self) -> &str {
        ""
    }

    fn open(&mut self, url: &URL) -> Option<Box<Resource>> {
        None
    }
}

/// Resource seek
pub enum ResourceSeek {
    /// Start point
    Start(usize),
    /// Current point
    Current(isize),
    /// End point
    End(isize),
}

/// A system resource
#[allow(unused_variables)]
pub trait Resource {
    /// Duplicate the resource
    fn dup(&self) -> Option<Box<Resource>> {
        None
    }
    /// Return the url of this resource
    fn url(&self) -> URL;
    // TODO: Make use of Write and Read trait
    /// Read data to buffer
    fn read(&mut self, buf: &mut [u8]) -> Option<usize> {
        None
    }
    /// Write to resource
    fn write(&mut self, buf: &[u8]) -> Option<usize> {
        None
    }
    /// Seek
    fn seek(&mut self, pos: ResourceSeek) -> Option<usize> {
        None
    }
    /// Sync the resource
    fn sync(&mut self) -> bool {
        false
    }

    //Helper functions
    fn read_to_end(&mut self, vec: &mut Vec<u8>) -> Option<usize> {
        let mut read = 0;
        loop {
            let mut bytes = [0; 1024];
            match self.read(&mut bytes) {
                Some(0) => return Some(read),
                None => return None,
                Some(count) => {
                    vec.push_all(&bytes[0..count]);
                    read += count;
                }
            }
        }
    }
}

/// An URL, see wiki
pub struct URL {
    pub string: String,
}

impl URL {
    /// Create a new empty URL
    pub fn new() -> Self {
        URL { string: String::new() }
    }

    /// Create an URL from a string literal
    pub fn from_str(url_str: &'static str) -> Self {
        return URL::from_string(&url_str.to_string());
    }

    /// Create an URL from `String`
    pub fn from_string(url_string: &String) -> Self {
        URL { string: url_string.clone() }
    }

    /// Convert to string
    pub fn to_string(&self) -> String {
        self.string.clone()
    }

    /// Get the length of this URL
    pub fn len(&self) -> usize {
        self.string.len()
    }

    /// Open this URL (returns a resource)
    pub fn open(&self) -> Option<Box<Resource>> {
        unsafe {
            return (*::session_ptr).open(&self);
        }
    }

    /// Return the scheme of this url
    pub fn scheme(&self) -> &str {
        &self.string[..self.string.find(':').unwrap_or(self.string.len())]
    }

    /// Get the reference (after the ':') of the url
    pub fn reference(&self) -> &str {
        &self.string[
        match self.string.find(':') {
            Some(pos) => pos + 1,
            None => self.string.len(),
        }
        ..]
    }

}

impl Clone for URL {
    fn clone(&self) -> Self {
        URL { string: self.string.clone() }
    }
}

/// A vector resource
pub struct VecResource {
    url: URL,
    vec: Vec<u8>,
    seek: usize,
}

impl VecResource {
    pub fn new(url: URL, vec: Vec<u8>) -> Self {
        VecResource {
            url: url,
            vec: vec,
            seek: 0,
        }
    }

    pub fn inner(&self) -> &Vec<u8> {
        return &self.vec;
    }
}

impl Resource for VecResource {
    fn dup(&self) -> Option<Box<Resource>> {
        Some(box VecResource {
            url: self.url.clone(),
            vec: self.vec.clone(),
            seek: self.seek,
        })
    }

    fn url(&self) -> URL {
        return self.url.clone();
    }

    fn read(&mut self, buf: &mut [u8]) -> Option<usize> {
        let mut i = 0;
        while i < buf.len() && self.seek < self.vec.len() {
            match self.vec.get(self.seek) {
                Some(b) => buf[i] = *b,
                None => (),
            }
            self.seek += 1;
            i += 1;
        }
        return Some(i);
    }

    fn write(&mut self, buf: &[u8]) -> Option<usize> {
        let mut i = 0;
        while i < buf.len() && self.seek < self.vec.len() {
            self.vec[self.seek] = buf[i];
            self.seek += 1;
            i += 1;
        }
        while i < buf.len() {
            self.vec.push(buf[i]);
            self.seek += 1;
            i += 1;
        }
        return Some(i);
    }

    fn seek(&mut self, pos: ResourceSeek) -> Option<usize> {
        match pos {
            ResourceSeek::Start(offset) => self.seek = min(self.vec.len(), offset),
            ResourceSeek::Current(offset) =>
                self.seek = max(0, min(self.seek as isize, self.seek as isize + offset)) as usize,
            ResourceSeek::End(offset) =>
                self.seek =
                    max(0, min(self.seek as isize, self.vec.len() as isize + offset)) as usize,
        }
        return Some(self.seek);
    }

    fn sync(&mut self) -> bool {
        return true;
    }
}
<|endoftext|>


<commit_before>// https://leetcode.com/problems/length-of-the-longest-alphabetical-continuous-substring/
pub fn longest_continuous_substring(s: String) -> i32 {
    todo!()
}

fn main() {
    println!("{}", longest_continuous_substring("abacaba".to_string())); // 2
    println!("{}", longest_continuous_substring("abcde".to_string())); // 5
}
<commit_msg>Update problem 2414<commit_after>// https://leetcode.com/problems/length-of-the-longest-alphabetical-continuous-substring/
pub fn longest_continuous_substring(s: String) -> i32 {
    todo!()
}

fn main() {
    println!("{}", longest_continuous_substring("abacaba".to_string())); // 2
    println!("{}", longest_continuous_substring("abcde".to_string())); // 5
    println!(
        "{}",
        longest_continuous_substring("xyziabcdefmnrvx".to_string())
    ); // 6
}
<|endoftext|>


<commit_before>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

extern crate num;

use self::num::complex::{Complex32, Complex64};
use pointer::CPtr;
use vector;
use vector::BlasVector;

pub trait Copy {
    fn copy(x: &BlasVector<Self>, y: &mut BlasVector<Self>);
}

macro_rules! copy_impl(
    ($t: ty, $copy_fn: ident) => (
        impl Copy for $t {
            fn copy(x: &BlasVector<$t>, y: &mut BlasVector<$t>) {
                unsafe {
                    vector::ll::$copy_fn(x.len(),
                        x.as_ptr().as_c_ptr(),  x.inc(),
                        y.as_mut_ptr().as_c_ptr(), y.inc());
                }
            }
        }
    );
)

copy_impl!(f32,       cblas_scopy)
copy_impl!(f64,       cblas_dcopy)
copy_impl!(Complex32, cblas_ccopy)
copy_impl!(Complex64, cblas_zcopy)
<commit_msg>Add Axpy trait<commit_after>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

extern crate num;

use self::num::complex::{Complex, Complex32, Complex64};
use std::cmp;
use pointer::CPtr;
use scalar::Scalar;
use vector;
use vector::BlasVector;

pub trait Copy {
    fn copy(x: &BlasVector<Self>, y: &mut BlasVector<Self>);
}

macro_rules! copy_impl(
    ($t: ty, $copy_fn: ident) => (
        impl Copy for $t {
            fn copy(x: &BlasVector<$t>, y: &mut BlasVector<$t>) {
                unsafe {
                    vector::ll::$copy_fn(x.len(),
                        x.as_ptr().as_c_ptr(),  x.inc(),
                        y.as_mut_ptr().as_c_ptr(), y.inc());
                }
            }
        }
    );
)

copy_impl!(f32,       cblas_scopy)
copy_impl!(f64,       cblas_dcopy)
copy_impl!(Complex32, cblas_ccopy)
copy_impl!(Complex64, cblas_zcopy)

pub trait Axpy {
    fn axpy(alpha: Self, x: &BlasVector<Self>, y: &mut BlasVector<Self>);
}

macro_rules! axpy_impl(
    ($t: ty, $update_fn: ident) => (
        impl Axpy for $t {
            fn axpy(alpha: $t, x: &BlasVector<$t>, y: &mut BlasVector<$t>) {
                unsafe {
                    let n = cmp::min(x.len(), y.len());

                    vector::ll::$update_fn(n,
                        (&alpha).as_const(),
                        x.as_ptr().as_c_ptr(), x.inc(),
                        y.as_mut_ptr().as_c_ptr(), y.inc());
                }
            }
        }
    );
)

axpy_impl!(f32,       cblas_saxpy)
axpy_impl!(f64,       cblas_daxpy)
axpy_impl!(Complex32, cblas_caxpy)
axpy_impl!(Complex64, cblas_zaxpy)

#[cfg(test)]
mod axpy_tests {
    extern crate num;
    extern crate test;

    use self::num::complex::Complex;
    use vector::ops::Axpy;

    #[test]
    fn real() {
        let x = vec![1f32,-2f32,3f32,4f32];
        let y = vec![3f32,7f32,-2f32,2f32];
        let mut z = y.clone();

        Axpy::axpy(1f32, &y, &mut z);
        Axpy::axpy(1f32, &x, &mut z);
        assert_eq!(z, vec![7f32,12f32,-1f32,8f32]);
    }

    #[test]
    fn complex() {
        let x = vec![Complex::new(1f32, 1f32), Complex::new(1f32, 3f32)];
        let y = vec![Complex::new(3f32, -2f32), Complex::new(2f32, 3f32)];
        let mut z = x.clone();

        Axpy::axpy(Complex::new(-1f32, 1f32), &y, &mut z);
        assert_eq!(z, vec![Complex::new(0f32, 6f32), Complex::new(-4f32, 2f32)]);
    }

}
<|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.

// Targets the Cortex-M4F and Cortex-M7F processors (ARMv7E-M)
//
// This target assumes that the device does have a FPU (Floating Point Unit) and lowers all (single
// precision) floating point operations to hardware instructions.
//
// Additionally, this target uses the "hard" floating convention (ABI) where floating point values
// are passed to/from subroutines via FPU registers (S0, S1, D0, D1, etc.).
//
// To opt into double precision hardware support, use the `-C target-feature=-fp-only-sp` flag.

use target::{Target, TargetOptions, TargetResult};

pub fn target() -> TargetResult {
    Ok(Target {
        llvm_target: "thumbv7em-none-eabihf".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "32".to_string(),
        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
        arch: "arm".to_string(),
        target_os: "none".to_string(),
        target_env: "".to_string(),
        target_vendor: "".to_string(),

        options: TargetOptions {
            // `+vfp4` is the lowest common denominator between the Cortex-M4 (vfp4-16) and the
            // Cortex-M7 (vfp5)
            // `+d16` both the Cortex-M4 and the Cortex-M7 only have 16 double-precision registers
            // available
            // `+fp-only-sp` The Cortex-M4 only supports single precision floating point operations
            // whereas in the Cortex-M7 double precision is optional
            features: "+vfp4,+d16,+fp-only-sp".to_string(),
            max_atomic_width: 32,
            .. super::thumb_base::opts()
        }
    })
}
<commit_msg>add a reference about the stated FP facts<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.

// Targets the Cortex-M4F and Cortex-M7F processors (ARMv7E-M)
//
// This target assumes that the device does have a FPU (Floating Point Unit) and lowers all (single
// precision) floating point operations to hardware instructions.
//
// Additionally, this target uses the "hard" floating convention (ABI) where floating point values
// are passed to/from subroutines via FPU registers (S0, S1, D0, D1, etc.).
//
// To opt into double precision hardware support, use the `-C target-feature=-fp-only-sp` flag.

use target::{Target, TargetOptions, TargetResult};

pub fn target() -> TargetResult {
    Ok(Target {
        llvm_target: "thumbv7em-none-eabihf".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "32".to_string(),
        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
        arch: "arm".to_string(),
        target_os: "none".to_string(),
        target_env: "".to_string(),
        target_vendor: "".to_string(),

        options: TargetOptions {
            // `+vfp4` is the lowest common denominator between the Cortex-M4 (vfp4-16) and the
            // Cortex-M7 (vfp5)
            // `+d16` both the Cortex-M4 and the Cortex-M7 only have 16 double-precision registers
            // available
            // `+fp-only-sp` The Cortex-M4 only supports single precision floating point operations
            // whereas in the Cortex-M7 double precision is optional
            //
            // Reference:
            // ARMv7-M Architecture Reference Manual - A2.5 The optional floating-point extension
            features: "+vfp4,+d16,+fp-only-sp".to_string(),
            max_atomic_width: 32,
            .. super::thumb_base::opts()
        }
    })
}
<|endoftext|>


<commit_before>
use std::error::Error;
use std::fs::File;
use std::io::{self, BufRead, BufReader};
use std::vec::Vec;

use std::collections::{HashMap, HashSet};

use rand::{thread_rng, Rng};

fn is_unique(s: &str) -> bool {
    let set : HashSet<char> = s.chars().collect();
    set.len() == s.len()
}

fn letter_combos(words: &[String]) -> HashMap<Vec<char>, Vec<&String>> {
    let mut combos = HashMap::new();
    for word in words {
        let mut chars : Vec<char> = word.chars().collect();
        chars.sort();
        combos.entry(chars).or_insert(Vec::new()).push(word);
    }
    combos
}

fn gen_guess<'a>(combos: &HashMap<Vec<char>, Vec<&'a String>>) -> &'a String {
    let mut rng = thread_rng();

    let size = combos.len();
    let select = rng.gen_range(0, size);
    let words = combos.iter().nth(select).unwrap().1;
    words[rng.gen_range(0, words.len())]
}

fn num_matches(first: &Vec<char>, second: &Vec<char>) -> i32 {
    let mut matches = 0;
    for c in first {
        if second.contains(&c) {
            matches += 1;
        }
    }
    matches
}

fn filter_matches(word: &str, matching: i32, combos: &mut HashMap<Vec<char>, Vec<&String>>) {
    let mut chars : Vec<char> = word.chars().collect();
    chars.sort();

    combos.retain(|k, _| num_matches(k, &chars) == matching);
}

fn main() {
    let f = match File::open("dictionary.txt") {
        Ok(f) => f,
        Err(why) => panic!("Failed to open links.txt: {}", Error::description(&why)),
    };

    let words: Vec<String> = BufReader::new(f)
        .lines()
        .map(|s| s.unwrap())
        .filter(|s| s.len() == 5)
        .filter(|s| is_unique(s))
        .collect();

    let mut combos = letter_combos(&words);
    println!("Ready?");
    let mut input = String::new();
    io::stdin().read_line(&mut input).unwrap();
    while combos.len() > 1 {
        input.clear();
        let guess = gen_guess(&combos);
        println!("My next guess is: {}", guess);
        io::stdin().read_line(&mut input).unwrap();
        let num_matching : i32 = input.trim().parse().unwrap();
        if num_matching < 0 || num_matching > 5 {
            println!("No cheating!");
            continue;
        }
        filter_matches(guess, num_matching, &mut combos);
        println!("{} letter combos remaining.", combos.len());
    }

    if combos.len() == 1 {
        println!("My guesses:");
        for combo in combos {
            for word in combo.1 {
                println!("{}", word);
            }
        }
    } else {
        println!("You failed!");
    }
}
<commit_msg>rustfmt<commit_after>use std::error::Error;
use std::fs::File;
use std::io::{self, BufRead, BufReader};
use std::vec::Vec;

use std::collections::{HashMap, HashSet};

use rand::{thread_rng, Rng};

fn is_unique(s: &str) -> bool {
    let set: HashSet<char> = s.chars().collect();
    set.len() == s.len()
}

fn letter_combos(words: &[String]) -> HashMap<Vec<char>, Vec<&String>> {
    let mut combos = HashMap::new();
    for word in words {
        let mut chars: Vec<char> = word.chars().collect();
        chars.sort();
        combos.entry(chars).or_insert(Vec::new()).push(word);
    }
    combos
}

fn gen_guess<'a>(combos: &HashMap<Vec<char>, Vec<&'a String>>) -> &'a String {
    let mut rng = thread_rng();

    let size = combos.len();
    let select = rng.gen_range(0, size);
    let words = combos.iter().nth(select).unwrap().1;
    words[rng.gen_range(0, words.len())]
}

fn num_matches(first: &Vec<char>, second: &Vec<char>) -> i32 {
    let mut matches = 0;
    for c in first {
        if second.contains(&c) {
            matches += 1;
        }
    }
    matches
}

fn filter_matches(word: &str, matching: i32, combos: &mut HashMap<Vec<char>, Vec<&String>>) {
    let mut chars: Vec<char> = word.chars().collect();
    chars.sort();

    combos.retain(|k, _| num_matches(k, &chars) == matching);
}

fn main() {
    let f = match File::open("dictionary.txt") {
        Ok(f) => f,
        Err(why) => panic!("Failed to open links.txt: {}", Error::description(&why)),
    };

    let words: Vec<String> = BufReader::new(f)
        .lines()
        .map(|s| s.unwrap())
        .filter(|s| s.len() == 5)
        .filter(|s| is_unique(s))
        .collect();

    let mut combos = letter_combos(&words);
    println!("Ready?");
    let mut input = String::new();
    io::stdin().read_line(&mut input).unwrap();
    while combos.len() > 1 {
        input.clear();
        let guess = gen_guess(&combos);
        println!("My next guess is: {}", guess);
        io::stdin().read_line(&mut input).unwrap();
        let num_matching: i32 = input.trim().parse().unwrap();
        if num_matching < 0 || num_matching > 5 {
            println!("No cheating!");
            continue;
        }
        filter_matches(guess, num_matching, &mut combos);
        println!("{} letter combos remaining.", combos.len());
    }

    if combos.len() == 1 {
        println!("My guesses:");
        for combo in combos {
            for word in combo.1 {
                println!("{}", word);
            }
        }
    } else {
        println!("You failed!");
    }
}
<|endoftext|>


<commit_before>// Copyright (C) 2019 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: Apache-2.0

//! Contains all the structures of the request and response
//! from the agent.

/// Body of `info` response.
pub mod info;

/// Body of `probe` request and response.
pub mod probe {
    use serde::{Deserialize, Serialize};

    #[derive(Clone, Debug, Deserialize, Serialize)]
    #[serde(deny_unknown_fields)]
    pub struct Request {
        pub custom_server: String,
    }

    #[derive(Clone, Debug, Deserialize, Serialize)]
    #[serde(rename_all = "snake_case")]
    pub enum Response {
        Updating,
        NoUpdate,
        TryAgain(i64),
    }
}

/// Body of `local_install` request.
pub mod local_install {
    use serde::{Deserialize, Serialize};

    #[derive(Deserialize, Clone, Debug, Serialize)]
    #[serde(deny_unknown_fields)]
    pub struct Request {
        pub file: std::path::PathBuf,
    }
}

/// Body of `remote_install` request.
pub mod remote_install {
    use serde::{Deserialize, Serialize};

    #[derive(Deserialize, Clone, Debug, Serialize)]
    #[serde(deny_unknown_fields)]
    pub struct Request {
        pub url: String,
    }
}

/// Body of `state` response.
pub mod state {
    use serde::{Deserialize, Serialize};

    #[derive(Clone, Debug, Deserialize, Serialize)]
    #[serde(rename_all = "lowercase")]
    pub enum Response {
        Park,
        EntryPoint,
        Poll,
        Probe,
        Validation,
        Download,
        Install,
        Reboot,
        DirectDownload,
        PrepareLocalInstall,
        Error,
    }
}

/// Body of `abort_download` response.
///
/// # Successful case
///
/// On a successful request, the body of response is a struct
/// called `Response` with a successful message.
///
/// # Failed case
///
/// On a failed request, the body of response is a struct
/// called `Refused` with a error message.
pub mod abort_download {
    use serde::{Deserialize, Serialize};

    #[derive(Clone, Debug, Deserialize, Serialize)]
    #[serde(deny_unknown_fields)]
    pub struct Response {
        pub message: String,
    }

    #[derive(Clone, Debug, Deserialize, Serialize)]
    #[serde(deny_unknown_fields)]
    pub struct Refused {
        pub error: String,
    }
}

/// Body of `log` response.
pub mod log {
    use serde::{Deserialize, Serialize};
    use std::collections::HashMap;

    #[derive(Clone, Debug, Deserialize, Serialize)]
    #[serde(rename_all = "lowercase")]
    pub enum Level {
        // We use alias here since some string conversions of slog::Level use
        // short names even when requesting the full name:
        // https://github.com/slog-rs/slog/issues/282
        #[serde(alias = "crit")]
        Critical,
        #[serde(alias = "erro")]
        Error,
        #[serde(alias = "warn")]
        Warning,
        #[serde(alias = "info")]
        Info,
        #[serde(alias = "debg")]
        Debug,
        #[serde(alias = "trce")]
        Trace,
    }

    #[derive(Clone, Debug, Deserialize, Serialize)]
    #[serde(deny_unknown_fields)]
    pub struct Log {
        entries: Vec<Entry>,
    }

    #[derive(Clone, Debug, Deserialize, Serialize)]
    #[serde(deny_unknown_fields)]
    pub struct Entry {
        level: Level,
        message: String,
        time: String,
        data: HashMap<String, String>,
    }

    impl core::fmt::Display for Log {
        fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
            for entry in &self.entries {
                let level = match entry.level {
                    Level::Critical => "CRIT",
                    Level::Error => "ERRO",
                    Level::Warning => "WARN",
                    Level::Info => "INFO",
                    Level::Debug => "DEBG",
                    Level::Trace => "TRCE",
                };

                writeln!(
                    f,
                    "{timestamp} {level} {msg}",
                    timestamp = entry.time,
                    level = level,
                    msg = entry.message
                )?;
            }
            Ok(())
        }
    }
}
<commit_msg>sdk: Widen permissions on Log API structures<commit_after>// Copyright (C) 2019 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: Apache-2.0

//! Contains all the structures of the request and response
//! from the agent.

/// Body of `info` response.
pub mod info;

/// Body of `probe` request and response.
pub mod probe {
    use serde::{Deserialize, Serialize};

    #[derive(Clone, Debug, Deserialize, Serialize)]
    #[serde(deny_unknown_fields)]
    pub struct Request {
        pub custom_server: String,
    }

    #[derive(Clone, Debug, Deserialize, Serialize)]
    #[serde(rename_all = "snake_case")]
    pub enum Response {
        Updating,
        NoUpdate,
        TryAgain(i64),
    }
}

/// Body of `local_install` request.
pub mod local_install {
    use serde::{Deserialize, Serialize};

    #[derive(Deserialize, Clone, Debug, Serialize)]
    #[serde(deny_unknown_fields)]
    pub struct Request {
        pub file: std::path::PathBuf,
    }
}

/// Body of `remote_install` request.
pub mod remote_install {
    use serde::{Deserialize, Serialize};

    #[derive(Deserialize, Clone, Debug, Serialize)]
    #[serde(deny_unknown_fields)]
    pub struct Request {
        pub url: String,
    }
}

/// Body of `state` response.
pub mod state {
    use serde::{Deserialize, Serialize};

    #[derive(Clone, Debug, Deserialize, Serialize)]
    #[serde(rename_all = "lowercase")]
    pub enum Response {
        Park,
        EntryPoint,
        Poll,
        Probe,
        Validation,
        Download,
        Install,
        Reboot,
        DirectDownload,
        PrepareLocalInstall,
        Error,
    }
}

/// Body of `abort_download` response.
///
/// # Successful case
///
/// On a successful request, the body of response is a struct
/// called `Response` with a successful message.
///
/// # Failed case
///
/// On a failed request, the body of response is a struct
/// called `Refused` with a error message.
pub mod abort_download {
    use serde::{Deserialize, Serialize};

    #[derive(Clone, Debug, Deserialize, Serialize)]
    #[serde(deny_unknown_fields)]
    pub struct Response {
        pub message: String,
    }

    #[derive(Clone, Debug, Deserialize, Serialize)]
    #[serde(deny_unknown_fields)]
    pub struct Refused {
        pub error: String,
    }
}

/// Body of `log` response.
pub mod log {
    use serde::{Deserialize, Serialize};
    use std::collections::HashMap;

    #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
    #[serde(rename_all = "lowercase")]
    pub enum Level {
        // We use alias here since some string conversions of slog::Level use
        // short names even when requesting the full name:
        // https://github.com/slog-rs/slog/issues/282
        #[serde(alias = "crit")]
        Critical,
        #[serde(alias = "erro")]
        Error,
        #[serde(alias = "warn")]
        Warning,
        #[serde(alias = "info")]
        Info,
        #[serde(alias = "debg")]
        Debug,
        #[serde(alias = "trce")]
        Trace,
    }

    #[derive(Clone, Debug, Deserialize, Serialize)]
    #[serde(deny_unknown_fields)]
    pub struct Log {
        pub entries: Vec<Entry>,
    }

    #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
    #[serde(deny_unknown_fields)]
    pub struct Entry {
        level: Level,
        message: String,
        time: String,
        data: HashMap<String, String>,
    }

    impl core::fmt::Display for Log {
        fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
            for entry in &self.entries {
                writeln!(f, "{}", entry)?;
            }
            Ok(())
        }
    }

    impl core::fmt::Display for Entry {
        fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
            let level = match self.level {
                Level::Critical => "CRIT",
                Level::Error => "ERRO",
                Level::Warning => "WARN",
                Level::Info => "INFO",
                Level::Debug => "DEBG",
                Level::Trace => "TRCE",
            };

            write!(
                f,
                "{timestamp} {level} {msg}",
                timestamp = self.time,
                level = level,
                msg = self.message
            )?;
            Ok(())
        }
    }
}
<|endoftext|>


<commit_before>use rustc::lint::*;
use std::collections::HashMap;
use std::char;
use syntax::ast::*;
use syntax::codemap::Span;
use syntax::visit::FnKind;
use utils::{span_lint, span_help_and_lint, snippet, snippet_opt, span_lint_and_then};

/// **What it does:** Checks for structure field patterns bound to wildcards.
///
/// **Why is this bad?** Using `..` instead is shorter and leaves the focus on
/// the fields that are actually bound.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// let { a: _, b: ref b, c: _ } = ..
/// ```
declare_lint! {
    pub UNNEEDED_FIELD_PATTERN,
    Warn,
    "struct fields bound to a wildcard instead of using `..`"
}

/// **What it does:** Checks for function arguments having the similar names
/// differing by an underscore.
///
/// **Why is this bad?** It affects code readability.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// fn foo(a: i32, _a: i32) {}
/// ```
declare_lint! {
    pub DUPLICATE_UNDERSCORE_ARGUMENT,
    Warn,
    "function arguments having names which only differ by an underscore"
}

/// **What it does:** Detects closures called in the same expression where they are defined.
///
/// **Why is this bad?** It is unnecessarily adding to the expression's complexity.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// (|| 42)()
/// ```
declare_lint! {
    pub REDUNDANT_CLOSURE_CALL,
    Warn,
    "throwaway closures called in the expression they are defined"
}

/// **What it does:** Detects expressions of the form `--x`.
///
/// **Why is this bad?** It can mislead C/C++ programmers to think `x` was
/// decremented.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// --x;
/// ```
declare_lint! {
    pub DOUBLE_NEG,
    Warn,
    "`--x`, which is a double negation of `x` and not a pre-decrement as in C/C++"
}

/// **What it does:** Warns on hexadecimal literals with mixed-case letter digits.
///
/// **Why is this bad?** It looks confusing.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// let y = 0x1a9BAcD;
/// ```
declare_lint! {
    pub MIXED_CASE_HEX_LITERALS,
    Warn,
    "hex literals whose letter digits are not consistently upper- or lowercased"
}

/// **What it does:** Warns if literal suffixes are not separated by an underscore.
///
/// **Why is this bad?** It is much less readable.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// let y = 123832i32;
/// ```
declare_lint! {
    pub UNSEPARATED_LITERAL_SUFFIX,
    Allow,
    "literals whose suffix is not separated by an underscore"
}

/// **What it does:** Warns if a integral constant literal starts with `0`.
///
/// **Why is this bad?** In some languages (including the infamous C language and most of its
/// familly), this marks an octal constant. In Rust however, this is a decimal constant. This could
/// be confusing for both the writer and a reader of the constant.
///
/// **Known problems:** None.
///
/// **Example:**
///
/// In Rust:
/// ```rust
/// fn main() {
///     let a = 0123;
///     println!("{}", a);
/// }
/// ```
///
/// prints `123`, while in C:
///
/// ```c
/// #include <stdio.h>
///
/// int main() {
///     int a = 0123;
///     printf("%d\n", a);
/// }
/// ```
///
/// prints `83` (as `89 == 0o123` while `123 == 0o173`).
declare_lint! {
    pub ZERO_PREFIXED_LITERAL,
    Warn,
    "integer literals starting with `0`"
}

#[derive(Copy, Clone)]
pub struct MiscEarly;

impl LintPass for MiscEarly {
    fn get_lints(&self) -> LintArray {
        lint_array!(UNNEEDED_FIELD_PATTERN, DUPLICATE_UNDERSCORE_ARGUMENT, REDUNDANT_CLOSURE_CALL,
                    DOUBLE_NEG, MIXED_CASE_HEX_LITERALS, UNSEPARATED_LITERAL_SUFFIX,
                    ZERO_PREFIXED_LITERAL)
    }
}

impl EarlyLintPass for MiscEarly {
    fn check_pat(&mut self, cx: &EarlyContext, pat: &Pat) {
        if let PatKind::Struct(ref npat, ref pfields, _) = pat.node {
            let mut wilds = 0;
            let type_name = npat.segments.last().expect("A path must have at least one segment").identifier.name;

            for field in pfields {
                if field.node.pat.node == PatKind::Wild {
                    wilds += 1;
                }
            }
            if !pfields.is_empty() && wilds == pfields.len() {
                span_help_and_lint(cx,
                                   UNNEEDED_FIELD_PATTERN,
                                   pat.span,
                                   "All the struct fields are matched to a wildcard pattern, consider using `..`.",
                                   &format!("Try with `{} {{ .. }}` instead", type_name));
                return;
            }
            if wilds > 0 {
                let mut normal = vec![];

                for field in pfields {
                    if field.node.pat.node != PatKind::Wild {
                        if let Ok(n) = cx.sess().codemap().span_to_snippet(field.span) {
                            normal.push(n);
                        }
                    }
                }
                for field in pfields {
                    if field.node.pat.node == PatKind::Wild {
                        wilds -= 1;
                        if wilds > 0 {
                            span_lint(cx,
                                      UNNEEDED_FIELD_PATTERN,
                                      field.span,
                                      "You matched a field with a wildcard pattern. Consider using `..` instead");
                        } else {
                            span_help_and_lint(cx,
                                               UNNEEDED_FIELD_PATTERN,
                                               field.span,
                                               "You matched a field with a wildcard pattern. Consider using `..` \
                                                instead",
                                               &format!("Try with `{} {{ {}, .. }}`",
                                                        type_name,
                                                        normal[..].join(", ")));
                        }
                    }
                }
            }
        }
    }

    fn check_fn(&mut self, cx: &EarlyContext, _: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) {
        let mut registered_names: HashMap<String, Span> = HashMap::new();

        for arg in &decl.inputs {
            if let PatKind::Ident(_, sp_ident, None) = arg.pat.node {
                let arg_name = sp_ident.node.to_string();

                if arg_name.starts_with('_') {
                    if let Some(correspondence) = registered_names.get(&arg_name[1..]) {
                        span_lint(cx,
                                  DUPLICATE_UNDERSCORE_ARGUMENT,
                                  *correspondence,
                                  &format!("`{}` already exists, having another argument having almost the same \
                                            name makes code comprehension and documentation more difficult",
                                           arg_name[1..].to_owned()));;
                    }
                } else {
                    registered_names.insert(arg_name, arg.pat.span);
                }
            }
        }
    }

    fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) {
        match expr.node {
            ExprKind::Call(ref paren, _) => {
                if let ExprKind::Paren(ref closure) = paren.node {
                    if let ExprKind::Closure(_, ref decl, ref block, _) = closure.node {
                        span_lint_and_then(cx,
                                           REDUNDANT_CLOSURE_CALL,
                                           expr.span,
                                           "Try not to call a closure in the expression where it is declared.",
                                           |db| {
                                               if decl.inputs.is_empty() {
                                                   let hint = snippet(cx, block.span, "..").into_owned();
                                                   db.span_suggestion(expr.span, "Try doing something like: ", hint);
                                               }
                                           });
                    }
                }
            }
            ExprKind::Unary(UnOp::Neg, ref inner) => {
                if let ExprKind::Unary(UnOp::Neg, _) = inner.node {
                    span_lint(cx,
                              DOUBLE_NEG,
                              expr.span,
                              "`--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op");
                }
            }
            ExprKind::Lit(ref lit) => {
                if_let_chain! {[
                    let LitKind::Int(value, ..) = lit.node,
                    let Some(src) = snippet_opt(cx, lit.span),
                    let Some(firstch) = src.chars().next(),
                    char::to_digit(firstch, 10).is_some()
                ], {
                    let mut prev = '\0';
                    for ch in src.chars() {
                        if ch == 'i' || ch == 'u' {
                            if prev != '_' {
                                span_lint(cx, UNSEPARATED_LITERAL_SUFFIX, lit.span,
                                          "integer type suffix should be separated by an underscore");
                            }
                            break;
                        }
                        prev = ch;
                    }
                    if src.starts_with("0x") {
                        let mut seen = (false, false);
                        for ch in src.chars() {
                            match ch {
                                'a' ... 'f' => seen.0 = true,
                                'A' ... 'F' => seen.1 = true,
                                'i' | 'u'   => break,   // start of suffix already
                                _ => ()
                            }
                        }
                        if seen.0 && seen.1 {
                            span_lint(cx, MIXED_CASE_HEX_LITERALS, lit.span,
                                      "inconsistent casing in hexadecimal literal");
                        }
                    } else if value != 0 && src.starts_with('0') {
                        span_lint_and_then(cx,
                                           ZERO_PREFIXED_LITERAL,
                                           lit.span,
                                           "this is a decimal constant",
                                           |db| {
                            db.span_suggestion(lit.span, "if you mean to use a decimal constant, remove the `0` to remove confusion:", src[1..].to_string());
                            db.span_suggestion(lit.span, "if you mean to use an octal constant, use `0o`:", format!("0o{}", &src[1..]));
                        });
                    }
                }}
                if_let_chain! {[
                    let LitKind::Float(..) = lit.node,
                    let Some(src) = snippet_opt(cx, lit.span),
                    let Some(firstch) = src.chars().next(),
                    char::to_digit(firstch, 10).is_some()
                ], {
                    let mut prev = '\0';
                    for ch in src.chars() {
                        if ch == 'f' {
                            if prev != '_' {
                                span_lint(cx, UNSEPARATED_LITERAL_SUFFIX, lit.span,
                                          "float type suffix should be separated by an underscore");
                            }
                            break;
                        }
                        prev = ch;
                    }
                }}
            }
            _ => ()
        }
    }

    fn check_block(&mut self, cx: &EarlyContext, block: &Block) {
        for w in block.stmts.windows(2) {
            if_let_chain! {[
                let StmtKind::Local(ref local) = w[0].node,
                let Option::Some(ref t) = local.init,
                let ExprKind::Closure(_, _, _, _) = t.node,
                let PatKind::Ident(_, sp_ident, _) = local.pat.node,
                let StmtKind::Semi(ref second) = w[1].node,
                let ExprKind::Assign(_, ref call) = second.node,
                let ExprKind::Call(ref closure, _) = call.node,
                let ExprKind::Path(_, ref path) = closure.node
            ], {
                if sp_ident.node == (&path.segments[0]).identifier {
                    span_lint(cx, REDUNDANT_CLOSURE_CALL, second.span, "Closure called just once immediately after it was declared");
                }
            }}
        }
    }
}
<commit_msg>Fix typos<commit_after>use rustc::lint::*;
use std::collections::HashMap;
use std::char;
use syntax::ast::*;
use syntax::codemap::Span;
use syntax::visit::FnKind;
use utils::{span_lint, span_help_and_lint, snippet, snippet_opt, span_lint_and_then};

/// **What it does:** Checks for structure field patterns bound to wildcards.
///
/// **Why is this bad?** Using `..` instead is shorter and leaves the focus on
/// the fields that are actually bound.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// let { a: _, b: ref b, c: _ } = ..
/// ```
declare_lint! {
    pub UNNEEDED_FIELD_PATTERN,
    Warn,
    "struct fields bound to a wildcard instead of using `..`"
}

/// **What it does:** Checks for function arguments having the similar names
/// differing by an underscore.
///
/// **Why is this bad?** It affects code readability.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// fn foo(a: i32, _a: i32) {}
/// ```
declare_lint! {
    pub DUPLICATE_UNDERSCORE_ARGUMENT,
    Warn,
    "function arguments having names which only differ by an underscore"
}

/// **What it does:** Detects closures called in the same expression where they are defined.
///
/// **Why is this bad?** It is unnecessarily adding to the expression's complexity.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// (|| 42)()
/// ```
declare_lint! {
    pub REDUNDANT_CLOSURE_CALL,
    Warn,
    "throwaway closures called in the expression they are defined"
}

/// **What it does:** Detects expressions of the form `--x`.
///
/// **Why is this bad?** It can mislead C/C++ programmers to think `x` was
/// decremented.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// --x;
/// ```
declare_lint! {
    pub DOUBLE_NEG,
    Warn,
    "`--x`, which is a double negation of `x` and not a pre-decrement as in C/C++"
}

/// **What it does:** Warns on hexadecimal literals with mixed-case letter digits.
///
/// **Why is this bad?** It looks confusing.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// let y = 0x1a9BAcD;
/// ```
declare_lint! {
    pub MIXED_CASE_HEX_LITERALS,
    Warn,
    "hex literals whose letter digits are not consistently upper- or lowercased"
}

/// **What it does:** Warns if literal suffixes are not separated by an underscore.
///
/// **Why is this bad?** It is much less readable.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// let y = 123832i32;
/// ```
declare_lint! {
    pub UNSEPARATED_LITERAL_SUFFIX,
    Allow,
    "literals whose suffix is not separated by an underscore"
}

/// **What it does:** Warns if an integral constant literal starts with `0`.
///
/// **Why is this bad?** In some languages (including the infamous C language and most of its
/// familly), this marks an octal constant. In Rust however, this is a decimal constant. This could
/// be confusing for both the writer and a reader of the constant.
///
/// **Known problems:** None.
///
/// **Example:**
///
/// In Rust:
/// ```rust
/// fn main() {
///     let a = 0123;
///     println!("{}", a);
/// }
/// ```
///
/// prints `123`, while in C:
///
/// ```c
/// #include <stdio.h>
///
/// int main() {
///     int a = 0123;
///     printf("%d\n", a);
/// }
/// ```
///
/// prints `83` (as `83 == 0o123` while `123 == 0o173`).
declare_lint! {
    pub ZERO_PREFIXED_LITERAL,
    Warn,
    "integer literals starting with `0`"
}

#[derive(Copy, Clone)]
pub struct MiscEarly;

impl LintPass for MiscEarly {
    fn get_lints(&self) -> LintArray {
        lint_array!(UNNEEDED_FIELD_PATTERN, DUPLICATE_UNDERSCORE_ARGUMENT, REDUNDANT_CLOSURE_CALL,
                    DOUBLE_NEG, MIXED_CASE_HEX_LITERALS, UNSEPARATED_LITERAL_SUFFIX,
                    ZERO_PREFIXED_LITERAL)
    }
}

impl EarlyLintPass for MiscEarly {
    fn check_pat(&mut self, cx: &EarlyContext, pat: &Pat) {
        if let PatKind::Struct(ref npat, ref pfields, _) = pat.node {
            let mut wilds = 0;
            let type_name = npat.segments.last().expect("A path must have at least one segment").identifier.name;

            for field in pfields {
                if field.node.pat.node == PatKind::Wild {
                    wilds += 1;
                }
            }
            if !pfields.is_empty() && wilds == pfields.len() {
                span_help_and_lint(cx,
                                   UNNEEDED_FIELD_PATTERN,
                                   pat.span,
                                   "All the struct fields are matched to a wildcard pattern, consider using `..`.",
                                   &format!("Try with `{} {{ .. }}` instead", type_name));
                return;
            }
            if wilds > 0 {
                let mut normal = vec![];

                for field in pfields {
                    if field.node.pat.node != PatKind::Wild {
                        if let Ok(n) = cx.sess().codemap().span_to_snippet(field.span) {
                            normal.push(n);
                        }
                    }
                }
                for field in pfields {
                    if field.node.pat.node == PatKind::Wild {
                        wilds -= 1;
                        if wilds > 0 {
                            span_lint(cx,
                                      UNNEEDED_FIELD_PATTERN,
                                      field.span,
                                      "You matched a field with a wildcard pattern. Consider using `..` instead");
                        } else {
                            span_help_and_lint(cx,
                                               UNNEEDED_FIELD_PATTERN,
                                               field.span,
                                               "You matched a field with a wildcard pattern. Consider using `..` \
                                                instead",
                                               &format!("Try with `{} {{ {}, .. }}`",
                                                        type_name,
                                                        normal[..].join(", ")));
                        }
                    }
                }
            }
        }
    }

    fn check_fn(&mut self, cx: &EarlyContext, _: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) {
        let mut registered_names: HashMap<String, Span> = HashMap::new();

        for arg in &decl.inputs {
            if let PatKind::Ident(_, sp_ident, None) = arg.pat.node {
                let arg_name = sp_ident.node.to_string();

                if arg_name.starts_with('_') {
                    if let Some(correspondence) = registered_names.get(&arg_name[1..]) {
                        span_lint(cx,
                                  DUPLICATE_UNDERSCORE_ARGUMENT,
                                  *correspondence,
                                  &format!("`{}` already exists, having another argument having almost the same \
                                            name makes code comprehension and documentation more difficult",
                                           arg_name[1..].to_owned()));;
                    }
                } else {
                    registered_names.insert(arg_name, arg.pat.span);
                }
            }
        }
    }

    fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) {
        match expr.node {
            ExprKind::Call(ref paren, _) => {
                if let ExprKind::Paren(ref closure) = paren.node {
                    if let ExprKind::Closure(_, ref decl, ref block, _) = closure.node {
                        span_lint_and_then(cx,
                                           REDUNDANT_CLOSURE_CALL,
                                           expr.span,
                                           "Try not to call a closure in the expression where it is declared.",
                                           |db| {
                                               if decl.inputs.is_empty() {
                                                   let hint = snippet(cx, block.span, "..").into_owned();
                                                   db.span_suggestion(expr.span, "Try doing something like: ", hint);
                                               }
                                           });
                    }
                }
            }
            ExprKind::Unary(UnOp::Neg, ref inner) => {
                if let ExprKind::Unary(UnOp::Neg, _) = inner.node {
                    span_lint(cx,
                              DOUBLE_NEG,
                              expr.span,
                              "`--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op");
                }
            }
            ExprKind::Lit(ref lit) => {
                if_let_chain! {[
                    let LitKind::Int(value, ..) = lit.node,
                    let Some(src) = snippet_opt(cx, lit.span),
                    let Some(firstch) = src.chars().next(),
                    char::to_digit(firstch, 10).is_some()
                ], {
                    let mut prev = '\0';
                    for ch in src.chars() {
                        if ch == 'i' || ch == 'u' {
                            if prev != '_' {
                                span_lint(cx, UNSEPARATED_LITERAL_SUFFIX, lit.span,
                                          "integer type suffix should be separated by an underscore");
                            }
                            break;
                        }
                        prev = ch;
                    }
                    if src.starts_with("0x") {
                        let mut seen = (false, false);
                        for ch in src.chars() {
                            match ch {
                                'a' ... 'f' => seen.0 = true,
                                'A' ... 'F' => seen.1 = true,
                                'i' | 'u'   => break,   // start of suffix already
                                _ => ()
                            }
                        }
                        if seen.0 && seen.1 {
                            span_lint(cx, MIXED_CASE_HEX_LITERALS, lit.span,
                                      "inconsistent casing in hexadecimal literal");
                        }
                    } else if value != 0 && src.starts_with('0') {
                        span_lint_and_then(cx,
                                           ZERO_PREFIXED_LITERAL,
                                           lit.span,
                                           "this is a decimal constant",
                                           |db| {
                            db.span_suggestion(lit.span, "if you mean to use a decimal constant, remove the `0` to remove confusion:", src[1..].to_string());
                            db.span_suggestion(lit.span, "if you mean to use an octal constant, use `0o`:", format!("0o{}", &src[1..]));
                        });
                    }
                }}
                if_let_chain! {[
                    let LitKind::Float(..) = lit.node,
                    let Some(src) = snippet_opt(cx, lit.span),
                    let Some(firstch) = src.chars().next(),
                    char::to_digit(firstch, 10).is_some()
                ], {
                    let mut prev = '\0';
                    for ch in src.chars() {
                        if ch == 'f' {
                            if prev != '_' {
                                span_lint(cx, UNSEPARATED_LITERAL_SUFFIX, lit.span,
                                          "float type suffix should be separated by an underscore");
                            }
                            break;
                        }
                        prev = ch;
                    }
                }}
            }
            _ => ()
        }
    }

    fn check_block(&mut self, cx: &EarlyContext, block: &Block) {
        for w in block.stmts.windows(2) {
            if_let_chain! {[
                let StmtKind::Local(ref local) = w[0].node,
                let Option::Some(ref t) = local.init,
                let ExprKind::Closure(_, _, _, _) = t.node,
                let PatKind::Ident(_, sp_ident, _) = local.pat.node,
                let StmtKind::Semi(ref second) = w[1].node,
                let ExprKind::Assign(_, ref call) = second.node,
                let ExprKind::Call(ref closure, _) = call.node,
                let ExprKind::Path(_, ref path) = closure.node
            ], {
                if sp_ident.node == (&path.segments[0]).identifier {
                    span_lint(cx, REDUNDANT_CLOSURE_CALL, second.span, "Closure called just once immediately after it was declared");
                }
            }}
        }
    }
}
<|endoftext|>


<commit_before>use std::fmt;

use base::ast::{self, DisplayEnv, Expr, MutVisitor, Pattern, SpannedExpr, Typed, TypedIdent};
use base::error::Errors;
use base::fnv::FnvMap;
use base::kind::{ArcKind, Kind, KindEnv};
use base::pos::{self, BytePos, Span, Spanned};
use base::scoped_map::ScopedMap;
use base::symbol::{Symbol, SymbolModule, SymbolRef};
use base::types::{self, Alias, ArcType, RecordSelector, Type, TypeEnv};
use unify_type::{State, TypeError};
use unify::{Error as UnifyError, Unifiable, Unifier, UnifierState};

pub type Error = Errors<Spanned<RenameError, BytePos>>;

#[derive(Clone, Debug, PartialEq)]
pub enum RenameError {
    NoMatchingType {
        symbol: String,
        expected: ArcType,
        possible_types: Vec<(Option<Span<BytePos>>, ArcType)>,
    },
}

impl fmt::Display for RenameError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            RenameError::NoMatchingType {
                ref symbol,
                ref expected,
                ref possible_types,
            } => {
                writeln!(
                    f,
                    "Could not resolve a binding for `{}` with type `{}`",
                    symbol,
                    expected
                )?;
                writeln!(f, "Possibilities:")?;
                for &(ref span, ref typ) in possible_types {
                    match *span {
                        Some(ref span) => writeln!(f, "{} at {}", typ, span.start)?,
                        None => writeln!(f, "{} at 'global'", typ)?,
                    }
                }
                Ok(())
            }
        }
    }
}

struct Environment<'b> {
    env: &'b TypeEnv,
    stack: ScopedMap<Symbol, (Symbol, Span<BytePos>, ArcType)>,
    stack_types: ScopedMap<Symbol, Alias<Symbol, ArcType>>,
}

impl<'a> KindEnv for Environment<'a> {
    fn find_kind(&self, _type_name: &SymbolRef) -> Option<ArcKind> {
        None
    }
}

impl<'a> TypeEnv for Environment<'a> {
    fn find_type(&self, id: &SymbolRef) -> Option<&ArcType> {
        self.stack
            .get(id)
            .map(|t| &t.2)
            .or_else(|| self.env.find_type(id))
    }

    fn find_type_info(&self, id: &SymbolRef) -> Option<&Alias<Symbol, ArcType>> {
        self.stack_types
            .get(id)
            .or_else(|| self.env.find_type_info(id))
    }

    fn find_record(
        &self,
        _fields: &[Symbol],
        _selector: RecordSelector,
    ) -> Option<(ArcType, ArcType)> {
        None
    }
}

pub fn rename(
    symbols: &mut SymbolModule,
    env: &TypeEnv,
    expr: &mut SpannedExpr<Symbol>,
) -> Result<(), Error> {
    use base::resolve;

    struct RenameVisitor<'a: 'b, 'b> {
        symbols: &'b mut SymbolModule<'a>,
        env: Environment<'b>,
        errors: Error,
    }

    impl<'a, 'b> RenameVisitor<'a, 'b> {
        fn find_fields(&self, typ: &ArcType) -> Vec<types::Field<Symbol, ArcType>> {
            // Walk through all type aliases
            let record = resolve::remove_aliases(&self.env, typ.remove_forall().clone());
            record.row_iter().cloned().collect()
        }

        fn new_pattern(&mut self, typ: &ArcType, pattern: &mut ast::SpannedPattern<Symbol>) {
            match pattern.value {
                ast::Pattern::Record {
                    ref mut fields,
                    ref types,
                    ..
                } => {
                    let field_types = self.find_fields(typ);
                    for field in fields {
                        let field_type = &field_types
                            .iter()
                            .find(|field_type| field_type.name.name_eq(&field.name.value))
                            .expect("ICE: Existing field")
                            .typ;
                        match field.value {
                            Some(ref mut pat) => self.new_pattern(field_type, pat),
                            None => {
                                let id = field.name.value.clone();
                                let pat = Pattern::Ident(TypedIdent {
                                    name: self.stack_var(id, pattern.span, field_type.clone()),
                                    typ: field_type.clone(),
                                });
                                field.value = Some(pos::spanned(pattern.span, pat));
                            }
                        }
                    }

                    let record_type = resolve::remove_aliases(&self.env, typ.clone()).clone();
                    for ast_field in types {
                        let field_type = record_type
                            .type_field_iter()
                            .find(|field| field.name.name_eq(&ast_field.name.value))
                            .expect("field_type");
                        self.stack_type(
                            ast_field.name.value.clone(),
                            pattern.span,
                            &field_type.typ,
                        );
                    }
                }
                ast::Pattern::Ident(ref mut id) => {
                    let new_name = self.stack_var(id.name.clone(), pattern.span, id.typ.clone());
                    id.name = new_name;
                }
                ast::Pattern::Tuple {
                    ref typ,
                    ref mut elems,
                } => for (field, elem) in typ.row_iter().zip(elems) {
                    self.new_pattern(&field.typ, elem);
                },
                ast::Pattern::Constructor(ref mut id, ref mut args) => {
                    let typ = self.env
                        .find_type(&id.name)
                        .unwrap_or_else(|| panic!("ICE: Expected constructor: {}", id.name))
                        .clone();
                    for (arg_type, arg) in types::arg_iter(&typ).zip(args) {
                        self.new_pattern(arg_type, arg);
                    }
                }
                ast::Pattern::Error => (),
            }
        }

        fn stack_var(&mut self, id: Symbol, span: Span<BytePos>, typ: ArcType) -> Symbol {
            let old_id = id.clone();
            let name = self.symbols.string(&id).to_owned();
            let new_id = self.symbols.symbol(format!("{}:{}", name, span.start));
            debug!(
                "Rename binding `{}` = `{}` `{}`",
                self.symbols.string(&old_id),
                self.symbols.string(&new_id),
                typ
            );
            self.env.stack.insert(old_id, (new_id.clone(), span, typ));
            new_id
        }

        fn stack_type(&mut self, id: Symbol, span: Span<BytePos>, alias: &Alias<Symbol, ArcType>) {
            // Insert variant constructors into the local scope
            let aliased_type = alias.typ();
            if let Type::Variant(ref row) = **aliased_type.remove_forall() {
                for field in row.row_iter().cloned() {
                    self.env
                        .stack
                        .insert(field.name.clone(), (field.name, span, field.typ));
                }
            }

            // FIXME: Workaround so that both the types name in this module and its global
            // name are imported. Without this aliases may not be traversed properly
            self.env
                .stack_types
                .insert(alias.name.clone(), alias.clone());
            self.env.stack_types.insert(id, alias.clone());
        }

        /// Renames `id` to the unique identifier which have the type `expected`
        /// Returns `Some(new_id)` if renaming was necessary or `None` if no renaming was necessary
        /// as `id` was currently unique (#Int+, #Float*, etc)
        fn rename(&self, id: &Symbol, expected: &ArcType) -> Result<Option<Symbol>, RenameError> {
            let locals = self.env.stack.get_all(id);
            let global = self.env.env.find_type(id).map(|typ| (id, None, typ));
            let candidates = || {
                locals
                    .iter()
                    .flat_map(|bindings| {
                        bindings
                            .iter()
                            .rev()
                            .map(|bind| (&bind.0, Some(&bind.1), &bind.2))
                    })
                    .chain(global)
            };
            // If there is a single binding (or no binding in case of primitives such as #Int+)
            // there is no need to check for equivalency as typechecker couldnt have infered a
            // different binding
            if candidates().count() <= 1 {
                return Ok(candidates().next().map(|tup| tup.0.clone()));
            }
            candidates()
                .find(|tup| equivalent(&self.env, tup.2, expected))
                .map(|tup| Some(tup.0.clone()))
                .ok_or_else(|| {
                    RenameError::NoMatchingType {
                        symbol: String::from(self.symbols.string(id)),
                        expected: expected.clone(),
                        possible_types: candidates()
                            .map(|tup| (tup.1.cloned(), tup.2.clone()))
                            .collect(),
                    }
                })
        }

        fn rename_expr(&mut self, expr: &mut SpannedExpr<Symbol>) -> Result<(), RenameError> {
            match expr.value {
                Expr::Ident(ref mut id) => if let Some(new_id) = self.rename(&id.name, &id.typ)? {
                    debug!("Rename identifier {} = {}", id.name, new_id);
                    id.name = new_id;
                },
                Expr::Record {
                    ref mut typ,
                    ref mut exprs,
                    ..
                } => {
                    let field_types = self.find_fields(typ);
                    for (field, expr_field) in field_types.iter().zip(exprs) {
                        match expr_field.value {
                            Some(ref mut expr) => self.visit_expr(expr),
                            None => if let Some(new_id) =
                                self.rename(&expr_field.name.value, &field.typ)?
                            {
                                debug!("Rename record field {} = {}", expr_field.name, new_id);
                                expr_field.value = Some(pos::spanned(
                                    expr.span,
                                    Expr::Ident(TypedIdent {
                                        name: new_id,
                                        typ: field.typ.clone(),
                                    }),
                                ));
                            },
                        }
                    }
                }
                Expr::Infix(ref mut lhs, ref mut op, ref mut rhs) => {
                    if let Some(new_id) = self.rename(&op.value.name, &op.value.typ)? {
                        debug!(
                            "Rename {} = {}",
                            self.symbols.string(&op.value.name),
                            self.symbols.string(&new_id)
                        );
                        op.value.name = new_id;
                    }
                    self.visit_expr(lhs);
                    self.visit_expr(rhs);
                }
                Expr::Match(ref mut expr, ref mut alts) => {
                    self.visit_expr(expr);
                    for alt in alts {
                        self.env.stack_types.enter_scope();
                        self.env.stack.enter_scope();
                        let typ = expr.env_type_of(&self.env);
                        self.new_pattern(&typ, &mut alt.pattern);
                        self.visit_expr(&mut alt.expr);
                        self.env.stack.exit_scope();
                        self.env.stack_types.exit_scope();
                    }
                }
                Expr::LetBindings(ref mut bindings, ref mut expr) => {
                    self.env.stack_types.enter_scope();
                    self.env.stack.enter_scope();
                    let is_recursive = bindings.iter().all(|bind| !bind.args.is_empty());
                    for bind in bindings.iter_mut() {
                        if !is_recursive {
                            self.visit_expr(&mut bind.expr);
                        }
                        self.new_pattern(&bind.resolved_type, &mut bind.name);
                    }
                    if is_recursive {
                        for bind in bindings {
                            self.env.stack.enter_scope();
                            for (typ, arg) in
                                types::arg_iter(&bind.resolved_type).zip(&mut bind.args)
                            {
                                arg.value.name =
                                    self.stack_var(arg.value.name.clone(), expr.span, typ.clone());
                            }
                            self.visit_expr(&mut bind.expr);
                            self.env.stack.exit_scope();
                        }
                    }
                    self.visit_expr(expr);
                    self.env.stack.exit_scope();
                    self.env.stack_types.exit_scope();
                }
                Expr::Lambda(ref mut lambda) => {
                    self.env.stack.enter_scope();
                    for (typ, arg) in types::arg_iter(&lambda.id.typ).zip(&mut lambda.args) {
                        arg.value.name =
                            self.stack_var(arg.value.name.clone(), expr.span, typ.clone());
                    }
                    self.visit_expr(&mut lambda.body);
                    self.env.stack.exit_scope();
                }
                Expr::TypeBindings(ref bindings, ref mut body) => {
                    self.env.stack_types.enter_scope();
                    for bind in bindings {
                        self.stack_type(
                            bind.name.value.clone(),
                            expr.span,
                            bind.finalized_alias.as_ref().expect(
                                "ICE: Alias should have been finalized \
                                 before renaming",
                            ),
                        );
                    }
                    self.visit_expr(body);
                    self.env.stack_types.exit_scope();
                }
                _ => ast::walk_mut_expr(self, expr),
            }
            Ok(())
        }
    }

    impl<'a, 'b> MutVisitor for RenameVisitor<'a, 'b> {
        type Ident = Symbol;

        fn visit_expr(&mut self, expr: &mut SpannedExpr<Self::Ident>) {
            if let Err(err) = self.rename_expr(expr) {
                self.errors.push(Spanned {
                    span: expr.span,
                    value: err,
                });
            }
        }
    }

    let mut visitor = RenameVisitor {
        symbols: symbols,
        errors: Errors::new(),
        env: Environment {
            env: env,
            stack: ScopedMap::new(),
            stack_types: ScopedMap::new(),
        },
    };
    visitor.visit_expr(expr);
    if visitor.errors.has_errors() {
        Err(visitor.errors)
    } else {
        Ok(())
    }
}

pub fn equivalent(env: &TypeEnv, actual: &ArcType, inferred: &ArcType) -> bool {
    use substitution::Substitution;
    // FIXME This Substitution is unnecessary for equivalence unification
    let subs = Substitution::new(Kind::typ());
    let mut unifier = UnifierState {
        state: State::new(env, &subs),
        unifier: Equivalent {
            map: FnvMap::default(),
            equiv: true,
        },
    };
    unifier.try_match(actual, inferred);
    unifier.unifier.equiv
}

struct Equivalent {
    map: FnvMap<Symbol, ArcType>,
    equiv: bool,
}

impl<'a> Unifier<State<'a>, ArcType> for Equivalent {
    fn report_error(
        unifier: &mut UnifierState<State<'a>, Self>,
        _error: UnifyError<ArcType, TypeError<Symbol>>,
    ) {
        unifier.unifier.equiv = false;
    }

    fn try_match_res(
        unifier: &mut UnifierState<State<'a>, Self>,
        l: &ArcType,
        r: &ArcType,
    ) -> Result<Option<ArcType>, UnifyError<ArcType, TypeError<Symbol>>> {
        debug!("{} ====> {}", l, r);
        match (&**l, &**r) {
            (&Type::Generic(ref gl), &Type::Generic(ref gr)) if gl == gr => Ok(None),
            (&Type::Generic(ref gl), _) => match unifier.unifier.map.get(&gl.id).cloned() {
                Some(ref typ) => unifier.try_match_res(typ, r),
                None => {
                    unifier.unifier.map.insert(gl.id.clone(), r.clone());
                    Ok(None)
                }
            },
            _ => l.zip_match(r, unifier),
        }
    }

    fn error_type(_unifier: &mut UnifierState<State<'a>, Self>) -> Option<ArcType> {
        None
    }
}
<commit_msg>Look at overloaded bindings without the outermost forall<commit_after>use std::fmt;

use base::ast::{self, DisplayEnv, Expr, MutVisitor, Pattern, SpannedExpr, Typed, TypedIdent};
use base::error::Errors;
use base::fnv::FnvMap;
use base::kind::{ArcKind, Kind, KindEnv};
use base::pos::{self, BytePos, Span, Spanned};
use base::scoped_map::ScopedMap;
use base::symbol::{Symbol, SymbolModule, SymbolRef};
use base::types::{self, Alias, ArcType, RecordSelector, Type, TypeEnv};
use unify_type::{State, TypeError};
use unify::{Error as UnifyError, Unifiable, Unifier, UnifierState};

pub type Error = Errors<Spanned<RenameError, BytePos>>;

#[derive(Clone, Debug, PartialEq)]
pub enum RenameError {
    NoMatchingType {
        symbol: String,
        expected: ArcType,
        possible_types: Vec<(Option<Span<BytePos>>, ArcType)>,
    },
}

impl fmt::Display for RenameError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            RenameError::NoMatchingType {
                ref symbol,
                ref expected,
                ref possible_types,
            } => {
                writeln!(
                    f,
                    "Could not resolve a binding for `{}` with type `{}`",
                    symbol,
                    expected
                )?;
                writeln!(f, "Possibilities:")?;
                for &(ref span, ref typ) in possible_types {
                    match *span {
                        Some(ref span) => writeln!(f, "{} at {}", typ, span.start)?,
                        None => writeln!(f, "{} at 'global'", typ)?,
                    }
                }
                Ok(())
            }
        }
    }
}

struct Environment<'b> {
    env: &'b TypeEnv,
    stack: ScopedMap<Symbol, (Symbol, Span<BytePos>, ArcType)>,
    stack_types: ScopedMap<Symbol, Alias<Symbol, ArcType>>,
}

impl<'a> KindEnv for Environment<'a> {
    fn find_kind(&self, _type_name: &SymbolRef) -> Option<ArcKind> {
        None
    }
}

impl<'a> TypeEnv for Environment<'a> {
    fn find_type(&self, id: &SymbolRef) -> Option<&ArcType> {
        self.stack
            .get(id)
            .map(|t| &t.2)
            .or_else(|| self.env.find_type(id))
    }

    fn find_type_info(&self, id: &SymbolRef) -> Option<&Alias<Symbol, ArcType>> {
        self.stack_types
            .get(id)
            .or_else(|| self.env.find_type_info(id))
    }

    fn find_record(
        &self,
        _fields: &[Symbol],
        _selector: RecordSelector,
    ) -> Option<(ArcType, ArcType)> {
        None
    }
}

pub fn rename(
    symbols: &mut SymbolModule,
    env: &TypeEnv,
    expr: &mut SpannedExpr<Symbol>,
) -> Result<(), Error> {
    use base::resolve;

    struct RenameVisitor<'a: 'b, 'b> {
        symbols: &'b mut SymbolModule<'a>,
        env: Environment<'b>,
        errors: Error,
    }

    impl<'a, 'b> RenameVisitor<'a, 'b> {
        fn find_fields(&self, typ: &ArcType) -> Vec<types::Field<Symbol, ArcType>> {
            // Walk through all type aliases
            let record = resolve::remove_aliases(&self.env, typ.remove_forall().clone());
            record.row_iter().cloned().collect()
        }

        fn new_pattern(&mut self, typ: &ArcType, pattern: &mut ast::SpannedPattern<Symbol>) {
            match pattern.value {
                ast::Pattern::Record {
                    ref mut fields,
                    ref types,
                    ..
                } => {
                    let field_types = self.find_fields(typ);
                    for field in fields {
                        let field_type = &field_types
                            .iter()
                            .find(|field_type| field_type.name.name_eq(&field.name.value))
                            .expect("ICE: Existing field")
                            .typ;
                        match field.value {
                            Some(ref mut pat) => self.new_pattern(field_type, pat),
                            None => {
                                let id = field.name.value.clone();
                                let pat = Pattern::Ident(TypedIdent {
                                    name: self.stack_var(id, pattern.span, field_type.clone()),
                                    typ: field_type.clone(),
                                });
                                field.value = Some(pos::spanned(pattern.span, pat));
                            }
                        }
                    }

                    let record_type = resolve::remove_aliases(&self.env, typ.clone()).clone();
                    for ast_field in types {
                        let field_type = record_type
                            .type_field_iter()
                            .find(|field| field.name.name_eq(&ast_field.name.value))
                            .expect("field_type");
                        self.stack_type(
                            ast_field.name.value.clone(),
                            pattern.span,
                            &field_type.typ,
                        );
                    }
                }
                ast::Pattern::Ident(ref mut id) => {
                    let new_name = self.stack_var(id.name.clone(), pattern.span, id.typ.clone());
                    id.name = new_name;
                }
                ast::Pattern::Tuple {
                    ref typ,
                    ref mut elems,
                } => for (field, elem) in typ.row_iter().zip(elems) {
                    self.new_pattern(&field.typ, elem);
                },
                ast::Pattern::Constructor(ref mut id, ref mut args) => {
                    let typ = self.env
                        .find_type(&id.name)
                        .unwrap_or_else(|| panic!("ICE: Expected constructor: {}", id.name))
                        .clone();
                    for (arg_type, arg) in types::arg_iter(&typ).zip(args) {
                        self.new_pattern(arg_type, arg);
                    }
                }
                ast::Pattern::Error => (),
            }
        }

        fn stack_var(&mut self, id: Symbol, span: Span<BytePos>, typ: ArcType) -> Symbol {
            let old_id = id.clone();
            let name = self.symbols.string(&id).to_owned();
            let new_id = self.symbols.symbol(format!("{}:{}", name, span.start));
            debug!(
                "Rename binding `{}` = `{}` `{}`",
                self.symbols.string(&old_id),
                self.symbols.string(&new_id),
                typ
            );
            self.env.stack.insert(old_id, (new_id.clone(), span, typ));
            new_id
        }

        fn stack_type(&mut self, id: Symbol, span: Span<BytePos>, alias: &Alias<Symbol, ArcType>) {
            // Insert variant constructors into the local scope
            let aliased_type = alias.typ();
            if let Type::Variant(ref row) = **aliased_type.remove_forall() {
                for field in row.row_iter().cloned() {
                    self.env
                        .stack
                        .insert(field.name.clone(), (field.name, span, field.typ));
                }
            }

            // FIXME: Workaround so that both the types name in this module and its global
            // name are imported. Without this aliases may not be traversed properly
            self.env
                .stack_types
                .insert(alias.name.clone(), alias.clone());
            self.env.stack_types.insert(id, alias.clone());
        }

        /// Renames `id` to the unique identifier which have the type `expected`
        /// Returns `Some(new_id)` if renaming was necessary or `None` if no renaming was necessary
        /// as `id` was currently unique (#Int+, #Float*, etc)
        fn rename(&self, id: &Symbol, expected: &ArcType) -> Result<Option<Symbol>, RenameError> {
            let locals = self.env.stack.get_all(id);
            let global = self.env.env.find_type(id).map(|typ| (id, None, typ));
            let candidates = || {
                locals
                    .iter()
                    .flat_map(|bindings| {
                        bindings
                            .iter()
                            .rev()
                            .map(|bind| (&bind.0, Some(&bind.1), &bind.2))
                    })
                    .chain(global)
            };
            // If there is a single binding (or no binding in case of primitives such as #Int+)
            // there is no need to check for equivalency as typechecker couldnt have infered a
            // different binding
            if candidates().count() <= 1 {
                return Ok(candidates().next().map(|tup| tup.0.clone()));
            }
            candidates()
                .find(|tup| equivalent(&self.env, tup.2.remove_forall(), expected))
                .map(|tup| Some(tup.0.clone()))
                .ok_or_else(|| {
                    RenameError::NoMatchingType {
                        symbol: String::from(self.symbols.string(id)),
                        expected: expected.clone(),
                        possible_types: candidates()
                            .map(|tup| (tup.1.cloned(), tup.2.clone()))
                            .collect(),
                    }
                })
        }

        fn rename_expr(&mut self, expr: &mut SpannedExpr<Symbol>) -> Result<(), RenameError> {
            match expr.value {
                Expr::Ident(ref mut id) => if let Some(new_id) = self.rename(&id.name, &id.typ)? {
                    debug!("Rename identifier {} = {}", id.name, new_id);
                    id.name = new_id;
                },
                Expr::Record {
                    ref mut typ,
                    ref mut exprs,
                    ..
                } => {
                    let field_types = self.find_fields(typ);
                    for (field, expr_field) in field_types.iter().zip(exprs) {
                        match expr_field.value {
                            Some(ref mut expr) => self.visit_expr(expr),
                            None => if let Some(new_id) =
                                self.rename(&expr_field.name.value, &field.typ)?
                            {
                                debug!("Rename record field {} = {}", expr_field.name, new_id);
                                expr_field.value = Some(pos::spanned(
                                    expr.span,
                                    Expr::Ident(TypedIdent {
                                        name: new_id,
                                        typ: field.typ.clone(),
                                    }),
                                ));
                            },
                        }
                    }
                }
                Expr::Infix(ref mut lhs, ref mut op, ref mut rhs) => {
                    if let Some(new_id) = self.rename(&op.value.name, &op.value.typ)? {
                        debug!(
                            "Rename {} = {}",
                            self.symbols.string(&op.value.name),
                            self.symbols.string(&new_id)
                        );
                        op.value.name = new_id;
                    }
                    self.visit_expr(lhs);
                    self.visit_expr(rhs);
                }
                Expr::Match(ref mut expr, ref mut alts) => {
                    self.visit_expr(expr);
                    for alt in alts {
                        self.env.stack_types.enter_scope();
                        self.env.stack.enter_scope();
                        let typ = expr.env_type_of(&self.env);
                        self.new_pattern(&typ, &mut alt.pattern);
                        self.visit_expr(&mut alt.expr);
                        self.env.stack.exit_scope();
                        self.env.stack_types.exit_scope();
                    }
                }
                Expr::LetBindings(ref mut bindings, ref mut expr) => {
                    self.env.stack_types.enter_scope();
                    self.env.stack.enter_scope();
                    let is_recursive = bindings.iter().all(|bind| !bind.args.is_empty());
                    for bind in bindings.iter_mut() {
                        if !is_recursive {
                            self.visit_expr(&mut bind.expr);
                        }
                        self.new_pattern(&bind.resolved_type, &mut bind.name);
                    }
                    if is_recursive {
                        for bind in bindings {
                            self.env.stack.enter_scope();
                            for (typ, arg) in
                                types::arg_iter(&bind.resolved_type).zip(&mut bind.args)
                            {
                                arg.value.name =
                                    self.stack_var(arg.value.name.clone(), expr.span, typ.clone());
                            }
                            self.visit_expr(&mut bind.expr);
                            self.env.stack.exit_scope();
                        }
                    }
                    self.visit_expr(expr);
                    self.env.stack.exit_scope();
                    self.env.stack_types.exit_scope();
                }
                Expr::Lambda(ref mut lambda) => {
                    self.env.stack.enter_scope();
                    for (typ, arg) in types::arg_iter(&lambda.id.typ).zip(&mut lambda.args) {
                        arg.value.name =
                            self.stack_var(arg.value.name.clone(), expr.span, typ.clone());
                    }
                    self.visit_expr(&mut lambda.body);
                    self.env.stack.exit_scope();
                }
                Expr::TypeBindings(ref bindings, ref mut body) => {
                    self.env.stack_types.enter_scope();
                    for bind in bindings {
                        self.stack_type(
                            bind.name.value.clone(),
                            expr.span,
                            bind.finalized_alias.as_ref().expect(
                                "ICE: Alias should have been finalized \
                                 before renaming",
                            ),
                        );
                    }
                    self.visit_expr(body);
                    self.env.stack_types.exit_scope();
                }
                _ => ast::walk_mut_expr(self, expr),
            }
            Ok(())
        }
    }

    impl<'a, 'b> MutVisitor for RenameVisitor<'a, 'b> {
        type Ident = Symbol;

        fn visit_expr(&mut self, expr: &mut SpannedExpr<Self::Ident>) {
            if let Err(err) = self.rename_expr(expr) {
                self.errors.push(Spanned {
                    span: expr.span,
                    value: err,
                });
            }
        }
    }

    let mut visitor = RenameVisitor {
        symbols: symbols,
        errors: Errors::new(),
        env: Environment {
            env: env,
            stack: ScopedMap::new(),
            stack_types: ScopedMap::new(),
        },
    };
    visitor.visit_expr(expr);
    if visitor.errors.has_errors() {
        Err(visitor.errors)
    } else {
        Ok(())
    }
}

pub fn equivalent(env: &TypeEnv, actual: &ArcType, inferred: &ArcType) -> bool {
    use substitution::Substitution;
    // FIXME This Substitution is unnecessary for equivalence unification
    let subs = Substitution::new(Kind::typ());
    let mut unifier = UnifierState {
        state: State::new(env, &subs),
        unifier: Equivalent {
            map: FnvMap::default(),
            equiv: true,
        },
    };
    unifier.try_match(actual, inferred);
    unifier.unifier.equiv
}

struct Equivalent {
    map: FnvMap<Symbol, ArcType>,
    equiv: bool,
}

impl<'a> Unifier<State<'a>, ArcType> for Equivalent {
    fn report_error(
        unifier: &mut UnifierState<State<'a>, Self>,
        _error: UnifyError<ArcType, TypeError<Symbol>>,
    ) {
        unifier.unifier.equiv = false;
    }

    fn try_match_res(
        unifier: &mut UnifierState<State<'a>, Self>,
        l: &ArcType,
        r: &ArcType,
    ) -> Result<Option<ArcType>, UnifyError<ArcType, TypeError<Symbol>>> {
        debug!("{} ====> {}", l, r);
        match (&**l, &**r) {
            (&Type::Generic(ref gl), &Type::Generic(ref gr)) if gl == gr => Ok(None),
            (&Type::Generic(ref gl), _) => match unifier.unifier.map.get(&gl.id).cloned() {
                Some(ref typ) => unifier.try_match_res(typ, r),
                None => {
                    unifier.unifier.map.insert(gl.id.clone(), r.clone());
                    Ok(None)
                }
            },
            _ => l.zip_match(r, unifier),
        }
    }

    fn error_type(_unifier: &mut UnifierState<State<'a>, Self>) -> Option<ArcType> {
        None
    }
}
<|endoftext|>