Auto merge of #151676 - adwinwhite:next-263, r=lcnr

Do not return incorrectly constrained opaques in `method_autoderef_steps`


Fixes https://github.com/rust-lang/trait-system-refactor-initiative/issues/263

r? @lcnr
This commit is contained in:
bors 2026-01-26 13:54:11 +00:00
commit 474276961f
4 changed files with 113 additions and 10 deletions

View file

@ -415,10 +415,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
infcx.instantiate_canonical(span, &query_input.canonical);
let query::MethodAutoderefSteps { predefined_opaques_in_body: _, self_ty } = value;
debug!(?self_ty, ?query_input, "probe_op: Mode::Path");
let prev_opaque_entries = self.inner.borrow_mut().opaque_types().num_entries();
MethodAutoderefStepsResult {
steps: infcx.tcx.arena.alloc_from_iter([CandidateStep {
self_ty: self
.make_query_response_ignoring_pending_obligations(var_values, self_ty),
self_ty: self.make_query_response_ignoring_pending_obligations(
var_values,
self_ty,
prev_opaque_entries,
),
self_ty_is_opaque: false,
autoderefs: 0,
from_unsafe_deref: false,
@ -607,6 +611,7 @@ pub(crate) fn method_autoderef_steps<'tcx>(
debug!(?key, ?ty, ?prev, "ignore duplicate in `opaque_types_storage`");
}
}
let prev_opaque_entries = infcx.inner.borrow_mut().opaque_types().num_entries();
// We accept not-yet-defined opaque types in the autoderef
// chain to support recursive calls. We do error if the final
@ -650,8 +655,11 @@ pub(crate) fn method_autoderef_steps<'tcx>(
.zip(reachable_via_deref)
.map(|((ty, d), reachable_via_deref)| {
let step = CandidateStep {
self_ty: infcx
.make_query_response_ignoring_pending_obligations(inference_vars, ty),
self_ty: infcx.make_query_response_ignoring_pending_obligations(
inference_vars,
ty,
prev_opaque_entries,
),
self_ty_is_opaque: self_ty_is_opaque(ty),
autoderefs: d,
from_unsafe_deref: reached_raw_pointer,
@ -671,8 +679,11 @@ pub(crate) fn method_autoderef_steps<'tcx>(
.by_ref()
.map(|(ty, d)| {
let step = CandidateStep {
self_ty: infcx
.make_query_response_ignoring_pending_obligations(inference_vars, ty),
self_ty: infcx.make_query_response_ignoring_pending_obligations(
inference_vars,
ty,
prev_opaque_entries,
),
self_ty_is_opaque: self_ty_is_opaque(ty),
autoderefs: d,
from_unsafe_deref: reached_raw_pointer,
@ -692,11 +703,19 @@ pub(crate) fn method_autoderef_steps<'tcx>(
let opt_bad_ty = match final_ty.kind() {
ty::Infer(ty::TyVar(_)) if !self_ty_is_opaque(final_ty) => Some(MethodAutoderefBadTy {
reached_raw_pointer,
ty: infcx.make_query_response_ignoring_pending_obligations(inference_vars, final_ty),
ty: infcx.make_query_response_ignoring_pending_obligations(
inference_vars,
final_ty,
prev_opaque_entries,
),
}),
ty::Error(_) => Some(MethodAutoderefBadTy {
reached_raw_pointer,
ty: infcx.make_query_response_ignoring_pending_obligations(inference_vars, final_ty),
ty: infcx.make_query_response_ignoring_pending_obligations(
inference_vars,
final_ty,
prev_opaque_entries,
),
}),
ty::Array(elem_ty, _) => {
let autoderefs = steps.iter().filter(|s| s.reachable_via_deref).count() - 1;
@ -704,6 +723,7 @@ pub(crate) fn method_autoderef_steps<'tcx>(
self_ty: infcx.make_query_response_ignoring_pending_obligations(
inference_vars,
Ty::new_slice(infcx.tcx, *elem_ty),
prev_opaque_entries,
),
self_ty_is_opaque: false,
autoderefs,

View file

@ -24,7 +24,8 @@ use crate::infer::canonical::{
};
use crate::infer::region_constraints::RegionConstraintData;
use crate::infer::{
DefineOpaqueTypes, InferCtxt, InferOk, InferResult, SubregionOrigin, TypeOutlivesConstraint,
DefineOpaqueTypes, InferCtxt, InferOk, InferResult, OpaqueTypeStorageEntries, SubregionOrigin,
TypeOutlivesConstraint,
};
use crate::traits::query::NoSolution;
use crate::traits::{ObligationCause, PredicateObligations, ScrubbedTraitError, TraitEngine};
@ -81,6 +82,7 @@ impl<'tcx> InferCtxt<'tcx> {
&self,
inference_vars: CanonicalVarValues<'tcx>,
answer: T,
prev_entries: OpaqueTypeStorageEntries,
) -> Canonical<'tcx, QueryResponse<'tcx, T>>
where
T: Debug + TypeFoldable<TyCtxt<'tcx>>,
@ -96,7 +98,7 @@ impl<'tcx> InferCtxt<'tcx> {
self.inner
.borrow_mut()
.opaque_type_storage
.iter_opaque_types()
.opaque_types_added_since(prev_entries)
.map(|(k, v)| (k, v.ty))
.collect()
} else {

View file

@ -0,0 +1,38 @@
//@ compile-flags: -Znext-solver
// Regression test for trait-system-refactor-initiative/issues/263
// Previously `method_auto_deref_steps` would also return opaque
// types which have already been defined in the parent context.
//
// We then handled these opaque types by emitting `AliasRelate` goals
// when instantiating its result, assuming that operation to be infallible.
// By returning opaque type constraints from the parent context and
// constraining the hidden type without reproving the item bounds of
// the opaque, this ended up causing ICE.
use std::ops::Deref;
trait Trait {}
struct Inv<T>(*mut T);
impl Trait for i32 {}
impl Deref for Inv<u32> {
type Target = u32;
fn deref(&self) -> &Self::Target {
todo!()
}
}
fn mk<T>() -> T { todo!() }
fn foo() -> Inv<impl Trait> {
//~^ ERROR: the trait bound `u32: Trait` is not satisfied [E0277]
let mut x: Inv<_> = mk();
if false {
return x;
//~^ ERROR: the trait bound `u32: Trait` is not satisfied [E0277]
}
x.count_ones();
x
//~^ ERROR: mismatched types [E0308]
}
fn main() {}

View file

@ -0,0 +1,43 @@
error[E0277]: the trait bound `u32: Trait` is not satisfied
--> $DIR/method_autoderef_constraints.rs:29:16
|
LL | return x;
| ^ the trait `Trait` is not implemented for `u32`
|
help: the trait `Trait` is implemented for `i32`
--> $DIR/method_autoderef_constraints.rs:16:1
|
LL | impl Trait for i32 {}
| ^^^^^^^^^^^^^^^^^^
error[E0308]: mismatched types
--> $DIR/method_autoderef_constraints.rs:34:5
|
LL | fn foo() -> Inv<impl Trait> {
| ---------------
| | |
| | the expected opaque type
| expected `Inv<impl Trait>` because of return type
...
LL | x
| ^ types differ
|
= note: expected struct `Inv<impl Trait>`
found struct `Inv<u32>`
error[E0277]: the trait bound `u32: Trait` is not satisfied
--> $DIR/method_autoderef_constraints.rs:25:1
|
LL | fn foo() -> Inv<impl Trait> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `u32`
|
help: the trait `Trait` is implemented for `i32`
--> $DIR/method_autoderef_constraints.rs:16:1
|
LL | impl Trait for i32 {}
| ^^^^^^^^^^^^^^^^^^
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.