Skip to content

Commit d99a07d

Browse files
committed
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.
1 parent f5c56ec commit d99a07d

File tree

4 files changed

+104
-106
lines changed

4 files changed

+104
-106
lines changed

compiler/rustc_infer/src/infer/freshen.rs

+70-76
Original file line numberDiff line numberDiff line change
@@ -56,49 +56,46 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> {
5656
}
5757
}
5858

59-
fn freshen_ty<F>(&mut self, opt_ty: Option<Ty<'tcx>>, key: ty::InferTy, mk_fresh: F) -> Ty<'tcx>
59+
fn freshen_ty<F>(&mut self, input: Result<Ty<'tcx>, ty::InferTy>, mk_fresh: F) -> Ty<'tcx>
6060
where
6161
F: FnOnce(u32) -> Ty<'tcx>,
6262
{
63-
if let Some(ty) = opt_ty {
64-
return ty.fold_with(self);
65-
}
66-
67-
match self.ty_freshen_map.entry(key) {
68-
Entry::Occupied(entry) => *entry.get(),
69-
Entry::Vacant(entry) => {
70-
let index = self.ty_freshen_count;
71-
self.ty_freshen_count += 1;
72-
let t = mk_fresh(index);
73-
entry.insert(t);
74-
t
75-
}
63+
match input {
64+
Ok(ty) => ty.fold_with(self),
65+
Err(key) => match self.ty_freshen_map.entry(key) {
66+
Entry::Occupied(entry) => *entry.get(),
67+
Entry::Vacant(entry) => {
68+
let index = self.ty_freshen_count;
69+
self.ty_freshen_count += 1;
70+
let t = mk_fresh(index);
71+
entry.insert(t);
72+
t
73+
}
74+
},
7675
}
7776
}
7877

7978
fn freshen_const<F>(
8079
&mut self,
81-
opt_ct: Option<ty::Const<'tcx>>,
82-
key: ty::InferConst,
80+
input: Result<ty::Const<'tcx>, ty::InferConst>,
8381
freshener: F,
8482
ty: Ty<'tcx>,
8583
) -> ty::Const<'tcx>
8684
where
8785
F: FnOnce(u32) -> ty::InferConst,
8886
{
89-
if let Some(ct) = opt_ct {
90-
return ct.fold_with(self);
91-
}
92-
93-
match self.const_freshen_map.entry(key) {
94-
Entry::Occupied(entry) => *entry.get(),
95-
Entry::Vacant(entry) => {
96-
let index = self.const_freshen_count;
97-
self.const_freshen_count += 1;
98-
let ct = ty::Const::new_infer(self.infcx.tcx, freshener(index), ty);
99-
entry.insert(ct);
100-
ct
101-
}
87+
match input {
88+
Ok(ct) => ct.fold_with(self),
89+
Err(key) => match self.const_freshen_map.entry(key) {
90+
Entry::Occupied(entry) => *entry.get(),
91+
Entry::Vacant(entry) => {
92+
let index = self.const_freshen_count;
93+
self.const_freshen_count += 1;
94+
let ct = ty::Const::new_infer(self.infcx.tcx, freshener(index), ty);
95+
entry.insert(ct);
96+
ct
97+
}
98+
},
10299
}
103100
}
104101
}
@@ -146,30 +143,25 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for TypeFreshener<'a, 'tcx> {
146143
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
147144
match ct.kind() {
148145
ty::ConstKind::Infer(ty::InferConst::Var(v)) => {
149-
let opt_ct = self
150-
.infcx
151-
.inner
152-
.borrow_mut()
153-
.const_unification_table()
154-
.probe_value(v)
155-
.val
156-
.known();
157-
self.freshen_const(opt_ct, ty::InferConst::Var(v), ty::InferConst::Fresh, ct.ty())
146+
let mut inner = self.infcx.inner.borrow_mut();
147+
let input =
148+
inner.const_unification_table().probe_value(v).val.known().ok_or_else(|| {
149+
ty::InferConst::Var(inner.const_unification_table().find(v).vid)
150+
});
151+
drop(inner);
152+
self.freshen_const(input, ty::InferConst::Fresh, ct.ty())
158153
}
159154
ty::ConstKind::Infer(ty::InferConst::EffectVar(v)) => {
160-
let opt_ct = self
161-
.infcx
162-
.inner
163-
.borrow_mut()
155+
let mut inner = self.infcx.inner.borrow_mut();
156+
let input = inner
164157
.effect_unification_table()
165158
.probe_value(v)
166-
.map(|effect| effect.as_const(self.infcx.tcx));
167-
self.freshen_const(
168-
opt_ct,
169-
ty::InferConst::EffectVar(v),
170-
ty::InferConst::Fresh,
171-
ct.ty(),
172-
)
159+
.map(|effect| effect.as_const(self.infcx.tcx))
160+
.ok_or_else(|| {
161+
ty::InferConst::EffectVar(inner.effect_unification_table().find(v).vid)
162+
});
163+
drop(inner);
164+
self.freshen_const(input, ty::InferConst::Fresh, ct.ty())
173165
}
174166
ty::ConstKind::Infer(ty::InferConst::Fresh(i)) => {
175167
if i >= self.const_freshen_count {
@@ -202,35 +194,37 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> {
202194
fn fold_infer_ty(&mut self, v: ty::InferTy) -> Option<Ty<'tcx>> {
203195
match v {
204196
ty::TyVar(v) => {
205-
let opt_ty = self.infcx.inner.borrow_mut().type_variables().probe(v).known();
206-
Some(self.freshen_ty(opt_ty, ty::TyVar(v), |n| Ty::new_fresh(self.infcx.tcx, n)))
197+
let mut inner = self.infcx.inner.borrow_mut();
198+
let input = inner
199+
.type_variables()
200+
.probe(v)
201+
.known()
202+
.ok_or_else(|| ty::TyVar(inner.type_variables().root_var(v)));
203+
drop(inner);
204+
Some(self.freshen_ty(input, |n| Ty::new_fresh(self.infcx.tcx, n)))
207205
}
208206

209-
ty::IntVar(v) => Some(
210-
self.freshen_ty(
211-
self.infcx
212-
.inner
213-
.borrow_mut()
214-
.int_unification_table()
215-
.probe_value(v)
216-
.map(|v| v.to_type(self.infcx.tcx)),
217-
ty::IntVar(v),
218-
|n| Ty::new_fresh_int(self.infcx.tcx, n),
219-
),
220-
),
221-
222-
ty::FloatVar(v) => Some(
223-
self.freshen_ty(
224-
self.infcx
225-
.inner
226-
.borrow_mut()
227-
.float_unification_table()
228-
.probe_value(v)
229-
.map(|v| v.to_type(self.infcx.tcx)),
230-
ty::FloatVar(v),
231-
|n| Ty::new_fresh_float(self.infcx.tcx, n),
232-
),
233-
),
207+
ty::IntVar(v) => {
208+
let mut inner = self.infcx.inner.borrow_mut();
209+
let input = inner
210+
.int_unification_table()
211+
.probe_value(v)
212+
.map(|v| v.to_type(self.infcx.tcx))
213+
.ok_or_else(|| ty::IntVar(inner.int_unification_table().find(v)));
214+
drop(inner);
215+
Some(self.freshen_ty(input, |n| Ty::new_fresh_int(self.infcx.tcx, n)))
216+
}
217+
218+
ty::FloatVar(v) => {
219+
let mut inner = self.infcx.inner.borrow_mut();
220+
let input = inner
221+
.float_unification_table()
222+
.probe_value(v)
223+
.map(|v| v.to_type(self.infcx.tcx))
224+
.ok_or_else(|| ty::FloatVar(inner.float_unification_table().find(v)));
225+
drop(inner);
226+
Some(self.freshen_ty(input, |n| Ty::new_fresh_float(self.infcx.tcx, n)))
227+
}
234228

235229
ty::FreshTy(ct) | ty::FreshIntTy(ct) | ty::FreshFloatTy(ct) => {
236230
if ct >= self.ty_freshen_count {

compiler/rustc_trait_selection/src/traits/select/mod.rs

+2-23
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ use rustc_middle::dep_graph::DepNodeIndex;
4040
use rustc_middle::mir::interpret::ErrorHandled;
4141
use rustc_middle::ty::_match::MatchAgainstFreshVars;
4242
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
43-
use rustc_middle::ty::fold::BottomUpFolder;
4443
use rustc_middle::ty::relate::TypeRelation;
4544
use rustc_middle::ty::GenericArgsRef;
4645
use rustc_middle::ty::{self, EarlyBinder, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate};
@@ -2417,28 +2416,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
24172416
match self.match_impl(impl_def_id, impl_trait_ref, obligation) {
24182417
Ok(args) => args,
24192418
Err(()) => {
2420-
// FIXME: A rematch may fail when a candidate cache hit occurs
2421-
// on the freshened form of the trait predicate, but the match
2422-
// fails for some reason that is not captured in the freshened
2423-
// cache key. For example, equating an impl trait ref against
2424-
// the placeholder trait ref may fail due the Generalizer relation
2425-
// raising a CyclicalTy error due to a sub_root_var relation
2426-
// for a variable being generalized...
2427-
let guar = self.infcx.dcx().span_delayed_bug(
2428-
obligation.cause.span,
2429-
format!(
2430-
"Impl {impl_def_id:?} was matchable against {obligation:?} but now is not"
2431-
),
2432-
);
2433-
let value = self.infcx.fresh_args_for_item(obligation.cause.span, impl_def_id);
2434-
let err = Ty::new_error(self.tcx(), guar);
2435-
let value = value.fold_with(&mut BottomUpFolder {
2436-
tcx: self.tcx(),
2437-
ty_op: |_| err,
2438-
lt_op: |l| l,
2439-
ct_op: |c| c,
2440-
});
2441-
Normalized { value, obligations: vec![] }
2419+
let predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);
2420+
bug!("impl {impl_def_id:?} was matchable against {predicate:?} but now is not")
24422421
}
24432422
}
24442423
}

tests/ui/impl-trait/issues/issue-62742.rs

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ use std::marker::PhantomData;
33
fn _alias_check() {
44
WrongImpl::foo(0i32);
55
//~^ ERROR the trait bound `RawImpl<_>: Raw<_>` is not satisfied
6+
//~| ERROR the trait bound `RawImpl<_>: Raw<_>` is not satisfied
7+
//~| ERROR the trait bound `RawImpl<_>: Raw<_>` is not satisfied
68
WrongImpl::<()>::foo(0i32);
79
//~^ ERROR the trait bound `RawImpl<()>: Raw<()>` is not satisfied
810
//~| ERROR trait bounds were not satisfied
+30-7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied
2+
--> $DIR/issue-62742.rs:4:5
3+
|
4+
LL | WrongImpl::foo(0i32);
5+
| ^^^^^^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>`
6+
|
7+
= help: the trait `Raw<[_]>` is implemented for `RawImpl<_>`
8+
note: required by a bound in `SafeImpl::<T, A>::foo`
9+
--> $DIR/issue-62742.rs:30:20
10+
|
11+
LL | impl<T: ?Sized, A: Raw<T>> SafeImpl<T, A> {
12+
| ^^^^^^ required by this bound in `SafeImpl::<T, A>::foo`
13+
LL | pub fn foo(value: A::Value) {}
14+
| --- required by a bound in this associated function
15+
116
error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied
217
--> $DIR/issue-62742.rs:4:5
318
|
@@ -6,13 +21,21 @@ LL | WrongImpl::foo(0i32);
621
|
722
= help: the trait `Raw<[_]>` is implemented for `RawImpl<_>`
823
note: required by a bound in `SafeImpl`
9-
--> $DIR/issue-62742.rs:26:35
24+
--> $DIR/issue-62742.rs:28:35
1025
|
1126
LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
1227
| ^^^^^^ required by this bound in `SafeImpl`
1328

29+
error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied
30+
--> $DIR/issue-62742.rs:4:5
31+
|
32+
LL | WrongImpl::foo(0i32);
33+
| ^^^^^^^^^^^^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>`
34+
|
35+
= help: the trait `Raw<[_]>` is implemented for `RawImpl<_>`
36+
1437
error[E0599]: the function or associated item `foo` exists for struct `SafeImpl<(), RawImpl<()>>`, but its trait bounds were not satisfied
15-
--> $DIR/issue-62742.rs:6:22
38+
--> $DIR/issue-62742.rs:8:22
1639
|
1740
LL | WrongImpl::<()>::foo(0i32);
1841
| ^^^ function or associated item cannot be called on `SafeImpl<(), RawImpl<()>>` due to unsatisfied trait bounds
@@ -24,33 +47,33 @@ LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
2447
| ----------------------------------------- function or associated item `foo` not found for this struct
2548
|
2649
note: trait bound `RawImpl<()>: Raw<()>` was not satisfied
27-
--> $DIR/issue-62742.rs:28:20
50+
--> $DIR/issue-62742.rs:30:20
2851
|
2952
LL | impl<T: ?Sized, A: Raw<T>> SafeImpl<T, A> {
3053
| ^^^^^^ --------------
3154
| |
3255
| unsatisfied trait bound introduced here
3356
note: the trait `Raw` must be implemented
34-
--> $DIR/issue-62742.rs:12:1
57+
--> $DIR/issue-62742.rs:14:1
3558
|
3659
LL | pub trait Raw<T: ?Sized> {
3760
| ^^^^^^^^^^^^^^^^^^^^^^^^
3861

3962
error[E0277]: the trait bound `RawImpl<()>: Raw<()>` is not satisfied
40-
--> $DIR/issue-62742.rs:6:5
63+
--> $DIR/issue-62742.rs:8:5
4164
|
4265
LL | WrongImpl::<()>::foo(0i32);
4366
| ^^^^^^^^^^^^^^^ the trait `Raw<()>` is not implemented for `RawImpl<()>`
4467
|
4568
= help: the trait `Raw<[()]>` is implemented for `RawImpl<()>`
4669
= help: for that trait implementation, expected `[()]`, found `()`
4770
note: required by a bound in `SafeImpl`
48-
--> $DIR/issue-62742.rs:26:35
71+
--> $DIR/issue-62742.rs:28:35
4972
|
5073
LL | pub struct SafeImpl<T: ?Sized, A: Raw<T>>(PhantomData<(A, T)>);
5174
| ^^^^^^ required by this bound in `SafeImpl`
5275

53-
error: aborting due to 3 previous errors
76+
error: aborting due to 5 previous errors
5477

5578
Some errors have detailed explanations: E0277, E0599.
5679
For more information about an error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)