diff options
Diffstat (limited to 'compiler/rustc_hir_typeck/src/op.rs')
-rw-r--r-- | compiler/rustc_hir_typeck/src/op.rs | 69 |
1 files changed, 33 insertions, 36 deletions
diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index b12d84af4..78cea1f4d 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -12,14 +12,16 @@ use rustc_middle::ty::adjustment::{ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, }; use rustc_middle::ty::print::with_no_trimmed_paths; -use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitable}; +use rustc_middle::ty::{ + self, DefIdTree, IsSuggestable, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitable, +}; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::source_map::Spanned; use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt as _; -use rustc_trait_selection::traits::FulfillmentError; +use rustc_trait_selection::traits::{self, FulfillmentError}; use rustc_type_ir::sty::TyKind::*; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -48,8 +50,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self .lookup_op_method( lhs_deref_ty, - Some(rhs_ty), - Some(rhs), + Some((rhs, rhs_ty)), Op::Binary(op, IsAssign::Yes), expected, ) @@ -60,8 +61,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self .lookup_op_method( lhs_ty, - Some(rhs_ty), - Some(rhs), + Some((rhs, rhs_ty)), Op::Binary(op, IsAssign::Yes), expected, ) @@ -248,8 +248,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let result = self.lookup_op_method( lhs_ty, - Some(rhs_ty_var), - Some(rhs_expr), + Some((rhs_expr, rhs_ty_var)), Op::Binary(op, is_assign), expected, ); @@ -382,8 +381,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self .lookup_op_method( lhs_deref_ty, - Some(rhs_ty), - Some(rhs_expr), + Some((rhs_expr, rhs_ty)), Op::Binary(op, is_assign), expected, ) @@ -410,8 +408,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let is_compatible = |lhs_ty, rhs_ty| { self.lookup_op_method( lhs_ty, - Some(rhs_ty), - Some(rhs_expr), + Some((rhs_expr, rhs_ty)), Op::Binary(op, is_assign), expected, ) @@ -471,8 +468,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let errors = self .lookup_op_method( lhs_ty, - Some(rhs_ty), - Some(rhs_expr), + Some((rhs_expr, rhs_ty)), Op::Binary(op, is_assign), expected, ) @@ -492,6 +488,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(output_def_id) = output_def_id && let Some(trait_def_id) = trait_def_id && self.tcx.parent(output_def_id) == trait_def_id + && output_ty.is_suggestable(self.tcx, false) { Some(("Output", *output_ty)) } else { @@ -625,7 +622,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Expectation<'tcx>, ) -> Ty<'tcx> { assert!(op.is_by_value()); - match self.lookup_op_method(operand_ty, None, None, Op::Unary(op, ex.span), expected) { + match self.lookup_op_method(operand_ty, None, Op::Unary(op, ex.span), expected) { Ok(method) => { self.write_method_call(ex.hir_id, method); method.sig.output() @@ -660,7 +657,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - let sp = self.tcx.sess.source_map().start_point(ex.span); + let sp = self.tcx.sess.source_map().start_point(ex.span).with_parent(None); if let Some(sp) = self.tcx.sess.parse_sess.ambiguous_block_expr_parse.borrow().get(&sp) { @@ -712,8 +709,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn lookup_op_method( &self, lhs_ty: Ty<'tcx>, - other_ty: Option<Ty<'tcx>>, - other_ty_expr: Option<&'tcx hir::Expr<'tcx>>, + opt_rhs: Option<(&'tcx hir::Expr<'tcx>, Ty<'tcx>)>, op: Op, expected: Expectation<'tcx>, ) -> Result<MethodCallee<'tcx>, Vec<FulfillmentError<'tcx>>> { @@ -742,20 +738,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Op::Unary(..) => 0, }, ) { + self.tcx + .sess + .delay_span_bug(span, "operator didn't have the right number of generic args"); return Err(vec![]); } let opname = Ident::with_dummy_span(opname); + let input_types = + opt_rhs.as_ref().map(|(_, ty)| std::slice::from_ref(ty)).unwrap_or_default(); + let cause = self.cause( + span, + traits::BinOp { + rhs_span: opt_rhs.map(|(expr, _)| expr.span), + is_lit: opt_rhs + .map_or(false, |(expr, _)| matches!(expr.kind, hir::ExprKind::Lit(_))), + output_ty: expected.only_has_type(self), + }, + ); + let method = trait_did.and_then(|trait_did| { - self.lookup_op_method_in_trait( - span, - opname, - trait_did, - lhs_ty, - other_ty, - other_ty_expr, - expected, - ) + self.lookup_method_in_trait(cause.clone(), opname, trait_did, lhs_ty, Some(input_types)) }); match (method, trait_did) { @@ -766,14 +769,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } (None, None) => Err(vec![]), (None, Some(trait_did)) => { - let (obligation, _) = self.obligation_for_op_method( - span, - trait_did, - lhs_ty, - other_ty, - other_ty_expr, - expected, - ); + let (obligation, _) = + self.obligation_for_method(cause, trait_did, lhs_ty, Some(input_types)); Err(rustc_trait_selection::traits::fully_solve_obligation(self, obligation)) } } @@ -904,7 +901,7 @@ enum Op { } /// Dereferences a single level of immutable referencing. -fn deref_ty_if_possible<'tcx>(ty: Ty<'tcx>) -> Ty<'tcx> { +fn deref_ty_if_possible(ty: Ty<'_>) -> Ty<'_> { match ty.kind() { ty::Ref(_, ty, hir::Mutability::Not) => *ty, _ => ty, |