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:
commit
474276961f
4 changed files with 113 additions and 10 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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() {}
|
||||
|
|
@ -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`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue