Skip to content

Commit 32600dd

Browse files
committed
i hate this :<
1 parent 01692cc commit 32600dd

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

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