Skip to content

Commit d0746e8

Browse files
Simplify printing operator lang item paths in error message
1 parent 00c9d3d commit d0746e8

File tree

1 file changed

+109
-150
lines changed
  • compiler/rustc_typeck/src/check

1 file changed

+109
-150
lines changed

compiler/rustc_typeck/src/check/op.rs

Lines changed: 109 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use rustc_infer::traits::ObligationCauseCode;
1111
use rustc_middle::ty::adjustment::{
1212
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability,
1313
};
14+
use rustc_middle::ty::print::with_no_trimmed_paths;
1415
use rustc_middle::ty::{
1516
self, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor,
1617
};
@@ -313,7 +314,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
313314
// error types are considered "builtin"
314315
Err(_) if lhs_ty.references_error() || rhs_ty.references_error() => self.tcx.ty_error(),
315316
Err(errors) => {
316-
let (mut err, missing_trait, use_output) = match is_assign {
317+
let (_, item) = lang_item_for_op(self.tcx, Op::Binary(op, is_assign), op.span);
318+
let missing_trait =
319+
item.map(|def_id| with_no_trimmed_paths!(self.tcx.def_path_str(def_id)));
320+
let (mut err, use_output) = match is_assign {
317321
IsAssign::Yes => {
318322
let mut err = struct_span_err!(
319323
self.tcx.sess,
@@ -327,112 +331,60 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
327331
lhs_expr.span,
328332
format!("cannot use `{}=` on type `{}`", op.node.as_str(), lhs_ty),
329333
);
330-
let missing_trait = match op.node {
331-
hir::BinOpKind::Add => Some("std::ops::AddAssign"),
332-
hir::BinOpKind::Sub => Some("std::ops::SubAssign"),
333-
hir::BinOpKind::Mul => Some("std::ops::MulAssign"),
334-
hir::BinOpKind::Div => Some("std::ops::DivAssign"),
335-
hir::BinOpKind::Rem => Some("std::ops::RemAssign"),
336-
hir::BinOpKind::BitAnd => Some("std::ops::BitAndAssign"),
337-
hir::BinOpKind::BitXor => Some("std::ops::BitXorAssign"),
338-
hir::BinOpKind::BitOr => Some("std::ops::BitOrAssign"),
339-
hir::BinOpKind::Shl => Some("std::ops::ShlAssign"),
340-
hir::BinOpKind::Shr => Some("std::ops::ShrAssign"),
341-
_ => None,
342-
};
343334
self.note_unmet_impls_on_type(&mut err, errors);
344-
(err, missing_trait, false)
335+
(err, false)
345336
}
346337
IsAssign::No => {
347-
let (message, missing_trait, use_output) = match op.node {
348-
hir::BinOpKind::Add => (
349-
format!("cannot add `{rhs_ty}` to `{lhs_ty}`"),
350-
Some("std::ops::Add"),
351-
true,
352-
),
353-
hir::BinOpKind::Sub => (
354-
format!("cannot subtract `{rhs_ty}` from `{lhs_ty}`"),
355-
Some("std::ops::Sub"),
356-
true,
357-
),
358-
hir::BinOpKind::Mul => (
359-
format!("cannot multiply `{lhs_ty}` by `{rhs_ty}`"),
360-
Some("std::ops::Mul"),
361-
true,
362-
),
363-
hir::BinOpKind::Div => (
364-
format!("cannot divide `{lhs_ty}` by `{rhs_ty}`"),
365-
Some("std::ops::Div"),
366-
true,
367-
),
368-
hir::BinOpKind::Rem => (
369-
format!("cannot mod `{lhs_ty}` by `{rhs_ty}`"),
370-
Some("std::ops::Rem"),
371-
true,
372-
),
373-
hir::BinOpKind::BitAnd => (
374-
format!("no implementation for `{lhs_ty} & {rhs_ty}`"),
375-
Some("std::ops::BitAnd"),
376-
true,
377-
),
378-
hir::BinOpKind::BitXor => (
379-
format!("no implementation for `{lhs_ty} ^ {rhs_ty}`"),
380-
Some("std::ops::BitXor"),
381-
true,
382-
),
383-
hir::BinOpKind::BitOr => (
384-
format!("no implementation for `{lhs_ty} | {rhs_ty}`"),
385-
Some("std::ops::BitOr"),
386-
true,
387-
),
388-
hir::BinOpKind::Shl => (
389-
format!("no implementation for `{lhs_ty} << {rhs_ty}`"),
390-
Some("std::ops::Shl"),
391-
true,
392-
),
393-
hir::BinOpKind::Shr => (
394-
format!("no implementation for `{lhs_ty} >> {rhs_ty}`"),
395-
Some("std::ops::Shr"),
396-
true,
397-
),
398-
hir::BinOpKind::Eq | hir::BinOpKind::Ne => (
399-
format!(
400-
"binary operation `{}` cannot be applied to type `{}`",
401-
op.node.as_str(),
402-
lhs_ty
403-
),
404-
Some("std::cmp::PartialEq"),
405-
false,
406-
),
407-
hir::BinOpKind::Lt
408-
| hir::BinOpKind::Le
409-
| hir::BinOpKind::Gt
410-
| hir::BinOpKind::Ge => (
411-
format!(
412-
"binary operation `{}` cannot be applied to type `{}`",
413-
op.node.as_str(),
414-
lhs_ty
415-
),
416-
Some("std::cmp::PartialOrd"),
417-
false,
418-
),
419-
_ => (
420-
format!(
421-
"binary operation `{}` cannot be applied to type `{}`",
422-
op.node.as_str(),
423-
lhs_ty
424-
),
425-
None,
426-
false,
338+
let message = match op.node {
339+
hir::BinOpKind::Add => {
340+
format!("cannot add `{rhs_ty}` to `{lhs_ty}`")
341+
}
342+
hir::BinOpKind::Sub => {
343+
format!("cannot subtract `{rhs_ty}` from `{lhs_ty}`")
344+
}
345+
hir::BinOpKind::Mul => {
346+
format!("cannot multiply `{lhs_ty}` by `{rhs_ty}`")
347+
}
348+
hir::BinOpKind::Div => {
349+
format!("cannot divide `{lhs_ty}` by `{rhs_ty}`")
350+
}
351+
hir::BinOpKind::Rem => {
352+
format!("cannot mod `{lhs_ty}` by `{rhs_ty}`")
353+
}
354+
hir::BinOpKind::BitAnd => {
355+
format!("no implementation for `{lhs_ty} & {rhs_ty}`")
356+
}
357+
hir::BinOpKind::BitXor => {
358+
format!("no implementation for `{lhs_ty} ^ {rhs_ty}`")
359+
}
360+
hir::BinOpKind::BitOr => {
361+
format!("no implementation for `{lhs_ty} | {rhs_ty}`")
362+
}
363+
hir::BinOpKind::Shl => {
364+
format!("no implementation for `{lhs_ty} << {rhs_ty}`")
365+
}
366+
hir::BinOpKind::Shr => {
367+
format!("no implementation for `{lhs_ty} >> {rhs_ty}`")
368+
}
369+
_ => format!(
370+
"binary operation `{}` cannot be applied to type `{}`",
371+
op.node.as_str(),
372+
lhs_ty
427373
),
428374
};
375+
let use_output = item.map_or(false, |def_id| {
376+
self.tcx.associated_item_def_ids(def_id).iter().any(|item_def_id| {
377+
self.tcx.opt_associated_item(*item_def_id).unwrap().name
378+
== sym::Output
379+
})
380+
});
429381
let mut err = struct_span_err!(self.tcx.sess, op.span, E0369, "{message}");
430382
if !lhs_expr.span.eq(&rhs_expr.span) {
431383
err.span_label(lhs_expr.span, lhs_ty.to_string());
432384
err.span_label(rhs_expr.span, rhs_ty.to_string());
433385
}
434386
self.note_unmet_impls_on_type(&mut err, errors);
435-
(err, missing_trait, use_output)
387+
(err, use_output)
436388
}
437389
};
438390

@@ -773,64 +725,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
773725
op: Op,
774726
expected: Expectation<'tcx>,
775727
) -> Result<MethodCallee<'tcx>, Vec<FulfillmentError<'tcx>>> {
776-
let lang = self.tcx.lang_items();
777-
778728
let span = match op {
779729
Op::Binary(op, _) => op.span,
780730
Op::Unary(_, span) => span,
781731
};
782-
let (opname, trait_did) = if let Op::Binary(op, IsAssign::Yes) = op {
783-
match op.node {
784-
hir::BinOpKind::Add => (sym::add_assign, lang.add_assign_trait()),
785-
hir::BinOpKind::Sub => (sym::sub_assign, lang.sub_assign_trait()),
786-
hir::BinOpKind::Mul => (sym::mul_assign, lang.mul_assign_trait()),
787-
hir::BinOpKind::Div => (sym::div_assign, lang.div_assign_trait()),
788-
hir::BinOpKind::Rem => (sym::rem_assign, lang.rem_assign_trait()),
789-
hir::BinOpKind::BitXor => (sym::bitxor_assign, lang.bitxor_assign_trait()),
790-
hir::BinOpKind::BitAnd => (sym::bitand_assign, lang.bitand_assign_trait()),
791-
hir::BinOpKind::BitOr => (sym::bitor_assign, lang.bitor_assign_trait()),
792-
hir::BinOpKind::Shl => (sym::shl_assign, lang.shl_assign_trait()),
793-
hir::BinOpKind::Shr => (sym::shr_assign, lang.shr_assign_trait()),
794-
hir::BinOpKind::Lt
795-
| hir::BinOpKind::Le
796-
| hir::BinOpKind::Ge
797-
| hir::BinOpKind::Gt
798-
| hir::BinOpKind::Eq
799-
| hir::BinOpKind::Ne
800-
| hir::BinOpKind::And
801-
| hir::BinOpKind::Or => {
802-
span_bug!(span, "impossible assignment operation: {}=", op.node.as_str())
803-
}
804-
}
805-
} else if let Op::Binary(op, IsAssign::No) = op {
806-
match op.node {
807-
hir::BinOpKind::Add => (sym::add, lang.add_trait()),
808-
hir::BinOpKind::Sub => (sym::sub, lang.sub_trait()),
809-
hir::BinOpKind::Mul => (sym::mul, lang.mul_trait()),
810-
hir::BinOpKind::Div => (sym::div, lang.div_trait()),
811-
hir::BinOpKind::Rem => (sym::rem, lang.rem_trait()),
812-
hir::BinOpKind::BitXor => (sym::bitxor, lang.bitxor_trait()),
813-
hir::BinOpKind::BitAnd => (sym::bitand, lang.bitand_trait()),
814-
hir::BinOpKind::BitOr => (sym::bitor, lang.bitor_trait()),
815-
hir::BinOpKind::Shl => (sym::shl, lang.shl_trait()),
816-
hir::BinOpKind::Shr => (sym::shr, lang.shr_trait()),
817-
hir::BinOpKind::Lt => (sym::lt, lang.partial_ord_trait()),
818-
hir::BinOpKind::Le => (sym::le, lang.partial_ord_trait()),
819-
hir::BinOpKind::Ge => (sym::ge, lang.partial_ord_trait()),
820-
hir::BinOpKind::Gt => (sym::gt, lang.partial_ord_trait()),
821-
hir::BinOpKind::Eq => (sym::eq, lang.eq_trait()),
822-
hir::BinOpKind::Ne => (sym::ne, lang.eq_trait()),
823-
hir::BinOpKind::And | hir::BinOpKind::Or => {
824-
span_bug!(span, "&& and || are not overloadable")
825-
}
826-
}
827-
} else if let Op::Unary(hir::UnOp::Not, _) = op {
828-
(sym::not, lang.not_trait())
829-
} else if let Op::Unary(hir::UnOp::Neg, _) = op {
830-
(sym::neg, lang.neg_trait())
831-
} else {
832-
bug!("lookup_op_method: op not supported: {:?}", op)
833-
};
732+
let (opname, trait_did) = lang_item_for_op(self.tcx, op, span);
834733

835734
debug!(
836735
"lookup_op_method(lhs_ty={:?}, op={:?}, opname={:?}, trait_did={:?})",
@@ -891,6 +790,66 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
891790
}
892791
}
893792

793+
fn lang_item_for_op(
794+
tcx: TyCtxt<'_>,
795+
op: Op,
796+
span: Span,
797+
) -> (rustc_span::Symbol, Option<hir::def_id::DefId>) {
798+
let lang = tcx.lang_items();
799+
if let Op::Binary(op, IsAssign::Yes) = op {
800+
match op.node {
801+
hir::BinOpKind::Add => (sym::add_assign, lang.add_assign_trait()),
802+
hir::BinOpKind::Sub => (sym::sub_assign, lang.sub_assign_trait()),
803+
hir::BinOpKind::Mul => (sym::mul_assign, lang.mul_assign_trait()),
804+
hir::BinOpKind::Div => (sym::div_assign, lang.div_assign_trait()),
805+
hir::BinOpKind::Rem => (sym::rem_assign, lang.rem_assign_trait()),
806+
hir::BinOpKind::BitXor => (sym::bitxor_assign, lang.bitxor_assign_trait()),
807+
hir::BinOpKind::BitAnd => (sym::bitand_assign, lang.bitand_assign_trait()),
808+
hir::BinOpKind::BitOr => (sym::bitor_assign, lang.bitor_assign_trait()),
809+
hir::BinOpKind::Shl => (sym::shl_assign, lang.shl_assign_trait()),
810+
hir::BinOpKind::Shr => (sym::shr_assign, lang.shr_assign_trait()),
811+
hir::BinOpKind::Lt
812+
| hir::BinOpKind::Le
813+
| hir::BinOpKind::Ge
814+
| hir::BinOpKind::Gt
815+
| hir::BinOpKind::Eq
816+
| hir::BinOpKind::Ne
817+
| hir::BinOpKind::And
818+
| hir::BinOpKind::Or => {
819+
span_bug!(span, "impossible assignment operation: {}=", op.node.as_str())
820+
}
821+
}
822+
} else if let Op::Binary(op, IsAssign::No) = op {
823+
match op.node {
824+
hir::BinOpKind::Add => (sym::add, lang.add_trait()),
825+
hir::BinOpKind::Sub => (sym::sub, lang.sub_trait()),
826+
hir::BinOpKind::Mul => (sym::mul, lang.mul_trait()),
827+
hir::BinOpKind::Div => (sym::div, lang.div_trait()),
828+
hir::BinOpKind::Rem => (sym::rem, lang.rem_trait()),
829+
hir::BinOpKind::BitXor => (sym::bitxor, lang.bitxor_trait()),
830+
hir::BinOpKind::BitAnd => (sym::bitand, lang.bitand_trait()),
831+
hir::BinOpKind::BitOr => (sym::bitor, lang.bitor_trait()),
832+
hir::BinOpKind::Shl => (sym::shl, lang.shl_trait()),
833+
hir::BinOpKind::Shr => (sym::shr, lang.shr_trait()),
834+
hir::BinOpKind::Lt => (sym::lt, lang.partial_ord_trait()),
835+
hir::BinOpKind::Le => (sym::le, lang.partial_ord_trait()),
836+
hir::BinOpKind::Ge => (sym::ge, lang.partial_ord_trait()),
837+
hir::BinOpKind::Gt => (sym::gt, lang.partial_ord_trait()),
838+
hir::BinOpKind::Eq => (sym::eq, lang.eq_trait()),
839+
hir::BinOpKind::Ne => (sym::ne, lang.eq_trait()),
840+
hir::BinOpKind::And | hir::BinOpKind::Or => {
841+
span_bug!(span, "&& and || are not overloadable")
842+
}
843+
}
844+
} else if let Op::Unary(hir::UnOp::Not, _) = op {
845+
(sym::not, lang.not_trait())
846+
} else if let Op::Unary(hir::UnOp::Neg, _) = op {
847+
(sym::neg, lang.neg_trait())
848+
} else {
849+
bug!("lookup_op_method: op not supported: {:?}", op)
850+
}
851+
}
852+
894853
// Binary operator categories. These categories summarize the behavior
895854
// with respect to the builtin operations supported.
896855
enum BinOpCategory {

0 commit comments

Comments
 (0)