freshen: resolve root vars
Without doing so we use the same candidate cache entry for `?0: Trait<?1>` and `?0: Trait<?0>`. These goals are different and we must not use the same entry for them.
This commit is contained in:
parent
91535ad026
commit
f392a870e9
@ -56,49 +56,46 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn freshen_ty<F>(&mut self, opt_ty: Option<Ty<'tcx>>, key: ty::InferTy, mk_fresh: F) -> Ty<'tcx>
|
fn freshen_ty<F>(&mut self, input: Result<Ty<'tcx>, ty::InferTy>, mk_fresh: F) -> Ty<'tcx>
|
||||||
where
|
where
|
||||||
F: FnOnce(u32) -> Ty<'tcx>,
|
F: FnOnce(u32) -> Ty<'tcx>,
|
||||||
{
|
{
|
||||||
if let Some(ty) = opt_ty {
|
match input {
|
||||||
return ty.fold_with(self);
|
Ok(ty) => ty.fold_with(self),
|
||||||
}
|
Err(key) => match self.ty_freshen_map.entry(key) {
|
||||||
|
Entry::Occupied(entry) => *entry.get(),
|
||||||
match self.ty_freshen_map.entry(key) {
|
Entry::Vacant(entry) => {
|
||||||
Entry::Occupied(entry) => *entry.get(),
|
let index = self.ty_freshen_count;
|
||||||
Entry::Vacant(entry) => {
|
self.ty_freshen_count += 1;
|
||||||
let index = self.ty_freshen_count;
|
let t = mk_fresh(index);
|
||||||
self.ty_freshen_count += 1;
|
entry.insert(t);
|
||||||
let t = mk_fresh(index);
|
t
|
||||||
entry.insert(t);
|
}
|
||||||
t
|
},
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn freshen_const<F>(
|
fn freshen_const<F>(
|
||||||
&mut self,
|
&mut self,
|
||||||
opt_ct: Option<ty::Const<'tcx>>,
|
input: Result<ty::Const<'tcx>, ty::InferConst>,
|
||||||
key: ty::InferConst,
|
|
||||||
freshener: F,
|
freshener: F,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
) -> ty::Const<'tcx>
|
) -> ty::Const<'tcx>
|
||||||
where
|
where
|
||||||
F: FnOnce(u32) -> ty::InferConst,
|
F: FnOnce(u32) -> ty::InferConst,
|
||||||
{
|
{
|
||||||
if let Some(ct) = opt_ct {
|
match input {
|
||||||
return ct.fold_with(self);
|
Ok(ct) => ct.fold_with(self),
|
||||||
}
|
Err(key) => match self.const_freshen_map.entry(key) {
|
||||||
|
Entry::Occupied(entry) => *entry.get(),
|
||||||
match self.const_freshen_map.entry(key) {
|
Entry::Vacant(entry) => {
|
||||||
Entry::Occupied(entry) => *entry.get(),
|
let index = self.const_freshen_count;
|
||||||
Entry::Vacant(entry) => {
|
self.const_freshen_count += 1;
|
||||||
let index = self.const_freshen_count;
|
let ct = ty::Const::new_infer(self.infcx.tcx, freshener(index), ty);
|
||||||
self.const_freshen_count += 1;
|
entry.insert(ct);
|
||||||
let ct = ty::Const::new_infer(self.infcx.tcx, freshener(index), ty);
|
ct
|
||||||
entry.insert(ct);
|
}
|
||||||
ct
|
},
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -146,19 +143,22 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for TypeFreshener<'a, 'tcx> {
|
|||||||
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
||||||
match ct.kind() {
|
match ct.kind() {
|
||||||
ty::ConstKind::Infer(ty::InferConst::Var(v)) => {
|
ty::ConstKind::Infer(ty::InferConst::Var(v)) => {
|
||||||
let opt_ct =
|
let mut inner = self.infcx.inner.borrow_mut();
|
||||||
self.infcx.inner.borrow_mut().const_unification_table().probe_value(v).known();
|
let input =
|
||||||
self.freshen_const(opt_ct, ty::InferConst::Var(v), ty::InferConst::Fresh, ct.ty())
|
inner.const_unification_table().probe_value(v).known().ok_or_else(|| {
|
||||||
|
ty::InferConst::Var(inner.const_unification_table().find(v).vid)
|
||||||
|
});
|
||||||
|
drop(inner);
|
||||||
|
self.freshen_const(input, ty::InferConst::Fresh, ct.ty())
|
||||||
}
|
}
|
||||||
ty::ConstKind::Infer(ty::InferConst::EffectVar(v)) => {
|
ty::ConstKind::Infer(ty::InferConst::EffectVar(v)) => {
|
||||||
let opt_ct =
|
let mut inner = self.infcx.inner.borrow_mut();
|
||||||
self.infcx.inner.borrow_mut().effect_unification_table().probe_value(v).known();
|
let input =
|
||||||
self.freshen_const(
|
inner.effect_unification_table().probe_value(v).known().ok_or_else(|| {
|
||||||
opt_ct,
|
ty::InferConst::EffectVar(inner.effect_unification_table().find(v).vid)
|
||||||
ty::InferConst::EffectVar(v),
|
});
|
||||||
ty::InferConst::Fresh,
|
drop(inner);
|
||||||
ct.ty(),
|
self.freshen_const(input, ty::InferConst::Fresh, ct.ty())
|
||||||
)
|
|
||||||
}
|
}
|
||||||
ty::ConstKind::Infer(ty::InferConst::Fresh(i)) => {
|
ty::ConstKind::Infer(ty::InferConst::Fresh(i)) => {
|
||||||
if i >= self.const_freshen_count {
|
if i >= self.const_freshen_count {
|
||||||
@ -191,35 +191,37 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> {
|
|||||||
fn fold_infer_ty(&mut self, v: ty::InferTy) -> Option<Ty<'tcx>> {
|
fn fold_infer_ty(&mut self, v: ty::InferTy) -> Option<Ty<'tcx>> {
|
||||||
match v {
|
match v {
|
||||||
ty::TyVar(v) => {
|
ty::TyVar(v) => {
|
||||||
let opt_ty = self.infcx.inner.borrow_mut().type_variables().probe(v).known();
|
let mut inner = self.infcx.inner.borrow_mut();
|
||||||
Some(self.freshen_ty(opt_ty, ty::TyVar(v), |n| Ty::new_fresh(self.infcx.tcx, n)))
|
let input = inner
|
||||||
|
.type_variables()
|
||||||
|
.probe(v)
|
||||||
|
.known()
|
||||||
|
.ok_or_else(|| ty::TyVar(inner.type_variables().root_var(v)));
|
||||||
|
drop(inner);
|
||||||
|
Some(self.freshen_ty(input, |n| Ty::new_fresh(self.infcx.tcx, n)))
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::IntVar(v) => Some(
|
ty::IntVar(v) => {
|
||||||
self.freshen_ty(
|
let mut inner = self.infcx.inner.borrow_mut();
|
||||||
self.infcx
|
let input = inner
|
||||||
.inner
|
.int_unification_table()
|
||||||
.borrow_mut()
|
.probe_value(v)
|
||||||
.int_unification_table()
|
.map(|v| v.to_type(self.infcx.tcx))
|
||||||
.probe_value(v)
|
.ok_or_else(|| ty::IntVar(inner.int_unification_table().find(v)));
|
||||||
.map(|v| v.to_type(self.infcx.tcx)),
|
drop(inner);
|
||||||
ty::IntVar(v),
|
Some(self.freshen_ty(input, |n| Ty::new_fresh_int(self.infcx.tcx, n)))
|
||||||
|n| Ty::new_fresh_int(self.infcx.tcx, n),
|
}
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
ty::FloatVar(v) => Some(
|
ty::FloatVar(v) => {
|
||||||
self.freshen_ty(
|
let mut inner = self.infcx.inner.borrow_mut();
|
||||||
self.infcx
|
let input = inner
|
||||||
.inner
|
.float_unification_table()
|
||||||
.borrow_mut()
|
.probe_value(v)
|
||||||
.float_unification_table()
|
.map(|v| v.to_type(self.infcx.tcx))
|
||||||
.probe_value(v)
|
.ok_or_else(|| ty::FloatVar(inner.float_unification_table().find(v)));
|
||||||
.map(|v| v.to_type(self.infcx.tcx)),
|
drop(inner);
|
||||||
ty::FloatVar(v),
|
Some(self.freshen_ty(input, |n| Ty::new_fresh_float(self.infcx.tcx, n)))
|
||||||
|n| Ty::new_fresh_float(self.infcx.tcx, n),
|
}
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
ty::FreshTy(ct) | ty::FreshIntTy(ct) | ty::FreshFloatTy(ct) => {
|
ty::FreshTy(ct) | ty::FreshIntTy(ct) | ty::FreshFloatTy(ct) => {
|
||||||
if ct >= self.ty_freshen_count {
|
if ct >= self.ty_freshen_count {
|
||||||
|
@ -40,7 +40,6 @@ use rustc_middle::dep_graph::DepNodeIndex;
|
|||||||
use rustc_middle::mir::interpret::ErrorHandled;
|
use rustc_middle::mir::interpret::ErrorHandled;
|
||||||
use rustc_middle::ty::_match::MatchAgainstFreshVars;
|
use rustc_middle::ty::_match::MatchAgainstFreshVars;
|
||||||
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
|
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
|
||||||
use rustc_middle::ty::fold::BottomUpFolder;
|
|
||||||
use rustc_middle::ty::relate::TypeRelation;
|
use rustc_middle::ty::relate::TypeRelation;
|
||||||
use rustc_middle::ty::GenericArgsRef;
|
use rustc_middle::ty::GenericArgsRef;
|
||||||
use rustc_middle::ty::{self, EarlyBinder, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate};
|
use rustc_middle::ty::{self, EarlyBinder, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate};
|
||||||
@ -2435,28 +2434,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
|||||||
match self.match_impl(impl_def_id, impl_trait_header, obligation) {
|
match self.match_impl(impl_def_id, impl_trait_header, obligation) {
|
||||||
Ok(args) => args,
|
Ok(args) => args,
|
||||||
Err(()) => {
|
Err(()) => {
|
||||||
// FIXME: A rematch may fail when a candidate cache hit occurs
|
let predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);
|
||||||
// on the freshened form of the trait predicate, but the match
|
bug!("impl {impl_def_id:?} was matchable against {predicate:?} but now is not")
|
||||||
// fails for some reason that is not captured in the freshened
|
|
||||||
// cache key. For example, equating an impl trait ref against
|
|
||||||
// the placeholder trait ref may fail due the Generalizer relation
|
|
||||||
// raising a CyclicalTy error due to a sub_root_var relation
|
|
||||||
// for a variable being generalized...
|
|
||||||
let guar = self.infcx.dcx().span_delayed_bug(
|
|
||||||
obligation.cause.span,
|
|
||||||
format!(
|
|
||||||
"Impl {impl_def_id:?} was matchable against {obligation:?} but now is not"
|
|
||||||
),
|
|
||||||
);
|
|
||||||
let value = self.infcx.fresh_args_for_item(obligation.cause.span, impl_def_id);
|
|
||||||
let err = Ty::new_error(self.tcx(), guar);
|
|
||||||
let value = value.fold_with(&mut BottomUpFolder {
|
|
||||||
tcx: self.tcx(),
|
|
||||||
ty_op: |_| err,
|
|
||||||
lt_op: |l| l,
|
|
||||||
ct_op: |c| c,
|
|
||||||
});
|
|
||||||
Normalized { value, obligations: vec![] }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,8 @@ use std::marker::PhantomData;
|
|||||||
fn _alias_check() {
|
fn _alias_check() {
|
||||||
WrongImpl::foo(0i32);
|
WrongImpl::foo(0i32);
|
||||||
//~^ ERROR the trait bound `RawImpl<_>: Raw<_>` is not satisfied
|
//~^ ERROR the trait bound `RawImpl<_>: Raw<_>` is not satisfied
|
||||||
|
//~| ERROR the trait bound `RawImpl<_>: Raw<_>` is not satisfied
|
||||||
|
//~| ERROR the trait bound `RawImpl<_>: Raw<_>` is not satisfied
|
||||||
WrongImpl::<()>::foo(0i32);
|
WrongImpl::<()>::foo(0i32);
|
||||||
//~^ ERROR the trait bound `RawImpl<()>: Raw<()>` is not satisfied
|
//~^ ERROR the trait bound `RawImpl<()>: Raw<()>` is not satisfied
|
||||||
//~| ERROR trait bounds were not satisfied
|
//~| ERROR trait bounds were not satisfied
|
||||||
|
@ -1,3 +1,18 @@
|
|||||||
|
error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied
|
||||||
|
--> $DIR/issue-62742.rs:4:5
|
||||||
|
|
|
||||||
|
LL | WrongImpl::foo(0i32);
|
||||||
|
| ^^^^^^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>`
|
||||||
|
|
|
||||||
|
= help: the trait `Raw<[_]>` is implemented for `RawImpl<_>`
|
||||||
|
note: required by a bound in `SafeImpl::<T, A>::foo`
|
||||||
|
--> $DIR/issue-62742.rs:30:20
|
||||||
|
|
|
||||||
|
LL | impl<T: ?Sized, A: Raw<T>> SafeImpl<T, A> {
|
||||||
|
| ^^^^^^ required by this bound in `SafeImpl::<T, A>::foo`
|
||||||
|
LL | pub fn foo(value: A::Value) {}
|
||||||
|
| --- required by a bound in this associated function
|
||||||
|
|
||||||
error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied
|
error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied
|
||||||
--> $DIR/issue-62742.rs:4:5
|
--> $DIR/issue-62742.rs:4:5
|
||||||
|
|
|
|
||||||
@ -6,13 +21,21 @@ LL | WrongImpl::foo(0i32);
|
|||||||
|
|
|
|
||||||
= help: the trait `Raw<[_]>` is implemented for `RawImpl<_>`
|
= help: the trait `Raw<[_]>` is implemented for `RawImpl<_>`
|
||||||
note: required by a bound in `SafeImpl`
|
note: required by a bound in `SafeImpl`
|
||||||
--> $DIR/issue-62742.rs:26:35
|
--> $DIR/issue-62742.rs:28:35
|
||||||
|
|
|
|
||||||
LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
|
LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
|
||||||
| ^^^^^^ required by this bound in `SafeImpl`
|
| ^^^^^^ required by this bound in `SafeImpl`
|
||||||
|
|
||||||
|
error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied
|
||||||
|
--> $DIR/issue-62742.rs:4:5
|
||||||
|
|
|
||||||
|
LL | WrongImpl::foo(0i32);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>`
|
||||||
|
|
|
||||||
|
= help: the trait `Raw<[_]>` is implemented for `RawImpl<_>`
|
||||||
|
|
||||||
error[E0599]: the function or associated item `foo` exists for struct `SafeImpl<(), RawImpl<()>>`, but its trait bounds were not satisfied
|
error[E0599]: the function or associated item `foo` exists for struct `SafeImpl<(), RawImpl<()>>`, but its trait bounds were not satisfied
|
||||||
--> $DIR/issue-62742.rs:6:22
|
--> $DIR/issue-62742.rs:8:22
|
||||||
|
|
|
|
||||||
LL | WrongImpl::<()>::foo(0i32);
|
LL | WrongImpl::<()>::foo(0i32);
|
||||||
| ^^^ function or associated item cannot be called on `SafeImpl<(), RawImpl<()>>` due to unsatisfied trait bounds
|
| ^^^ function or associated item cannot be called on `SafeImpl<(), RawImpl<()>>` due to unsatisfied trait bounds
|
||||||
@ -24,20 +47,20 @@ LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
|
|||||||
| ----------------------------------------- function or associated item `foo` not found for this struct
|
| ----------------------------------------- function or associated item `foo` not found for this struct
|
||||||
|
|
|
|
||||||
note: trait bound `RawImpl<()>: Raw<()>` was not satisfied
|
note: trait bound `RawImpl<()>: Raw<()>` was not satisfied
|
||||||
--> $DIR/issue-62742.rs:28:20
|
--> $DIR/issue-62742.rs:30:20
|
||||||
|
|
|
|
||||||
LL | impl<T: ?Sized, A: Raw<T>> SafeImpl<T, A> {
|
LL | impl<T: ?Sized, A: Raw<T>> SafeImpl<T, A> {
|
||||||
| ^^^^^^ --------------
|
| ^^^^^^ --------------
|
||||||
| |
|
| |
|
||||||
| unsatisfied trait bound introduced here
|
| unsatisfied trait bound introduced here
|
||||||
note: the trait `Raw` must be implemented
|
note: the trait `Raw` must be implemented
|
||||||
--> $DIR/issue-62742.rs:12:1
|
--> $DIR/issue-62742.rs:14:1
|
||||||
|
|
|
|
||||||
LL | pub trait Raw<T: ?Sized> {
|
LL | pub trait Raw<T: ?Sized> {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0277]: the trait bound `RawImpl<()>: Raw<()>` is not satisfied
|
error[E0277]: the trait bound `RawImpl<()>: Raw<()>` is not satisfied
|
||||||
--> $DIR/issue-62742.rs:6:5
|
--> $DIR/issue-62742.rs:8:5
|
||||||
|
|
|
|
||||||
LL | WrongImpl::<()>::foo(0i32);
|
LL | WrongImpl::<()>::foo(0i32);
|
||||||
| ^^^^^^^^^^^^^^^ the trait `Raw<()>` is not implemented for `RawImpl<()>`
|
| ^^^^^^^^^^^^^^^ the trait `Raw<()>` is not implemented for `RawImpl<()>`
|
||||||
@ -45,12 +68,12 @@ LL | WrongImpl::<()>::foo(0i32);
|
|||||||
= help: the trait `Raw<[()]>` is implemented for `RawImpl<()>`
|
= help: the trait `Raw<[()]>` is implemented for `RawImpl<()>`
|
||||||
= help: for that trait implementation, expected `[()]`, found `()`
|
= help: for that trait implementation, expected `[()]`, found `()`
|
||||||
note: required by a bound in `SafeImpl`
|
note: required by a bound in `SafeImpl`
|
||||||
--> $DIR/issue-62742.rs:26:35
|
--> $DIR/issue-62742.rs:28:35
|
||||||
|
|
|
|
||||||
LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
|
LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
|
||||||
| ^^^^^^ required by this bound in `SafeImpl`
|
| ^^^^^^ required by this bound in `SafeImpl`
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 5 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0277, E0599.
|
Some errors have detailed explanations: E0277, E0599.
|
||||||
For more information about an error, try `rustc --explain E0277`.
|
For more information about an error, try `rustc --explain E0277`.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user