Inline create_maybe_get_coercion_reason macro
This commit is contained in:
parent
4e21ef2a4e
commit
8746b79a38
2 changed files with 50 additions and 52 deletions
|
@ -13,41 +13,6 @@ use rustc_trait_selection::traits::{
|
||||||
StatementAsExpression,
|
StatementAsExpression,
|
||||||
};
|
};
|
||||||
|
|
||||||
macro_rules! create_maybe_get_coercion_reason {
|
|
||||||
($fn_name:ident, $node:expr) => {
|
|
||||||
pub(crate) fn $fn_name(&self, hir_id: hir::HirId, sp: Span) -> Option<(Span, String)> {
|
|
||||||
let node = $node(self.tcx.hir(), hir_id);
|
|
||||||
if let hir::Node::Block(block) = node {
|
|
||||||
// check that the body's parent is an fn
|
|
||||||
let parent = self.tcx.hir().get(
|
|
||||||
self.tcx.hir().get_parent_node(self.tcx.hir().get_parent_node(block.hir_id)),
|
|
||||||
);
|
|
||||||
if let (
|
|
||||||
Some(expr),
|
|
||||||
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(..), .. }),
|
|
||||||
) = (&block.expr, parent)
|
|
||||||
{
|
|
||||||
// check that the `if` expr without `else` is the fn body's expr
|
|
||||||
if expr.span == sp {
|
|
||||||
return self.get_fn_decl(hir_id).and_then(|(fn_decl, _)| {
|
|
||||||
let span = fn_decl.output.span();
|
|
||||||
let snippet = self.tcx.sess.source_map().span_to_snippet(span).ok()?;
|
|
||||||
Some((
|
|
||||||
span,
|
|
||||||
format!("expected `{}` because of this return type", snippet),
|
|
||||||
))
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let hir::Node::Local(hir::Local { ty: Some(_), pat, .. }) = node {
|
|
||||||
return Some((pat.span, "expected because of this assignment".to_string()));
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
pub fn check_match(
|
pub fn check_match(
|
||||||
&self,
|
&self,
|
||||||
|
@ -154,7 +119,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
expr.span,
|
expr.span,
|
||||||
&arms[0].body,
|
&arms[0].body,
|
||||||
&mut coercion,
|
&mut coercion,
|
||||||
|hir_id, span| self.maybe_get_coercion_reason(hir_id, span),
|
|hir_id, span| self.coercion_reason_match(hir_id, span),
|
||||||
) {
|
) {
|
||||||
tcx.ty_error()
|
tcx.ty_error()
|
||||||
} else {
|
} else {
|
||||||
|
@ -373,23 +338,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
error
|
error
|
||||||
}
|
}
|
||||||
|
|
||||||
create_maybe_get_coercion_reason!(
|
pub(crate) fn coercion_reason_if(
|
||||||
maybe_get_coercion_reason,
|
&self,
|
||||||
|hir: rustc_middle::hir::map::Map<'a>, id| {
|
hir_id: hir::HirId,
|
||||||
let arm_id = hir.get_parent_node(id);
|
span: Span,
|
||||||
let match_id = hir.get_parent_node(arm_id);
|
) -> Option<(Span, String)> {
|
||||||
let containing_id = hir.get_parent_node(match_id);
|
self.coercion_reason_inner(hir_id, span, 1)
|
||||||
hir.get(containing_id)
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
|
||||||
create_maybe_get_coercion_reason!(
|
pub(crate) fn coercion_reason_match(
|
||||||
maybe_get_coercion_reason_if,
|
&self,
|
||||||
|hir: rustc_middle::hir::map::Map<'a>, id| {
|
hir_id: hir::HirId,
|
||||||
let rslt = hir.get_parent_node(hir.get_parent_node(id));
|
span: Span,
|
||||||
hir.get(rslt)
|
) -> Option<(Span, String)> {
|
||||||
|
self.coercion_reason_inner(hir_id, span, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn coercion_reason_inner(
|
||||||
|
&self,
|
||||||
|
hir_id: hir::HirId,
|
||||||
|
span: Span,
|
||||||
|
parent_index: usize,
|
||||||
|
) -> Option<(Span, String)> {
|
||||||
|
let hir = self.tcx.hir();
|
||||||
|
let mut parent_iter = hir.parent_iter(hir_id);
|
||||||
|
let (_, node) = parent_iter.nth(parent_index)?;
|
||||||
|
match node {
|
||||||
|
hir::Node::Block(block) => {
|
||||||
|
let expr = block.expr?;
|
||||||
|
// check that the body's parent is an fn
|
||||||
|
let (_, parent) = parent_iter.nth(1)?;
|
||||||
|
if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(..), .. }) = parent {
|
||||||
|
// check that the `if` expr without `else` is the fn body's expr
|
||||||
|
if expr.span == span {
|
||||||
|
let (fn_decl, _) = self.get_fn_decl(hir_id)?;
|
||||||
|
let span = fn_decl.output.span();
|
||||||
|
let snippet = self.tcx.sess.source_map().span_to_snippet(span).ok()?;
|
||||||
|
return Some((
|
||||||
|
span,
|
||||||
|
format!("expected `{}` because of this return type", snippet),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
hir::Node::Local(hir::Local { ty: Some(_), pat, .. }) => {
|
||||||
|
Some((pat.span, "expected because of this assignment".to_string()))
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
|
||||||
pub(crate) fn if_cause(
|
pub(crate) fn if_cause(
|
||||||
&self,
|
&self,
|
||||||
|
|
|
@ -838,7 +838,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
self.diverges.set(cond_diverges | then_diverges & else_diverges);
|
self.diverges.set(cond_diverges | then_diverges & else_diverges);
|
||||||
} else {
|
} else {
|
||||||
self.if_fallback_coercion(sp, then_expr, &mut coerce, |hir_id, span| {
|
self.if_fallback_coercion(sp, then_expr, &mut coerce, |hir_id, span| {
|
||||||
self.maybe_get_coercion_reason_if(hir_id, span)
|
self.coercion_reason_if(hir_id, span)
|
||||||
});
|
});
|
||||||
|
|
||||||
// If the condition is false we can't diverge.
|
// If the condition is false we can't diverge.
|
||||||
|
|
Loading…
Reference in a new issue