Skip to content

Commit 9958f8d

Browse files
authored
Rollup merge of rust-lang#123962 - oli-obk:define_opaque_types5, r=lcnr
change method resolution to constrain hidden types instead of rejecting method candidates Some of these are in probes and may affect inference. This is therefore a breaking change. This allows new code to compile on stable: ```rust trait Trait {} impl Trait for u32 {} struct Bar<T>(T); impl Bar<u32> { fn foo(self) {} } fn foo(x: bool) -> Bar<impl Sized> { if x { let x = foo(false); x.foo(); //^ this used to not find the `foo` method, because while we did equate `x`'s type with possible candidates, we didn't allow opaque type inference while doing so } todo!() } ``` r? ```@compiler-errors``` fixes rust-lang#121404 cc rust-lang#116652
2 parents a5709f3 + 9cf60ee commit 9958f8d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+922
-79
lines changed

compiler/rustc_hir_typeck/src/callee.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
628628
return;
629629
};
630630

631-
let pick = self.confirm_method(
631+
let pick = self.confirm_method_for_diagnostic(
632632
call_expr.span,
633633
callee_expr,
634634
call_expr,

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1418,7 +1418,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14181418
let impl_ty = self.normalize(span, tcx.type_of(impl_def_id).instantiate(tcx, args));
14191419
let self_ty = self.normalize(span, self_ty);
14201420
match self.at(&self.misc(span), self.param_env).eq(
1421-
DefineOpaqueTypes::No,
1421+
DefineOpaqueTypes::Yes,
14221422
impl_ty,
14231423
self_ty,
14241424
) {

compiler/rustc_hir_typeck/src/method/confirm.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
497497
args,
498498
})),
499499
);
500-
match self.at(&cause, self.param_env).sup(DefineOpaqueTypes::No, method_self_ty, self_ty) {
500+
match self.at(&cause, self.param_env).sup(DefineOpaqueTypes::Yes, method_self_ty, self_ty) {
501501
Ok(InferOk { obligations, value: () }) => {
502502
self.register_predicates(obligations);
503503
}

compiler/rustc_hir_typeck/src/method/probe.rs

+29-36
Original file line numberDiff line numberDiff line change
@@ -634,8 +634,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
634634
}
635635
}
636636

637+
#[instrument(level = "debug", skip(self))]
637638
fn assemble_probe(&mut self, self_ty: &Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>) {
638-
debug!("assemble_probe: self_ty={:?}", self_ty);
639639
let raw_self_ty = self_ty.value.value;
640640
match *raw_self_ty.kind() {
641641
ty::Dynamic(data, ..) if let Some(p) = data.principal() => {
@@ -713,13 +713,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
713713
}
714714
}
715715

716+
#[instrument(level = "debug", skip(self))]
716717
fn assemble_inherent_impl_probe(&mut self, impl_def_id: DefId) {
717718
if !self.impl_dups.insert(impl_def_id) {
718719
return; // already visited
719720
}
720721

721-
debug!("assemble_inherent_impl_probe {:?}", impl_def_id);
722-
723722
for item in self.impl_or_trait_item(impl_def_id) {
724723
if !self.has_applicable_self(&item) {
725724
// No receiver declared. Not a candidate.
@@ -737,9 +736,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
737736
}
738737
}
739738

739+
#[instrument(level = "debug", skip(self))]
740740
fn assemble_inherent_candidates_from_object(&mut self, self_ty: Ty<'tcx>) {
741-
debug!("assemble_inherent_candidates_from_object(self_ty={:?})", self_ty);
742-
743741
let principal = match self_ty.kind() {
744742
ty::Dynamic(ref data, ..) => Some(data),
745743
_ => None,
@@ -768,9 +766,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
768766
});
769767
}
770768

769+
#[instrument(level = "debug", skip(self))]
771770
fn assemble_inherent_candidates_from_param(&mut self, param_ty: ty::ParamTy) {
772771
// FIXME: do we want to commit to this behavior for param bounds?
773-
debug!("assemble_inherent_candidates_from_param(param_ty={:?})", param_ty);
774772

775773
let bounds = self.param_env.caller_bounds().iter().filter_map(|predicate| {
776774
let bound_predicate = predicate.kind();
@@ -826,6 +824,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
826824
}
827825
}
828826

827+
#[instrument(level = "debug", skip(self))]
829828
fn assemble_extension_candidates_for_traits_in_scope(&mut self) {
830829
let mut duplicates = FxHashSet::default();
831830
let opt_applicable_traits = self.tcx.in_scope_traits(self.scope_expr_id);
@@ -842,6 +841,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
842841
}
843842
}
844843

844+
#[instrument(level = "debug", skip(self))]
845845
fn assemble_extension_candidates_for_all_traits(&mut self) {
846846
let mut duplicates = FxHashSet::default();
847847
for trait_info in suggest::all_traits(self.tcx) {
@@ -863,12 +863,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
863863
}
864864
}
865865

866+
#[instrument(level = "debug", skip(self))]
866867
fn assemble_extension_candidates_for_trait(
867868
&mut self,
868869
import_ids: &SmallVec<[LocalDefId; 1]>,
869870
trait_def_id: DefId,
870871
) {
871-
debug!("assemble_extension_candidates_for_trait(trait_def_id={:?})", trait_def_id);
872872
let trait_args = self.fresh_args_for_item(self.span, trait_def_id);
873873
let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, trait_args);
874874

@@ -958,6 +958,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
958958
///////////////////////////////////////////////////////////////////////////
959959
// THE ACTUAL SEARCH
960960

961+
#[instrument(level = "debug", skip(self))]
961962
fn pick(mut self) -> PickResult<'tcx> {
962963
assert!(self.method_name.is_some());
963964

@@ -1386,6 +1387,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
13861387
}
13871388
}
13881389

1390+
#[instrument(level = "trace", skip(self, possibly_unsatisfied_predicates), ret)]
13891391
fn consider_probe(
13901392
&self,
13911393
self_ty: Ty<'tcx>,
@@ -1415,15 +1417,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
14151417
(xform_self_ty, xform_ret_ty) =
14161418
self.xform_self_ty(probe.item, impl_ty, impl_args);
14171419
xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
1418-
// FIXME: Make this `ocx.sup` once we define opaques more eagerly.
1419-
match self.at(cause, self.param_env).sup(
1420-
DefineOpaqueTypes::No,
1421-
xform_self_ty,
1422-
self_ty,
1423-
) {
1424-
Ok(infer_ok) => {
1425-
ocx.register_infer_ok_obligations(infer_ok);
1426-
}
1420+
match ocx.sup(cause, self.param_env, xform_self_ty, self_ty) {
1421+
Ok(()) => {}
14271422
Err(err) => {
14281423
debug!("--> cannot relate self-types {:?}", err);
14291424
return ProbeResult::NoMatch;
@@ -1484,19 +1479,23 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
14841479
(xform_self_ty, xform_ret_ty) =
14851480
self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args);
14861481
xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
1487-
// FIXME: Make this `ocx.sup` once we define opaques more eagerly.
1488-
match self.at(cause, self.param_env).sup(
1489-
DefineOpaqueTypes::No,
1490-
xform_self_ty,
1491-
self_ty,
1492-
) {
1493-
Ok(infer_ok) => {
1494-
ocx.register_infer_ok_obligations(infer_ok);
1495-
}
1496-
Err(err) => {
1497-
debug!("--> cannot relate self-types {:?}", err);
1482+
match self_ty.kind() {
1483+
// HACK: opaque types will match anything for which their bounds hold.
1484+
// Thus we need to prevent them from trying to match the `&_` autoref
1485+
// candidates that get created for `&self` trait methods.
1486+
ty::Alias(ty::Opaque, alias_ty)
1487+
if self.infcx.can_define_opaque_ty(alias_ty.def_id)
1488+
&& !xform_self_ty.is_ty_var() =>
1489+
{
14981490
return ProbeResult::NoMatch;
14991491
}
1492+
_ => match ocx.sup(cause, self.param_env, xform_self_ty, self_ty) {
1493+
Ok(()) => {}
1494+
Err(err) => {
1495+
debug!("--> cannot relate self-types {:?}", err);
1496+
return ProbeResult::NoMatch;
1497+
}
1498+
},
15001499
}
15011500
let obligation = traits::Obligation::new(
15021501
self.tcx,
@@ -1536,15 +1535,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
15361535
(xform_self_ty, xform_ret_ty) =
15371536
self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args);
15381537
xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
1539-
// FIXME: Make this `ocx.sup` once we define opaques more eagerly.
1540-
match self.at(cause, self.param_env).sup(
1541-
DefineOpaqueTypes::No,
1542-
xform_self_ty,
1543-
self_ty,
1544-
) {
1545-
Ok(infer_ok) => {
1546-
ocx.register_infer_ok_obligations(infer_ok);
1547-
}
1538+
match ocx.sup(cause, self.param_env, xform_self_ty, self_ty) {
1539+
Ok(()) => {}
15481540
Err(err) => {
15491541
debug!("--> cannot relate self-types {:?}", err);
15501542
return ProbeResult::NoMatch;
@@ -1665,6 +1657,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
16651657
/// Similarly to `probe_for_return_type`, this method attempts to find the best matching
16661658
/// candidate method where the method name may have been misspelled. Similarly to other
16671659
/// edit distance based suggestions, we provide at most one such suggestion.
1660+
#[instrument(level = "debug", skip(self))]
16681661
pub(crate) fn probe_for_similar_candidate(
16691662
&mut self,
16701663
) -> Result<Option<ty::AssocItem>, MethodError<'tcx>> {

compiler/rustc_middle/src/traits/query.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ pub struct CandidateStep<'tcx> {
156156

157157
#[derive(Copy, Clone, Debug, HashStable)]
158158
pub struct MethodAutoderefStepsResult<'tcx> {
159-
/// The valid autoderef steps that could be find.
159+
/// The valid autoderef steps that could be found.
160160
pub steps: &'tcx [CandidateStep<'tcx>],
161161
/// If Some(T), a type autoderef reported an error on.
162162
pub opt_bad_ty: Option<&'tcx MethodAutoderefBadTy<'tcx>>,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error[E0282]: type annotations needed
2+
--> $DIR/call_method_ambiguous.rs:29:13
3+
|
4+
LL | let mut iter = foo(n - 1, m);
5+
| ^^^^^^^^
6+
LL |
7+
LL | assert_eq!(iter.get(), 1);
8+
| ---- type must be known at this point
9+
|
10+
help: consider giving `iter` an explicit type
11+
|
12+
LL | let mut iter: /* Type */ = foo(n - 1, m);
13+
| ++++++++++++
14+
15+
error: aborting due to 1 previous error
16+
17+
For more information about this error, try `rustc --explain E0282`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//@ revisions: current next
2+
//@[next] compile-flags: -Znext-solver
3+
//@[current] run-pass
4+
5+
#![feature(precise_capturing)]
6+
#![allow(incomplete_features)]
7+
8+
trait Get {
9+
fn get(&mut self) -> u32;
10+
}
11+
12+
impl Get for () {
13+
fn get(&mut self) -> u32 {
14+
0
15+
}
16+
}
17+
18+
impl<T> Get for &mut T
19+
where
20+
T: Get,
21+
{
22+
fn get(&mut self) -> u32 {
23+
T::get(self) + 1
24+
}
25+
}
26+
27+
fn foo(n: usize, m: &mut ()) -> impl use<'_> Get {
28+
if n > 0 {
29+
let mut iter = foo(n - 1, m);
30+
//[next]~^ type annotations needed
31+
assert_eq!(iter.get(), 1);
32+
}
33+
m
34+
}
35+
36+
fn main() {
37+
let g = foo(1, &mut ()).get();
38+
assert_eq!(g, 1);
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error[E0282]: type annotations needed
2+
--> $DIR/call_method_on_inherent_impl.rs:18:13
3+
|
4+
LL | let x = my_foo();
5+
| ^
6+
LL |
7+
LL | x.my_debug();
8+
| - type must be known at this point
9+
|
10+
help: consider giving `x` an explicit type
11+
|
12+
LL | let x: /* Type */ = my_foo();
13+
| ++++++++++++
14+
15+
error: aborting due to 1 previous error
16+
17+
For more information about this error, try `rustc --explain E0282`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//@ revisions: current next
2+
//@[next] compile-flags: -Znext-solver
3+
//@[current] check-pass
4+
5+
trait MyDebug {
6+
fn my_debug(&self);
7+
}
8+
9+
impl<T> MyDebug for T
10+
where
11+
T: std::fmt::Debug,
12+
{
13+
fn my_debug(&self) {}
14+
}
15+
16+
fn my_foo() -> impl std::fmt::Debug {
17+
if false {
18+
let x = my_foo();
19+
//[next]~^ type annotations needed
20+
x.my_debug();
21+
}
22+
()
23+
}
24+
25+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error[E0599]: no method named `my_debug` found for reference `&impl Debug` in the current scope
2+
--> $DIR/call_method_on_inherent_impl_on_rigid_type.rs:16:11
3+
|
4+
LL | x.my_debug();
5+
| ^^^^^^^^ method not found in `&impl Debug`
6+
|
7+
= help: items from traits can only be used if the trait is implemented and in scope
8+
note: `MyDebug` defines an item `my_debug`, perhaps you need to implement it
9+
--> $DIR/call_method_on_inherent_impl_on_rigid_type.rs:4:1
10+
|
11+
LL | trait MyDebug {
12+
| ^^^^^^^^^^^^^
13+
14+
error: aborting due to 1 previous error
15+
16+
For more information about this error, try `rustc --explain E0599`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error[E0282]: type annotations needed for `&_`
2+
--> $DIR/call_method_on_inherent_impl_on_rigid_type.rs:14:13
3+
|
4+
LL | let x = &my_foo();
5+
| ^
6+
LL |
7+
LL | x.my_debug();
8+
| -------- type must be known at this point
9+
|
10+
help: consider giving `x` an explicit type, where the placeholders `_` are specified
11+
|
12+
LL | let x: &_ = &my_foo();
13+
| ++++
14+
15+
error: aborting due to 1 previous error
16+
17+
For more information about this error, try `rustc --explain E0282`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//@ revisions: current next
2+
//@[next] compile-flags: -Znext-solver
3+
4+
trait MyDebug {
5+
fn my_debug(&self);
6+
}
7+
8+
impl MyDebug for &() {
9+
fn my_debug(&self) {}
10+
}
11+
12+
fn my_foo() -> impl std::fmt::Debug {
13+
if false {
14+
let x = &my_foo();
15+
//[next]~^ ERROR: type annotations needed
16+
x.my_debug();
17+
//[current]~^ ERROR: no method named `my_debug`
18+
}
19+
()
20+
}
21+
22+
fn main() {}

0 commit comments

Comments
 (0)