Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 28 additions & 8 deletions compiler/rustc_hir_typeck/src/method/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -692,18 +703,27 @@ 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;
steps.push(CandidateStep {
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,
Expand Down
6 changes: 4 additions & 2 deletions compiler/rustc_infer/src/infer/canonical/query_response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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>>,
Expand All @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
@@ -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() {}
Original file line number Diff line number Diff line change
@@ -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