Skip to content

Commit 8bf7ec7

Browse files
Deduplicate more op-flavored methods
1 parent 43b2486 commit 8bf7ec7

File tree

4 files changed

+37
-84
lines changed

4 files changed

+37
-84
lines changed

compiler/rustc_hir_typeck/src/callee.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
241241
});
242242

243243
if let Some(ok) = self.lookup_method_in_trait(
244-
call_expr.span,
244+
self.misc(call_expr.span),
245245
method_name,
246246
trait_def_id,
247247
adjusted_ty,

compiler/rustc_hir_typeck/src/method/mod.rs

+12-77
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ pub use self::suggest::SelfSource;
1111
pub use self::MethodError::*;
1212

1313
use crate::errors::OpMethodGenericParams;
14-
use crate::{Expectation, FnCtxt};
14+
use crate::FnCtxt;
1515
use rustc_data_structures::sync::Lrc;
1616
use rustc_errors::{Applicability, Diagnostic};
1717
use rustc_hir as hir;
@@ -264,7 +264,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
264264

265265
pub(super) fn obligation_for_method(
266266
&self,
267-
span: Span,
267+
cause: ObligationCause<'tcx>,
268268
trait_def_id: DefId,
269269
self_ty: Ty<'tcx>,
270270
opt_input_types: Option<&[Ty<'tcx>]>,
@@ -282,70 +282,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
282282
}
283283
}
284284
}
285-
self.var_for_def(span, param)
286-
});
287-
288-
let trait_ref = self.tcx.mk_trait_ref(trait_def_id, substs);
289-
290-
// Construct an obligation
291-
let poly_trait_ref = ty::Binder::dummy(trait_ref);
292-
(
293-
traits::Obligation::misc(
294-
self.tcx,
295-
span,
296-
self.body_id,
297-
self.param_env,
298-
poly_trait_ref.without_const(),
299-
),
300-
substs,
301-
)
302-
}
303-
304-
pub(super) fn obligation_for_op_method(
305-
&self,
306-
span: Span,
307-
trait_def_id: DefId,
308-
self_ty: Ty<'tcx>,
309-
opt_rhs: Option<(&'tcx hir::Expr<'tcx>, Ty<'tcx>)>,
310-
expected: Expectation<'tcx>,
311-
) -> (traits::Obligation<'tcx, ty::Predicate<'tcx>>, &'tcx ty::List<ty::subst::GenericArg<'tcx>>)
312-
{
313-
// Construct a trait-reference `self_ty : Trait<input_tys>`
314-
let substs = InternalSubsts::for_item(self.tcx, trait_def_id, |param, _| {
315-
match param.kind {
316-
GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => {}
317-
GenericParamDefKind::Type { .. } => {
318-
if param.index == 0 {
319-
return self_ty.into();
320-
} else if let Some((_, input_type)) = opt_rhs {
321-
return input_type.into();
322-
}
323-
}
324-
}
325-
self.var_for_def(span, param)
285+
self.var_for_def(cause.span, param)
326286
});
327287

328288
let trait_ref = self.tcx.mk_trait_ref(trait_def_id, substs);
329289

330290
// Construct an obligation
331291
let poly_trait_ref = ty::Binder::dummy(trait_ref);
332-
let output_ty = expected.only_has_type(self).and_then(|ty| (!ty.needs_infer()).then(|| ty));
333-
334292
(
335293
traits::Obligation::new(
336294
self.tcx,
337-
traits::ObligationCause::new(
338-
span,
339-
self.body_id,
340-
traits::BinOp {
341-
rhs_span: opt_rhs.map(|(expr, _)| expr.span),
342-
is_lit: opt_rhs
343-
.map_or(false, |(expr, _)| matches!(expr.kind, hir::ExprKind::Lit(_))),
344-
output_ty,
345-
},
346-
),
295+
cause,
347296
self.param_env,
348-
poly_trait_ref,
297+
poly_trait_ref.without_const(),
349298
),
350299
substs,
351300
)
@@ -356,40 +305,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
356305
/// In particular, it doesn't really do any probing: it simply constructs
357306
/// an obligation for a particular trait with the given self type and checks
358307
/// whether that trait is implemented.
359-
#[instrument(level = "debug", skip(self, span))]
308+
#[instrument(level = "debug", skip(self))]
360309
pub(super) fn lookup_method_in_trait(
361310
&self,
362-
span: Span,
311+
cause: ObligationCause<'tcx>,
363312
m_name: Ident,
364313
trait_def_id: DefId,
365314
self_ty: Ty<'tcx>,
366315
opt_input_types: Option<&[Ty<'tcx>]>,
367316
) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
368317
let (obligation, substs) =
369-
self.obligation_for_method(span, trait_def_id, self_ty, opt_input_types);
370-
self.construct_obligation_for_trait(span, m_name, trait_def_id, obligation, substs)
371-
}
372-
373-
pub(super) fn lookup_op_method_in_trait(
374-
&self,
375-
span: Span,
376-
m_name: Ident,
377-
trait_def_id: DefId,
378-
self_ty: Ty<'tcx>,
379-
opt_rhs: Option<(&'tcx hir::Expr<'tcx>, Ty<'tcx>)>,
380-
expected: Expectation<'tcx>,
381-
) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
382-
let (obligation, substs) =
383-
self.obligation_for_op_method(span, trait_def_id, self_ty, opt_rhs, expected);
384-
self.construct_obligation_for_trait(span, m_name, trait_def_id, obligation, substs)
318+
self.obligation_for_method(cause, trait_def_id, self_ty, opt_input_types);
319+
self.construct_obligation_for_trait(m_name, trait_def_id, obligation, substs)
385320
}
386321

387322
// FIXME(#18741): it seems likely that we can consolidate some of this
388323
// code with the other method-lookup code. In particular, the second half
389324
// of this method is basically the same as confirmation.
390325
fn construct_obligation_for_trait(
391326
&self,
392-
span: Span,
393327
m_name: Ident,
394328
trait_def_id: DefId,
395329
obligation: traits::PredicateObligation<'tcx>,
@@ -409,7 +343,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
409343
let tcx = self.tcx;
410344
let Some(method_item) = self.associated_value(trait_def_id, m_name) else {
411345
tcx.sess.delay_span_bug(
412-
span,
346+
obligation.cause.span,
413347
"operator trait does not have corresponding operator method",
414348
);
415349
return None;
@@ -435,7 +369,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
435369
// with bound regions.
436370
let fn_sig = tcx.bound_fn_sig(def_id);
437371
let fn_sig = fn_sig.subst(self.tcx, substs);
438-
let fn_sig = self.replace_bound_vars_with_fresh_vars(span, infer::FnCall, fn_sig);
372+
let fn_sig =
373+
self.replace_bound_vars_with_fresh_vars(obligation.cause.span, infer::FnCall, fn_sig);
439374

440375
let InferOk { value, obligations: o } =
441376
self.at(&obligation.cause, self.param_env).normalize(fn_sig);

compiler/rustc_hir_typeck/src/op.rs

+22-4
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,16 @@ use rustc_middle::ty::adjustment::{
1212
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability,
1313
};
1414
use rustc_middle::ty::print::with_no_trimmed_paths;
15-
use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitable};
15+
use rustc_middle::ty::{
16+
self, DefIdTree, IsSuggestable, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitable,
17+
};
1618
use rustc_session::errors::ExprParenthesesNeeded;
1719
use rustc_span::source_map::Spanned;
1820
use rustc_span::symbol::{sym, Ident};
1921
use rustc_span::Span;
2022
use rustc_trait_selection::infer::InferCtxtExt;
2123
use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt as _;
22-
use rustc_trait_selection::traits::FulfillmentError;
24+
use rustc_trait_selection::traits::{self, FulfillmentError};
2325
use rustc_type_ir::sty::TyKind::*;
2426

2527
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -486,6 +488,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
486488
if let Some(output_def_id) = output_def_id
487489
&& let Some(trait_def_id) = trait_def_id
488490
&& self.tcx.parent(output_def_id) == trait_def_id
491+
&& output_ty.is_suggestable(self.tcx, false)
489492
{
490493
Some(("Output", *output_ty))
491494
} else {
@@ -735,12 +738,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
735738
Op::Unary(..) => 0,
736739
},
737740
) {
741+
self.tcx
742+
.sess
743+
.delay_span_bug(span, "operator didn't have the right number of generic args");
738744
return Err(vec![]);
739745
}
740746

741747
let opname = Ident::with_dummy_span(opname);
748+
let input_types =
749+
opt_rhs.as_ref().map(|(_, ty)| std::slice::from_ref(ty)).unwrap_or_default();
750+
let cause = self.cause(
751+
span,
752+
traits::BinOp {
753+
rhs_span: opt_rhs.map(|(expr, _)| expr.span),
754+
is_lit: opt_rhs
755+
.map_or(false, |(expr, _)| matches!(expr.kind, hir::ExprKind::Lit(_))),
756+
output_ty: expected.only_has_type(self),
757+
},
758+
);
759+
742760
let method = trait_did.and_then(|trait_did| {
743-
self.lookup_op_method_in_trait(span, opname, trait_did, lhs_ty, opt_rhs, expected)
761+
self.lookup_method_in_trait(cause.clone(), opname, trait_did, lhs_ty, Some(input_types))
744762
});
745763

746764
match (method, trait_did) {
@@ -752,7 +770,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
752770
(None, None) => Err(vec![]),
753771
(None, Some(trait_did)) => {
754772
let (obligation, _) =
755-
self.obligation_for_op_method(span, trait_did, lhs_ty, opt_rhs, expected);
773+
self.obligation_for_method(cause, trait_did, lhs_ty, Some(input_types));
756774
Err(rustc_trait_selection::traits::fully_solve_obligation(self, obligation))
757775
}
758776
}

compiler/rustc_hir_typeck/src/place_op.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
225225

226226
imm_tr.and_then(|trait_did| {
227227
self.lookup_method_in_trait(
228-
span,
228+
self.misc(span),
229229
Ident::with_dummy_span(imm_op),
230230
trait_did,
231231
base_ty,
@@ -264,7 +264,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
264264

265265
mut_tr.and_then(|trait_did| {
266266
self.lookup_method_in_trait(
267-
span,
267+
self.misc(span),
268268
Ident::with_dummy_span(mut_op),
269269
trait_did,
270270
base_ty,

0 commit comments

Comments
 (0)