Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 2e8de27

Browse filesBrowse files
Incompletely allow overloaded call from opaque when self type bottoms out in infer
1 parent 07ad2fa commit 2e8de27
Copy full SHA for 2e8de27

File tree

Expand file treeCollapse file tree

2 files changed

+140
-35
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+140
-35
lines changed

‎compiler/rustc_hir_typeck/src/callee.rs

Copy file name to clipboardExpand all lines: compiler/rustc_hir_typeck/src/callee.rs
+123-35Lines changed: 123 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use rustc_middle::ty::adjustment::{
1414
use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt};
1515
use rustc_middle::{bug, span_bug};
1616
use rustc_span::def_id::LocalDefId;
17-
use rustc_span::{Span, sym};
17+
use rustc_span::{Span, Symbol, sym};
1818
use rustc_trait_selection::error_reporting::traits::DefIdOrName;
1919
use rustc_trait_selection::infer::InferCtxtExt as _;
2020
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
@@ -66,7 +66,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
6666
arg_exprs: &'tcx [hir::Expr<'tcx>],
6767
expected: Expectation<'tcx>,
6868
) -> Ty<'tcx> {
69-
let original_callee_ty = match &callee_expr.kind {
69+
let expr_ty = match &callee_expr.kind {
7070
hir::ExprKind::Path(hir::QPath::Resolved(..) | hir::QPath::TypeRelative(..)) => self
7171
.check_expr_with_expectation_and_args(
7272
callee_expr,
@@ -76,8 +76,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
7676
_ => self.check_expr(callee_expr),
7777
};
7878

79-
let expr_ty = self.structurally_resolve_type(call_expr.span, original_callee_ty);
80-
8179
let mut autoderef = self.autoderef(callee_expr.span, expr_ty);
8280
let mut result = None;
8381
while result.is_none() && autoderef.next().is_some() {
@@ -144,7 +142,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
144142
autoderef: &Autoderef<'a, 'tcx>,
145143
) -> Option<CallStep<'tcx>> {
146144
let adjusted_ty =
147-
self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false));
145+
self.try_structurally_resolve_type(autoderef.span(), autoderef.final_ty(false));
148146

149147
// If the callee is a bare function or a closure, then we're all set.
150148
match *adjusted_ty.kind() {
@@ -241,6 +239,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
241239
return None;
242240
}
243241

242+
// We only want to confirm a call step here if the infer var
243+
// originated from the defining use of an opaque.
244+
ty::Infer(ty::TyVar(vid))
245+
if let Some(alias_ty) = self.find_sup_as_registered_opaque(vid) =>
246+
{
247+
return self
248+
.try_overloaded_call_traits_for_alias(call_expr, alias_ty, arg_exprs)
249+
.map(|(autoref, method)| {
250+
let mut adjustments = self.adjust_steps(autoderef);
251+
adjustments.extend(autoref);
252+
self.apply_adjustments(callee_expr, adjustments);
253+
CallStep::Overloaded(method)
254+
});
255+
}
256+
257+
ty::Infer(_) => {
258+
return None;
259+
}
260+
244261
ty::Error(_) => {
245262
return None;
246263
}
@@ -305,40 +322,111 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
305322

306323
// Try the options that are least restrictive on the caller first.
307324
for (opt_trait_def_id, method_name, borrow) in call_trait_choices {
308-
let Some(trait_def_id) = opt_trait_def_id else { continue };
325+
if let Some(confirmed) = self.try_overloaded_call_trait(
326+
call_expr,
327+
adjusted_ty,
328+
opt_arg_exprs,
329+
opt_trait_def_id,
330+
method_name,
331+
borrow,
332+
) {
333+
return Some(confirmed);
334+
}
335+
}
336+
337+
None
338+
}
339+
340+
fn try_overloaded_call_trait(
341+
&self,
342+
call_expr: &hir::Expr<'_>,
343+
call_ty: Ty<'tcx>,
344+
opt_arg_exprs: Option<&'tcx [hir::Expr<'tcx>]>,
345+
opt_trait_def_id: Option<DefId>,
346+
method_name: Symbol,
347+
borrow: bool,
348+
) -> Option<(Option<Adjustment<'tcx>>, MethodCallee<'tcx>)> {
349+
let Some(trait_def_id) = opt_trait_def_id else {
350+
return None;
351+
};
352+
353+
let opt_input_type = opt_arg_exprs.map(|arg_exprs| {
354+
Ty::new_tup_from_iter(self.tcx, arg_exprs.iter().map(|e| self.next_ty_var(e.span)))
355+
});
356+
357+
let Some(ok) = self.lookup_method_for_operator(
358+
self.misc(call_expr.span),
359+
method_name,
360+
trait_def_id,
361+
call_ty,
362+
opt_input_type,
363+
) else {
364+
return None;
365+
};
366+
let method = self.register_infer_ok_obligations(ok);
367+
let mut autoref = None;
368+
if borrow {
369+
// Check for &self vs &mut self in the method signature. Since this is either
370+
// the Fn or FnMut trait, it should be one of those.
371+
let ty::Ref(_, _, mutbl) = *method.sig.inputs()[0].kind() else {
372+
bug!("Expected `FnMut`/`Fn` to take receiver by-ref/by-mut")
373+
};
309374

310-
let opt_input_type = opt_arg_exprs.map(|arg_exprs| {
311-
Ty::new_tup_from_iter(self.tcx, arg_exprs.iter().map(|e| self.next_ty_var(e.span)))
375+
// For initial two-phase borrow
376+
// deployment, conservatively omit
377+
// overloaded function call ops.
378+
let mutbl = AutoBorrowMutability::new(mutbl, AllowTwoPhase::No);
379+
380+
autoref = Some(Adjustment {
381+
kind: Adjust::Borrow(AutoBorrow::Ref(mutbl)),
382+
target: method.sig.inputs()[0],
312383
});
384+
}
313385

314-
if let Some(ok) = self.lookup_method_for_operator(
315-
self.misc(call_expr.span),
316-
method_name,
317-
trait_def_id,
318-
adjusted_ty,
319-
opt_input_type,
320-
) {
321-
let method = self.register_infer_ok_obligations(ok);
322-
let mut autoref = None;
323-
if borrow {
324-
// Check for &self vs &mut self in the method signature. Since this is either
325-
// the Fn or FnMut trait, it should be one of those.
326-
let ty::Ref(_, _, mutbl) = method.sig.inputs()[0].kind() else {
327-
bug!("Expected `FnMut`/`Fn` to take receiver by-ref/by-mut")
328-
};
329-
330-
// For initial two-phase borrow
331-
// deployment, conservatively omit
332-
// overloaded function call ops.
333-
let mutbl = AutoBorrowMutability::new(*mutbl, AllowTwoPhase::No);
334-
335-
autoref = Some(Adjustment {
336-
kind: Adjust::Borrow(AutoBorrow::Ref(mutbl)),
337-
target: method.sig.inputs()[0],
338-
});
339-
}
386+
Some((autoref, method))
387+
}
340388

341-
return Some((autoref, method));
389+
fn try_overloaded_call_traits_for_alias(
390+
&self,
391+
call_expr: &'tcx hir::Expr<'tcx>,
392+
alias_ty: ty::AliasTy<'tcx>,
393+
arg_exprs: &'tcx [rustc_hir::Expr<'tcx>],
394+
) -> Option<(Option<Adjustment<'tcx>>, MethodCallee<'tcx>)> {
395+
let call_ty = alias_ty.to_ty(self.tcx);
396+
397+
let call_traits = [
398+
(self.tcx.lang_items().fn_trait(), sym::call, true),
399+
(self.tcx.lang_items().fn_mut_trait(), sym::call_mut, true),
400+
(self.tcx.lang_items().fn_once_trait(), sym::call_once, false),
401+
(self.tcx.lang_items().async_fn_trait(), sym::async_call, true),
402+
(self.tcx.lang_items().async_fn_mut_trait(), sym::async_call_mut, true),
403+
(self.tcx.lang_items().async_fn_once_trait(), sym::async_call_once, false),
404+
];
405+
// We only want to try a call trait if it shows up in the bounds
406+
// of the opaque. We confirm the first one that shows up in the
407+
// bounds list, which can lead to inference weirdness but doesn't
408+
// matter today.
409+
for clause in
410+
self.tcx.item_self_bounds(alias_ty.def_id).iter_instantiated(self.tcx, alias_ty.args)
411+
{
412+
let Some(poly_trait_ref) = clause.as_trait_clause() else {
413+
continue;
414+
};
415+
416+
if let Some(&(opt_trait_def_id, method_name, borrow)) =
417+
call_traits.iter().find(|(trait_def_id, _, _)| {
418+
trait_def_id.is_some_and(|trait_def_id| trait_def_id == poly_trait_ref.def_id())
419+
})
420+
&& let Some(confirmed) = self.try_overloaded_call_trait(
421+
call_expr,
422+
call_ty,
423+
Some(arg_exprs),
424+
opt_trait_def_id,
425+
method_name,
426+
borrow,
427+
)
428+
{
429+
return Some(confirmed);
342430
}
343431
}
344432

‎compiler/rustc_infer/src/infer/mod.rs

Copy file name to clipboardExpand all lines: compiler/rustc_infer/src/infer/mod.rs
+17Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -955,6 +955,23 @@ impl<'tcx> InferCtxt<'tcx> {
955955
self.inner.borrow_mut().opaque_type_storage.iter_opaque_types().collect()
956956
}
957957

958+
pub fn find_sup_as_registered_opaque(&self, ty_vid: TyVid) -> Option<ty::AliasTy<'tcx>> {
959+
let ty_sub_vid = self.sub_root_var(ty_vid);
960+
let opaques: Vec<_> = self.inner.borrow_mut().opaque_types().iter_opaque_types().collect();
961+
opaques
962+
.into_iter()
963+
.find(|(_, hidden_ty)| {
964+
if let ty::Infer(ty::TyVar(hidden_vid)) = *hidden_ty.ty.kind()
965+
&& self.sub_root_var(hidden_vid) == ty_sub_vid
966+
{
967+
true
968+
} else {
969+
false
970+
}
971+
})
972+
.map(|(key, _)| ty::AliasTy::new_from_args(self.tcx, key.def_id.to_def_id(), key.args))
973+
}
974+
958975
#[inline(always)]
959976
pub fn can_define_opaque_ty(&self, id: impl Into<DefId>) -> bool {
960977
debug_assert!(!self.next_trait_solver());

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.