Skip to content

Commit b85bf1e

Browse files
committed
i hate this :<
1 parent 3a5a0bd commit b85bf1e

24 files changed

+166
-125
lines changed

compiler/rustc_hir_typeck/src/expr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1591,7 +1591,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15911591
) -> Ty<'tcx> {
15921592
let rcvr_t = self.check_expr(rcvr);
15931593
// no need to check for bot/err -- callee does that
1594-
let rcvr_t = self.structurally_resolve_type(rcvr.span, rcvr_t);
1594+
let rcvr_t = self.try_structurally_resolve_type(rcvr.span, rcvr_t);
15951595

15961596
match self.lookup_method(rcvr_t, segment, segment.ident.span, expr, rcvr, args) {
15971597
Ok(method) => {

compiler/rustc_hir_typeck/src/method/confirm.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
190190
assert_eq!(n, pick.autoderefs);
191191

192192
let mut adjustments = self.adjust_steps(&autoderef);
193-
let mut target = self.structurally_resolve_type(autoderef.span(), ty);
193+
let mut target = self.try_structurally_resolve_type(autoderef.span(), ty);
194194

195195
match pick.autoref_or_ptr_adjustment {
196196
Some(probe::AutorefOrPtrAdjustment::Autoref { mutbl, unsize }) => {

compiler/rustc_hir_typeck/src/method/probe.rs

Lines changed: 123 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_hir::HirId;
1111
use rustc_hir::def::DefKind;
1212
use rustc_hir_analysis::autoderef::{self, Autoderef};
1313
use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
14-
use rustc_infer::infer::{self, DefineOpaqueTypes, InferOk, TyCtxtInferExt};
14+
use rustc_infer::infer::{self, DefineOpaqueTypes, InferCtxt, InferOk, TyCtxtInferExt};
1515
use rustc_infer::traits::ObligationCauseCode;
1616
use rustc_middle::middle::stability;
1717
use rustc_middle::query::Providers;
@@ -443,7 +443,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
443443
// If we encountered an `_` type or an error type during autoderef, this is
444444
// ambiguous.
445445
if let Some(bad_ty) = &steps.opt_bad_ty {
446-
if is_suggestion.0 {
446+
// Ended up encountering a type variable when doing autoderef,
447+
// but it may not be a type variable after processing obligations
448+
// in our local `FnCtxt`, so don't call `structurally_resolve_type`.
449+
let ty = &bad_ty.ty;
450+
let ty = self
451+
.probe_instantiate_query_response(span, &orig_values, ty)
452+
.unwrap_or_else(|_| span_bug!(span, "instantiating {:?} failed?", ty));
453+
if bad_ty.is_opaque_type || final_ty_is_opaque(&self.infcx, ty.value) {
454+
// FIXME(-Znext-solver): This isn't really what we want :<
455+
assert!(self.tcx.next_trait_solver_globally());
456+
} else if is_suggestion.0 {
447457
// Ambiguity was encountered during a suggestion. There's really
448458
// not much use in suggesting methods in this case.
449459
return Err(MethodError::NoMatch(NoMatchData {
@@ -469,13 +479,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
469479
},
470480
);
471481
} else {
472-
// Ended up encountering a type variable when doing autoderef,
473-
// but it may not be a type variable after processing obligations
474-
// in our local `FnCtxt`, so don't call `structurally_resolve_type`.
475-
let ty = &bad_ty.ty;
476-
let ty = self
477-
.probe_instantiate_query_response(span, &orig_values, ty)
478-
.unwrap_or_else(|_| span_bug!(span, "instantiating {:?} failed?", ty));
479482
let ty = self.resolve_vars_if_possible(ty.value);
480483
let guar = match *ty.kind() {
481484
ty::Infer(ty::TyVar(_)) => {
@@ -583,60 +586,75 @@ fn method_autoderef_steps<'tcx>(
583586
let mut reached_raw_pointer = false;
584587
let arbitrary_self_types_enabled =
585588
tcx.features().arbitrary_self_types() || tcx.features().arbitrary_self_types_pointers();
586-
let (mut steps, reached_recursion_limit): (Vec<_>, bool) = if arbitrary_self_types_enabled {
587-
let reachable_via_deref =
588-
autoderef_via_deref.by_ref().map(|_| true).chain(std::iter::repeat(false));
589-
590-
let mut autoderef_via_receiver =
591-
Autoderef::new(infcx, param_env, hir::def_id::CRATE_DEF_ID, DUMMY_SP, self_ty)
592-
.include_raw_pointers()
593-
.use_receiver_trait()
594-
.silence_errors();
595-
let steps = autoderef_via_receiver
596-
.by_ref()
597-
.zip(reachable_via_deref)
598-
.map(|((ty, d), reachable_via_deref)| {
599-
let step = CandidateStep {
600-
self_ty: infcx
601-
.make_query_response_ignoring_pending_obligations(inference_vars, ty),
602-
autoderefs: d,
603-
from_unsafe_deref: reached_raw_pointer,
604-
unsize: false,
605-
reachable_via_deref,
606-
};
607-
if ty.is_raw_ptr() {
608-
// all the subsequent steps will be from_unsafe_deref
609-
reached_raw_pointer = true;
610-
}
611-
step
612-
})
613-
.collect();
614-
(steps, autoderef_via_receiver.reached_recursion_limit())
615-
} else {
616-
let steps = autoderef_via_deref
617-
.by_ref()
618-
.map(|(ty, d)| {
619-
let step = CandidateStep {
620-
self_ty: infcx
621-
.make_query_response_ignoring_pending_obligations(inference_vars, ty),
622-
autoderefs: d,
623-
from_unsafe_deref: reached_raw_pointer,
624-
unsize: false,
625-
reachable_via_deref: true,
626-
};
627-
if ty.is_raw_ptr() {
628-
// all the subsequent steps will be from_unsafe_deref
629-
reached_raw_pointer = true;
630-
}
631-
step
632-
})
633-
.collect();
634-
(steps, autoderef_via_deref.reached_recursion_limit())
635-
};
636-
let final_ty = autoderef_via_deref.final_ty(true);
589+
let (mut steps, final_ty, reached_recursion_limit): (Vec<_>, _, _) =
590+
if arbitrary_self_types_enabled {
591+
let reachable_via_deref =
592+
autoderef_via_deref.by_ref().map(|_| true).chain(std::iter::repeat(false));
593+
594+
let mut autoderef_via_receiver =
595+
Autoderef::new(infcx, param_env, hir::def_id::CRATE_DEF_ID, DUMMY_SP, self_ty)
596+
.include_raw_pointers()
597+
.use_receiver_trait()
598+
.silence_errors();
599+
let steps = autoderef_via_receiver
600+
.by_ref()
601+
.zip(reachable_via_deref)
602+
.map(|((ty, d), reachable_via_deref)| {
603+
let step = CandidateStep {
604+
self_ty: infcx
605+
.make_query_response_ignoring_pending_obligations(inference_vars, ty),
606+
autoderefs: d,
607+
from_unsafe_deref: reached_raw_pointer,
608+
unsize: false,
609+
reachable_via_deref,
610+
};
611+
if ty.is_raw_ptr() {
612+
// all the subsequent steps will be from_unsafe_deref
613+
reached_raw_pointer = true;
614+
}
615+
step
616+
})
617+
.collect();
618+
(
619+
steps,
620+
// FIXME(arbitrary_self_types): This is sus.
621+
autoderef_via_deref.final_ty(true),
622+
autoderef_via_receiver.reached_recursion_limit(),
623+
)
624+
} else {
625+
let steps = autoderef_via_deref
626+
.by_ref()
627+
.map(|(ty, d)| {
628+
let step = CandidateStep {
629+
self_ty: infcx
630+
.make_query_response_ignoring_pending_obligations(inference_vars, ty),
631+
autoderefs: d,
632+
from_unsafe_deref: reached_raw_pointer,
633+
unsize: false,
634+
reachable_via_deref: true,
635+
};
636+
if ty.is_raw_ptr() {
637+
// all the subsequent steps will be from_unsafe_deref
638+
reached_raw_pointer = true;
639+
}
640+
step
641+
})
642+
.collect();
643+
(
644+
steps,
645+
autoderef_via_deref.final_ty(true),
646+
autoderef_via_deref.reached_recursion_limit(),
647+
)
648+
};
637649
let opt_bad_ty = match final_ty.kind() {
638-
ty::Infer(ty::TyVar(_)) | ty::Error(_) => Some(MethodAutoderefBadTy {
650+
ty::Infer(ty::TyVar(_)) => Some(MethodAutoderefBadTy {
651+
reached_raw_pointer,
652+
is_opaque_type: final_ty_is_opaque(infcx, final_ty),
653+
ty: infcx.make_query_response_ignoring_pending_obligations(inference_vars, final_ty),
654+
}),
655+
ty::Error(_) => Some(MethodAutoderefBadTy {
639656
reached_raw_pointer,
657+
is_opaque_type: false,
640658
ty: infcx.make_query_response_ignoring_pending_obligations(inference_vars, final_ty),
641659
}),
642660
ty::Array(elem_ty, _) => {
@@ -669,6 +687,20 @@ fn method_autoderef_steps<'tcx>(
669687
}
670688
}
671689

690+
/// Returns `true` in case the final type is the hidden type of an opaque.
691+
#[instrument(level = "debug", skip(infcx), ret)]
692+
fn final_ty_is_opaque<'tcx>(infcx: &InferCtxt<'tcx>, final_ty: Ty<'tcx>) -> bool {
693+
// nyaaaa~
694+
if infcx.next_trait_solver() {
695+
let &ty::Infer(ty::TyVar(vid)) = final_ty.kind() else {
696+
return false;
697+
};
698+
infcx.find_sup_as_registered_opaque(vid).is_some()
699+
} else {
700+
false
701+
}
702+
}
703+
672704
impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
673705
fn new(
674706
fcx: &'a FnCtxt<'a, 'tcx>,
@@ -1882,31 +1914,39 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
18821914
(xform_self_ty, xform_ret_ty) =
18831915
self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args);
18841916
xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
1885-
match self_ty.kind() {
1886-
// HACK: opaque types will match anything for which their bounds hold.
1887-
// Thus we need to prevent them from trying to match the `&_` autoref
1888-
// candidates that get created for `&self` trait methods.
1889-
ty::Alias(ty::Opaque, alias_ty)
1890-
if !self.next_trait_solver()
1891-
&& self.infcx.can_define_opaque_ty(alias_ty.def_id)
1892-
&& !xform_self_ty.is_ty_var() =>
1893-
{
1894-
return ProbeResult::NoMatch;
1895-
}
1896-
_ => match ocx.relate(
1897-
cause,
1898-
self.param_env,
1899-
self.variance(),
1900-
self_ty,
1901-
xform_self_ty,
1902-
) {
1903-
Ok(()) => {}
1904-
Err(err) => {
1905-
debug!("--> cannot relate self-types {:?}", err);
1917+
1918+
// HACK: opaque types will match anything for which their bounds hold.
1919+
// Thus we need to prevent them from trying to match the `&_` autoref
1920+
// candidates that get created for `&self` trait methods.
1921+
if self.mode == Mode::MethodCall {
1922+
match self_ty.kind() {
1923+
ty::Infer(ty::TyVar(_)) => {
1924+
assert!(self.infcx.next_trait_solver());
1925+
if !xform_self_ty.is_ty_var() {
1926+
return ProbeResult::NoMatch;
1927+
}
1928+
}
1929+
ty::Alias(ty::Opaque, alias_ty)
1930+
if !self.infcx.next_trait_solver()
1931+
&& self.infcx.can_define_opaque_ty(alias_ty.def_id)
1932+
&& !xform_self_ty.is_ty_var() =>
1933+
{
1934+
assert!(!self.infcx.next_trait_solver());
19061935
return ProbeResult::NoMatch;
19071936
}
1908-
},
1937+
_ => {}
1938+
}
1939+
}
1940+
1941+
match ocx.relate(cause, self.param_env, self.variance(), self_ty, xform_self_ty)
1942+
{
1943+
Ok(()) => {}
1944+
Err(err) => {
1945+
debug!("--> cannot relate self-types {:?}", err);
1946+
return ProbeResult::NoMatch;
1947+
}
19091948
}
1949+
19101950
let obligation = traits::Obligation::new(
19111951
self.tcx,
19121952
cause.clone(),

compiler/rustc_middle/src/traits/query.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ pub struct MethodAutoderefStepsResult<'tcx> {
178178
#[derive(Debug, HashStable)]
179179
pub struct MethodAutoderefBadTy<'tcx> {
180180
pub reached_raw_pointer: bool,
181+
pub is_opaque_type: bool,
181182
pub ty: Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>,
182183
}
183184

tests/ui/closures/deduce-signature/obligation-with-leaking-placeholders.next.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | needs_foo(|x| {
55
| ^
66
...
77
LL | x.to_string();
8-
| - type must be known at this point
8+
| --------- type must be known at this point
99
|
1010
help: consider giving this closure parameter an explicit type
1111
|

tests/ui/impl-trait/call_method_ambiguous.next.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | let mut iter = foo(n - 1, m);
55
| ^^^^^^^^
66
LL |
77
LL | assert_eq!(iter.get(), 1);
8-
| ---- type must be known at this point
8+
| --- type must be known at this point
99
|
1010
help: consider giving `iter` an explicit type
1111
|

tests/ui/impl-trait/call_method_on_inherent_impl.next.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | let x = my_foo();
55
| ^
66
LL |
77
LL | x.my_debug();
8-
| - type must be known at this point
8+
| -------- type must be known at this point
99
|
1010
help: consider giving `x` an explicit type
1111
|

tests/ui/impl-trait/call_method_on_inherent_impl_ref.next.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | let x = my_foo();
55
| ^
66
LL |
77
LL | x.my_debug();
8-
| - type must be known at this point
8+
| -------- type must be known at this point
99
|
1010
help: consider giving `x` an explicit type
1111
|

tests/ui/impl-trait/hidden-type-is-opaque-2.default.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | Thunk::new(|mut cont| {
55
| ^^^^^^^^
66
LL |
77
LL | cont.reify_as();
8-
| ---- type must be known at this point
8+
| -------- type must be known at this point
99
|
1010
help: consider giving this closure parameter an explicit type
1111
|
@@ -19,7 +19,7 @@ LL | Thunk::new(|mut cont| {
1919
| ^^^^^^^^
2020
LL |
2121
LL | cont.reify_as();
22-
| ---- type must be known at this point
22+
| -------- type must be known at this point
2323
|
2424
help: consider giving this closure parameter an explicit type
2525
|

tests/ui/impl-trait/hidden-type-is-opaque-2.next.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | Thunk::new(|mut cont| {
55
| ^^^^^^^^
66
LL |
77
LL | cont.reify_as();
8-
| ---- type must be known at this point
8+
| -------- type must be known at this point
99
|
1010
help: consider giving this closure parameter an explicit type
1111
|
@@ -19,7 +19,7 @@ LL | Thunk::new(|mut cont| {
1919
| ^^^^^^^^
2020
LL |
2121
LL | cont.reify_as();
22-
| ---- type must be known at this point
22+
| -------- type must be known at this point
2323
|
2424
help: consider giving this closure parameter an explicit type
2525
|

tests/ui/impl-trait/method-resolution4.next.stderr

Lines changed: 0 additions & 9 deletions
This file was deleted.

tests/ui/impl-trait/method-resolution4.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,11 @@
66
77
//@ revisions: current next
88
//@[next] compile-flags: -Znext-solver
9-
//@[current] check-pass
9+
//@ check-pass
1010

1111
fn foo(b: bool) -> impl Iterator<Item = ()> {
1212
if b {
1313
foo(false).next().unwrap();
14-
//[next]~^ ERROR type annotations needed
1514
}
1615
std::iter::empty()
1716
}

tests/ui/impl-trait/recursive-bound-eval.next.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error[E0282]: type annotations needed
2-
--> $DIR/recursive-bound-eval.rs:20:13
2+
--> $DIR/recursive-bound-eval.rs:20:28
33
|
44
LL | move || recursive_fn().parse()
5-
| ^^^^^^^^^^^^^^ cannot infer type
5+
| ^^^^^ cannot infer type
66

77
error: aborting due to 1 previous error
88

tests/ui/inference/need_type_info/incompat-call-after-qualified-path-0.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0282]: type annotations needed
22
--> $DIR/incompat-call-after-qualified-path-0.rs:21:6
33
|
44
LL | f(|a, b| a.cmp(b));
5-
| ^ - type must be known at this point
5+
| ^ --- type must be known at this point
66
|
77
help: consider giving this closure parameter an explicit type
88
|

0 commit comments

Comments
 (0)