<commit_before>extern crate glob;

use glob::glob;
use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
use std::fmt;

fn main() {
    let mut output = String::new();

    fmt::write(
        &mut output,
        format_args!("pub static PATTERNS: &[(&'static str, &'static str)] = &[\n"),
    ).unwrap();

    for line in glob("patterns/*.pattern").unwrap() // load filepaths
        // extract the filepath
        .map(|e| e.unwrap())
        // open file for path
        .map(|path| File::open(path).unwrap())
        // flatten to actual lines
        .flat_map(|f| BufReader::new(f).lines())
        .map(|line| line.unwrap())
        // filter comments
        .filter(|line| !line.starts_with("#"))
        // filter empty lines
        .filter(|line| !line.is_empty())
    {
        let (key, value) = line.split_at(line.find(" ").unwrap());
        fmt::write(
            &mut output,
            format_args!("\t(\"{}\", r#\"{}\"#),\n", key, &value[1..]),
        ).unwrap();
    }

    fmt::write(&mut output, format_args!("];\n")).unwrap();

    let mut file = File::create("src/patterns.rs").unwrap();
    file.write_all(output.as_bytes()).unwrap();
}
<commit_msg>Build patterns in OUT_DIR only<commit_after>extern crate glob;

use glob::glob;
use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
use std::fmt;
use std::env;
use std::path::Path;

fn main() {
    let mut output = String::new();

    fmt::write(
        &mut output,
        format_args!("pub static PATTERNS: &[(&'static str, &'static str)] = &[\n"),
    ).unwrap();

    for line in glob("patterns/*.pattern").unwrap() // load filepaths
        // extract the filepath
        .map(|e| e.unwrap())
        // open file for path
        .map(|path| File::open(path).unwrap())
        // flatten to actual lines
        .flat_map(|f| BufReader::new(f).lines())
        .map(|line| line.unwrap())
        // filter comments
        .filter(|line| !line.starts_with("#"))
        // filter empty lines
        .filter(|line| !line.is_empty())
    {
        let (key, value) = line.split_at(line.find(" ").unwrap());
        fmt::write(
            &mut output,
            format_args!("\t(\"{}\", r#\"{}\"#),\n", key, &value[1..]),
        ).unwrap();
    }

    fmt::write(&mut output, format_args!("];\n")).unwrap();

    let out_dir = env::var("OUT_DIR").unwrap();
    let dest_path = Path::new(&out_dir).join("patterns.rs");
    let mut file = File::create(&dest_path).unwrap();
    file.write_all(output.as_bytes()).unwrap();
}
<|endoftext|>


<commit_before>extern crate crowbook_localize;
use crowbook_localize::{Localizer, Extractor};

use std::path::Path;

fn main() {
    println!("cargo:rerun-if-changed=build.rs");
    println!("cargo:rerun-if-changed=lang/fr.po");
    let mut extractor = Extractor::new();
    extractor.add_messages_from_dir(concat!(env!("CARGO_MANIFEST_DIR"), "/src")).unwrap();
    extractor.write_pot_file(concat!(env!("CARGO_MANIFEST_DIR"), "/lang/crowbook.pot")).unwrap();

    let mut localizer = Localizer::new(&extractor);
    localizer.add_lang("fr", include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/lang/fr.po"))).unwrap();
    let dest_path = Path::new(env!("OUT_DIR")).join("localize_macros.rs");
    localizer.write_macro_file(dest_path.to_str().unwrap()).unwrap();
}
<commit_msg>Use env::arg instead of env macro<commit_after>extern crate crowbook_localize;
use crowbook_localize::{Localizer, Extractor};

use std::path::Path;
use std::env;

fn main() {
//    println!("cargo:rerun-if-changed=build.rs");
//    println!("cargo:rerun-if-changed=lang/fr.po");
    let mut extractor = Extractor::new();
    extractor.add_messages_from_dir(concat!(env!("CARGO_MANIFEST_DIR"), "/src")).unwrap();
    extractor.write_pot_file(concat!(env!("CARGO_MANIFEST_DIR"), "/lang/crowbook.pot")).unwrap();

    let mut localizer = Localizer::new(&extractor);
    localizer.add_lang("fr", include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/lang/fr.po"))).unwrap();
    let out_dir_path = env::var("OUT_DIR").unwrap();
    let out_dir = Path::new(&out_dir_path);
    let dest_path = out_dir.join("localize_macros.rs");
    localizer.write_macro_file(dest_path.to_str().unwrap()).unwrap();
}
<|endoftext|>


<commit_before>/*
At this stage this build script is just a shim to get the old build script
working. At some point they'll both need to be refactored into a single
unified build.rs
*/
#![feature(io, os)]

use std::process::Command;
use std::os;

fn main() {
    // Build nanovg
    Command::new("make").arg("-f").arg("nanovg.mk").status().unwrap();

    let out_dir = os::getenv("OUT_DIR").unwrap();
    println!("cargo:rustc-flags=-L native={} -l static=nanovg_shim", out_dir);
}
<commit_msg>Update build.rs<commit_after>/*
At this stage this build script is just a shim to get the old build script
working. At some point they'll both need to be refactored into a single
unified build.rs
*/
#![feature(io, os)]

use std::process::Command;
use std::env;

fn main() {
    // Build nanovg
    Command::new("make").arg("-f").arg("nanovg.mk").status().unwrap();

    let out_dir = env::var("OUT_DIR").unwrap();
    println!("cargo:rustc-flags=-L native={} -l static=nanovg_shim", out_dir);
}
<|endoftext|>


<commit_before>use std::cmp::{max, min};

use cssparser::Parser;
use markup5ever::{expanded_name, local_name, namespace_url, ns};

use crate::attributes::Attributes;
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::{ElementResult, SetAttributes};
use crate::error::*;
use crate::node::Node;
use crate::parsers::{NumberOptionalNumber, Parse, ParseValue};
use crate::rect::IRect;
use crate::surface_utils::{
    iterators::{PixelRectangle, Pixels},
    shared_surface::ExclusiveImageSurface,
    EdgeMode, ImageSurfaceDataExt, Pixel,
};

use super::context::{FilterContext, FilterOutput, FilterResult};
use super::{FilterEffect, FilterError, PrimitiveWithInput};

/// Enumeration of the possible morphology operations.
enum Operator {
    Erode,
    Dilate,
}

/// The `feMorphology` filter primitive.
pub struct FeMorphology {
    base: PrimitiveWithInput,
    operator: Operator,
    radius: (f64, f64),
}

impl Default for FeMorphology {
    /// Constructs a new `Morphology` with empty properties.
    #[inline]
    fn default() -> FeMorphology {
        FeMorphology {
            base: PrimitiveWithInput::new::<Self>(),
            operator: Operator::Erode,
            radius: (0.0, 0.0),
        }
    }
}

impl SetAttributes for FeMorphology {
    fn set_attributes(&mut self, attrs: &Attributes) -> ElementResult {
        self.base.set_attributes(attrs)?;

        for (attr, value) in attrs.iter() {
            match attr.expanded() {
                expanded_name!("", "operator") => self.operator = attr.parse(value)?,
                expanded_name!("", "radius") => {
                    let NumberOptionalNumber(x, y) =
                        attr.parse_and_validate(value, |v: NumberOptionalNumber<f64>| {
                            if v.0 >= 0.0 && v.1 >= 0.0 {
                                Ok(v)
                            } else {
                                Err(ValueErrorKind::value_error("radius cannot be negative"))
                            }
                        })?;

                    self.radius = (x, y);
                }
                _ => (),
            }
        }

        Ok(())
    }
}

impl FilterEffect for FeMorphology {
    fn render(
        &self,
        node: &Node,
        ctx: &FilterContext,
        acquired_nodes: &mut AcquiredNodes<'_>,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<FilterResult, FilterError> {
        let input = self.base.get_input(ctx, acquired_nodes, draw_ctx)?;
        let bounds = self
            .base
            .get_bounds(ctx, node.parent().as_ref())?
            .add_input(&input)
            .into_irect(draw_ctx);

        let (rx, ry) = self.radius;
        let (rx, ry) = ctx.paffine().transform_distance(rx, ry);

        // The radii can become negative here due to the transform.
        let (rx, ry) = (rx.abs(), ry.abs());

        let mut surface = ExclusiveImageSurface::new(
            ctx.source_graphic().width(),
            ctx.source_graphic().height(),
            input.surface().surface_type(),
        )?;

        surface.modify(&mut |data, stride| {
            for (x, y, _pixel) in Pixels::within(input.surface(), bounds) {
                // Compute the kernel rectangle bounds.
                let kernel_bounds = IRect::new(
                    (f64::from(x) - rx).floor() as i32,
                    (f64::from(y) - ry).floor() as i32,
                    (f64::from(x) + rx).ceil() as i32 + 1,
                    (f64::from(y) + ry).ceil() as i32 + 1,
                );

                // Compute the new pixel values.
                let initial = match self.operator {
                    Operator::Erode => u8::max_value(),
                    Operator::Dilate => u8::min_value(),
                };

                let mut output_pixel = Pixel {
                    r: initial,
                    g: initial,
                    b: initial,
                    a: initial,
                };

                for (_x, _y, pixel) in
                    PixelRectangle::within(&input.surface(), bounds, kernel_bounds, EdgeMode::None)
                {
                    let op = match self.operator {
                        Operator::Erode => min,
                        Operator::Dilate => max,
                    };

                    output_pixel.r = op(output_pixel.r, pixel.r);
                    output_pixel.g = op(output_pixel.g, pixel.g);
                    output_pixel.b = op(output_pixel.b, pixel.b);
                    output_pixel.a = op(output_pixel.a, pixel.a);
                }

                data.set_pixel(stride, output_pixel, x, y);
            }
        });

        Ok(FilterResult {
            name: self.base.result.clone(),
            output: FilterOutput {
                surface: surface.share()?,
                bounds,
            },
        })
    }

    #[inline]
    fn is_affected_by_color_interpolation_filters(&self) -> bool {
        false
    }
}

impl Parse for Operator {
    fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<Self, ParseError<'i>> {
        Ok(parse_identifiers!(
            parser,
            "erode" => Operator::Erode,
            "dilate" => Operator::Dilate,
        )?)
    }
}
<commit_msg>morphology: use NonNegative for parsing<commit_after>use std::cmp::{max, min};

use cssparser::Parser;
use markup5ever::{expanded_name, local_name, namespace_url, ns};

use crate::attributes::Attributes;
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::{ElementResult, SetAttributes};
use crate::error::*;
use crate::node::Node;
use crate::parsers::{NonNegative, NumberOptionalNumber, Parse, ParseValue};
use crate::rect::IRect;
use crate::surface_utils::{
    iterators::{PixelRectangle, Pixels},
    shared_surface::ExclusiveImageSurface,
    EdgeMode, ImageSurfaceDataExt, Pixel,
};

use super::context::{FilterContext, FilterOutput, FilterResult};
use super::{FilterEffect, FilterError, PrimitiveWithInput};

/// Enumeration of the possible morphology operations.
enum Operator {
    Erode,
    Dilate,
}

/// The `feMorphology` filter primitive.
pub struct FeMorphology {
    base: PrimitiveWithInput,
    operator: Operator,
    radius: (f64, f64),
}

impl Default for FeMorphology {
    /// Constructs a new `Morphology` with empty properties.
    #[inline]
    fn default() -> FeMorphology {
        FeMorphology {
            base: PrimitiveWithInput::new::<Self>(),
            operator: Operator::Erode,
            radius: (0.0, 0.0),
        }
    }
}

impl SetAttributes for FeMorphology {
    fn set_attributes(&mut self, attrs: &Attributes) -> ElementResult {
        self.base.set_attributes(attrs)?;

        for (attr, value) in attrs.iter() {
            match attr.expanded() {
                expanded_name!("", "operator") => self.operator = attr.parse(value)?,
                expanded_name!("", "radius") => {
                    let NumberOptionalNumber(NonNegative(x), NonNegative(y)) = attr.parse(value)?;
                    self.radius = (x, y);
                }
                _ => (),
            }
        }

        Ok(())
    }
}

impl FilterEffect for FeMorphology {
    fn render(
        &self,
        node: &Node,
        ctx: &FilterContext,
        acquired_nodes: &mut AcquiredNodes<'_>,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<FilterResult, FilterError> {
        let input = self.base.get_input(ctx, acquired_nodes, draw_ctx)?;
        let bounds = self
            .base
            .get_bounds(ctx, node.parent().as_ref())?
            .add_input(&input)
            .into_irect(draw_ctx);

        let (rx, ry) = self.radius;
        let (rx, ry) = ctx.paffine().transform_distance(rx, ry);

        // The radii can become negative here due to the transform.
        let (rx, ry) = (rx.abs(), ry.abs());

        let mut surface = ExclusiveImageSurface::new(
            ctx.source_graphic().width(),
            ctx.source_graphic().height(),
            input.surface().surface_type(),
        )?;

        surface.modify(&mut |data, stride| {
            for (x, y, _pixel) in Pixels::within(input.surface(), bounds) {
                // Compute the kernel rectangle bounds.
                let kernel_bounds = IRect::new(
                    (f64::from(x) - rx).floor() as i32,
                    (f64::from(y) - ry).floor() as i32,
                    (f64::from(x) + rx).ceil() as i32 + 1,
                    (f64::from(y) + ry).ceil() as i32 + 1,
                );

                // Compute the new pixel values.
                let initial = match self.operator {
                    Operator::Erode => u8::max_value(),
                    Operator::Dilate => u8::min_value(),
                };

                let mut output_pixel = Pixel {
                    r: initial,
                    g: initial,
                    b: initial,
                    a: initial,
                };

                for (_x, _y, pixel) in
                    PixelRectangle::within(&input.surface(), bounds, kernel_bounds, EdgeMode::None)
                {
                    let op = match self.operator {
                        Operator::Erode => min,
                        Operator::Dilate => max,
                    };

                    output_pixel.r = op(output_pixel.r, pixel.r);
                    output_pixel.g = op(output_pixel.g, pixel.g);
                    output_pixel.b = op(output_pixel.b, pixel.b);
                    output_pixel.a = op(output_pixel.a, pixel.a);
                }

                data.set_pixel(stride, output_pixel, x, y);
            }
        });

        Ok(FilterResult {
            name: self.base.result.clone(),
            output: FilterOutput {
                surface: surface.share()?,
                bounds,
            },
        })
    }

    #[inline]
    fn is_affected_by_color_interpolation_filters(&self) -> bool {
        false
    }
}

impl Parse for Operator {
    fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<Self, ParseError<'i>> {
        Ok(parse_identifiers!(
            parser,
            "erode" => Operator::Erode,
            "dilate" => Operator::Dilate,
        )?)
    }
}
<|endoftext|>


<commit_before>//! Tests for when multiple artifacts have the same output filename.
//! See https://github.com/rust-lang/cargo/issues/6313 for more details.
//! Ideally these should never happen, but I don't think we'll ever be able to
//! prevent all collisions.

use cargo_test_support::basic_manifest;
use cargo_test_support::project;
use std::env;

#[cargo_test]
fn collision_dylib() {
    // Path dependencies don't include metadata hash in filename for dylibs.
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [workspace]
            members = ["a", "b"]
            "#,
        )
        .file(
            "a/Cargo.toml",
            r#"
            [package]
            name = "a"
            version = "1.0.0"

            [lib]
            crate-type = ["dylib"]
            "#,
        )
        .file("a/src/lib.rs", "")
        .file(
            "b/Cargo.toml",
            r#"
            [package]
            name = "b"
            version = "1.0.0"

            [lib]
            crate-type = ["dylib"]
            name = "a"
            "#,
        )
        .file("b/src/lib.rs", "")
        .build();

    // `j=1` is required because on Windows you'll get an error due to
    // two processes writing to the file at the same time.
    p.cargo("build -j=1")
        .with_stderr_contains(&format!("\
[WARNING] output filename collision.
The lib target `a` in package `b v1.0.0 ([..]/foo/b)` has the same output filename as the lib target `a` in package `a v1.0.0 ([..]/foo/a)`.
Colliding filename is: [..]/foo/target/debug/deps/{}a{}
The targets should have unique names.
Consider changing their names to be unique or compiling them separately.
This may become a hard error in the future; see <https://github.com/rust-lang/cargo/issues/6313>.
", env::consts::DLL_PREFIX, env::consts::DLL_SUFFIX))
        .run();
}

#[cargo_test]
fn collision_example() {
    // Examples in a workspace can easily collide.
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [workspace]
            members = ["a", "b"]
            "#,
        )
        .file("a/Cargo.toml", &basic_manifest("a", "1.0.0"))
        .file("a/examples/ex1.rs", "fn main() {}")
        .file("b/Cargo.toml", &basic_manifest("b", "1.0.0"))
        .file("b/examples/ex1.rs", "fn main() {}")
        .build();

    // `j=1` is required because on Windows you'll get an error due to
    // two processes writing to the file at the same time.
    p.cargo("build --examples -j=1")
        .with_stderr_contains("\
[WARNING] output filename collision.
The example target `ex1` in package `b v1.0.0 ([..]/foo/b)` has the same output filename as the example target `ex1` in package `a v1.0.0 ([..]/foo/a)`.
Colliding filename is: [..]/foo/target/debug/examples/ex1[EXE]
The targets should have unique names.
Consider changing their names to be unique or compiling them separately.
This may become a hard error in the future; see <https://github.com/rust-lang/cargo/issues/6313>.
")
        .run();
}

#[cargo_test]
#[cfg(not(target_env = "msvc"))]
fn collision_export() {
    // `--out-dir` combines some things which can cause conflicts.
    let p = project()
        .file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
        .file("examples/foo.rs", "fn main() {}")
        .file("src/main.rs", "fn main() {}")
        .build();

    p.cargo("build --out-dir=out -Z unstable-options --bins --examples")
        .masquerade_as_nightly_cargo()
        .with_stderr_contains("\
[WARNING] `--out-dir` filename collision.
The example target `foo` in package `foo v1.0.0 ([..]/foo)` has the same output filename as the bin target `foo` in package `foo v1.0.0 ([..]/foo)`.
Colliding filename is: [..]/foo/out/foo[EXE]
The exported filenames should be unique.
Consider changing their names to be unique or compiling them separately.
This may become a hard error in the future; see <https://github.com/rust-lang/cargo/issues/6313>.
")
        .run();
}

#[cargo_test]
fn collision_doc() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [package]
            name = "foo"
            version = "0.1.0"

            [dependencies]
            foo2 = { path = "foo2" }
            "#,
        )
        .file("src/lib.rs", "")
        .file(
            "foo2/Cargo.toml",
            r#"
            [package]
            name = "foo2"
            version = "0.1.0"

            [lib]
            name = "foo"
            "#,
        )
        .file("foo2/src/lib.rs", "")
        .build();

    p.cargo("doc")
        .with_stderr_contains(
            "\
[WARNING] output filename collision.
The lib target `foo` in package `foo2 v0.1.0 ([..]/foo/foo2)` has the same output \
filename as the lib target `foo` in package `foo v0.1.0 ([..]/foo)`.
Colliding filename is: [..]/foo/target/doc/foo/index.html
The targets should have unique names.
This is a known bug where multiple crates with the same name use
the same path; see <https://github.com/rust-lang/cargo/issues/6313>.
",
        )
        .run();
}
<commit_msg>Auto merge of #7956 - ehuss:fix-collision-test, r=alexcrichton<commit_after>//! Tests for when multiple artifacts have the same output filename.
//! See https://github.com/rust-lang/cargo/issues/6313 for more details.
//! Ideally these should never happen, but I don't think we'll ever be able to
//! prevent all collisions.

use cargo_test_support::basic_manifest;
use cargo_test_support::project;
use std::env;

#[cargo_test]
fn collision_dylib() {
    // Path dependencies don't include metadata hash in filename for dylibs.
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [workspace]
            members = ["a", "b"]
            "#,
        )
        .file(
            "a/Cargo.toml",
            r#"
            [package]
            name = "a"
            version = "1.0.0"

            [lib]
            crate-type = ["dylib"]
            "#,
        )
        .file("a/src/lib.rs", "")
        .file(
            "b/Cargo.toml",
            r#"
            [package]
            name = "b"
            version = "1.0.0"

            [lib]
            crate-type = ["dylib"]
            name = "a"
            "#,
        )
        .file("b/src/lib.rs", "")
        .build();

    // `j=1` is required because on Windows you'll get an error due to
    // two processes writing to the file at the same time.
    p.cargo("build -j=1")
        .with_stderr_contains(&format!("\
[WARNING] output filename collision.
The lib target `a` in package `b v1.0.0 ([..]/foo/b)` has the same output filename as the lib target `a` in package `a v1.0.0 ([..]/foo/a)`.
Colliding filename is: [..]/foo/target/debug/deps/{}a{}
The targets should have unique names.
Consider changing their names to be unique or compiling them separately.
This may become a hard error in the future; see <https://github.com/rust-lang/cargo/issues/6313>.
", env::consts::DLL_PREFIX, env::consts::DLL_SUFFIX))
        .run();
}

#[cargo_test]
fn collision_example() {
    // Examples in a workspace can easily collide.
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [workspace]
            members = ["a", "b"]
            "#,
        )
        .file("a/Cargo.toml", &basic_manifest("a", "1.0.0"))
        .file("a/examples/ex1.rs", "fn main() {}")
        .file("b/Cargo.toml", &basic_manifest("b", "1.0.0"))
        .file("b/examples/ex1.rs", "fn main() {}")
        .build();

    // `j=1` is required because on Windows you'll get an error due to
    // two processes writing to the file at the same time.
    p.cargo("build --examples -j=1")
        .with_stderr_contains("\
[WARNING] output filename collision.
The example target `ex1` in package `b v1.0.0 ([..]/foo/b)` has the same output filename as the example target `ex1` in package `a v1.0.0 ([..]/foo/a)`.
Colliding filename is: [..]/foo/target/debug/examples/ex1[EXE]
The targets should have unique names.
Consider changing their names to be unique or compiling them separately.
This may become a hard error in the future; see <https://github.com/rust-lang/cargo/issues/6313>.
")
        .run();
}

#[cargo_test]
// --out-dir and examples are currently broken on MSVC.
// See https://github.com/rust-lang/cargo/issues/7493
#[cfg(not(target_env = "msvc"))]
fn collision_export() {
    // `--out-dir` combines some things which can cause conflicts.
    let p = project()
        .file("Cargo.toml", &basic_manifest("foo", "1.0.0"))
        .file("examples/foo.rs", "fn main() {}")
        .file("src/main.rs", "fn main() {}")
        .build();

    // -j1 to avoid issues with two processes writing to the same file at the
    // same time.
    p.cargo("build -j1 --out-dir=out -Z unstable-options --bins --examples")
        .masquerade_as_nightly_cargo()
        .with_stderr_contains("\
[WARNING] `--out-dir` filename collision.
The example target `foo` in package `foo v1.0.0 ([..]/foo)` has the same output filename as the bin target `foo` in package `foo v1.0.0 ([..]/foo)`.
Colliding filename is: [..]/foo/out/foo[EXE]
The exported filenames should be unique.
Consider changing their names to be unique or compiling them separately.
This may become a hard error in the future; see <https://github.com/rust-lang/cargo/issues/6313>.
")
        .run();
}

#[cargo_test]
fn collision_doc() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [package]
            name = "foo"
            version = "0.1.0"

            [dependencies]
            foo2 = { path = "foo2" }
            "#,
        )
        .file("src/lib.rs", "")
        .file(
            "foo2/Cargo.toml",
            r#"
            [package]
            name = "foo2"
            version = "0.1.0"

            [lib]
            name = "foo"
            "#,
        )
        .file("foo2/src/lib.rs", "")
        .build();

    p.cargo("doc")
        .with_stderr_contains(
            "\
[WARNING] output filename collision.
The lib target `foo` in package `foo2 v0.1.0 ([..]/foo/foo2)` has the same output \
filename as the lib target `foo` in package `foo v0.1.0 ([..]/foo)`.
Colliding filename is: [..]/foo/target/doc/foo/index.html
The targets should have unique names.
This is a known bug where multiple crates with the same name use
the same path; see <https://github.com/rust-lang/cargo/issues/6313>.
",
        )
        .run();
}
<|endoftext|>


<commit_before>//! Tests for --unit-graph option.

use cargo_test_support::project;
use cargo_test_support::registry::Package;

#[cargo_test]
fn gated() {
    let p = project().file("src/lib.rs", "").build();
    p.cargo("build --unit-graph")
        .with_status(101)
        .with_stderr(
            "\
[ERROR] the `--unit-graph` flag is unstable[..]
See [..]
See [..]
",
        )
        .run();
}

#[cargo_test]
fn simple() {
    Package::new("a", "1.0.0")
        .dep("b", "1.0")
        .feature("feata", &["b/featb"])
        .publish();
    Package::new("b", "1.0.0")
        .dep("c", "1.0")
        .feature("featb", &["c/featc"])
        .publish();
    Package::new("c", "1.0.0").feature("featc", &[]).publish();

    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [package]
            name = "foo"
            version = "0.1.0"

            [dependencies]
            a = "1.0"
            "#,
        )
        .file("src/lib.rs", "")
        .build();

    p.cargo("build --features a/feata --unit-graph -Zunstable-options")
        .masquerade_as_nightly_cargo()
        .with_json(
            r#"{
  "version": 1,
  "units": [
    {
      "pkg_id": "a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
      "target": {
        "kind": [
          "lib"
        ],
        "crate_types": [
          "lib"
        ],
        "name": "a",
        "src_path": "[..]/a-1.0.0/src/lib.rs",
        "edition": "2015",
        "doctest": true
      },
      "profile": {
        "name": "dev",
        "opt_level": "0",
        "lto": "false",
        "codegen_units": null,
        "debuginfo": 2,
        "debug_assertions": true,
        "overflow_checks": true,
        "rpath": false,
        "incremental": false,
        "panic": "unwind"
      },
      "platform": null,
      "mode": "build",
      "features": [
        "feata"
      ],
      "dependencies": [
        {
          "index": 1,
          "extern_crate_name": "b",
          "public": false,
          "noprelude": false
        }
      ]
    },
    {
      "pkg_id": "b 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
      "target": {
        "kind": [
          "lib"
        ],
        "crate_types": [
          "lib"
        ],
        "name": "b",
        "src_path": "[..]/b-1.0.0/src/lib.rs",
        "edition": "2015",
        "doctest": true
      },
      "profile": {
        "name": "dev",
        "opt_level": "0",
        "lto": "false",
        "codegen_units": null,
        "debuginfo": 2,
        "debug_assertions": true,
        "overflow_checks": true,
        "rpath": false,
        "incremental": false,
        "panic": "unwind"
      },
      "platform": null,
      "mode": "build",
      "features": [
        "featb"
      ],
      "dependencies": [
        {
          "index": 2,
          "extern_crate_name": "c",
          "public": false,
          "noprelude": false
        }
      ]
    },
    {
      "pkg_id": "c 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
      "target": {
        "kind": [
          "lib"
        ],
        "crate_types": [
          "lib"
        ],
        "name": "c",
        "src_path": "[..]/c-1.0.0/src/lib.rs",
        "edition": "2015",
        "doctest": true
      },
      "profile": {
        "name": "dev",
        "opt_level": "0",
        "lto": "false",
        "codegen_units": null,
        "debuginfo": 2,
        "debug_assertions": true,
        "overflow_checks": true,
        "rpath": false,
        "incremental": false,
        "panic": "unwind"
      },
      "platform": null,
      "mode": "build",
      "features": [
        "featc"
      ],
      "dependencies": []
    },
    {
      "pkg_id": "foo 0.1.0 (path+file://[..]/foo)",
      "target": {
        "kind": [
          "lib"
        ],
        "crate_types": [
          "lib"
        ],
        "name": "foo",
        "src_path": "[..]/foo/src/lib.rs",
        "edition": "2015",
        "doctest": true
      },
      "profile": {
        "name": "dev",
        "opt_level": "0",
        "lto": "false",
        "codegen_units": null,
        "debuginfo": 2,
        "debug_assertions": true,
        "overflow_checks": true,
        "rpath": false,
        "incremental": false,
        "panic": "unwind"
      },
      "platform": null,
      "mode": "build",
      "features": [],
      "dependencies": [
        {
          "index": 0,
          "extern_crate_name": "a",
          "public": false,
          "noprelude": false
        }
      ]
    }
  ],
  "roots": [3]
}
"#,
        )
        .run();
}
<commit_msg>Fix tests<commit_after>//! Tests for --unit-graph option.

use cargo_test_support::project;
use cargo_test_support::registry::Package;

#[cargo_test]
fn gated() {
    let p = project().file("src/lib.rs", "").build();
    p.cargo("build --unit-graph")
        .with_status(101)
        .with_stderr(
            "\
[ERROR] the `--unit-graph` flag is unstable[..]
See [..]
See [..]
",
        )
        .run();
}

#[cargo_test]
fn simple() {
    Package::new("a", "1.0.0")
        .dep("b", "1.0")
        .feature("feata", &["b/featb"])
        .publish();
    Package::new("b", "1.0.0")
        .dep("c", "1.0")
        .feature("featb", &["c/featc"])
        .publish();
    Package::new("c", "1.0.0").feature("featc", &[]).publish();

    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [package]
            name = "foo"
            version = "0.1.0"

            [dependencies]
            a = "1.0"
            "#,
        )
        .file("src/lib.rs", "")
        .build();

    p.cargo("build --features a/feata --unit-graph -Zunstable-options")
        .masquerade_as_nightly_cargo()
        .with_json(
            r#"{
  "version": 1,
  "units": [
    {
      "pkg_id": "a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
      "target": {
        "kind": [
          "lib"
        ],
        "crate_types": [
          "lib"
        ],
        "name": "a",
        "src_path": "[..]/a-1.0.0/src/lib.rs",
        "edition": "2015",
        "doctest": true
      },
      "profile": {
        "name": "dev",
        "opt_level": "0",
        "lto": "false",
        "codegen_units": null,
        "debuginfo": 2,
        "debug_assertions": true,
        "overflow_checks": true,
        "rpath": false,
        "incremental": false,
        "panic": "unwind",
        "strip": "none"
      },
      "platform": null,
      "mode": "build",
      "features": [
        "feata"
      ],
      "dependencies": [
        {
          "index": 1,
          "extern_crate_name": "b",
          "public": false,
          "noprelude": false
        }
      ]
    },
    {
      "pkg_id": "b 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
      "target": {
        "kind": [
          "lib"
        ],
        "crate_types": [
          "lib"
        ],
        "name": "b",
        "src_path": "[..]/b-1.0.0/src/lib.rs",
        "edition": "2015",
        "doctest": true
      },
      "profile": {
        "name": "dev",
        "opt_level": "0",
        "lto": "false",
        "codegen_units": null,
        "debuginfo": 2,
        "debug_assertions": true,
        "overflow_checks": true,
        "rpath": false,
        "incremental": false,
        "panic": "unwind",
        "strip": "none"
      },
      "platform": null,
      "mode": "build",
      "features": [
        "featb"
      ],
      "dependencies": [
        {
          "index": 2,
          "extern_crate_name": "c",
          "public": false,
          "noprelude": false
        }
      ]
    },
    {
      "pkg_id": "c 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
      "target": {
        "kind": [
          "lib"
        ],
        "crate_types": [
          "lib"
        ],
        "name": "c",
        "src_path": "[..]/c-1.0.0/src/lib.rs",
        "edition": "2015",
        "doctest": true
      },
      "profile": {
        "name": "dev",
        "opt_level": "0",
        "lto": "false",
        "codegen_units": null,
        "debuginfo": 2,
        "debug_assertions": true,
        "overflow_checks": true,
        "rpath": false,
        "incremental": false,
        "panic": "unwind",
        "strip": "none"
      },
      "platform": null,
      "mode": "build",
      "features": [
        "featc"
      ],
      "dependencies": []
    },
    {
      "pkg_id": "foo 0.1.0 (path+file://[..]/foo)",
      "target": {
        "kind": [
          "lib"
        ],
        "crate_types": [
          "lib"
        ],
        "name": "foo",
        "src_path": "[..]/foo/src/lib.rs",
        "edition": "2015",
        "doctest": true
      },
      "profile": {
        "name": "dev",
        "opt_level": "0",
        "lto": "false",
        "codegen_units": null,
        "debuginfo": 2,
        "debug_assertions": true,
        "overflow_checks": true,
        "rpath": false,
        "incremental": false,
        "panic": "unwind",
        "strip": "none"
      },
      "platform": null,
      "mode": "build",
      "features": [],
      "dependencies": [
        {
          "index": 0,
          "extern_crate_name": "a",
          "public": false,
          "noprelude": false
        }
      ]
    }
  ],
  "roots": [3]
}
"#,
        )
        .run();
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate test;
extern crate rand;
extern crate presort;

use test::Bencher;
use rand::Rng;

use presort::PresortedVec;
use presort::inc_tree::{Tree, IncTree, dump, update};

const NODES: usize = 10000;
const BINARY_DEPTH: usize = 13;
const DEEP_DEPTH: usize = 150;
const WIDE_DEPTH: usize = 6;
const DEPTH: usize = BINARY_DEPTH;

//creates a random tree with the requested parameters
fn build_tree(max_depth: usize, nodes: usize) -> Tree<usize> {
    let mut rng = rand::thread_rng();

    let tree = Tree::new_node(rng.gen());

    for _ in 0..nodes {
        let mut branch = tree.clone();
        let depth = rng.gen::<usize>() % max_depth;
        for _ in 0..depth {
            let num = branch.num_children();
            if num <= 0 {break};
            branch = branch.get_child(rng.gen::<usize>() % num);
        }
        branch.push_child(Tree::new_node(rng.gen()));
    }

    tree
}

// Pick a random subtree from the tree
fn random_subtree(tree: &Tree<usize>, high_depth: usize) -> Tree<usize> {
    let mut rng = rand::thread_rng();
    let mut subtree = tree.clone();
    let depth = rng.gen::<usize>() % high_depth;
    for _ in 0..depth {
        let num = subtree.num_children();
        if num <= 0 { return subtree; }
        subtree = subtree.get_child(rng.gen::<usize>() % num);
    }
    return subtree;
}

// mutates `edits` number of values of `tree`,
// at no more than a max depth of `high_depth`
// shorter branches may have the ends updated more often
fn mutate_vals(tree: &Tree<usize>, high_depth: usize, edits: usize) {
    let mut rng = rand::thread_rng();
    for _ in 0..edits {
        random_subtree(tree, high_depth).set_data(rng.gen());
    }
}

fn add_branches(tree: &Tree<usize>, high_depth: usize, adds: usize) {
    let mut rng = rand::thread_rng();
    for _ in 0..adds {
        random_subtree(tree, high_depth).push_child(Tree::new_node(rng.gen()));
    }
}

#[bench]
fn edit_50_batch(b: &mut Bencher) {
    let mut vec = PresortedVec::new();
    let tree = build_tree(DEPTH, NODES);
    dump(&tree, &mut vec);
    b.iter(|| {
        mutate_vals(&tree, DEPTH, 50);
        update(&tree, 0, &mut vec);
    })
}

#[bench]
fn edit_50_seperate(b: &mut Bencher) {
    let mut vec = PresortedVec::new();
    let tree = build_tree(DEPTH, NODES);
    dump(&tree, &mut vec);
    b.iter(|| {
        for _ in 0..50 {
            mutate_vals(&tree, DEPTH, 1);
            update(&tree, 0, &mut vec);
        }
    })
}

#[bench]
fn add_50_batch(b: &mut Bencher) {
    let mut vec = PresortedVec::new();
    let tree = build_tree(DEPTH, NODES);
    dump(&tree, &mut vec);
    b.iter(|| {
        add_branches(&tree, DEPTH, 50);
        update(&tree, 0, &mut vec);
    })
}

#[bench]
fn add_50_seperate(b: &mut Bencher) {
    let mut vec = PresortedVec::new();
    let tree = build_tree(DEPTH, NODES);
    dump(&tree, &mut vec);
    b.iter(|| {
        for _ in 0..50 {
            add_branches(&tree, DEPTH, 50);
            update(&tree, 0, &mut vec);
        }
    })
}

<commit_msg>Added test to increment rather than randomize data.<commit_after>#![feature(test)]

extern crate test;
extern crate rand;
extern crate presort;

use test::Bencher;
use rand::Rng;

use presort::PresortedVec;
use presort::inc_tree::{Tree, IncTree, dump, update};

const NODES: usize = 10000;
const BINARY_DEPTH: usize = 13;
const DEEP_DEPTH: usize = 150;
const WIDE_DEPTH: usize = 6;
const DEPTH: usize = BINARY_DEPTH;

//creates a random tree with the requested parameters
fn build_tree(max_depth: usize, nodes: usize) -> Tree<usize> {
    let mut rng = rand::thread_rng();

    let tree = Tree::new_node(rng.gen());

    for _ in 0..nodes {
        let mut branch = tree.clone();
        let depth = rng.gen::<usize>() % max_depth;
        for _ in 0..depth {
            let num = branch.num_children();
            if num <= 0 {break};
            branch = branch.get_child(rng.gen::<usize>() % num);
        }
        branch.push_child(Tree::new_node(rng.gen()));
    }

    tree
}

// Pick a random subtree from the tree
fn random_subtree(tree: &Tree<usize>, high_depth: usize) -> Tree<usize> {
    let mut rng = rand::thread_rng();
    let mut subtree = tree.clone();
    let depth = rng.gen::<usize>() % high_depth;
    for _ in 0..depth {
        let num = subtree.num_children();
        if num <= 0 { return subtree; }
        subtree = subtree.get_child(rng.gen::<usize>() % num);
    }
    return subtree;
}

// mutates `edits` number of values of `tree`,
// at no more than a max depth of `high_depth`
// shorter branches may have the ends updated more often
fn mutate_vals(tree: &Tree<usize>, high_depth: usize, edits: usize) {
    let mut rng = rand::thread_rng();
    for _ in 0..edits {
        random_subtree(tree, high_depth).set_data(rng.gen());
    }
}

fn incr_vals(tree: &Tree<usize>, high_depth: usize, edits: usize) {
    for _ in 0..edits {
        let subtree = random_subtree(tree, high_depth);
        subtree.set_data(subtree.get_data() + 1);
    }
}

fn add_branches(tree: &Tree<usize>, high_depth: usize, adds: usize) {
    let mut rng = rand::thread_rng();
    for _ in 0..adds {
        random_subtree(tree, high_depth).push_child(Tree::new_node(rng.gen()));
    }
}

#[bench]
fn edit_50_batch(b: &mut Bencher) {
    let mut vec = PresortedVec::new();
    let tree = build_tree(DEPTH, NODES);
    dump(&tree, &mut vec);
    b.iter(|| {
        mutate_vals(&tree, DEPTH, 50);
        update(&tree, 0, &mut vec);
    })
}

#[bench]
fn edit_50_seperate(b: &mut Bencher) {
    let mut vec = PresortedVec::new();
    let tree = build_tree(DEPTH, NODES);
    dump(&tree, &mut vec);
    b.iter(|| {
        for _ in 0..50 {
            mutate_vals(&tree, DEPTH, 1);
            update(&tree, 0, &mut vec);
        }
    })
}

#[bench]
fn incr_50_batch(b: &mut Bencher) {
    let mut vec = PresortedVec::new();
    let tree = build_tree(DEPTH, NODES);
    dump(&tree, &mut vec);
    b.iter(|| {
        incr_vals(&tree, DEPTH, 50);
        update(&tree, 0, &mut vec);
    })
}

#[bench]
fn incr_50_seperate(b: &mut Bencher) {
    let mut vec = PresortedVec::new();
    let tree = build_tree(DEPTH, NODES);
    dump(&tree, &mut vec);
    b.iter(|| {
        for _ in 0..50 {
            incr_vals(&tree, DEPTH, 1);
            update(&tree, 0, &mut vec);
        }
    })
}

#[bench]
fn add_50_batch(b: &mut Bencher) {
    let mut vec = PresortedVec::new();
    let tree = build_tree(DEPTH, NODES);
    dump(&tree, &mut vec);
    b.iter(|| {
        add_branches(&tree, DEPTH, 50);
        update(&tree, 0, &mut vec);
    })
}

#[bench]
fn add_50_seperate(b: &mut Bencher) {
    let mut vec = PresortedVec::new();
    let tree = build_tree(DEPTH, NODES);
    dump(&tree, &mut vec);
    b.iter(|| {
        for _ in 0..50 {
            add_branches(&tree, DEPTH, 50);
            update(&tree, 0, &mut vec);
        }
    })
}

<|endoftext|>


<commit_before>//! A framework that can express both [gen-kill] and generic dataflow problems.
//!
//! There is another interface for dataflow in the compiler in `librustc_mir/dataflow/mod.rs`. The
//! interface in this module will eventually [replace that one][design-meeting].
//!
//! To actually use this framework, you must implement either the `Analysis` or the `GenKillAnalysis`
//! trait. If your transfer function can be expressed with only gen/kill operations, prefer
//! `GenKillAnalysis` since it will run faster while iterating to fixpoint. Create an `Engine` using
//! the appropriate constructor and call `iterate_to_fixpoint`. You can use a `ResultsCursor` to
//! inspect the fixpoint solution to your dataflow problem.
//!
//! ```ignore(cross-crate-imports)
//! fn do_my_analysis(tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>, did: DefId) {
//!     let analysis = MyAnalysis::new();
//!
//!     // If `MyAnalysis` implements `GenKillAnalysis`.
//!     let results = Engine::new_gen_kill(tcx, body, did, analysis).iterate_to_fixpoint();
//!
//!     // If `MyAnalysis` implements `Analysis`.
//!     // let results = Engine::new_generic(tcx, body, did, analysis).iterate_to_fixpoint();
//!
//!     let mut cursor = ResultsCursor::new(body, results);
//!
//!     for (_, statement_index) in body.block_data[START_BLOCK].statements.iter_enumerated() {
//!         cursor.seek_after(Location { block: START_BLOCK, statement_index });
//!         let state = cursor.get();
//!         println!("{:?}", state);
//!     }
//! }
//! ```
//!
//! [gen-kill]: https://en.wikipedia.org/wiki/Data-flow_analysis#Bit_vector_problems
//! [design-meeting]https://github.com/rust-lang/compiler-team/issues/202

use std::io;

use rustc::mir::{self, BasicBlock, Location};
use rustc::ty::TyCtxt;
use rustc_hir::def_id::DefId;
use rustc_index::bit_set::{BitSet, HybridBitSet};
use rustc_index::vec::{Idx, IndexVec};

use crate::dataflow::BottomValue;

mod cursor;
mod engine;
mod graphviz;
mod visitor;

pub use self::cursor::{ResultsCursor, ResultsRefCursor};
pub use self::engine::Engine;
pub use self::visitor::{visit_results, ResultsVisitor};
pub use self::visitor::{BorrowckFlowState, BorrowckResults};

/// A dataflow analysis that has converged to fixpoint.
pub struct Results<'tcx, A>
where
    A: Analysis<'tcx>,
{
    pub analysis: A,
    entry_sets: IndexVec<BasicBlock, BitSet<A::Idx>>,
}

impl<A> Results<'tcx, A>
where
    A: Analysis<'tcx>,
{
    /// Creates a `ResultsCursor` that can inspect these `Results`.
    pub fn into_results_cursor(self, body: &'mir mir::Body<'tcx>) -> ResultsCursor<'mir, 'tcx, A> {
        ResultsCursor::new(body, self)
    }

    /// Gets the entry set for the given block.
    pub fn entry_set_for_block(&self, block: BasicBlock) -> &BitSet<A::Idx> {
        &self.entry_sets[block]
    }
}

/// Define the domain of a dataflow problem.
///
/// This trait specifies the lattice on which this analysis operates. For now, this must be a
/// powerset of values of type `Idx`. The elements of this lattice are represented with a `BitSet`
/// and referred to as the state vector.
///
/// This trait also defines the initial value for the dataflow state upon entry to the
/// `START_BLOCK`, as well as some names used to refer to this analysis when debugging.
pub trait AnalysisDomain<'tcx>: BottomValue {
    /// The type of the elements in the state vector.
    type Idx: Idx;

    /// A descriptive name for this analysis. Used only for debugging.
    ///
    /// This name should be brief and contain no spaces, periods or other characters that are not
    /// suitable as part of a filename.
    const NAME: &'static str;

    /// The size of the state vector.
    fn bits_per_block(&self, body: &mir::Body<'tcx>) -> usize;

    /// Mutates the entry set of the `START_BLOCK` to contain the initial state for dataflow
    /// analysis.
    fn initialize_start_block(&self, body: &mir::Body<'tcx>, state: &mut BitSet<Self::Idx>);

    /// Prints an element in the state vector for debugging.
    fn pretty_print_idx(&self, w: &mut impl io::Write, idx: Self::Idx) -> io::Result<()> {
        write!(w, "{:?}", idx)
    }
}

/// A dataflow problem with an arbitrarily complex transfer function.
pub trait Analysis<'tcx>: AnalysisDomain<'tcx> {
    /// Updates the current dataflow state with the effect of evaluating a statement.
    fn apply_statement_effect(
        &self,
        state: &mut BitSet<Self::Idx>,
        statement: &mir::Statement<'tcx>,
        location: Location,
    );

    /// Updates the current dataflow state with an effect that occurs immediately *before* the
    /// given statement.
    ///
    /// This method is useful if the consumer of the results of this analysis needs only to observe
    /// *part* of the effect of a statement (e.g. for two-phase borrows). As a general rule,
    /// analyses should not implement this without implementing `apply_statement_effect`.
    fn apply_before_statement_effect(
        &self,
        _state: &mut BitSet<Self::Idx>,
        _statement: &mir::Statement<'tcx>,
        _location: Location,
    ) {
    }

    /// Updates the current dataflow state with the effect of evaluating a terminator.
    ///
    /// The effect of a successful return from a `Call` terminator should **not** be accounted for
    /// in this function. That should go in `apply_call_return_effect`. For example, in the
    /// `InitializedPlaces` analyses, the return place for a function call is not marked as
    /// initialized here.
    fn apply_terminator_effect(
        &self,
        state: &mut BitSet<Self::Idx>,
        terminator: &mir::Terminator<'tcx>,
        location: Location,
    );

    /// Updates the current dataflow state with an effect that occurs immediately *before* the
    /// given terminator.
    ///
    /// This method is useful if the consumer of the results of this analysis needs only to observe
    /// *part* of the effect of a terminator (e.g. for two-phase borrows). As a general rule,
    /// analyses should not implement this without implementing `apply_terminator_effect`.
    fn apply_before_terminator_effect(
        &self,
        _state: &mut BitSet<Self::Idx>,
        _terminator: &mir::Terminator<'tcx>,
        _location: Location,
    ) {
    }

    /// Updates the current dataflow state with the effect of a successful return from a `Call`
    /// terminator.
    ///
    /// This is separate from `apply_terminator_effect` to properly track state across unwind
    /// edges.
    fn apply_call_return_effect(
        &self,
        state: &mut BitSet<Self::Idx>,
        block: BasicBlock,
        func: &mir::Operand<'tcx>,
        args: &[mir::Operand<'tcx>],
        return_place: &mir::Place<'tcx>,
    );

    /// Calls the appropriate `Engine` constructor to find the fixpoint for this dataflow problem.
    ///
    /// You shouldn't need to override this outside this module, since the combination of the
    /// default impl and the one for all `A: GenKillAnalysis` will do the right thing.
    /// Its purpose is to enable method chaining like so:
    ///
    /// ```ignore(cross-crate-imports)
    /// let results = MyAnalysis::new(tcx, body)
    ///     .into_engine(tcx, body, def_id)
    ///     .iterate_to_fixpoint()
    ///     .into_results_cursor(body);
    /// ```
    fn into_engine(
        self,
        tcx: TyCtxt<'tcx>,
        body: &'mir mir::Body<'tcx>,
        def_id: DefId,
    ) -> Engine<'mir, 'tcx, Self>
    where
        Self: Sized,
    {
        Engine::new_generic(tcx, body, def_id, self)
    }
}

/// A gen/kill dataflow problem.
///
/// Each method in this trait has a corresponding one in `Analysis`. However, these methods only
/// allow modification of the dataflow state via "gen" and "kill" operations. By defining transfer
/// functions for each statement in this way, the transfer function for an entire basic block can
/// be computed efficiently.
///
/// `Analysis` is automatically implemented for all implementers of `GenKillAnalysis`.
pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> {
    /// See `Analysis::apply_statement_effect`.
    fn statement_effect(
        &self,
        trans: &mut impl GenKill<Self::Idx>,
        statement: &mir::Statement<'tcx>,
        location: Location,
    );

    /// See `Analysis::apply_before_statement_effect`.
    fn before_statement_effect(
        &self,
        _trans: &mut impl GenKill<Self::Idx>,
        _statement: &mir::Statement<'tcx>,
        _location: Location,
    ) {
    }

    /// See `Analysis::apply_terminator_effect`.
    fn terminator_effect(
        &self,
        trans: &mut impl GenKill<Self::Idx>,
        terminator: &mir::Terminator<'tcx>,
        location: Location,
    );

    /// See `Analysis::apply_before_terminator_effect`.
    fn before_terminator_effect(
        &self,
        _trans: &mut impl GenKill<Self::Idx>,
        _terminator: &mir::Terminator<'tcx>,
        _location: Location,
    ) {
    }

    /// See `Analysis::apply_call_return_effect`.
    fn call_return_effect(
        &self,
        trans: &mut impl GenKill<Self::Idx>,
        block: BasicBlock,
        func: &mir::Operand<'tcx>,
        args: &[mir::Operand<'tcx>],
        return_place: &mir::Place<'tcx>,
    );
}

impl<A> Analysis<'tcx> for A
where
    A: GenKillAnalysis<'tcx>,
{
    fn apply_statement_effect(
        &self,
        state: &mut BitSet<Self::Idx>,
        statement: &mir::Statement<'tcx>,
        location: Location,
    ) {
        self.statement_effect(state, statement, location);
    }

    fn apply_before_statement_effect(
        &self,
        state: &mut BitSet<Self::Idx>,
        statement: &mir::Statement<'tcx>,
        location: Location,
    ) {
        self.before_statement_effect(state, statement, location);
    }

    fn apply_terminator_effect(
        &self,
        state: &mut BitSet<Self::Idx>,
        terminator: &mir::Terminator<'tcx>,
        location: Location,
    ) {
        self.terminator_effect(state, terminator, location);
    }

    fn apply_before_terminator_effect(
        &self,
        state: &mut BitSet<Self::Idx>,
        terminator: &mir::Terminator<'tcx>,
        location: Location,
    ) {
        self.before_terminator_effect(state, terminator, location);
    }

    fn apply_call_return_effect(
        &self,
        state: &mut BitSet<Self::Idx>,
        block: BasicBlock,
        func: &mir::Operand<'tcx>,
        args: &[mir::Operand<'tcx>],
        return_place: &mir::Place<'tcx>,
    ) {
        self.call_return_effect(state, block, func, args, return_place);
    }

    fn into_engine(
        self,
        tcx: TyCtxt<'tcx>,
        body: &'mir mir::Body<'tcx>,
        def_id: DefId,
    ) -> Engine<'mir, 'tcx, Self>
    where
        Self: Sized,
    {
        Engine::new_gen_kill(tcx, body, def_id, self)
    }
}

/// The legal operations for a transfer function in a gen/kill problem.
///
/// This abstraction exists because there are two different contexts in which we call the methods in
/// `GenKillAnalysis`. Sometimes we need to store a single transfer function that can be efficiently
/// applied multiple times, such as when computing the cumulative transfer function for each block.
/// These cases require a `GenKillSet`, which in turn requires two `BitSet`s of storage. Oftentimes,
/// however, we only need to apply an effect once. In *these* cases, it is more efficient to pass the
/// `BitSet` representing the state vector directly into the `*_effect` methods as opposed to
/// building up a `GenKillSet` and then throwing it away.
pub trait GenKill<T> {
    /// Inserts `elem` into the state vector.
    fn gen(&mut self, elem: T);

    /// Removes `elem` from the state vector.
    fn kill(&mut self, elem: T);

    /// Calls `gen` for each element in `elems`.
    fn gen_all(&mut self, elems: impl IntoIterator<Item = T>) {
        for elem in elems {
            self.gen(elem);
        }
    }

    /// Calls `kill` for each element in `elems`.
    fn kill_all(&mut self, elems: impl IntoIterator<Item = T>) {
        for elem in elems {
            self.kill(elem);
        }
    }
}

/// Stores a transfer function for a gen/kill problem.
///
/// Calling `gen`/`kill` on a `GenKillSet` will "build up" a transfer function so that it can be
/// applied multiple times efficiently. When there are multiple calls to `gen` and/or `kill` for
/// the same element, the most recent one takes precedence.
#[derive(Clone)]
pub struct GenKillSet<T: Idx> {
    gen: HybridBitSet<T>,
    kill: HybridBitSet<T>,
}

impl<T: Idx> GenKillSet<T> {
    /// Creates a new transfer function that will leave the dataflow state unchanged.
    pub fn identity(universe: usize) -> Self {
        GenKillSet {
            gen: HybridBitSet::new_empty(universe),
            kill: HybridBitSet::new_empty(universe),
        }
    }

    /// Applies this transfer function to the given state vector.
    pub fn apply(&self, state: &mut BitSet<T>) {
        state.union(&self.gen);
        state.subtract(&self.kill);
    }
}

impl<T: Idx> GenKill<T> for GenKillSet<T> {
    fn gen(&mut self, elem: T) {
        self.gen.insert(elem);
        self.kill.remove(elem);
    }

    fn kill(&mut self, elem: T) {
        self.kill.insert(elem);
        self.gen.remove(elem);
    }
}

impl<T: Idx> GenKill<T> for BitSet<T> {
    fn gen(&mut self, elem: T) {
        self.insert(elem);
    }

    fn kill(&mut self, elem: T) {
        self.remove(elem);
    }
}

#[cfg(test)]
mod tests;
<commit_msg>Impl `GenKill` for old dataflow framework's `GenKillSet`<commit_after>//! A framework that can express both [gen-kill] and generic dataflow problems.
//!
//! There is another interface for dataflow in the compiler in `librustc_mir/dataflow/mod.rs`. The
//! interface in this module will eventually [replace that one][design-meeting].
//!
//! To actually use this framework, you must implement either the `Analysis` or the `GenKillAnalysis`
//! trait. If your transfer function can be expressed with only gen/kill operations, prefer
//! `GenKillAnalysis` since it will run faster while iterating to fixpoint. Create an `Engine` using
//! the appropriate constructor and call `iterate_to_fixpoint`. You can use a `ResultsCursor` to
//! inspect the fixpoint solution to your dataflow problem.
//!
//! ```ignore(cross-crate-imports)
//! fn do_my_analysis(tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>, did: DefId) {
//!     let analysis = MyAnalysis::new();
//!
//!     // If `MyAnalysis` implements `GenKillAnalysis`.
//!     let results = Engine::new_gen_kill(tcx, body, did, analysis).iterate_to_fixpoint();
//!
//!     // If `MyAnalysis` implements `Analysis`.
//!     // let results = Engine::new_generic(tcx, body, did, analysis).iterate_to_fixpoint();
//!
//!     let mut cursor = ResultsCursor::new(body, results);
//!
//!     for (_, statement_index) in body.block_data[START_BLOCK].statements.iter_enumerated() {
//!         cursor.seek_after(Location { block: START_BLOCK, statement_index });
//!         let state = cursor.get();
//!         println!("{:?}", state);
//!     }
//! }
//! ```
//!
//! [gen-kill]: https://en.wikipedia.org/wiki/Data-flow_analysis#Bit_vector_problems
//! [design-meeting]https://github.com/rust-lang/compiler-team/issues/202

use std::io;

use rustc::mir::{self, BasicBlock, Location};
use rustc::ty::TyCtxt;
use rustc_hir::def_id::DefId;
use rustc_index::bit_set::{BitSet, HybridBitSet};
use rustc_index::vec::{Idx, IndexVec};

use crate::dataflow::BottomValue;

mod cursor;
mod engine;
mod graphviz;
mod visitor;

pub use self::cursor::{ResultsCursor, ResultsRefCursor};
pub use self::engine::Engine;
pub use self::visitor::{visit_results, ResultsVisitor};
pub use self::visitor::{BorrowckFlowState, BorrowckResults};

/// A dataflow analysis that has converged to fixpoint.
pub struct Results<'tcx, A>
where
    A: Analysis<'tcx>,
{
    pub analysis: A,
    entry_sets: IndexVec<BasicBlock, BitSet<A::Idx>>,
}

impl<A> Results<'tcx, A>
where
    A: Analysis<'tcx>,
{
    /// Creates a `ResultsCursor` that can inspect these `Results`.
    pub fn into_results_cursor(self, body: &'mir mir::Body<'tcx>) -> ResultsCursor<'mir, 'tcx, A> {
        ResultsCursor::new(body, self)
    }

    /// Gets the entry set for the given block.
    pub fn entry_set_for_block(&self, block: BasicBlock) -> &BitSet<A::Idx> {
        &self.entry_sets[block]
    }
}

/// Define the domain of a dataflow problem.
///
/// This trait specifies the lattice on which this analysis operates. For now, this must be a
/// powerset of values of type `Idx`. The elements of this lattice are represented with a `BitSet`
/// and referred to as the state vector.
///
/// This trait also defines the initial value for the dataflow state upon entry to the
/// `START_BLOCK`, as well as some names used to refer to this analysis when debugging.
pub trait AnalysisDomain<'tcx>: BottomValue {
    /// The type of the elements in the state vector.
    type Idx: Idx;

    /// A descriptive name for this analysis. Used only for debugging.
    ///
    /// This name should be brief and contain no spaces, periods or other characters that are not
    /// suitable as part of a filename.
    const NAME: &'static str;

    /// The size of the state vector.
    fn bits_per_block(&self, body: &mir::Body<'tcx>) -> usize;

    /// Mutates the entry set of the `START_BLOCK` to contain the initial state for dataflow
    /// analysis.
    fn initialize_start_block(&self, body: &mir::Body<'tcx>, state: &mut BitSet<Self::Idx>);

    /// Prints an element in the state vector for debugging.
    fn pretty_print_idx(&self, w: &mut impl io::Write, idx: Self::Idx) -> io::Result<()> {
        write!(w, "{:?}", idx)
    }
}

/// A dataflow problem with an arbitrarily complex transfer function.
pub trait Analysis<'tcx>: AnalysisDomain<'tcx> {
    /// Updates the current dataflow state with the effect of evaluating a statement.
    fn apply_statement_effect(
        &self,
        state: &mut BitSet<Self::Idx>,
        statement: &mir::Statement<'tcx>,
        location: Location,
    );

    /// Updates the current dataflow state with an effect that occurs immediately *before* the
    /// given statement.
    ///
    /// This method is useful if the consumer of the results of this analysis needs only to observe
    /// *part* of the effect of a statement (e.g. for two-phase borrows). As a general rule,
    /// analyses should not implement this without implementing `apply_statement_effect`.
    fn apply_before_statement_effect(
        &self,
        _state: &mut BitSet<Self::Idx>,
        _statement: &mir::Statement<'tcx>,
        _location: Location,
    ) {
    }

    /// Updates the current dataflow state with the effect of evaluating a terminator.
    ///
    /// The effect of a successful return from a `Call` terminator should **not** be accounted for
    /// in this function. That should go in `apply_call_return_effect`. For example, in the
    /// `InitializedPlaces` analyses, the return place for a function call is not marked as
    /// initialized here.
    fn apply_terminator_effect(
        &self,
        state: &mut BitSet<Self::Idx>,
        terminator: &mir::Terminator<'tcx>,
        location: Location,
    );

    /// Updates the current dataflow state with an effect that occurs immediately *before* the
    /// given terminator.
    ///
    /// This method is useful if the consumer of the results of this analysis needs only to observe
    /// *part* of the effect of a terminator (e.g. for two-phase borrows). As a general rule,
    /// analyses should not implement this without implementing `apply_terminator_effect`.
    fn apply_before_terminator_effect(
        &self,
        _state: &mut BitSet<Self::Idx>,
        _terminator: &mir::Terminator<'tcx>,
        _location: Location,
    ) {
    }

    /// Updates the current dataflow state with the effect of a successful return from a `Call`
    /// terminator.
    ///
    /// This is separate from `apply_terminator_effect` to properly track state across unwind
    /// edges.
    fn apply_call_return_effect(
        &self,
        state: &mut BitSet<Self::Idx>,
        block: BasicBlock,
        func: &mir::Operand<'tcx>,
        args: &[mir::Operand<'tcx>],
        return_place: &mir::Place<'tcx>,
    );

    /// Calls the appropriate `Engine` constructor to find the fixpoint for this dataflow problem.
    ///
    /// You shouldn't need to override this outside this module, since the combination of the
    /// default impl and the one for all `A: GenKillAnalysis` will do the right thing.
    /// Its purpose is to enable method chaining like so:
    ///
    /// ```ignore(cross-crate-imports)
    /// let results = MyAnalysis::new(tcx, body)
    ///     .into_engine(tcx, body, def_id)
    ///     .iterate_to_fixpoint()
    ///     .into_results_cursor(body);
    /// ```
    fn into_engine(
        self,
        tcx: TyCtxt<'tcx>,
        body: &'mir mir::Body<'tcx>,
        def_id: DefId,
    ) -> Engine<'mir, 'tcx, Self>
    where
        Self: Sized,
    {
        Engine::new_generic(tcx, body, def_id, self)
    }
}

/// A gen/kill dataflow problem.
///
/// Each method in this trait has a corresponding one in `Analysis`. However, these methods only
/// allow modification of the dataflow state via "gen" and "kill" operations. By defining transfer
/// functions for each statement in this way, the transfer function for an entire basic block can
/// be computed efficiently.
///
/// `Analysis` is automatically implemented for all implementers of `GenKillAnalysis`.
pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> {
    /// See `Analysis::apply_statement_effect`.
    fn statement_effect(
        &self,
        trans: &mut impl GenKill<Self::Idx>,
        statement: &mir::Statement<'tcx>,
        location: Location,
    );

    /// See `Analysis::apply_before_statement_effect`.
    fn before_statement_effect(
        &self,
        _trans: &mut impl GenKill<Self::Idx>,
        _statement: &mir::Statement<'tcx>,
        _location: Location,
    ) {
    }

    /// See `Analysis::apply_terminator_effect`.
    fn terminator_effect(
        &self,
        trans: &mut impl GenKill<Self::Idx>,
        terminator: &mir::Terminator<'tcx>,
        location: Location,
    );

    /// See `Analysis::apply_before_terminator_effect`.
    fn before_terminator_effect(
        &self,
        _trans: &mut impl GenKill<Self::Idx>,
        _terminator: &mir::Terminator<'tcx>,
        _location: Location,
    ) {
    }

    /// See `Analysis::apply_call_return_effect`.
    fn call_return_effect(
        &self,
        trans: &mut impl GenKill<Self::Idx>,
        block: BasicBlock,
        func: &mir::Operand<'tcx>,
        args: &[mir::Operand<'tcx>],
        return_place: &mir::Place<'tcx>,
    );
}

impl<A> Analysis<'tcx> for A
where
    A: GenKillAnalysis<'tcx>,
{
    fn apply_statement_effect(
        &self,
        state: &mut BitSet<Self::Idx>,
        statement: &mir::Statement<'tcx>,
        location: Location,
    ) {
        self.statement_effect(state, statement, location);
    }

    fn apply_before_statement_effect(
        &self,
        state: &mut BitSet<Self::Idx>,
        statement: &mir::Statement<'tcx>,
        location: Location,
    ) {
        self.before_statement_effect(state, statement, location);
    }

    fn apply_terminator_effect(
        &self,
        state: &mut BitSet<Self::Idx>,
        terminator: &mir::Terminator<'tcx>,
        location: Location,
    ) {
        self.terminator_effect(state, terminator, location);
    }

    fn apply_before_terminator_effect(
        &self,
        state: &mut BitSet<Self::Idx>,
        terminator: &mir::Terminator<'tcx>,
        location: Location,
    ) {
        self.before_terminator_effect(state, terminator, location);
    }

    fn apply_call_return_effect(
        &self,
        state: &mut BitSet<Self::Idx>,
        block: BasicBlock,
        func: &mir::Operand<'tcx>,
        args: &[mir::Operand<'tcx>],
        return_place: &mir::Place<'tcx>,
    ) {
        self.call_return_effect(state, block, func, args, return_place);
    }

    fn into_engine(
        self,
        tcx: TyCtxt<'tcx>,
        body: &'mir mir::Body<'tcx>,
        def_id: DefId,
    ) -> Engine<'mir, 'tcx, Self>
    where
        Self: Sized,
    {
        Engine::new_gen_kill(tcx, body, def_id, self)
    }
}

/// The legal operations for a transfer function in a gen/kill problem.
///
/// This abstraction exists because there are two different contexts in which we call the methods in
/// `GenKillAnalysis`. Sometimes we need to store a single transfer function that can be efficiently
/// applied multiple times, such as when computing the cumulative transfer function for each block.
/// These cases require a `GenKillSet`, which in turn requires two `BitSet`s of storage. Oftentimes,
/// however, we only need to apply an effect once. In *these* cases, it is more efficient to pass the
/// `BitSet` representing the state vector directly into the `*_effect` methods as opposed to
/// building up a `GenKillSet` and then throwing it away.
pub trait GenKill<T> {
    /// Inserts `elem` into the state vector.
    fn gen(&mut self, elem: T);

    /// Removes `elem` from the state vector.
    fn kill(&mut self, elem: T);

    /// Calls `gen` for each element in `elems`.
    fn gen_all(&mut self, elems: impl IntoIterator<Item = T>) {
        for elem in elems {
            self.gen(elem);
        }
    }

    /// Calls `kill` for each element in `elems`.
    fn kill_all(&mut self, elems: impl IntoIterator<Item = T>) {
        for elem in elems {
            self.kill(elem);
        }
    }
}

/// Stores a transfer function for a gen/kill problem.
///
/// Calling `gen`/`kill` on a `GenKillSet` will "build up" a transfer function so that it can be
/// applied multiple times efficiently. When there are multiple calls to `gen` and/or `kill` for
/// the same element, the most recent one takes precedence.
#[derive(Clone)]
pub struct GenKillSet<T: Idx> {
    gen: HybridBitSet<T>,
    kill: HybridBitSet<T>,
}

impl<T: Idx> GenKillSet<T> {
    /// Creates a new transfer function that will leave the dataflow state unchanged.
    pub fn identity(universe: usize) -> Self {
        GenKillSet {
            gen: HybridBitSet::new_empty(universe),
            kill: HybridBitSet::new_empty(universe),
        }
    }

    /// Applies this transfer function to the given state vector.
    pub fn apply(&self, state: &mut BitSet<T>) {
        state.union(&self.gen);
        state.subtract(&self.kill);
    }
}

impl<T: Idx> GenKill<T> for GenKillSet<T> {
    fn gen(&mut self, elem: T) {
        self.gen.insert(elem);
        self.kill.remove(elem);
    }

    fn kill(&mut self, elem: T) {
        self.kill.insert(elem);
        self.gen.remove(elem);
    }
}

impl<T: Idx> GenKill<T> for BitSet<T> {
    fn gen(&mut self, elem: T) {
        self.insert(elem);
    }

    fn kill(&mut self, elem: T) {
        self.remove(elem);
    }
}

// For compatibility with old framework
impl<T: Idx> GenKill<T> for crate::dataflow::GenKillSet<T> {
    fn gen(&mut self, elem: T) {
        self.gen(elem);
    }

    fn kill(&mut self, elem: T) {
        self.kill(elem);
    }
}

#[cfg(test)]
mod tests;
<|endoftext|>


<commit_before>use crate::graphics::*;

use mint;

/// A struct containing all the necessary info for drawing a [`Drawable`](trait.Drawable.html).
///
/// This struct implements the `Default` trait, so to set only some parameter
/// you can just do:
///
/// ```rust
/// # use ggez::*;
/// # use ggez::graphics::*;
/// # fn t<P>(ctx: &mut Context, drawable: &P) where P: Drawable {
/// let my_dest = mint::Point2::new(13.0, 37.0);
/// graphics::draw(ctx, drawable, DrawParam::default().dest(my_dest) );
/// # }
/// ```
///
/// As a shortcut, it also implements `From` for a variety of tuple types.
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct DrawParam {
    /// A portion of the drawable to clip, as a fraction of the whole image.
    /// Defaults to the whole image `(0,0 to 1,1)` if omitted.
    pub src: Rect,
    /// The position to draw the graphic expressed as a `Point2`.
    pub dest: mint::Point2<f32>,
    /// The orientation of the graphic in radians.
    pub rotation: f32,
    /// The x/y scale factors expressed as a `Vector2`.
    pub scale: mint::Vector2<f32>,
    /// An offset from the center for transform operations like scale/rotation,
    /// with `0,0` meaning the origin and `1,1` meaning the opposite corner from the origin.
    /// By default these operations are done from the top-left corner, so to rotate something
    /// from the center specify `Point2::new(0.5, 0.5)` here.
    pub offset: mint::Point2<f32>,
    /// A color to draw the target with.
    /// Default: white.
    pub color: Color,
}

impl Default for DrawParam {
    fn default() -> Self {
        DrawParam {
            src: Rect::one(),
            dest: mint::Point2 { x: 0.0, y: 0.0 },
            rotation: 0.0,
            scale: mint::Vector2 { x: 1.0, y: 1.0 },
            offset: mint::Point2 { x: 0.0, y: 0.0 },
            color: WHITE,
        }
    }
}

impl DrawParam {
    /// Create a new DrawParam with default values.
    pub fn new() -> Self {
        Self::default()
    }

    /// Set the source rect
    pub fn src(mut self, src: Rect) -> Self {
        self.src = src;
        self
    }

    /// Set the dest point
    pub fn dest<P>(mut self, dest: P) -> Self
    where
        P: Into<mint::Point2<f32>>,
    {
        let p: mint::Point2<f32> = dest.into();
        self.dest = p;
        self
    }

    /// Set the drawable color.  This will be blended with whatever
    /// color the drawn object already is.
    pub fn color(mut self, color: Color) -> Self {
        self.color = color;
        self
    }

    /// Set the rotation of the drawable.
    pub fn rotation(mut self, rotation: f32) -> Self {
        self.rotation = rotation;
        self
    }

    /// Set the scaling factors of the drawable.
    pub fn scale<V>(mut self, scale: V) -> Self
    where
        V: Into<mint::Vector2<f32>>,
    {
        let p: mint::Vector2<f32> = scale.into();
        self.scale = p;
        self
    }

    /// Set the transformation offset of the drawable.
    pub fn offset<P>(mut self, offset: P) -> Self
    where
        P: Into<mint::Point2<f32>>,
    {
        let p: mint::Point2<f32> = offset.into();
        self.offset = p;
        self
    }

    /// A [`DrawParam`](struct.DrawParam.html) that has been crunched down to a single matrix.
    fn to_na_matrix(&self) -> Matrix4 {
        // Calculate a matrix equivalent to doing this:
        //  type Vec3 = na::Vector3<f32>;
        //  let translate = Matrix4::new_translation(&Vec3::new(self.dest.x, self.dest.y, 0.0));
        //  let offset = Matrix4::new_translation(&Vec3::new(self.offset.x, self.offset.y, 0.0));
        //  let offset_inverse =
        //      Matrix4::new_translation(&Vec3::new(-self.offset.x, -self.offset.y, 0.0));
        //  let axis_angle = Vec3::z() * self.rotation;
        //  let rotation = Matrix4::new_rotation(axis_angle);
        //  let scale = Matrix4::new_nonuniform_scaling(&Vec3::new(self.scale.x, self.scale.y, 1.0));
        //  translate * offset * rotation * scale * offset_inverse
        let cosr = self.rotation.cos();
        let sinr = self.rotation.sin();
        let m00 = cosr * self.scale.x;
        let m01 = -sinr * self.scale.y;
        let m10 = sinr * self.scale.x;
        let m11 = cosr * self.scale.y;
        let m03 = self.offset.x * (1.0 - m00) - self.offset.y * m01 + self.dest.x;
        let m13 = self.offset.y * (1.0 - m11) - self.offset.x * m10 + self.dest.y;
        // Welp, this transpose fixes some bug that makes nothing draw,
        // that was introduced in commit 2c6b3cc03f34fb240f4246f5a68c75bd85b60eae.
        // The best part is, I don't know if this code is wrong, or whether there's
        // some reversed matrix multiply or such somewhere else that this cancel
        // out.  Probably the former though.
        Matrix4::from_cols_array(&[
            m00, m01, 0.0, m03, // oh rustfmt you so fine
            m10, m11, 0.0, m13, // you so fine you blow my mind
            0.0, 0.0, 1.0, 0.0, // but leave my matrix formatting alone
            0.0, 0.0, 0.0, 1.0, // plz
        ])
        .transpose()
    }

    /// A [`DrawParam`](struct.DrawParam.html) that has been crunched down to a single
    ///matrix.  Because of this it only contains the transform part (rotation/scale/etc),
    /// with no src/dest/color info.
    pub fn to_matrix(&self) -> mint::ColumnMatrix4<f32> {
        self.to_na_matrix().into()
    }
}

/// Create a `DrawParam` from a location.
/// Note that this takes a single-element tuple.
/// It's a little weird but keeps the trait implementations
/// from clashing.
impl<P> From<(P,)> for DrawParam
where
    P: Into<mint::Point2<f32>>,
{
    fn from(location: (P,)) -> Self {
        DrawParam::new().dest(location.0)
    }
}

/// Create a `DrawParam` from a location and color
impl<P> From<(P, Color)> for DrawParam
where
    P: Into<mint::Point2<f32>>,
{
    fn from((location, color): (P, Color)) -> Self {
        DrawParam::new().dest(location).color(color)
    }
}

/// Create a `DrawParam` from a location, rotation and color
impl<P> From<(P, f32, Color)> for DrawParam
where
    P: Into<mint::Point2<f32>>,
{
    fn from((location, rotation, color): (P, f32, Color)) -> Self {
        DrawParam::new()
            .dest(location)
            .rotation(rotation)
            .color(color)
    }
}

/// Create a `DrawParam` from a location, rotation, offset and color
impl<P> From<(P, f32, P, Color)> for DrawParam
where
    P: Into<mint::Point2<f32>>,
{
    fn from((location, rotation, offset, color): (P, f32, P, Color)) -> Self {
        DrawParam::new()
            .dest(location)
            .rotation(rotation)
            .offset(offset)
            .color(color)
    }
}

/// Create a `DrawParam` from a location, rotation, offset, scale and color
impl<P, V> From<(P, f32, P, V, Color)> for DrawParam
where
    P: Into<mint::Point2<f32>>,
    V: Into<mint::Vector2<f32>>,
{
    fn from((location, rotation, offset, scale, color): (P, f32, P, V, Color)) -> Self {
        DrawParam::new()
            .dest(location)
            .rotation(rotation)
            .offset(offset)
            .scale(scale)
            .color(color)
    }
}

/// A [`DrawParam`](struct.DrawParam.html) that has been crunched down to a single matrix.
/// This is a lot less useful for doing transformations than I'd hoped; basically, we sometimes
/// have to modify parameters of a `DrawParam` based *on* the parameters of a `DrawParam`, for
/// instance when scaling images so that they are in units of pixels.  This makes it really
/// hard to extract scale and rotation and such, so meh.
///
/// It's still useful for a couple internal things though, so it's kept around.
#[derive(Debug, Copy, Clone, PartialEq)]
pub(crate) struct DrawTransform {
    /// The transform matrix for the DrawParams
    pub matrix: Matrix4,
    /// A portion of the drawable to clip, as a fraction of the whole image.
    /// Defaults to the whole image (1.0) if omitted.
    pub src: Rect,
    /// A color to draw the target with.
    /// Default: white.
    pub color: Color,
}

impl Default for DrawTransform {
    fn default() -> Self {
        DrawTransform {
            matrix: Matrix4::identity(),
            src: Rect::one(),
            color: WHITE,
        }
    }
}

impl From<DrawParam> for DrawTransform {
    fn from(param: DrawParam) -> Self {
        // TODO: Double-check this all lines up
        let transform = param.to_na_matrix();
        DrawTransform {
            src: param.src,
            color: param.color,
            matrix: transform,
        }
    }
}

impl DrawTransform {
    pub(crate) fn to_instance_properties(&self, srgb: bool) -> InstanceProperties {
        // TODO: Verify 'row arrays' is correct here.
        let mat: [[f32; 4]; 4] = self.matrix.to_cols_array_2d();
        let color: [f32; 4] = if srgb {
            let linear_color: types::LinearColor = self.color.into();
            linear_color.into()
        } else {
            self.color.into()
        };
        InstanceProperties {
            src: self.src.into(),
            col1: mat[0],
            col2: mat[1],
            col3: mat[2],
            col4: mat[3],
            color,
        }
    }
}
<commit_msg>Removes redundant imports on drawparam.rs<commit_after>use crate::graphics::*;

/// A struct containing all the necessary info for drawing a [`Drawable`](trait.Drawable.html).
///
/// This struct implements the `Default` trait, so to set only some parameter
/// you can just do:
///
/// ```rust
/// # use ggez::*;
/// # use ggez::graphics::*;
/// # fn t<P>(ctx: &mut Context, drawable: &P) where P: Drawable {
/// let my_dest = mint::Point2::new(13.0, 37.0);
/// graphics::draw(ctx, drawable, DrawParam::default().dest(my_dest) );
/// # }
/// ```
///
/// As a shortcut, it also implements `From` for a variety of tuple types.
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct DrawParam {
    /// A portion of the drawable to clip, as a fraction of the whole image.
    /// Defaults to the whole image `(0,0 to 1,1)` if omitted.
    pub src: Rect,
    /// The position to draw the graphic expressed as a `Point2`.
    pub dest: mint::Point2<f32>,
    /// The orientation of the graphic in radians.
    pub rotation: f32,
    /// The x/y scale factors expressed as a `Vector2`.
    pub scale: mint::Vector2<f32>,
    /// An offset from the center for transform operations like scale/rotation,
    /// with `0,0` meaning the origin and `1,1` meaning the opposite corner from the origin.
    /// By default these operations are done from the top-left corner, so to rotate something
    /// from the center specify `Point2::new(0.5, 0.5)` here.
    pub offset: mint::Point2<f32>,
    /// A color to draw the target with.
    /// Default: white.
    pub color: Color,
}

impl Default for DrawParam {
    fn default() -> Self {
        DrawParam {
            src: Rect::one(),
            dest: mint::Point2 { x: 0.0, y: 0.0 },
            rotation: 0.0,
            scale: mint::Vector2 { x: 1.0, y: 1.0 },
            offset: mint::Point2 { x: 0.0, y: 0.0 },
            color: WHITE,
        }
    }
}

impl DrawParam {
    /// Create a new DrawParam with default values.
    pub fn new() -> Self {
        Self::default()
    }

    /// Set the source rect
    pub fn src(mut self, src: Rect) -> Self {
        self.src = src;
        self
    }

    /// Set the dest point
    pub fn dest<P>(mut self, dest: P) -> Self
    where
        P: Into<mint::Point2<f32>>,
    {
        let p: mint::Point2<f32> = dest.into();
        self.dest = p;
        self
    }

    /// Set the drawable color.  This will be blended with whatever
    /// color the drawn object already is.
    pub fn color(mut self, color: Color) -> Self {
        self.color = color;
        self
    }

    /// Set the rotation of the drawable.
    pub fn rotation(mut self, rotation: f32) -> Self {
        self.rotation = rotation;
        self
    }

    /// Set the scaling factors of the drawable.
    pub fn scale<V>(mut self, scale: V) -> Self
    where
        V: Into<mint::Vector2<f32>>,
    {
        let p: mint::Vector2<f32> = scale.into();
        self.scale = p;
        self
    }

    /// Set the transformation offset of the drawable.
    pub fn offset<P>(mut self, offset: P) -> Self
    where
        P: Into<mint::Point2<f32>>,
    {
        let p: mint::Point2<f32> = offset.into();
        self.offset = p;
        self
    }

    /// A [`DrawParam`](struct.DrawParam.html) that has been crunched down to a single matrix.
    fn to_na_matrix(&self) -> Matrix4 {
        // Calculate a matrix equivalent to doing this:
        //  type Vec3 = na::Vector3<f32>;
        //  let translate = Matrix4::new_translation(&Vec3::new(self.dest.x, self.dest.y, 0.0));
        //  let offset = Matrix4::new_translation(&Vec3::new(self.offset.x, self.offset.y, 0.0));
        //  let offset_inverse =
        //      Matrix4::new_translation(&Vec3::new(-self.offset.x, -self.offset.y, 0.0));
        //  let axis_angle = Vec3::z() * self.rotation;
        //  let rotation = Matrix4::new_rotation(axis_angle);
        //  let scale = Matrix4::new_nonuniform_scaling(&Vec3::new(self.scale.x, self.scale.y, 1.0));
        //  translate * offset * rotation * scale * offset_inverse
        let cosr = self.rotation.cos();
        let sinr = self.rotation.sin();
        let m00 = cosr * self.scale.x;
        let m01 = -sinr * self.scale.y;
        let m10 = sinr * self.scale.x;
        let m11 = cosr * self.scale.y;
        let m03 = self.offset.x * (1.0 - m00) - self.offset.y * m01 + self.dest.x;
        let m13 = self.offset.y * (1.0 - m11) - self.offset.x * m10 + self.dest.y;
        // Welp, this transpose fixes some bug that makes nothing draw,
        // that was introduced in commit 2c6b3cc03f34fb240f4246f5a68c75bd85b60eae.
        // The best part is, I don't know if this code is wrong, or whether there's
        // some reversed matrix multiply or such somewhere else that this cancel
        // out.  Probably the former though.
        Matrix4::from_cols_array(&[
            m00, m01, 0.0, m03, // oh rustfmt you so fine
            m10, m11, 0.0, m13, // you so fine you blow my mind
            0.0, 0.0, 1.0, 0.0, // but leave my matrix formatting alone
            0.0, 0.0, 0.0, 1.0, // plz
        ])
        .transpose()
    }

    /// A [`DrawParam`](struct.DrawParam.html) that has been crunched down to a single
    ///matrix.  Because of this it only contains the transform part (rotation/scale/etc),
    /// with no src/dest/color info.
    pub fn to_matrix(&self) -> mint::ColumnMatrix4<f32> {
        self.to_na_matrix().into()
    }
}

/// Create a `DrawParam` from a location.
/// Note that this takes a single-element tuple.
/// It's a little weird but keeps the trait implementations
/// from clashing.
impl<P> From<(P,)> for DrawParam
where
    P: Into<mint::Point2<f32>>,
{
    fn from(location: (P,)) -> Self {
        DrawParam::new().dest(location.0)
    }
}

/// Create a `DrawParam` from a location and color
impl<P> From<(P, Color)> for DrawParam
where
    P: Into<mint::Point2<f32>>,
{
    fn from((location, color): (P, Color)) -> Self {
        DrawParam::new().dest(location).color(color)
    }
}

/// Create a `DrawParam` from a location, rotation and color
impl<P> From<(P, f32, Color)> for DrawParam
where
    P: Into<mint::Point2<f32>>,
{
    fn from((location, rotation, color): (P, f32, Color)) -> Self {
        DrawParam::new()
            .dest(location)
            .rotation(rotation)
            .color(color)
    }
}

/// Create a `DrawParam` from a location, rotation, offset and color
impl<P> From<(P, f32, P, Color)> for DrawParam
where
    P: Into<mint::Point2<f32>>,
{
    fn from((location, rotation, offset, color): (P, f32, P, Color)) -> Self {
        DrawParam::new()
            .dest(location)
            .rotation(rotation)
            .offset(offset)
            .color(color)
    }
}

/// Create a `DrawParam` from a location, rotation, offset, scale and color
impl<P, V> From<(P, f32, P, V, Color)> for DrawParam
where
    P: Into<mint::Point2<f32>>,
    V: Into<mint::Vector2<f32>>,
{
    fn from((location, rotation, offset, scale, color): (P, f32, P, V, Color)) -> Self {
        DrawParam::new()
            .dest(location)
            .rotation(rotation)
            .offset(offset)
            .scale(scale)
            .color(color)
    }
}

/// A [`DrawParam`](struct.DrawParam.html) that has been crunched down to a single matrix.
/// This is a lot less useful for doing transformations than I'd hoped; basically, we sometimes
/// have to modify parameters of a `DrawParam` based *on* the parameters of a `DrawParam`, for
/// instance when scaling images so that they are in units of pixels.  This makes it really
/// hard to extract scale and rotation and such, so meh.
///
/// It's still useful for a couple internal things though, so it's kept around.
#[derive(Debug, Copy, Clone, PartialEq)]
pub(crate) struct DrawTransform {
    /// The transform matrix for the DrawParams
    pub matrix: Matrix4,
    /// A portion of the drawable to clip, as a fraction of the whole image.
    /// Defaults to the whole image (1.0) if omitted.
    pub src: Rect,
    /// A color to draw the target with.
    /// Default: white.
    pub color: Color,
}

impl Default for DrawTransform {
    fn default() -> Self {
        DrawTransform {
            matrix: Matrix4::identity(),
            src: Rect::one(),
            color: WHITE,
        }
    }
}

impl From<DrawParam> for DrawTransform {
    fn from(param: DrawParam) -> Self {
        // TODO: Double-check this all lines up
        let transform = param.to_na_matrix();
        DrawTransform {
            src: param.src,
            color: param.color,
            matrix: transform,
        }
    }
}

impl DrawTransform {
    pub(crate) fn to_instance_properties(&self, srgb: bool) -> InstanceProperties {
        // TODO: Verify 'row arrays' is correct here.
        let mat: [[f32; 4]; 4] = self.matrix.to_cols_array_2d();
        let color: [f32; 4] = if srgb {
            let linear_color: types::LinearColor = self.color.into();
            linear_color.into()
        } else {
            self.color.into()
        };
        InstanceProperties {
            src: self.src.into(),
            col1: mat[0],
            col2: mat[1],
            col3: mat[2],
            col4: mat[3],
            color,
        }
    }
}
<|endoftext|>