Skip to content

Commit 4742769

Browse files
committed
Auto merge of rust-lang#151676 - adwinwhite:next-263, r=lcnr
Do not return incorrectly constrained opaques in `method_autoderef_steps` Fixes rust-lang/trait-system-refactor-initiative#263 r? @lcnr
2 parents db6bc0f + f6efe7e commit 4742769

File tree

4 files changed

+113
-10
lines changed

4 files changed

+113
-10
lines changed

compiler/rustc_hir_typeck/src/method/probe.rs

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -415,10 +415,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
415415
infcx.instantiate_canonical(span, &query_input.canonical);
416416
let query::MethodAutoderefSteps { predefined_opaques_in_body: _, self_ty } = value;
417417
debug!(?self_ty, ?query_input, "probe_op: Mode::Path");
418+
let prev_opaque_entries = self.inner.borrow_mut().opaque_types().num_entries();
418419
MethodAutoderefStepsResult {
419420
steps: infcx.tcx.arena.alloc_from_iter([CandidateStep {
420-
self_ty: self
421-
.make_query_response_ignoring_pending_obligations(var_values, self_ty),
421+
self_ty: self.make_query_response_ignoring_pending_obligations(
422+
var_values,
423+
self_ty,
424+
prev_opaque_entries,
425+
),
422426
self_ty_is_opaque: false,
423427
autoderefs: 0,
424428
from_unsafe_deref: false,
@@ -607,6 +611,7 @@ pub(crate) fn method_autoderef_steps<'tcx>(
607611
debug!(?key, ?ty, ?prev, "ignore duplicate in `opaque_types_storage`");
608612
}
609613
}
614+
let prev_opaque_entries = infcx.inner.borrow_mut().opaque_types().num_entries();
610615

611616
// We accept not-yet-defined opaque types in the autoderef
612617
// chain to support recursive calls. We do error if the final
@@ -650,8 +655,11 @@ pub(crate) fn method_autoderef_steps<'tcx>(
650655
.zip(reachable_via_deref)
651656
.map(|((ty, d), reachable_via_deref)| {
652657
let step = CandidateStep {
653-
self_ty: infcx
654-
.make_query_response_ignoring_pending_obligations(inference_vars, ty),
658+
self_ty: infcx.make_query_response_ignoring_pending_obligations(
659+
inference_vars,
660+
ty,
661+
prev_opaque_entries,
662+
),
655663
self_ty_is_opaque: self_ty_is_opaque(ty),
656664
autoderefs: d,
657665
from_unsafe_deref: reached_raw_pointer,
@@ -671,8 +679,11 @@ pub(crate) fn method_autoderef_steps<'tcx>(
671679
.by_ref()
672680
.map(|(ty, d)| {
673681
let step = CandidateStep {
674-
self_ty: infcx
675-
.make_query_response_ignoring_pending_obligations(inference_vars, ty),
682+
self_ty: infcx.make_query_response_ignoring_pending_obligations(
683+
inference_vars,
684+
ty,
685+
prev_opaque_entries,
686+
),
676687
self_ty_is_opaque: self_ty_is_opaque(ty),
677688
autoderefs: d,
678689
from_unsafe_deref: reached_raw_pointer,
@@ -692,18 +703,27 @@ pub(crate) fn method_autoderef_steps<'tcx>(
692703
let opt_bad_ty = match final_ty.kind() {
693704
ty::Infer(ty::TyVar(_)) if !self_ty_is_opaque(final_ty) => Some(MethodAutoderefBadTy {
694705
reached_raw_pointer,
695-
ty: infcx.make_query_response_ignoring_pending_obligations(inference_vars, final_ty),
706+
ty: infcx.make_query_response_ignoring_pending_obligations(
707+
inference_vars,
708+
final_ty,
709+
prev_opaque_entries,
710+
),
696711
}),
697712
ty::Error(_) => Some(MethodAutoderefBadTy {
698713
reached_raw_pointer,
699-
ty: infcx.make_query_response_ignoring_pending_obligations(inference_vars, final_ty),
714+
ty: infcx.make_query_response_ignoring_pending_obligations(
715+
inference_vars,
716+
final_ty,
717+
prev_opaque_entries,
718+
),
700719
}),
701720
ty::Array(elem_ty, _) => {
702721
let autoderefs = steps.iter().filter(|s| s.reachable_via_deref).count() - 1;
703722
steps.push(CandidateStep {
704723
self_ty: infcx.make_query_response_ignoring_pending_obligations(
705724
inference_vars,
706725
Ty::new_slice(infcx.tcx, *elem_ty),
726+
prev_opaque_entries,
707727
),
708728
self_ty_is_opaque: false,
709729
autoderefs,

compiler/rustc_infer/src/infer/canonical/query_response.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ use crate::infer::canonical::{
2424
};
2525
use crate::infer::region_constraints::RegionConstraintData;
2626
use crate::infer::{
27-
DefineOpaqueTypes, InferCtxt, InferOk, InferResult, SubregionOrigin, TypeOutlivesConstraint,
27+
DefineOpaqueTypes, InferCtxt, InferOk, InferResult, OpaqueTypeStorageEntries, SubregionOrigin,
28+
TypeOutlivesConstraint,
2829
};
2930
use crate::traits::query::NoSolution;
3031
use crate::traits::{ObligationCause, PredicateObligations, ScrubbedTraitError, TraitEngine};
@@ -81,6 +82,7 @@ impl<'tcx> InferCtxt<'tcx> {
8182
&self,
8283
inference_vars: CanonicalVarValues<'tcx>,
8384
answer: T,
85+
prev_entries: OpaqueTypeStorageEntries,
8486
) -> Canonical<'tcx, QueryResponse<'tcx, T>>
8587
where
8688
T: Debug + TypeFoldable<TyCtxt<'tcx>>,
@@ -96,7 +98,7 @@ impl<'tcx> InferCtxt<'tcx> {
9698
self.inner
9799
.borrow_mut()
98100
.opaque_type_storage
99-
.iter_opaque_types()
101+
.opaque_types_added_since(prev_entries)
100102
.map(|(k, v)| (k, v.ty))
101103
.collect()
102104
} else {
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//@ compile-flags: -Znext-solver
2+
3+
// Regression test for trait-system-refactor-initiative/issues/263
4+
// Previously `method_auto_deref_steps` would also return opaque
5+
// types which have already been defined in the parent context.
6+
//
7+
// We then handled these opaque types by emitting `AliasRelate` goals
8+
// when instantiating its result, assuming that operation to be infallible.
9+
// By returning opaque type constraints from the parent context and
10+
// constraining the hidden type without reproving the item bounds of
11+
// the opaque, this ended up causing ICE.
12+
13+
use std::ops::Deref;
14+
trait Trait {}
15+
struct Inv<T>(*mut T);
16+
impl Trait for i32 {}
17+
impl Deref for Inv<u32> {
18+
type Target = u32;
19+
fn deref(&self) -> &Self::Target {
20+
todo!()
21+
}
22+
}
23+
24+
fn mk<T>() -> T { todo!() }
25+
fn foo() -> Inv<impl Trait> {
26+
//~^ ERROR: the trait bound `u32: Trait` is not satisfied [E0277]
27+
let mut x: Inv<_> = mk();
28+
if false {
29+
return x;
30+
//~^ ERROR: the trait bound `u32: Trait` is not satisfied [E0277]
31+
}
32+
33+
x.count_ones();
34+
x
35+
//~^ ERROR: mismatched types [E0308]
36+
}
37+
38+
fn main() {}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
error[E0277]: the trait bound `u32: Trait` is not satisfied
2+
--> $DIR/method_autoderef_constraints.rs:29:16
3+
|
4+
LL | return x;
5+
| ^ the trait `Trait` is not implemented for `u32`
6+
|
7+
help: the trait `Trait` is implemented for `i32`
8+
--> $DIR/method_autoderef_constraints.rs:16:1
9+
|
10+
LL | impl Trait for i32 {}
11+
| ^^^^^^^^^^^^^^^^^^
12+
13+
error[E0308]: mismatched types
14+
--> $DIR/method_autoderef_constraints.rs:34:5
15+
|
16+
LL | fn foo() -> Inv<impl Trait> {
17+
| ---------------
18+
| | |
19+
| | the expected opaque type
20+
| expected `Inv<impl Trait>` because of return type
21+
...
22+
LL | x
23+
| ^ types differ
24+
|
25+
= note: expected struct `Inv<impl Trait>`
26+
found struct `Inv<u32>`
27+
28+
error[E0277]: the trait bound `u32: Trait` is not satisfied
29+
--> $DIR/method_autoderef_constraints.rs:25:1
30+
|
31+
LL | fn foo() -> Inv<impl Trait> {
32+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `u32`
33+
|
34+
help: the trait `Trait` is implemented for `i32`
35+
--> $DIR/method_autoderef_constraints.rs:16:1
36+
|
37+
LL | impl Trait for i32 {}
38+
| ^^^^^^^^^^^^^^^^^^
39+
40+
error: aborting due to 3 previous errors
41+
42+
Some errors have detailed explanations: E0277, E0308.
43+
For more information about an error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)