Skip to content

Commit

Permalink
Recognize full path to std types/functions
Browse files Browse the repository at this point in the history
  • Loading branch information
taiki-e committed Oct 21, 2023
1 parent 01c290a commit 28507ca
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 10 deletions.
13 changes: 9 additions & 4 deletions src/auto_enum/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use syn::{
};

use super::{visitor, Context, NAME, NESTED, NEVER};
use crate::utils::{expr_block, replace_block, replace_expr, Attrs};
use crate::utils::{expr_block, path_eq, replace_block, replace_expr, Attrs};

/// Visits last expression.
///
Expand Down Expand Up @@ -57,9 +57,13 @@ pub(super) fn is_unreachable(cx: &Context, expr: &Expr) -> bool {

// `Err(expr)?` or `None?`.
Expr::Try(ExprTry { expr, .. }) => match &**expr {
Expr::Path(ExprPath { path, qself: None, .. }) => path.is_ident("None"),
Expr::Path(ExprPath { path, qself: None, .. }) => {
path_eq(path, &["std", "core"], &["option", "Option", "None"])
}
Expr::Call(ExprCall { args, func, .. }) if args.len() == 1 => match &**func {
Expr::Path(ExprPath { path, qself: None, .. }) => path.is_ident("Err"),
Expr::Path(ExprPath { path, qself: None, .. }) => {
path_eq(path, &["std", "core"], &["result", "Result", "Err"])
}
_ => false,
},
_ => false,
Expand All @@ -77,7 +81,8 @@ fn is_unreachable_macro(cx: &Context, mac: &Macro) -> bool {
const UNREACHABLE_MACROS: &[&str] = &["unreachable", "panic"];

// `unreachable!`, `panic!` or an expression level marker (`marker!` macro).
UNREACHABLE_MACROS.iter().any(|i| mac.path.is_ident(i)) || cx.is_marker_macro(mac)
UNREACHABLE_MACROS.iter().any(|i| path_eq(&mac.path, &["std", "core"], &[i]))
|| cx.is_marker_macro(mac)
}

fn is_unreachable_stmt(cx: &Context, stmt: Option<&Stmt>) -> bool {
Expand Down
6 changes: 4 additions & 2 deletions src/auto_enum/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use self::{
context::{Context, VisitLastMode, VisitMode, DEFAULT_MARKER},
expr::child_expr,
};
use crate::utils::{block, expr_block, replace_expr};
use crate::utils::{block, expr_block, path_eq, replace_expr};

/// The attribute name.
const NAME: &str = "auto_enum";
Expand Down Expand Up @@ -173,7 +173,9 @@ fn expand_parent_item_fn(cx: &mut Context, item: &mut ItemFn) {
colon2_token: None,
args,
..
}) if args.len() == 2 && ty.ident == "Result" => {
}) if args.len() == 2
&& path_eq(path, &["std", "core"], &["result", "Result"]) =>
{
if let (
GenericArgument::Type(_),
GenericArgument::Type(Type::ImplTrait(_)),
Expand Down
18 changes: 18 additions & 0 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,24 @@ pub(crate) fn replace_block(this: &mut Block, f: impl FnOnce(Block) -> Expr) {
this.stmts = vec![Stmt::Expr(f(block(stmts)), None)];
}

pub(crate) fn path_eq(path: &syn::Path, expected_crates: &[&str], expected_path: &[&str]) -> bool {
if path.segments.len() == 1 && path.segments[0].ident == expected_path.last().unwrap() {
return true;
}
if path.segments.len() == expected_path.len() + 1 {
if !expected_crates.iter().any(|&c| path.segments[0].ident == c) {
return false;
}
for i in 1..path.segments.len() {
if path.segments[i].ident != expected_path[i - 1] {
return false;
}
}
return true;
}
false
}

// =================================================================================================
// extension traits

Expand Down
57 changes: 53 additions & 4 deletions tests/auto_enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,11 +133,21 @@ fn stable() {
assert_eq!(no_return3(i).sum::<i32>(), *x);
}
#[auto_enum(Iterator)]
fn no_return4(x: usize) -> impl Iterator<Item = i32> {
if x == 0 {
fn no_return4(i: usize) -> impl Iterator<Item = i32> {
if i == 0 {
1..8
} else if x > 3 {
} else if i > 6 {
panic!();
} else if i > 5 {
std::panic!("5");
} else if i > 4 {
core::panic!("4");
} else if i > 3 {
unreachable!("3");
} else if i > 2 {
std::unreachable!("2");
} else if i > 1 {
core::unreachable!();
} else {
(0..2).map(|x| x + 1)
}
Expand Down Expand Up @@ -257,13 +267,35 @@ fn stable() {
#[auto_enum(Iterator)]
let iter = match x {
0 => 2..8,
1 => None?,
2 => std::option::Option::None?,
3 => core::option::Option::None?,
_ => 2..=10,
};

Some(iter)
}
assert_eq!(return3(10).unwrap().sum::<i32>(), 54);

#[auto_enum]
fn return4(x: i32) -> Result<impl Iterator<Item = i32>, ()> {
if x < 0 {
return Err(());
}

#[auto_enum(Iterator)]
let iter = match x {
0 => 2..8,
1 => Err(())?,
2 => std::result::Result::Err(())?,
3 => core::result::Result::Err(())?,
_ => 2..=10,
};

Ok(iter)
}
assert_eq!(return4(10).unwrap().sum::<i32>(), 54);

#[auto_enum(Debug, Display)]
fn try_operator1(x: i32) -> Result<impl Iterator<Item = i32>, impl core::fmt::Debug> {
if x < 0 {
Expand All @@ -280,7 +312,9 @@ fn stable() {
assert_eq!(try_operator1(10).unwrap().sum::<i32>(), 54);

#[auto_enum(Debug)]
fn try_operator2(x: i32) -> Result<impl Iterator<Item = i32>, impl core::fmt::Debug> {
fn try_operator2(
x: i32,
) -> std::result::Result<impl Iterator<Item = i32>, impl core::fmt::Debug> {
if x < 0 {
Err(1_i32)?;
}
Expand All @@ -292,6 +326,21 @@ fn stable() {
}
assert_eq!(try_operator2(10).unwrap().sum::<i32>(), 54);

#[auto_enum(Debug)]
fn try_operator3(
x: i32,
) -> core::result::Result<impl Iterator<Item = i32>, impl core::fmt::Debug> {
if x < 0 {
Err(1_i32)?;
}

match x {
0 => Err(())?,
_ => Ok(2..=10),
}
}
assert_eq!(try_operator3(10).unwrap().sum::<i32>(), 54);

#[auto_enum]
fn closure() {
#[auto_enum(Iterator)]
Expand Down

0 comments on commit 28507ca

Please sign in to comment.