<commit_before>//! Query excecution moduleT
//!
//! This module takes the output of the SQL parser and executed that query
//! by calling the appropriate `storage` and `auth` methods.
//!

use super::parse::ast::*;
use super::storage::{Database, Column, Table, Rows};
use super::storage;
use super::auth;
use super::parse::parser::ParseError;

pub struct Executor<'a> {
    pub user: &'a mut auth::User,
}

    pub fn execute_from_ast<'a>(query: Query, user: &'a mut auth::User)
        -> Result<Rows, ExecutionError> {

        let mut executor = Executor::new(user);

        match query {
            Query::ManipulationStmt(stmt) => executor.execute_manipulation_stmt(stmt),
            Query::DefStmt(stmt) => executor.execute_def_stmt(stmt),
            _ => Err(ExecutionError::ParseError(ParseError::UnknownError)),

        }

    //info!("Not implemented! :-(");
    }

impl<'a> Executor<'a> {

    pub fn new(user: &'a mut auth::User) -> Executor<'a> {
        Executor { user: user }
    }

    fn execute_manipulation_stmt(&mut self, query: ManipulationStmt)
        -> Result<Rows, ExecutionError> {

        match query {
            ManipulationStmt::Use(stmt) => self.execute_use_stmt(stmt),
            ManipulationStmt::Insert(stmt) => self.execute_insert_stmt(stmt),
            ManipulationStmt::Describe(stmt) => self.execute_describe_stmt(stmt),
            ManipulationStmt::Select(stmt) => self.execute_select_stmt(stmt),
            _ => Err(ExecutionError::DebugError("Feature not implemented yet!".into())),
        }

    }

    fn execute_def_stmt(&mut self, query: DefStmt) -> Result<Rows, ExecutionError> {
        match query {
            DefStmt::Create(stmt) => self.execute_create_stmt(stmt),
            DefStmt::Drop(stmt) =>  self.execute_drop_stmt(stmt),
            DefStmt::Alter(stmt) => self.execute_alt_stmt(stmt),
        }
    }

    fn execute_use_stmt(&mut self, query: UseStmt) -> Result<Rows, ExecutionError> {
        match query {
            UseStmt::Database(querybase) => {
                self.user._currentDatabase = Some(try!(Database::load(&querybase)));
                Ok(generate_rows_dummy())
            }
        }
    }

    fn execute_insert_stmt(&mut self, stmt: InsertStmt) -> Result<Rows, ExecutionError> {
        let table = try!(self.get_table(&stmt.tid));

        if !stmt.col.is_empty() {
            return Err(ExecutionError::DebugError("Not implemented:
            Insert just some values into some columns.
            Use insert into table values (_,....) instead".into()))
        }

        let n: Vec<_> = stmt.val.iter().map(|l| Some(l.into_DataSrc())).collect();
        let mut engine = table.create_engine();
        try!(engine.insert_row(&n));
        Ok(generate_rows_dummy())

    }

    fn execute_select_stmt(&mut self, stmt: SelectStmt) -> Result<Rows, ExecutionError> {
        if stmt.target.len() != 1 {
            return Err(ExecutionError::DebugError("Select only implemented for select * ".into()));
        }
        if stmt.target[0].col != Col::Every {
            return Err(ExecutionError::DebugError("Select only implemented for select * ".into()));
        }
        if stmt.tid.len() != 1 {
            return Err(ExecutionError::DebugError("Select only implemented for 1 table ".into()));
        }
        let table = try!(self.get_table(&stmt.tid[0]));
        let engine = table.create_engine();
        Ok(try!(engine.full_scan()))

    }
    fn execute_describe_stmt(&mut self, query: String) -> Result<Rows, ExecutionError>{
        let table = try!(self.get_table(&query));
        let columns = table.columns();
        let mut columnvec = Vec::new();

        columnvec.extend(columns.iter().cloned());
        Ok(Rows { data: Vec::new(), columns: columnvec } )
    }

    fn execute_create_stmt(&mut self, query: CreateStmt) -> Result<Rows, ExecutionError> {
        match query {
            CreateStmt::Database(s) => {
                self.user._currentDatabase = Some(try!(Database::create(&s)));
                Ok(generate_rows_dummy())
            }
            CreateStmt::Table(stmt) => self.execute_create_table_stmt(stmt),
        }
    }

    fn execute_create_table_stmt(&mut self, query: CreateTableStmt)
         -> Result<Rows, ExecutionError> {
        let base = try!(self.get_own_database());
        let tmp_vec : Vec<_> = query.cols.into_iter().map(|c| Column {
            name: c.cid,
            sql_type: c.datatype,
            allow_null: false,
            description: "this is a column".to_string(),
             is_primary_key: c.primary,
        }).collect();
        let table = try!(base.create_table(&query.tid, tmp_vec, 0));
        let mut engine = table.create_engine();
        engine.create_table();
        Ok(generate_rows_dummy())
    }

    fn execute_drop_stmt(&mut self, query: DropStmt) -> Result<Rows, ExecutionError> {
        match query {
            DropStmt::Table(s) => {
                let base = try!(self.get_own_database());
                let table = try!(base.load_table(&s));
                try!(table.delete());
                Ok(generate_rows_dummy())
            },
            DropStmt::Database(s) => {
                let base = try!(Database::load(&s));
                try!(base.delete());
                let mut baseinuse = false;
                match self.user._currentDatabase {
                    Some(ref base) => {
                        if base.name == s {
                            baseinuse = true;
                        };
                        ()
                    },
                    None => (),
                };
                if baseinuse {
                    self.user._currentDatabase = None;
                };
                Ok(generate_rows_dummy())
            },
        }
    }

    fn execute_alt_stmt(&mut self, query: AltStmt) -> Result<Rows, ExecutionError> {
        match query {
            AltStmt::Table(stmt) => self.execute_alt_table_stmt(stmt),
        }

    }

    fn execute_alt_table_stmt(&mut self, stmt: AlterTableStmt) -> Result<Rows, ExecutionError> {
        let table = try!(self.get_table(&stmt.tid));
        match stmt.op {
            AlterOp::Add(columninfo) => Ok(generate_rows_dummy()),
            AlterOp::Drop(column) => Ok(generate_rows_dummy()),
            AlterOp::Modify(columninfo) => Ok(generate_rows_dummy()),
        }

    }

    fn get_own_database(&self) -> Result<&Database, ExecutionError> {
        match self.user._currentDatabase {
            Some(ref base) => Ok(base),
            None => Err(ExecutionError::NoDatabaseSelected),
        }
    }

    fn get_table(&self, table: &str) -> Result<Table, ExecutionError>{
        let dbase = try!(self.get_own_database());
        Ok(try!(dbase.load_table(table)))
    }

}

fn generate_rows_dummy() -> Rows {
    Rows {
    data: Vec::new(),
    columns: Vec::new(),
}
}

#[derive(Debug)]
pub enum ExecutionError {

    ParseError(ParseError),
    StorageError(storage::Error),
    UnknownError,
    NoDatabaseSelected,

    DebugError(String),
}

impl From<ParseError> for ExecutionError {
    fn from(error: ParseError) -> ExecutionError {
        ExecutionError::ParseError(error)
    }
}

impl From<storage::Error> for ExecutionError {
    fn from(error: storage::Error) -> ExecutionError {
        ExecutionError::StorageError(error)
    }
}
<commit_msg>Fix compile issues<commit_after>//! Query excecution moduleT
//!
//! This module takes the output of the SQL parser and executed that query
//! by calling the appropriate `storage` and `auth` methods.
//!

use super::parse::ast::*;
use super::storage::{Database, Column, Table, Rows};
use super::storage;
use super::auth;
use super::parse::parser::ParseError;

pub struct Executor<'a> {
    pub user: &'a mut auth::User,
}

    pub fn execute_from_ast<'a>(query: Query, user: &'a mut auth::User)
        -> Result<Rows, ExecutionError> {

        let mut executor = Executor::new(user);

        match query {
            Query::ManipulationStmt(stmt) => executor.execute_manipulation_stmt(stmt),
            Query::DefStmt(stmt) => executor.execute_def_stmt(stmt),
            _ => Err(ExecutionError::ParseError(ParseError::UnknownError)),

        }

    //info!("Not implemented! :-(");
    }

impl<'a> Executor<'a> {

    pub fn new(user: &'a mut auth::User) -> Executor<'a> {
        Executor { user: user }
    }

    fn execute_manipulation_stmt(&mut self, query: ManipulationStmt)
        -> Result<Rows, ExecutionError> {

        match query {
            ManipulationStmt::Use(stmt) => self.execute_use_stmt(stmt),
            ManipulationStmt::Insert(stmt) => self.execute_insert_stmt(stmt),
            ManipulationStmt::Describe(stmt) => self.execute_describe_stmt(stmt),
            ManipulationStmt::Select(stmt) => self.execute_select_stmt(stmt),
            _ => Err(ExecutionError::DebugError("Feature not implemented yet!".into())),
        }

    }

    fn execute_def_stmt(&mut self, query: DefStmt) -> Result<Rows, ExecutionError> {
        match query {
            DefStmt::Create(stmt) => self.execute_create_stmt(stmt),
            DefStmt::Drop(stmt) =>  self.execute_drop_stmt(stmt),
            DefStmt::Alter(stmt) => self.execute_alt_stmt(stmt),
        }
    }

    fn execute_use_stmt(&mut self, query: UseStmt) -> Result<Rows, ExecutionError> {
        match query {
            UseStmt::Database(querybase) => {
                self.user._currentDatabase = Some(try!(Database::load(&querybase)));
                Ok(generate_rows_dummy())
            }
        }
    }

    fn execute_insert_stmt(&mut self, stmt: InsertStmt) -> Result<Rows, ExecutionError> {
        let table = try!(self.get_table(&stmt.tid));

        if !stmt.col.is_empty() {
            return Err(ExecutionError::DebugError("Not implemented:
            Insert just some values into some columns.
            Use insert into table values (_,....) instead".into()))
        }

        let n: Vec<_> = stmt.val.iter().map(|l| Some(l.into_DataSrc())).collect();
        let mut engine = table.create_engine();
        try!(engine.insert_row(&n));
        Ok(generate_rows_dummy())

    }

    fn execute_select_stmt(&mut self, stmt: SelectStmt) -> Result<Rows, ExecutionError> {
        if stmt.target.len() != 1 {
            return Err(ExecutionError::DebugError("Select only implemented for select * ".into()));
        }
        if stmt.target[0].col != Col::Every {
            return Err(ExecutionError::DebugError("Select only implemented for select * ".into()));
        }
        if stmt.tid.len() != 1 {
            return Err(ExecutionError::DebugError("Select only implemented for 1 table ".into()));
        }
        let table = try!(self.get_table(&stmt.tid[0]));
        let engine = table.create_engine();
        Ok(try!(engine.full_scan()))

    }
    fn execute_describe_stmt(&mut self, query: String) -> Result<Rows, ExecutionError>{
        let table = try!(self.get_table(&query));
        let columns = table.columns();
        let mut columnvec = Vec::new();

        columnvec.extend(columns.iter().cloned());
        Ok(Rows { data: Vec::new(), columns: columnvec } )
    }

    fn execute_create_stmt(&mut self, query: CreateStmt) -> Result<Rows, ExecutionError> {
        match query {
            CreateStmt::Database(s) => {
                self.user._currentDatabase = Some(try!(Database::create(&s)));
                Ok(generate_rows_dummy())
            },
            CreateStmt::Table(stmt) => self.execute_create_table_stmt(stmt),
            _ => Err(ExecutionError::DebugError("to_do".into())),
        }
    }

    fn execute_create_table_stmt(&mut self, query: CreateTableStmt)
         -> Result<Rows, ExecutionError> {
        let base = try!(self.get_own_database());
        let tmp_vec : Vec<_> = query.cols.into_iter().map(|c| Column {
            name: c.cid,
            sql_type: c.datatype,
            allow_null: false,
            description: "this is a column".to_string(),
             is_primary_key: c.primary,
        }).collect();
        let table = try!(base.create_table(&query.tid, tmp_vec, 0));
        let mut engine = table.create_engine();
        engine.create_table();
        Ok(generate_rows_dummy())
    }

    fn execute_drop_stmt(&mut self, query: DropStmt) -> Result<Rows, ExecutionError> {
        match query {
            DropStmt::Table(s) => {
                let base = try!(self.get_own_database());
                let table = try!(base.load_table(&s));
                try!(table.delete());
                Ok(generate_rows_dummy())
            },
            DropStmt::Database(s) => {
                let base = try!(Database::load(&s));
                try!(base.delete());
                let mut baseinuse = false;
                match self.user._currentDatabase {
                    Some(ref base) => {
                        if base.name == s {
                            baseinuse = true;
                        };
                        ()
                    },
                    None => (),
                };
                if baseinuse {
                    self.user._currentDatabase = None;
                };
                Ok(generate_rows_dummy())
            },
            _ => Err(ExecutionError::DebugError("to_do".into())),
        }
    }

    fn execute_alt_stmt(&mut self, query: AltStmt) -> Result<Rows, ExecutionError> {
        match query {
            AltStmt::Table(stmt) => self.execute_alt_table_stmt(stmt),
        }

    }

    fn execute_alt_table_stmt(&mut self, stmt: AlterTableStmt) -> Result<Rows, ExecutionError> {
        let table = try!(self.get_table(&stmt.tid));
        match stmt.op {
            AlterOp::Add(columninfo) => Ok(generate_rows_dummy()),
            AlterOp::Drop(column) => Ok(generate_rows_dummy()),
            AlterOp::Modify(columninfo) => Ok(generate_rows_dummy()),
        }

    }

    fn get_own_database(&self) -> Result<&Database, ExecutionError> {
        match self.user._currentDatabase {
            Some(ref base) => Ok(base),
            None => Err(ExecutionError::NoDatabaseSelected),
        }
    }

    fn get_table(&self, table: &str) -> Result<Table, ExecutionError>{
        let dbase = try!(self.get_own_database());
        Ok(try!(dbase.load_table(table)))
    }

}

fn generate_rows_dummy() -> Rows {
    Rows {
    data: Vec::new(),
    columns: Vec::new(),
}
}

#[derive(Debug)]
pub enum ExecutionError {

    ParseError(ParseError),
    StorageError(storage::Error),
    UnknownError,
    NoDatabaseSelected,

    DebugError(String),
}

impl From<ParseError> for ExecutionError {
    fn from(error: ParseError) -> ExecutionError {
        ExecutionError::ParseError(error)
    }
}

impl From<storage::Error> for ExecutionError {
    fn from(error: storage::Error) -> ExecutionError {
        ExecutionError::StorageError(error)
    }
}
<|endoftext|>


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

//! Project and package linters that run queries on guppy.

use crate::config::{BannedDepsConfig, EnforcedAttributesConfig, OverlayConfig};
use anyhow::anyhow;
use guppy::{graph::feature::FeatureFilterFn, Version, VersionReq};
use hakari::summaries::HakariBuilderSummary;
use std::{
    collections::{BTreeMap, HashMap},
    ffi::OsStr,
    iter,
};
use x_core::WorkspaceStatus;
use x_lint::prelude::*;

/// Ban certain crates from being used as direct dependencies or in the default build.
#[derive(Debug)]
pub struct BannedDeps<'cfg> {
    config: &'cfg BannedDepsConfig,
}

impl<'cfg> BannedDeps<'cfg> {
    pub fn new(config: &'cfg BannedDepsConfig) -> Self {
        Self { config }
    }
}

impl<'cfg> Linter for BannedDeps<'cfg> {
    fn name(&self) -> &'static str {
        "banned-deps"
    }
}

impl<'cfg> ProjectLinter for BannedDeps<'cfg> {
    fn run<'l>(
        &self,
        ctx: &ProjectContext<'l>,
        out: &mut LintFormatter<'l, '_>,
    ) -> Result<RunStatus<'l>> {
        let package_graph = ctx.package_graph()?;

        let filter_ban = |banned: &'cfg HashMap<String, String>| {
            package_graph.packages().filter_map(move |package| {
                banned
                    .get(package.name())
                    .map(move |message| (package, message))
            })
        };

        let banned_direct = &self.config.direct;
        for (package, message) in filter_ban(banned_direct) {
            // Look at the reverse direct dependencies of this package.
            for link in package.reverse_direct_links() {
                let from = link.from();
                if let Some(workspace_path) = from.source().workspace_path() {
                    out.write_kind(
                        LintKind::Package {
                            name: from.name(),
                            workspace_path,
                        },
                        LintLevel::Error,
                        format!("banned direct dependency '{}': {}", package.name(), message),
                    );
                }
            }
        }

        let default_members = ctx.default_members()?;

        let banned_default_build = &self.config.default_build;
        for (package, message) in filter_ban(banned_default_build) {
            if default_members.status_of(package.id()) != WorkspaceStatus::Absent {
                out.write(
                    LintLevel::Error,
                    format!(
                        "banned dependency in default build '{}': {}",
                        package.name(),
                        message
                    ),
                );
            }
        }

        Ok(RunStatus::Executed)
    }
}

/// Enforce attributes on workspace crates.
#[derive(Debug)]
pub struct EnforcedAttributes<'cfg> {
    config: &'cfg EnforcedAttributesConfig,
}

impl<'cfg> EnforcedAttributes<'cfg> {
    pub fn new(config: &'cfg EnforcedAttributesConfig) -> Self {
        Self { config }
    }
}

impl<'cfg> Linter for EnforcedAttributes<'cfg> {
    fn name(&self) -> &'static str {
        "enforced-attributes"
    }
}

impl<'cfg> PackageLinter for EnforcedAttributes<'cfg> {
    fn run<'l>(
        &self,
        ctx: &PackageContext<'l>,
        out: &mut LintFormatter<'l, '_>,
    ) -> Result<RunStatus<'l>> {
        let metadata = ctx.metadata();
        if let Some(authors) = &self.config.authors {
            if metadata.authors() != authors.as_slice() {
                out.write(
                    LintLevel::Error,
                    format!("invalid authors (expected {:?})", authors.join(", "),),
                );
            }
        }
        if let Some(license) = &self.config.license {
            if metadata.license() != Some(license.as_str()) {
                out.write(
                    LintLevel::Error,
                    format!("invalid license (expected {})", license),
                )
            }
        }

        Ok(RunStatus::Executed)
    }
}

/// Check conventions in crate names and paths.
#[derive(Debug)]
pub struct CrateNamesPaths;

impl Linter for CrateNamesPaths {
    fn name(&self) -> &'static str {
        "crate-names-paths"
    }
}

impl PackageLinter for CrateNamesPaths {
    fn run<'l>(
        &self,
        ctx: &PackageContext<'l>,
        out: &mut LintFormatter<'l, '_>,
    ) -> Result<RunStatus<'l>> {
        let name = ctx.metadata().name();
        if name.contains('_') {
            out.write(
                LintLevel::Error,
                "crate name contains '_' (use '-' instead)",
            );
        }

        let workspace_path = ctx.workspace_path();
        if workspace_path.as_str().contains('_') {
            out.write(
                LintLevel::Error,
                "workspace path contains '_' (use '-' instead)",
            );
        }

        for build_target in ctx.metadata().build_targets() {
            let target_name = build_target.name();
            if target_name.contains('_') {
                // If the path is implicitly specified by the name, don't warn about it.
                let file_stem = build_target.path().file_stem();
                if file_stem != Some(OsStr::new(target_name)) {
                    out.write(
                        LintLevel::Error,
                        format!(
                            "build target '{}' contains '_' (use '-' instead)",
                            target_name
                        ),
                    );
                }
            }
        }

        Ok(RunStatus::Executed)
    }
}

/// Ensure that any workspace packages with build dependencies also have a build script.
#[derive(Debug)]
pub struct IrrelevantBuildDeps;

impl Linter for IrrelevantBuildDeps {
    fn name(&self) -> &'static str {
        "irrelevant-build-deps"
    }
}

impl PackageLinter for IrrelevantBuildDeps {
    fn run<'l>(
        &self,
        ctx: &PackageContext<'l>,
        out: &mut LintFormatter<'l, '_>,
    ) -> Result<RunStatus<'l>> {
        let metadata = ctx.metadata();

        let has_build_dep = metadata
            .direct_links()
            .any(|link| link.build().is_present());

        if !metadata.has_build_script() && has_build_dep {
            out.write(LintLevel::Error, "build dependencies but no build script");
        }

        Ok(RunStatus::Executed)
    }
}

/// Ensure that packages within the workspace only depend on one version of a third-party crate.
#[derive(Debug)]
pub struct DirectDepDups<'cfg> {
    hakari_package: &'cfg str,
}

impl<'cfg> DirectDepDups<'cfg> {
    pub fn new(hakari_config: &'cfg HakariBuilderSummary) -> crate::Result<Self> {
        let hakari_package = hakari_config
            .hakari_package
            .as_deref()
            .ok_or_else(|| anyhow!("hakari.hakari-package not defined in x.toml"))?;
        Ok(Self { hakari_package })
    }
}

impl<'cfg> Linter for DirectDepDups<'cfg> {
    fn name(&self) -> &'static str {
        "direct-dep-dups"
    }
}

impl<'cfg> ProjectLinter for DirectDepDups<'cfg> {
    fn run<'l>(
        &self,
        ctx: &ProjectContext<'l>,
        out: &mut LintFormatter<'l, '_>,
    ) -> Result<RunStatus<'l>> {
        let package_graph = ctx.package_graph()?;

        // This is a map of direct deps by name -> version -> packages that depend on it.
        let mut direct_deps: BTreeMap<&str, BTreeMap<&Version, Vec<&str>>> = BTreeMap::new();
        package_graph.query_workspace().resolve_with_fn(|_, link| {
            // Collect direct dependencies of workspace packages.
            let (from, to) = link.endpoints();
            if from.name() == self.hakari_package {
                // Skip the workspace hack package.
                return false;
            }
            if from.in_workspace() && !to.in_workspace() {
                direct_deps
                    .entry(to.name())
                    .or_default()
                    .entry(to.version())
                    .or_default()
                    .push(from.name());
            }
            // query_workspace + preventing further traversals will mean that only direct
            // dependencies are considered.
            false
        });
        for (direct_dep, versions) in direct_deps {
            if versions.len() > 1 {
                let mut msg = format!("duplicate direct dependency '{}':\n", direct_dep);
                for (version, packages) in versions {
                    msg.push_str(&format!("  * {} (", version));
                    msg.push_str(&packages.join(", "));
                    msg.push_str(")\n");
                }
                out.write(LintLevel::Error, msg);
            }
        }

        Ok(RunStatus::Executed)
    }
}

/// Assertions for "overlay" features.
///
/// An "overlay" feature is a feature name used throughout the codebase, whose purpose it is to
/// augment each package with extra code (e.g. proptest generators). Overlay features shouldn't be
/// enabled by anything except overlay features on workspace members, but may be enabled by default
/// by test-only or other non-default workspace members.
#[derive(Debug)]
pub struct OverlayFeatures<'cfg> {
    config: &'cfg OverlayConfig,
}

impl<'cfg> OverlayFeatures<'cfg> {
    pub fn new(config: &'cfg OverlayConfig) -> Self {
        Self { config }
    }

    fn is_overlay(&self, feature: Option<&str>) -> bool {
        match feature {
            Some(feature) => self.config.features.iter().any(|f| *f == feature),
            // The base feature isn't banned.
            None => false,
        }
    }
}

impl<'cfg> Linter for OverlayFeatures<'cfg> {
    fn name(&self) -> &'static str {
        "overlay-features"
    }
}

impl<'cfg> PackageLinter for OverlayFeatures<'cfg> {
    fn run<'l>(
        &self,
        ctx: &PackageContext<'l>,
        out: &mut LintFormatter<'l, '_>,
    ) -> Result<RunStatus<'l>> {
        let package = ctx.metadata();
        if !ctx.is_default_member() {
            return Ok(RunStatus::Skipped(SkipReason::UnsupportedPackage(
                package.id(),
            )));
        }

        let filter = FeatureFilterFn::new(|_, feature_id| {
            // Accept all features except for overlay ones.
            !self.is_overlay(feature_id.feature())
        });

        let package_graph = ctx.package_graph();

        let feature_query = package_graph
            .query_forward(iter::once(package.id()))
            .expect("valid package ID")
            .to_feature_query(filter);

        let mut overlays: Vec<(Option<&str>, &str, Option<&str>)> = vec![];

        feature_query.resolve_with_fn(|_, link| {
            // We now use the v2 resolver, so dev-only links can be skipped.
            if !link.dev_only() {
                let (from, to) = link.endpoints();
                let to_package = to.package();
                if to_package.in_workspace() && self.is_overlay(to.feature_id().feature()) {
                    overlays.push((
                        from.feature_id().feature(),
                        to_package.name(),
                        to.feature_id().feature(),
                    ));
                }
            }

            // Don't need to traverse past direct dependencies.
            false
        });

        if !overlays.is_empty() {
            let mut msg = "overlay features enabled by default:\n".to_string();
            for (from_feature, to_package, to_feature) in overlays {
                msg.push_str(&format!(
                    "  * {} -> {}/{}\n",
                    feature_str(from_feature),
                    to_package,
                    feature_str(to_feature)
                ));
            }
            msg.push_str("Use a line in the [features] section instead.\n");
            out.write(LintLevel::Error, msg);
        }

        Ok(RunStatus::Executed)
    }
}

fn feature_str(feature: Option<&str>) -> &str {
    feature.unwrap_or("[base]")
}

/// Ensure that all unpublished packages only use path dependencies for workspace dependencies
#[derive(Debug)]
pub struct UnpublishedPackagesOnlyUsePathDependencies {
    no_version_req: VersionReq,
}

impl UnpublishedPackagesOnlyUsePathDependencies {
    pub fn new() -> Self {
        Self {
            no_version_req: VersionReq::parse(">=0.0.0").expect(">=0.0.0 should be a valid req"),
        }
    }
}

impl Linter for UnpublishedPackagesOnlyUsePathDependencies {
    fn name(&self) -> &'static str {
        "unpublished-packages-only-use-path-dependencies"
    }
}

impl PackageLinter for UnpublishedPackagesOnlyUsePathDependencies {
    fn run<'l>(
        &self,
        ctx: &PackageContext<'l>,
        out: &mut LintFormatter<'l, '_>,
    ) -> Result<RunStatus<'l>> {
        let metadata = ctx.metadata();

        // Skip all packages which aren't 'publish = false'
        if !matches!(metadata.publish(), Some(&[])) {
            return Ok(RunStatus::Executed);
        }

        for direct_dep in metadata.direct_links().filter(|p| p.to().in_workspace()) {
            if direct_dep.version_req() != &self.no_version_req {
                let msg = format!(
                    "unpublished package specifies a version of first-party dependency '{}'; \
                    unpublished packages should only use path dependencies for first-party packages.",
                    direct_dep.dep_name(),
                );
                out.write(LintLevel::Error, msg);
            }
        }

        Ok(RunStatus::Executed)
    }
}

/// Ensure that all published packages only depend on other, published packages
#[derive(Debug)]
pub struct PublishedPackagesDontDependOnUnpublishedPackages;

impl Linter for PublishedPackagesDontDependOnUnpublishedPackages {
    fn name(&self) -> &'static str {
        "published-packages-dont-depend-on-unpublished-packages"
    }
}

impl PackageLinter for PublishedPackagesDontDependOnUnpublishedPackages {
    fn run<'l>(
        &self,
        ctx: &PackageContext<'l>,
        out: &mut LintFormatter<'l, '_>,
    ) -> Result<RunStatus<'l>> {
        let metadata = ctx.metadata();

        // Skip all packages which aren't publishable
        if matches!(metadata.publish(), Some(&[])) {
            return Ok(RunStatus::Executed);
        }

        for direct_dep in metadata.direct_links().filter(|p| p.to().in_workspace()) {
            // If the direct dependency isn't publishable
            if matches!(direct_dep.to().publish(), Some(&[])) {
                out.write(
                    LintLevel::Error,
                    format!(
                        "published package can't depend on unpublished package '{}'",
                        direct_dep.dep_name()
                    ),
                );
            }
        }

        Ok(RunStatus::Executed)
    }
}

/// Only allow crates to be published to crates.io
#[derive(Debug)]
pub struct OnlyPublishToCratesIo;

impl Linter for OnlyPublishToCratesIo {
    fn name(&self) -> &'static str {
        "only-publish-to-crates-io"
    }
}

impl PackageLinter for OnlyPublishToCratesIo {
    fn run<'l>(
        &self,
        ctx: &PackageContext<'l>,
        out: &mut LintFormatter<'l, '_>,
    ) -> Result<RunStatus<'l>> {
        let metadata = ctx.metadata();

        match metadata.publish() {
            Some(&[]) => {}
            Some(&[ref r]) if r == "crates-io" => {}
            _ => {
                out.write(
                    LintLevel::Error,
                    "published package should only be publishable to crates.io. \
                        If you intend to publish this package, ensure the 'publish' \
                        field in the package's Cargo.toml is 'publish = [\"crates-io\"]. \
                        Otherwise set the 'publish' field to 'publish = false'.",
                );
            }
        }

        Ok(RunStatus::Executed)
    }
}
<commit_msg>x: don't check dev-dependencies for unpublishable crates<commit_after>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

//! Project and package linters that run queries on guppy.

use crate::config::{BannedDepsConfig, EnforcedAttributesConfig, OverlayConfig};
use anyhow::anyhow;
use guppy::{graph::feature::FeatureFilterFn, Version, VersionReq};
use hakari::summaries::HakariBuilderSummary;
use std::{
    collections::{BTreeMap, HashMap},
    ffi::OsStr,
    iter,
};
use x_core::WorkspaceStatus;
use x_lint::prelude::*;

/// Ban certain crates from being used as direct dependencies or in the default build.
#[derive(Debug)]
pub struct BannedDeps<'cfg> {
    config: &'cfg BannedDepsConfig,
}

impl<'cfg> BannedDeps<'cfg> {
    pub fn new(config: &'cfg BannedDepsConfig) -> Self {
        Self { config }
    }
}

impl<'cfg> Linter for BannedDeps<'cfg> {
    fn name(&self) -> &'static str {
        "banned-deps"
    }
}

impl<'cfg> ProjectLinter for BannedDeps<'cfg> {
    fn run<'l>(
        &self,
        ctx: &ProjectContext<'l>,
        out: &mut LintFormatter<'l, '_>,
    ) -> Result<RunStatus<'l>> {
        let package_graph = ctx.package_graph()?;

        let filter_ban = |banned: &'cfg HashMap<String, String>| {
            package_graph.packages().filter_map(move |package| {
                banned
                    .get(package.name())
                    .map(move |message| (package, message))
            })
        };

        let banned_direct = &self.config.direct;
        for (package, message) in filter_ban(banned_direct) {
            // Look at the reverse direct dependencies of this package.
            for link in package.reverse_direct_links() {
                let from = link.from();
                if let Some(workspace_path) = from.source().workspace_path() {
                    out.write_kind(
                        LintKind::Package {
                            name: from.name(),
                            workspace_path,
                        },
                        LintLevel::Error,
                        format!("banned direct dependency '{}': {}", package.name(), message),
                    );
                }
            }
        }

        let default_members = ctx.default_members()?;

        let banned_default_build = &self.config.default_build;
        for (package, message) in filter_ban(banned_default_build) {
            if default_members.status_of(package.id()) != WorkspaceStatus::Absent {
                out.write(
                    LintLevel::Error,
                    format!(
                        "banned dependency in default build '{}': {}",
                        package.name(),
                        message
                    ),
                );
            }
        }

        Ok(RunStatus::Executed)
    }
}

/// Enforce attributes on workspace crates.
#[derive(Debug)]
pub struct EnforcedAttributes<'cfg> {
    config: &'cfg EnforcedAttributesConfig,
}

impl<'cfg> EnforcedAttributes<'cfg> {
    pub fn new(config: &'cfg EnforcedAttributesConfig) -> Self {
        Self { config }
    }
}

impl<'cfg> Linter for EnforcedAttributes<'cfg> {
    fn name(&self) -> &'static str {
        "enforced-attributes"
    }
}

impl<'cfg> PackageLinter for EnforcedAttributes<'cfg> {
    fn run<'l>(
        &self,
        ctx: &PackageContext<'l>,
        out: &mut LintFormatter<'l, '_>,
    ) -> Result<RunStatus<'l>> {
        let metadata = ctx.metadata();
        if let Some(authors) = &self.config.authors {
            if metadata.authors() != authors.as_slice() {
                out.write(
                    LintLevel::Error,
                    format!("invalid authors (expected {:?})", authors.join(", "),),
                );
            }
        }
        if let Some(license) = &self.config.license {
            if metadata.license() != Some(license.as_str()) {
                out.write(
                    LintLevel::Error,
                    format!("invalid license (expected {})", license),
                )
            }
        }

        Ok(RunStatus::Executed)
    }
}

/// Check conventions in crate names and paths.
#[derive(Debug)]
pub struct CrateNamesPaths;

impl Linter for CrateNamesPaths {
    fn name(&self) -> &'static str {
        "crate-names-paths"
    }
}

impl PackageLinter for CrateNamesPaths {
    fn run<'l>(
        &self,
        ctx: &PackageContext<'l>,
        out: &mut LintFormatter<'l, '_>,
    ) -> Result<RunStatus<'l>> {
        let name = ctx.metadata().name();
        if name.contains('_') {
            out.write(
                LintLevel::Error,
                "crate name contains '_' (use '-' instead)",
            );
        }

        let workspace_path = ctx.workspace_path();
        if workspace_path.as_str().contains('_') {
            out.write(
                LintLevel::Error,
                "workspace path contains '_' (use '-' instead)",
            );
        }

        for build_target in ctx.metadata().build_targets() {
            let target_name = build_target.name();
            if target_name.contains('_') {
                // If the path is implicitly specified by the name, don't warn about it.
                let file_stem = build_target.path().file_stem();
                if file_stem != Some(OsStr::new(target_name)) {
                    out.write(
                        LintLevel::Error,
                        format!(
                            "build target '{}' contains '_' (use '-' instead)",
                            target_name
                        ),
                    );
                }
            }
        }

        Ok(RunStatus::Executed)
    }
}

/// Ensure that any workspace packages with build dependencies also have a build script.
#[derive(Debug)]
pub struct IrrelevantBuildDeps;

impl Linter for IrrelevantBuildDeps {
    fn name(&self) -> &'static str {
        "irrelevant-build-deps"
    }
}

impl PackageLinter for IrrelevantBuildDeps {
    fn run<'l>(
        &self,
        ctx: &PackageContext<'l>,
        out: &mut LintFormatter<'l, '_>,
    ) -> Result<RunStatus<'l>> {
        let metadata = ctx.metadata();

        let has_build_dep = metadata
            .direct_links()
            .any(|link| link.build().is_present());

        if !metadata.has_build_script() && has_build_dep {
            out.write(LintLevel::Error, "build dependencies but no build script");
        }

        Ok(RunStatus::Executed)
    }
}

/// Ensure that packages within the workspace only depend on one version of a third-party crate.
#[derive(Debug)]
pub struct DirectDepDups<'cfg> {
    hakari_package: &'cfg str,
}

impl<'cfg> DirectDepDups<'cfg> {
    pub fn new(hakari_config: &'cfg HakariBuilderSummary) -> crate::Result<Self> {
        let hakari_package = hakari_config
            .hakari_package
            .as_deref()
            .ok_or_else(|| anyhow!("hakari.hakari-package not defined in x.toml"))?;
        Ok(Self { hakari_package })
    }
}

impl<'cfg> Linter for DirectDepDups<'cfg> {
    fn name(&self) -> &'static str {
        "direct-dep-dups"
    }
}

impl<'cfg> ProjectLinter for DirectDepDups<'cfg> {
    fn run<'l>(
        &self,
        ctx: &ProjectContext<'l>,
        out: &mut LintFormatter<'l, '_>,
    ) -> Result<RunStatus<'l>> {
        let package_graph = ctx.package_graph()?;

        // This is a map of direct deps by name -> version -> packages that depend on it.
        let mut direct_deps: BTreeMap<&str, BTreeMap<&Version, Vec<&str>>> = BTreeMap::new();
        package_graph.query_workspace().resolve_with_fn(|_, link| {
            // Collect direct dependencies of workspace packages.
            let (from, to) = link.endpoints();
            if from.name() == self.hakari_package {
                // Skip the workspace hack package.
                return false;
            }
            if from.in_workspace() && !to.in_workspace() {
                direct_deps
                    .entry(to.name())
                    .or_default()
                    .entry(to.version())
                    .or_default()
                    .push(from.name());
            }
            // query_workspace + preventing further traversals will mean that only direct
            // dependencies are considered.
            false
        });
        for (direct_dep, versions) in direct_deps {
            if versions.len() > 1 {
                let mut msg = format!("duplicate direct dependency '{}':\n", direct_dep);
                for (version, packages) in versions {
                    msg.push_str(&format!("  * {} (", version));
                    msg.push_str(&packages.join(", "));
                    msg.push_str(")\n");
                }
                out.write(LintLevel::Error, msg);
            }
        }

        Ok(RunStatus::Executed)
    }
}

/// Assertions for "overlay" features.
///
/// An "overlay" feature is a feature name used throughout the codebase, whose purpose it is to
/// augment each package with extra code (e.g. proptest generators). Overlay features shouldn't be
/// enabled by anything except overlay features on workspace members, but may be enabled by default
/// by test-only or other non-default workspace members.
#[derive(Debug)]
pub struct OverlayFeatures<'cfg> {
    config: &'cfg OverlayConfig,
}

impl<'cfg> OverlayFeatures<'cfg> {
    pub fn new(config: &'cfg OverlayConfig) -> Self {
        Self { config }
    }

    fn is_overlay(&self, feature: Option<&str>) -> bool {
        match feature {
            Some(feature) => self.config.features.iter().any(|f| *f == feature),
            // The base feature isn't banned.
            None => false,
        }
    }
}

impl<'cfg> Linter for OverlayFeatures<'cfg> {
    fn name(&self) -> &'static str {
        "overlay-features"
    }
}

impl<'cfg> PackageLinter for OverlayFeatures<'cfg> {
    fn run<'l>(
        &self,
        ctx: &PackageContext<'l>,
        out: &mut LintFormatter<'l, '_>,
    ) -> Result<RunStatus<'l>> {
        let package = ctx.metadata();
        if !ctx.is_default_member() {
            return Ok(RunStatus::Skipped(SkipReason::UnsupportedPackage(
                package.id(),
            )));
        }

        let filter = FeatureFilterFn::new(|_, feature_id| {
            // Accept all features except for overlay ones.
            !self.is_overlay(feature_id.feature())
        });

        let package_graph = ctx.package_graph();

        let feature_query = package_graph
            .query_forward(iter::once(package.id()))
            .expect("valid package ID")
            .to_feature_query(filter);

        let mut overlays: Vec<(Option<&str>, &str, Option<&str>)> = vec![];

        feature_query.resolve_with_fn(|_, link| {
            // We now use the v2 resolver, so dev-only links can be skipped.
            if !link.dev_only() {
                let (from, to) = link.endpoints();
                let to_package = to.package();
                if to_package.in_workspace() && self.is_overlay(to.feature_id().feature()) {
                    overlays.push((
                        from.feature_id().feature(),
                        to_package.name(),
                        to.feature_id().feature(),
                    ));
                }
            }

            // Don't need to traverse past direct dependencies.
            false
        });

        if !overlays.is_empty() {
            let mut msg = "overlay features enabled by default:\n".to_string();
            for (from_feature, to_package, to_feature) in overlays {
                msg.push_str(&format!(
                    "  * {} -> {}/{}\n",
                    feature_str(from_feature),
                    to_package,
                    feature_str(to_feature)
                ));
            }
            msg.push_str("Use a line in the [features] section instead.\n");
            out.write(LintLevel::Error, msg);
        }

        Ok(RunStatus::Executed)
    }
}

fn feature_str(feature: Option<&str>) -> &str {
    feature.unwrap_or("[base]")
}

/// Ensure that all unpublished packages only use path dependencies for workspace dependencies
#[derive(Debug)]
pub struct UnpublishedPackagesOnlyUsePathDependencies {
    no_version_req: VersionReq,
}

impl UnpublishedPackagesOnlyUsePathDependencies {
    pub fn new() -> Self {
        Self {
            no_version_req: VersionReq::parse(">=0.0.0").expect(">=0.0.0 should be a valid req"),
        }
    }
}

impl Linter for UnpublishedPackagesOnlyUsePathDependencies {
    fn name(&self) -> &'static str {
        "unpublished-packages-only-use-path-dependencies"
    }
}

impl PackageLinter for UnpublishedPackagesOnlyUsePathDependencies {
    fn run<'l>(
        &self,
        ctx: &PackageContext<'l>,
        out: &mut LintFormatter<'l, '_>,
    ) -> Result<RunStatus<'l>> {
        let metadata = ctx.metadata();

        // Skip all packages which aren't 'publish = false'
        if !matches!(metadata.publish(), Some(&[])) {
            return Ok(RunStatus::Executed);
        }

        for direct_dep in metadata.direct_links().filter(|p| p.to().in_workspace()) {
            if direct_dep.version_req() != &self.no_version_req {
                let msg = format!(
                    "unpublished package specifies a version of first-party dependency '{}'; \
                    unpublished packages should only use path dependencies for first-party packages.",
                    direct_dep.dep_name(),
                );
                out.write(LintLevel::Error, msg);
            }
        }

        Ok(RunStatus::Executed)
    }
}

/// Ensure that all published packages only depend on other, published packages
#[derive(Debug)]
pub struct PublishedPackagesDontDependOnUnpublishedPackages;

impl Linter for PublishedPackagesDontDependOnUnpublishedPackages {
    fn name(&self) -> &'static str {
        "published-packages-dont-depend-on-unpublished-packages"
    }
}

impl PackageLinter for PublishedPackagesDontDependOnUnpublishedPackages {
    fn run<'l>(
        &self,
        ctx: &PackageContext<'l>,
        out: &mut LintFormatter<'l, '_>,
    ) -> Result<RunStatus<'l>> {
        let metadata = ctx.metadata();

        // Skip all packages which aren't publishable
        if matches!(metadata.publish(), Some(&[])) {
            return Ok(RunStatus::Executed);
        }

        for direct_dep in metadata
            .direct_links()
            .filter(|p| !p.dev_only() && p.to().in_workspace())
        {
            // If the direct dependency isn't publishable
            if matches!(direct_dep.to().publish(), Some(&[])) {
                out.write(
                    LintLevel::Error,
                    format!(
                        "published package can't depend on unpublished package '{}'",
                        direct_dep.dep_name()
                    ),
                );
            }
        }

        Ok(RunStatus::Executed)
    }
}

/// Only allow crates to be published to crates.io
#[derive(Debug)]
pub struct OnlyPublishToCratesIo;

impl Linter for OnlyPublishToCratesIo {
    fn name(&self) -> &'static str {
        "only-publish-to-crates-io"
    }
}

impl PackageLinter for OnlyPublishToCratesIo {
    fn run<'l>(
        &self,
        ctx: &PackageContext<'l>,
        out: &mut LintFormatter<'l, '_>,
    ) -> Result<RunStatus<'l>> {
        let metadata = ctx.metadata();

        match metadata.publish() {
            Some(&[]) => {}
            Some(&[ref r]) if r == "crates-io" => {}
            _ => {
                out.write(
                    LintLevel::Error,
                    "published package should only be publishable to crates.io. \
                        If you intend to publish this package, ensure the 'publish' \
                        field in the package's Cargo.toml is 'publish = [\"crates-io\"]. \
                        Otherwise set the 'publish' field to 'publish = false'.",
                );
            }
        }

        Ok(RunStatus::Executed)
    }
}
<|endoftext|>


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

use hir;
use ty::{self, Region, TyCtxt};
use hir::map as hir_map;
use middle::resolve_lifetime as rl;
use hir::intravisit::{self, NestedVisitorMap, Visitor};
use infer::error_reporting::nice_region_error::NiceRegionError;

impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
    /// This function calls the `visit_ty` method for the parameters
    /// corresponding to the anonymous regions. The `nested_visitor.found_type`
    /// contains the anonymous type.
    ///
    /// # Arguments
    /// region - the anonymous region corresponding to the anon_anon conflict
    /// br - the bound region corresponding to the above region which is of type `BrAnon(_)`
    ///
    /// # Example
    /// ```
    /// fn foo(x: &mut Vec<&u8>, y: &u8)
    ///    { x.push(y); }
    /// ```
    /// The function returns the nested type corresponding to the anonymous region
    /// for e.g. `&u8` and Vec<`&u8`.
    pub(super) fn find_anon_type(
        &self,
        region: Region<'tcx>,
        br: &ty::BoundRegion,
    ) -> Option<(&hir::Ty, &hir::FnDecl)> {
        if let Some(anon_reg) = self.is_suitable_region(region) {
            let def_id = anon_reg.def_id;
            if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) {
                let fndecl = match self.tcx.hir.get(node_id) {
                    hir_map::NodeItem(&hir::Item {
                        node: hir::ItemFn(ref fndecl, ..),
                        ..
                    }) => &fndecl,
                    hir_map::NodeTraitItem(&hir::TraitItem {
                        node: hir::TraitItemKind::Method(ref m, ..),
                        ..
                    })
                    | hir_map::NodeImplItem(&hir::ImplItem {
                        node: hir::ImplItemKind::Method(ref m, ..),
                        ..
                    }) => &m.decl,
                    _ => return None,
                };

                return fndecl
                    .inputs
                    .iter()
                    .filter_map(|arg| self.find_component_for_bound_region(arg, br))
                    .next()
                    .map(|ty| (ty, &**fndecl));
            }
        }
        None
    }

    // This method creates a FindNestedTypeVisitor which returns the type corresponding
    // to the anonymous region.
    fn find_component_for_bound_region(
        &self,
        arg: &'gcx hir::Ty,
        br: &ty::BoundRegion,
    ) -> Option<(&'gcx hir::Ty)> {
        let mut nested_visitor = FindNestedTypeVisitor {
            tcx: self.tcx,
            bound_region: *br,
            found_type: None,
            depth: 1,
        };
        nested_visitor.visit_ty(arg);
        nested_visitor.found_type
    }
}

// The FindNestedTypeVisitor captures the corresponding `hir::Ty` of the
// anonymous region. The example above would lead to a conflict between
// the two anonymous lifetimes for &u8 in x and y respectively. This visitor
// would be invoked twice, once for each lifetime, and would
// walk the types like &mut Vec<&u8> and &u8 looking for the HIR
// where that lifetime appears. This allows us to highlight the
// specific part of the type in the error message.
struct FindNestedTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
    tcx: TyCtxt<'a, 'gcx, 'tcx>,
    // The bound_region corresponding to the Refree(freeregion)
    // associated with the anonymous region we are looking for.
    bound_region: ty::BoundRegion,
    // The type where the anonymous lifetime appears
    // for e.g. Vec<`&u8`> and <`&u8`>
    found_type: Option<&'gcx hir::Ty>,
    depth: u32,
}

impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindNestedTypeVisitor<'a, 'gcx, 'tcx> {
    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
        NestedVisitorMap::OnlyBodies(&self.tcx.hir)
    }

    fn visit_ty(&mut self, arg: &'gcx hir::Ty) {
        match arg.node {
            hir::TyBareFn(_) => {
                self.depth += 1;
                intravisit::walk_ty(self, arg);
                self.depth -= 1;
                return;
            }

            hir::TyTraitObject(ref bounds, _) => for bound in bounds {
                self.depth += 1;
                self.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None);
                self.depth -= 1;
            },

            hir::TyRptr(ref lifetime, _) => {
                // the lifetime of the TyRptr
                let hir_id = self.tcx.hir.node_to_hir_id(lifetime.id);
                match (self.tcx.named_region(hir_id), self.bound_region) {
                    // Find the index of the anonymous region that was part of the
                    // error. We will then search the function parameters for a bound
                    // region at the right depth with the same index
                    (
                        Some(rl::Region::LateBoundAnon(debruijn_index, anon_index)),
                        ty::BrAnon(br_index),
                    ) => {
                        debug!(
                            "LateBoundAnon depth = {:?} anon_index = {:?} br_index={:?}",
                            debruijn_index.depth,
                            anon_index,
                            br_index
                        );
                        if debruijn_index.depth == self.depth && anon_index == br_index {
                            self.found_type = Some(arg);
                            return; // we can stop visiting now
                        }
                    }

                    // Find the index of the named region that was part of the
                    // error. We will then search the function parameters for a bound
                    // region at the right depth with the same index
                    (Some(rl::Region::EarlyBound(_, id, _)), ty::BrNamed(def_id, _)) => {
                        debug!(
                            "EarlyBound self.infcx.tcx.hir.local_def_id(id)={:?} \
                             def_id={:?}",
                            id,
                            def_id
                        );
                        if id == def_id {
                            self.found_type = Some(arg);
                            return; // we can stop visiting now
                        }
                    }

                    // Find the index of the named region that was part of the
                    // error. We will then search the function parameters for a bound
                    // region at the right depth with the same index
                    (
                        Some(rl::Region::LateBound(debruijn_index, id, _)),
                        ty::BrNamed(def_id, _),
                    ) => {
                        debug!(
                            "FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}",
                            debruijn_index.depth
                        );
                        debug!("self.infcx.tcx.hir.local_def_id(id)={:?}", id);
                        debug!("def_id={:?}", def_id);
                        if debruijn_index.depth == self.depth && id == def_id {
                            self.found_type = Some(arg);
                            return; // we can stop visiting now
                        }
                    }

                    (Some(rl::Region::Static), _)
                    | (Some(rl::Region::Free(_, _)), _)
                    | (Some(rl::Region::EarlyBound(_, _, _)), _)
                    | (Some(rl::Region::LateBound(_, _, _)), _)
                    | (Some(rl::Region::LateBoundAnon(_, _)), _)
                    | (None, _) => {
                        debug!("no arg found");
                    }
                }
            }
            // Checks if it is of type `hir::TyPath` which corresponds to a struct.
            hir::TyPath(_) => {
                let subvisitor = &mut TyPathVisitor {
                    tcx: self.tcx,
                    found_it: false,
                    bound_region: self.bound_region,
                    depth: self.depth,
                };
                intravisit::walk_ty(subvisitor, arg); // call walk_ty; as visit_ty is empty,
                                                      // this will visit only outermost type
                if subvisitor.found_it {
                    self.found_type = Some(arg);
                }
            }
            _ => {}
        }
        // walk the embedded contents: e.g., if we are visiting `Vec<&Foo>`,
        // go on to visit `&Foo`
        intravisit::walk_ty(self, arg);
    }
}

// The visitor captures the corresponding `hir::Ty` of the anonymous region
// in the case of structs ie. `hir::TyPath`.
// This visitor would be invoked for each lifetime corresponding to a struct,
// and would walk the types like Vec<Ref> in the above example and Ref looking for the HIR
// where that lifetime appears. This allows us to highlight the
// specific part of the type in the error message.
struct TyPathVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
    tcx: TyCtxt<'a, 'gcx, 'tcx>,
    found_it: bool,
    bound_region: ty::BoundRegion,
    depth: u32,
}

impl<'a, 'gcx, 'tcx> Visitor<'gcx> for TyPathVisitor<'a, 'gcx, 'tcx> {
    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
        NestedVisitorMap::OnlyBodies(&self.tcx.hir)
    }

    fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) {
        let hir_id = self.tcx.hir.node_to_hir_id(lifetime.id);
        match (self.tcx.named_region(hir_id), self.bound_region) {
            // the lifetime of the TyPath!
            (Some(rl::Region::LateBoundAnon(debruijn_index, anon_index)), ty::BrAnon(br_index)) => {
                if debruijn_index.depth == self.depth && anon_index == br_index {
                    self.found_it = true;
                    return;
                }
            }

            (Some(rl::Region::EarlyBound(_, id, _)), ty::BrNamed(def_id, _)) => {
                debug!(
                    "EarlyBound self.infcx.tcx.hir.local_def_id(id)={:?} \
                     def_id={:?}",
                    id,
                    def_id
                );
                if id == def_id {
                    self.found_it = true;
                    return; // we can stop visiting now
                }
            }

            (Some(rl::Region::LateBound(debruijn_index, id, _)), ty::BrNamed(def_id, _)) => {
                debug!(
                    "FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}",
                    debruijn_index.depth
                );
                debug!("id={:?}", id);
                debug!("def_id={:?}", def_id);
                if debruijn_index.depth == self.depth && id == def_id {
                    self.found_it = true;
                    return; // we can stop visiting now
                }
            }

            (Some(rl::Region::Static), _)
            | (Some(rl::Region::EarlyBound(_, _, _)), _)
            | (Some(rl::Region::LateBound(_, _, _)), _)
            | (Some(rl::Region::LateBoundAnon(_, _)), _)
            | (Some(rl::Region::Free(_, _)), _)
            | (None, _) => {
                debug!("no arg found");
            }
        }
    }

    fn visit_ty(&mut self, arg: &'gcx hir::Ty) {
        // ignore nested types
        //
        // If you have a type like `Foo<'a, &Ty>` we
        // are only interested in the immediate lifetimes ('a).
        //
        // Making `visit_ty` empty will ignore the `&Ty` embedded
        // inside, it will get reached by the outer visitor.
        debug!("`Ty` corresponding to a struct is {:?}", arg);
    }
}
<commit_msg>port `nice_region_error` code to not track depth but rather index<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use hir;
use ty::{self, Region, TyCtxt};
use hir::map as hir_map;
use middle::resolve_lifetime as rl;
use hir::intravisit::{self, NestedVisitorMap, Visitor};
use infer::error_reporting::nice_region_error::NiceRegionError;

impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
    /// This function calls the `visit_ty` method for the parameters
    /// corresponding to the anonymous regions. The `nested_visitor.found_type`
    /// contains the anonymous type.
    ///
    /// # Arguments
    /// region - the anonymous region corresponding to the anon_anon conflict
    /// br - the bound region corresponding to the above region which is of type `BrAnon(_)`
    ///
    /// # Example
    /// ```
    /// fn foo(x: &mut Vec<&u8>, y: &u8)
    ///    { x.push(y); }
    /// ```
    /// The function returns the nested type corresponding to the anonymous region
    /// for e.g. `&u8` and Vec<`&u8`.
    pub(super) fn find_anon_type(
        &self,
        region: Region<'tcx>,
        br: &ty::BoundRegion,
    ) -> Option<(&hir::Ty, &hir::FnDecl)> {
        if let Some(anon_reg) = self.is_suitable_region(region) {
            let def_id = anon_reg.def_id;
            if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) {
                let fndecl = match self.tcx.hir.get(node_id) {
                    hir_map::NodeItem(&hir::Item {
                        node: hir::ItemFn(ref fndecl, ..),
                        ..
                    }) => &fndecl,
                    hir_map::NodeTraitItem(&hir::TraitItem {
                        node: hir::TraitItemKind::Method(ref m, ..),
                        ..
                    })
                    | hir_map::NodeImplItem(&hir::ImplItem {
                        node: hir::ImplItemKind::Method(ref m, ..),
                        ..
                    }) => &m.decl,
                    _ => return None,
                };

                return fndecl
                    .inputs
                    .iter()
                    .filter_map(|arg| self.find_component_for_bound_region(arg, br))
                    .next()
                    .map(|ty| (ty, &**fndecl));
            }
        }
        None
    }

    // This method creates a FindNestedTypeVisitor which returns the type corresponding
    // to the anonymous region.
    fn find_component_for_bound_region(
        &self,
        arg: &'gcx hir::Ty,
        br: &ty::BoundRegion,
    ) -> Option<(&'gcx hir::Ty)> {
        let mut nested_visitor = FindNestedTypeVisitor {
            tcx: self.tcx,
            bound_region: *br,
            found_type: None,
            current_index: ty::DebruijnIndex::INNERMOST,
        };
        nested_visitor.visit_ty(arg);
        nested_visitor.found_type
    }
}

// The FindNestedTypeVisitor captures the corresponding `hir::Ty` of the
// anonymous region. The example above would lead to a conflict between
// the two anonymous lifetimes for &u8 in x and y respectively. This visitor
// would be invoked twice, once for each lifetime, and would
// walk the types like &mut Vec<&u8> and &u8 looking for the HIR
// where that lifetime appears. This allows us to highlight the
// specific part of the type in the error message.
struct FindNestedTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
    tcx: TyCtxt<'a, 'gcx, 'tcx>,
    // The bound_region corresponding to the Refree(freeregion)
    // associated with the anonymous region we are looking for.
    bound_region: ty::BoundRegion,
    // The type where the anonymous lifetime appears
    // for e.g. Vec<`&u8`> and <`&u8`>
    found_type: Option<&'gcx hir::Ty>,
    current_index: ty::DebruijnIndex,
}

impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindNestedTypeVisitor<'a, 'gcx, 'tcx> {
    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
        NestedVisitorMap::OnlyBodies(&self.tcx.hir)
    }

    fn visit_ty(&mut self, arg: &'gcx hir::Ty) {
        match arg.node {
            hir::TyBareFn(_) => {
                self.current_index.shift_in(1);
                intravisit::walk_ty(self, arg);
                self.current_index.shift_out(1);
                return;
            }

            hir::TyTraitObject(ref bounds, _) => for bound in bounds {
                self.current_index.shift_in(1);
                self.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None);
                self.current_index.shift_out(1);
            },

            hir::TyRptr(ref lifetime, _) => {
                // the lifetime of the TyRptr
                let hir_id = self.tcx.hir.node_to_hir_id(lifetime.id);
                match (self.tcx.named_region(hir_id), self.bound_region) {
                    // Find the index of the anonymous region that was part of the
                    // error. We will then search the function parameters for a bound
                    // region at the right depth with the same index
                    (
                        Some(rl::Region::LateBoundAnon(debruijn_index, anon_index)),
                        ty::BrAnon(br_index),
                    ) => {
                        debug!(
                            "LateBoundAnon depth = {:?} anon_index = {:?} br_index={:?}",
                            debruijn_index,
                            anon_index,
                            br_index
                        );
                        if debruijn_index == self.current_index && anon_index == br_index {
                            self.found_type = Some(arg);
                            return; // we can stop visiting now
                        }
                    }

                    // Find the index of the named region that was part of the
                    // error. We will then search the function parameters for a bound
                    // region at the right depth with the same index
                    (Some(rl::Region::EarlyBound(_, id, _)), ty::BrNamed(def_id, _)) => {
                        debug!(
                            "EarlyBound self.infcx.tcx.hir.local_def_id(id)={:?} \
                             def_id={:?}",
                            id,
                            def_id
                        );
                        if id == def_id {
                            self.found_type = Some(arg);
                            return; // we can stop visiting now
                        }
                    }

                    // Find the index of the named region that was part of the
                    // error. We will then search the function parameters for a bound
                    // region at the right depth with the same index
                    (
                        Some(rl::Region::LateBound(debruijn_index, id, _)),
                        ty::BrNamed(def_id, _),
                    ) => {
                        debug!(
                            "FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}",
                            debruijn_index
                        );
                        debug!("self.infcx.tcx.hir.local_def_id(id)={:?}", id);
                        debug!("def_id={:?}", def_id);
                        if debruijn_index == self.current_index && id == def_id {
                            self.found_type = Some(arg);
                            return; // we can stop visiting now
                        }
                    }

                    (Some(rl::Region::Static), _)
                    | (Some(rl::Region::Free(_, _)), _)
                    | (Some(rl::Region::EarlyBound(_, _, _)), _)
                    | (Some(rl::Region::LateBound(_, _, _)), _)
                    | (Some(rl::Region::LateBoundAnon(_, _)), _)
                    | (None, _) => {
                        debug!("no arg found");
                    }
                }
            }
            // Checks if it is of type `hir::TyPath` which corresponds to a struct.
            hir::TyPath(_) => {
                let subvisitor = &mut TyPathVisitor {
                    tcx: self.tcx,
                    found_it: false,
                    bound_region: self.bound_region,
                    current_index: self.current_index,
                };
                intravisit::walk_ty(subvisitor, arg); // call walk_ty; as visit_ty is empty,
                                                      // this will visit only outermost type
                if subvisitor.found_it {
                    self.found_type = Some(arg);
                }
            }
            _ => {}
        }
        // walk the embedded contents: e.g., if we are visiting `Vec<&Foo>`,
        // go on to visit `&Foo`
        intravisit::walk_ty(self, arg);
    }
}

// The visitor captures the corresponding `hir::Ty` of the anonymous region
// in the case of structs ie. `hir::TyPath`.
// This visitor would be invoked for each lifetime corresponding to a struct,
// and would walk the types like Vec<Ref> in the above example and Ref looking for the HIR
// where that lifetime appears. This allows us to highlight the
// specific part of the type in the error message.
struct TyPathVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
    tcx: TyCtxt<'a, 'gcx, 'tcx>,
    found_it: bool,
    bound_region: ty::BoundRegion,
    current_index: ty::DebruijnIndex,
}

impl<'a, 'gcx, 'tcx> Visitor<'gcx> for TyPathVisitor<'a, 'gcx, 'tcx> {
    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
        NestedVisitorMap::OnlyBodies(&self.tcx.hir)
    }

    fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) {
        let hir_id = self.tcx.hir.node_to_hir_id(lifetime.id);
        match (self.tcx.named_region(hir_id), self.bound_region) {
            // the lifetime of the TyPath!
            (Some(rl::Region::LateBoundAnon(debruijn_index, anon_index)), ty::BrAnon(br_index)) => {
                if debruijn_index == self.current_index && anon_index == br_index {
                    self.found_it = true;
                    return;
                }
            }

            (Some(rl::Region::EarlyBound(_, id, _)), ty::BrNamed(def_id, _)) => {
                debug!(
                    "EarlyBound self.infcx.tcx.hir.local_def_id(id)={:?} \
                     def_id={:?}",
                    id,
                    def_id
                );
                if id == def_id {
                    self.found_it = true;
                    return; // we can stop visiting now
                }
            }

            (Some(rl::Region::LateBound(debruijn_index, id, _)), ty::BrNamed(def_id, _)) => {
                debug!(
                    "FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}",
                    debruijn_index,
                );
                debug!("id={:?}", id);
                debug!("def_id={:?}", def_id);
                if debruijn_index == self.current_index && id == def_id {
                    self.found_it = true;
                    return; // we can stop visiting now
                }
            }

            (Some(rl::Region::Static), _)
            | (Some(rl::Region::EarlyBound(_, _, _)), _)
            | (Some(rl::Region::LateBound(_, _, _)), _)
            | (Some(rl::Region::LateBoundAnon(_, _)), _)
            | (Some(rl::Region::Free(_, _)), _)
            | (None, _) => {
                debug!("no arg found");
            }
        }
    }

    fn visit_ty(&mut self, arg: &'gcx hir::Ty) {
        // ignore nested types
        //
        // If you have a type like `Foo<'a, &Ty>` we
        // are only interested in the immediate lifetimes ('a).
        //
        // Making `visit_ty` empty will ignore the `&Ty` embedded
        // inside, it will get reached by the outer visitor.
        debug!("`Ty` corresponding to a struct is {:?}", arg);
    }
}
<|endoftext|>


<commit_before>/// Internal namespace.
pub mod internal
{
  use crate::prelude::*;
  use crate::canonical::*;
  use std::collections::HashMap;
  use wtools::prelude::*;
  // use core::cell::RefCell;
  // use std::sync::Arc;

  ///
  /// Node factory.
  ///

  #[ derive( Debug ) ]
  pub struct NodeFactory
  {
    /// Map id to node.
    pub id_to_node_map : HashMap< < < Self as NodeFactoryInterface >::Node as HasId >::Id, crate::NodeCell< Node > >,
  }

  impls!
  {

    ///
    /// Constructor.
    ///

    pub fn make() -> Self
    {
      let id_to_node_map = HashMap::new();
      Self
      {
        id_to_node_map,
      }
    }

    ///
    /// Get node.
    ///

    pub fn node< Id >( &self, id : Id )
    -> &crate::NodeCell< Node >
    where
      Id : Into< < < Self as NodeFactoryInterface >::Node as HasId >::Id >,
    {
      let id = id.into();
      let got = self.id_to_node_map.get( &id );
      if got.is_some()
      {
        let result : &crate::NodeCell< Node > = got.unwrap().clone();
        return result;
      }
      unreachable!( "No node with id {:?} found", id );
    }

    ///
    /// Get node, making a new one if no such exist. Returns id of the node.
    ///

    pub fn node_making_id< Id >( &mut self, id : Id ) -> < < Self as NodeFactoryInterface >::Node as HasId >::Id
    where
      Id : Into< < < Self as NodeFactoryInterface >::Node as HasId >::Id >,
    {
      let id = id.into();

      let result = self.id_to_node_map
      .entry( id )
      .or_insert_with( || crate::NodeCell::make( Node::make_named( id ) ) )
      ;

      result.borrow().id()
    }

  }

  // trace_macros!( true );
  // impl NodeFactory{ index2!
  // {
  //   make,
  //   node,
  //   node_making_id,
  // }}
  // trace_macros!( false );

  impl NodeFactory
  {

    index!
    {
      make,
      node,
      node_making_id,
    }

  }

  impl NodeFactoryInterface
  for NodeFactory
  {
    type Node = Node;

  }

}

/// Own namespace of the module.
pub mod own
{
  // use super::internal as i;
  pub use super::parented::*;
}

pub use own::*;

/// Parented namespace of the module.
pub mod parented
{
  pub use super::exposed::*;
  use super::internal as i;
  pub use i::NodeFactory;
}

/// Exposed namespace of the module.
pub mod exposed
{
  pub use super::prelude::*;
  // use super::internal as i;
}

/// Prelude to use: `use wtools::prelude::*`.
pub mod prelude
{
  // use super::internal as i;
}
<commit_msg>evolve graph<commit_after>/// Internal namespace.
pub mod internal
{
  use crate::prelude::*;
  use crate::canonical::*;
  use std::collections::HashMap;
  use wtools::prelude::*;

  ///
  /// Node factory.
  ///

  #[ derive( Debug ) ]
  pub struct NodeFactory
  {
    /// Map id to node.
    pub id_to_node_map : HashMap< < < Self as NodeFactoryInterface >::Node as HasId >::Id, crate::NodeCell< Node > >,
  }

  impls!
  {

    ///
    /// Constructor.
    ///

    pub fn make() -> Self
    {
      let id_to_node_map = HashMap::new();
      Self
      {
        id_to_node_map,
      }
    }

    ///
    /// Get node.
    ///

    pub fn node< Id >( &self, id : Id )
    -> &crate::NodeCell< Node >
    where
      Id : Into< Self::Id >,
    {
      let id = id.into();
      let got = self.id_to_node_map.get( &id );
      if got.is_some()
      {
        let result : &crate::NodeCell< Node > = got.unwrap().clone();
        return result;
      }
      unreachable!( "No node with id {:?} found", id );
    }

    ///
    /// Get node, making a new one if no such exist. Returns id of the node.
    ///

    pub fn node_making_id< Id >( &mut self, id : Id ) -> < < Self as NodeFactoryInterface >::Node as HasId >::Id
    where
      Id : Into< < < Self as NodeFactoryInterface >::Node as HasId >::Id >,
    {
      let id = id.into();

      let result = self.id_to_node_map
      .entry( id )
      .or_insert_with( || crate::NodeCell::make( Node::make_named( id ) ) )
      ;

      result.borrow().id()
    }

  }

  impl NodeFactory
  {

    index!
    {
      make,
      node,
      node_making_id,
    }

  }

  impl NodeFactoryInterface
  for NodeFactory
  {
    type Node = Node;

  }

}

/// Own namespace of the module.
pub mod own
{
  // use super::internal as i;
  pub use super::parented::*;
}

pub use own::*;

/// Parented namespace of the module.
pub mod parented
{
  pub use super::exposed::*;
  use super::internal as i;
  pub use i::NodeFactory;
}

/// Exposed namespace of the module.
pub mod exposed
{
  pub use super::prelude::*;
  // use super::internal as i;
}

/// Prelude to use: `use wtools::prelude::*`.
pub mod prelude
{
  // use super::internal as i;
}
<|endoftext|>


<commit_before>// run-pass

#[derive(Debug, PartialEq, Eq)]
enum Foo {
    Bar(i32),
    Baz { i: i32 },
}

type FooAlias = Foo;
type OptionAlias = Option<i32>;

impl Foo {
    fn foo() -> Self {
        Self::Bar(3)
    }
}

fn main() {
    let t = FooAlias::Bar(1);
    assert_eq!(t, Foo::Bar(1));
    let t = FooAlias::Baz { i: 2 };
    assert_eq!(t, Foo::Baz { i: 2 });
    match t {
        FooAlias::Bar(_i) => {}
        FooAlias::Baz { i } => { assert_eq!(i, 2); }
    }
    assert_eq!(Foo::foo(), Foo::Bar(3));

    assert_eq!(OptionAlias::Some(4), Option::Some(4));
}
<commit_msg>type_alias_enum_variants: remove duplicate run-pass test.<commit_after><|endoftext|>


<commit_before>//! This pass replaces a drop of a type that does not need dropping, with a goto

use crate::MirPass;
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;

use super::simplify::simplify_cfg;

pub struct RemoveUnneededDrops;

impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops {
    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
        trace!("Running RemoveUnneededDrops on {:?}", body.source);

        let did = body.source.def_id();
        let param_env = tcx.param_env(did);
        let mut should_simplify = false;

        let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
        for block in basic_blocks {
            let terminator = block.terminator_mut();
            if let TerminatorKind::Drop { place, target, .. } = terminator.kind {
                let ty = place.ty(local_decls, tcx);
                if ty.ty.needs_drop(tcx, param_env) {
                    continue;
                }
                if !tcx.consider_optimizing(|| format!("RemoveUnneededDrops {:?} ", did)) {
                    continue;
                }
                debug!("SUCCESS: replacing `drop` with goto({:?})", target);
                terminator.kind = TerminatorKind::Goto { target };
                should_simplify = true;
            }
        }

        // if we applied optimizations, we potentially have some cfg to cleanup to
        // make it easier for further passes
        if should_simplify {
            simplify_cfg(tcx, body);
        }
    }
}
<commit_msg>Fix remove_unneeded_drops pass.<commit_after>//! This pass replaces a drop of a type that does not need dropping, with a goto

use crate::MirPass;
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;

use super::simplify::simplify_cfg;

pub struct RemoveUnneededDrops;

impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops {
    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
        trace!("Running RemoveUnneededDrops on {:?}", body.source);

        let did = body.source.def_id();
        let param_env = tcx.param_env_reveal_all_normalized(did);
        let mut should_simplify = false;

        let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
        for block in basic_blocks {
            let terminator = block.terminator_mut();
            if let TerminatorKind::Drop { place, target, .. } = terminator.kind {
                let ty = place.ty(local_decls, tcx);
                if ty.ty.needs_drop(tcx, param_env) {
                    continue;
                }
                if !tcx.consider_optimizing(|| format!("RemoveUnneededDrops {:?} ", did)) {
                    continue;
                }
                debug!("SUCCESS: replacing `drop` with goto({:?})", target);
                terminator.kind = TerminatorKind::Goto { target };
                should_simplify = true;
            }
        }

        // if we applied optimizations, we potentially have some cfg to cleanup to
        // make it easier for further passes
        if should_simplify {
            simplify_cfg(tcx, body);
        }
    }
}
<|endoftext|>


<commit_before>//! [GET /_matrix/federation/v1/make_join/{roomId}/{userId}](https://matrix.org/docs/spec/server_server/r0.1.3#get-matrix-federation-v1-make-join-roomid-userid)

use js_int::UInt;
use ruma_api::ruma_api;
use ruma_common::Raw;
use ruma_events::pdu::Pdu;
use ruma_identifiers::{RoomId, UserId};

ruma_api! {
    metadata: {
        description: "Send a request for a join event template to a resident server.",
        name: "create_join_event_template",
        method: GET,
        path: "/_matrix/federation/v1/make_join/:room_id/:user_id",
        rate_limited: false,
        requires_authentication: true,
    }

    request: {
        /// The room ID that is about to be joined.
        #[ruma_api(path)]
        pub room_id: RoomId,
        /// The user ID the join event will be for.
        #[ruma_api(path)]
        pub user_id: UserId,
        #[ruma_api(query)]
        /// The room versions the sending server has support for. Defaults to 1.
        #[serde(skip_serializing_if = "Vec::is_empty")]
        pub ver: Vec<UInt>,
    }

    response: {
        /// The version of the room where the server is trying to join.
        pub room_version: Option<UInt>,
        /// An unsigned template event.
        pub event: Raw<Pdu>,
    }
}
<commit_msg>federation-api: Fix types in create_join_event_template::v1 request & response<commit_after>//! [GET /_matrix/federation/v1/make_join/{roomId}/{userId}](https://matrix.org/docs/spec/server_server/r0.1.3#get-matrix-federation-v1-make-join-roomid-userid)

use ruma_api::ruma_api;
use ruma_common::Raw;
use ruma_events::pdu::Pdu;
use ruma_identifiers::{RoomId, RoomVersionId, UserId};

ruma_api! {
    metadata: {
        description: "Send a request for a join event template to a resident server.",
        name: "create_join_event_template",
        method: GET,
        path: "/_matrix/federation/v1/make_join/:room_id/:user_id",
        rate_limited: false,
        requires_authentication: true,
    }

    request: {
        /// The room ID that is about to be joined.
        #[ruma_api(path)]
        pub room_id: RoomId,
        /// The user ID the join event will be for.
        #[ruma_api(path)]
        pub user_id: UserId,
        #[ruma_api(query)]
        /// The room versions the sending server has support for. Defaults to 1.
        #[serde(skip_serializing_if = "Vec::is_empty")]
        pub ver: Vec<RoomVersionId>,
    }

    response: {
        /// The version of the room where the server is trying to join.
        pub room_version: Option<RoomVersionId>,
        /// An unsigned template event.
        pub event: Raw<Pdu>,
    }
}
<|endoftext|>