1
Fork 0

Rollup merge of #70725 - Centril:nix-unwraps, r=estebank

Avoid `.unwrap()`s on `.span_to_snippet(...)`s

First commit fixes https://github.com/rust-lang/rust/issues/70724 and the others fix similar issues found by grepping.

r? @estebank
This commit is contained in:
Dylan DPC 2020-04-03 13:31:25 +02:00 committed by GitHub
commit b91c376e4a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 116 additions and 75 deletions

View file

@ -165,9 +165,9 @@ impl<'a> Parser<'a> {
// Rewind to before attempting to parse the type and continue parsing. // Rewind to before attempting to parse the type and continue parsing.
let parser_snapshot_after_type = self.clone(); let parser_snapshot_after_type = self.clone();
mem::replace(self, parser_snapshot_before_type); mem::replace(self, parser_snapshot_before_type);
if let Ok(snip) = self.span_to_snippet(pat.span) {
let snippet = self.span_to_snippet(pat.span).unwrap(); err.span_label(pat.span, format!("while parsing the type for `{}`", snip));
err.span_label(pat.span, format!("while parsing the type for `{}`", snippet)); }
(Some((parser_snapshot_after_type, colon_sp, err)), None) (Some((parser_snapshot_after_type, colon_sp, err)), None)
} }
} }

View file

@ -65,7 +65,7 @@ pub trait InferCtxtExt<'tcx> {
/// returns a span and `ArgKind` information that describes the /// returns a span and `ArgKind` information that describes the
/// arguments it expects. This can be supplied to /// arguments it expects. This can be supplied to
/// `report_arg_count_mismatch`. /// `report_arg_count_mismatch`.
fn get_fn_like_arguments(&self, node: Node<'_>) -> (Span, Vec<ArgKind>); fn get_fn_like_arguments(&self, node: Node<'_>) -> Option<(Span, Vec<ArgKind>)>;
/// Reports an error when the number of arguments needed by a /// Reports an error when the number of arguments needed by a
/// trait match doesn't match the number that the expression /// trait match doesn't match the number that the expression
@ -611,10 +611,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
) )
} else { } else {
let (closure_span, found) = found_did let (closure_span, found) = found_did
.and_then(|did| self.tcx.hir().get_if_local(did)) .and_then(|did| {
.map(|node| { let node = self.tcx.hir().get_if_local(did)?;
let (found_span, found) = self.get_fn_like_arguments(node); let (found_span, found) = self.get_fn_like_arguments(node)?;
(Some(found_span), found) Some((Some(found_span), found))
}) })
.unwrap_or((found_span, found)); .unwrap_or((found_span, found));
@ -672,43 +672,38 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
/// returns a span and `ArgKind` information that describes the /// returns a span and `ArgKind` information that describes the
/// arguments it expects. This can be supplied to /// arguments it expects. This can be supplied to
/// `report_arg_count_mismatch`. /// `report_arg_count_mismatch`.
fn get_fn_like_arguments(&self, node: Node<'_>) -> (Span, Vec<ArgKind>) { fn get_fn_like_arguments(&self, node: Node<'_>) -> Option<(Span, Vec<ArgKind>)> {
match node { let sm = self.tcx.sess.source_map();
let hir = self.tcx.hir();
Some(match node {
Node::Expr(&hir::Expr { Node::Expr(&hir::Expr {
kind: hir::ExprKind::Closure(_, ref _decl, id, span, _), kind: hir::ExprKind::Closure(_, ref _decl, id, span, _),
.. ..
}) => ( }) => (
self.tcx.sess.source_map().guess_head_span(span), sm.guess_head_span(span),
self.tcx hir.body(id)
.hir()
.body(id)
.params .params
.iter() .iter()
.map(|arg| { .map(|arg| {
if let hir::Pat { kind: hir::PatKind::Tuple(ref args, _), span, .. } = if let hir::Pat { kind: hir::PatKind::Tuple(ref args, _), span, .. } =
*arg.pat *arg.pat
{ {
ArgKind::Tuple( Some(ArgKind::Tuple(
Some(span), Some(span),
args.iter() args.iter()
.map(|pat| { .map(|pat| {
let snippet = self sm.span_to_snippet(pat.span)
.tcx .ok()
.sess .map(|snippet| (snippet, "_".to_owned()))
.source_map()
.span_to_snippet(pat.span)
.unwrap();
(snippet, "_".to_owned())
}) })
.collect::<Vec<_>>(), .collect::<Option<Vec<_>>>()?,
) ))
} else { } else {
let name = let name = sm.span_to_snippet(arg.pat.span).ok()?;
self.tcx.sess.source_map().span_to_snippet(arg.pat.span).unwrap(); Some(ArgKind::Arg(name, "_".to_owned()))
ArgKind::Arg(name, "_".to_owned())
} }
}) })
.collect::<Vec<ArgKind>>(), .collect::<Option<Vec<ArgKind>>>()?,
), ),
Node::Item(&hir::Item { span, kind: hir::ItemKind::Fn(ref sig, ..), .. }) Node::Item(&hir::Item { span, kind: hir::ItemKind::Fn(ref sig, ..), .. })
| Node::ImplItem(&hir::ImplItem { | Node::ImplItem(&hir::ImplItem {
@ -721,7 +716,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
kind: hir::TraitItemKind::Fn(ref sig, _), kind: hir::TraitItemKind::Fn(ref sig, _),
.. ..
}) => ( }) => (
self.tcx.sess.source_map().guess_head_span(span), sm.guess_head_span(span),
sig.decl sig.decl
.inputs .inputs
.iter() .iter()
@ -735,16 +730,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
.collect::<Vec<ArgKind>>(), .collect::<Vec<ArgKind>>(),
), ),
Node::Ctor(ref variant_data) => { Node::Ctor(ref variant_data) => {
let span = variant_data let span = variant_data.ctor_hir_id().map(|id| hir.span(id)).unwrap_or(DUMMY_SP);
.ctor_hir_id() let span = sm.guess_head_span(span);
.map(|hir_id| self.tcx.hir().span(hir_id))
.unwrap_or(DUMMY_SP);
let span = self.tcx.sess.source_map().guess_head_span(span);
(span, vec![ArgKind::empty(); variant_data.fields().len()]) (span, vec![ArgKind::empty(); variant_data.fields().len()])
} }
_ => panic!("non-FnLike node found: {:?}", node), _ => panic!("non-FnLike node found: {:?}", node),
} })
} }
/// Reports an error when the number of arguments needed by a /// Reports an error when the number of arguments needed by a

View file

@ -732,12 +732,13 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
true true
}; };
let sm = self.tcx.sess.source_map();
let (snippet, last_ty) = let (snippet, last_ty) =
if let (true, hir::TyKind::TraitObject(..), Ok(snippet), true, Some(last_ty)) = ( if let (true, hir::TyKind::TraitObject(..), Ok(snippet), true, Some(last_ty)) = (
// Verify that we're dealing with a return `dyn Trait` // Verify that we're dealing with a return `dyn Trait`
ret_ty.span.overlaps(span), ret_ty.span.overlaps(span),
&ret_ty.kind, &ret_ty.kind,
self.tcx.sess.source_map().span_to_snippet(ret_ty.span), sm.span_to_snippet(ret_ty.span),
// If any of the return types does not conform to the trait, then we can't // If any of the return types does not conform to the trait, then we can't
// suggest `impl Trait` nor trait objects, it is a type mismatch error. // suggest `impl Trait` nor trait objects, it is a type mismatch error.
all_returns_conform_to_trait, all_returns_conform_to_trait,
@ -775,19 +776,15 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
if is_object_safe { if is_object_safe {
// Suggest `-> Box<dyn Trait>` and `Box::new(returned_value)`. // Suggest `-> Box<dyn Trait>` and `Box::new(returned_value)`.
// Get all the return values and collect their span and suggestion. // Get all the return values and collect their span and suggestion.
let mut suggestions = visitor if let Some(mut suggestions) = visitor
.returns .returns
.iter() .iter()
.map(|expr| { .map(|expr| {
( let snip = sm.span_to_snippet(expr.span).ok()?;
expr.span, Some((expr.span, format!("Box::new({})", snip)))
format!(
"Box::new({})",
self.tcx.sess.source_map().span_to_snippet(expr.span).unwrap()
),
)
}) })
.collect::<Vec<_>>(); .collect::<Option<Vec<_>>>()
{
// Add the suggestion for the return type. // Add the suggestion for the return type.
suggestions.push((ret_ty.span, format!("Box<dyn {}>", trait_obj))); suggestions.push((ret_ty.span, format!("Box<dyn {}>", trait_obj)));
err.multipart_suggestion( err.multipart_suggestion(
@ -795,6 +792,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
suggestions, suggestions,
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,
); );
}
} else { } else {
// This is currently not possible to trigger because E0038 takes precedence, but // This is currently not possible to trigger because E0038 takes precedence, but
// leave it in for completeness in case anything changes in an earlier stage. // leave it in for completeness in case anything changes in an earlier stage.

View file

@ -432,18 +432,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
body: &hir::Body<'_>, body: &hir::Body<'_>,
expected_sig: ExpectedSig<'tcx>, expected_sig: ExpectedSig<'tcx>,
) -> ClosureSignatures<'tcx> { ) -> ClosureSignatures<'tcx> {
let expr_map_node = self.tcx.hir().get_if_local(expr_def_id).unwrap(); let hir = self.tcx.hir();
let expr_map_node = hir.get_if_local(expr_def_id).unwrap();
let expected_args: Vec<_> = expected_sig let expected_args: Vec<_> = expected_sig
.sig .sig
.inputs() .inputs()
.iter() .iter()
.map(|ty| ArgKind::from_expected_ty(ty, None)) .map(|ty| ArgKind::from_expected_ty(ty, None))
.collect(); .collect();
let (closure_span, found_args) = self.get_fn_like_arguments(expr_map_node); let (closure_span, found_args) = match self.get_fn_like_arguments(expr_map_node) {
let expected_span = expected_sig.cause_span.unwrap_or(closure_span); Some((sp, args)) => (Some(sp), args),
None => (None, Vec::new()),
};
let expected_span =
expected_sig.cause_span.unwrap_or_else(|| hir.span_if_local(expr_def_id).unwrap());
self.report_arg_count_mismatch( self.report_arg_count_mismatch(
expected_span, expected_span,
Some(closure_span), closure_span,
expected_args, expected_args,
found_args, found_args,
true, true,

View file

@ -481,7 +481,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
/// If one of the types is an uncalled function and calling it would yield the other type, /// If one of the types is an uncalled function and calling it would yield the other type,
/// suggest calling the function. Returns whether a suggestion was given. /// suggest calling the function. Returns `true` if suggestion would apply (even if not given).
fn add_type_neq_err_label( fn add_type_neq_err_label(
&self, &self,
err: &mut rustc_errors::DiagnosticBuilder<'_>, err: &mut rustc_errors::DiagnosticBuilder<'_>,
@ -514,16 +514,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.lookup_op_method(fn_sig.output(), &[other_ty], Op::Binary(op, is_assign)) .lookup_op_method(fn_sig.output(), &[other_ty], Op::Binary(op, is_assign))
.is_ok() .is_ok()
{ {
if let Ok(snippet) = source_map.span_to_snippet(span) {
let (variable_snippet, applicability) = if !fn_sig.inputs().is_empty() { let (variable_snippet, applicability) = if !fn_sig.inputs().is_empty() {
( (format!("{}( /* arguments */ )", snippet), Applicability::HasPlaceholders)
format!("{}( /* arguments */ )", source_map.span_to_snippet(span).unwrap()),
Applicability::HasPlaceholders,
)
} else { } else {
( (format!("{}()", snippet), Applicability::MaybeIncorrect)
format!("{}()", source_map.span_to_snippet(span).unwrap()),
Applicability::MaybeIncorrect,
)
}; };
err.span_suggestion( err.span_suggestion(
@ -532,6 +527,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
variable_snippet, variable_snippet,
applicability, applicability,
); );
}
return true; return true;
} }
} }

View file

@ -0,0 +1,10 @@
fn a() -> i32 {
3
}
pub fn main() {
assert_eq!(a, 0);
//~^ ERROR binary operation `==` cannot
//~| ERROR mismatched types
//~| ERROR doesn't implement
}

View file

@ -0,0 +1,41 @@
error[E0369]: binary operation `==` cannot be applied to type `fn() -> i32 {a}`
--> $DIR/issue-70724-add_type_neq_err_label-unwrap.rs:6:5
|
LL | assert_eq!(a, 0);
| ^^^^^^^^^^^^^^^^^
| |
| fn() -> i32 {a}
| {integer}
| help: you might have forgotten to call this function: `*left_val()`
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0308]: mismatched types
--> $DIR/issue-70724-add_type_neq_err_label-unwrap.rs:6:5
|
LL | assert_eq!(a, 0);
| ^^^^^^^^^^^^^^^^^ expected fn item, found integer
|
= note: expected fn item `fn() -> i32 {a}`
found type `i32`
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: `fn() -> i32 {a}` doesn't implement `std::fmt::Debug`
--> $DIR/issue-70724-add_type_neq_err_label-unwrap.rs:6:5
|
LL | fn a() -> i32 {
| - consider calling this function
...
LL | assert_eq!(a, 0);
| ^^^^^^^^^^^^^^^^^ `fn() -> i32 {a}` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`
|
= help: the trait `std::fmt::Debug` is not implemented for `fn() -> i32 {a}`
= help: use parentheses to call the function: `a()`
= note: required because of the requirements on the impl of `std::fmt::Debug` for `&fn() -> i32 {a}`
= note: required by `std::fmt::Debug::fmt`
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0277, E0308, E0369.
For more information about an error, try `rustc --explain E0277`.