Skip to content

Commit 407c117

Browse files
committed
cleanup and comments
1 parent f69d672 commit 407c117

File tree

10 files changed

+224
-26
lines changed

10 files changed

+224
-26
lines changed

Diff for: compiler/rustc_infer/src/infer/combine.rs

+9-7
Original file line numberDiff line numberDiff line change
@@ -326,18 +326,16 @@ impl<'tcx> InferCtxt<'tcx> {
326326
) -> RelateResult<'tcx, ty::Const<'tcx>> {
327327
let span =
328328
self.inner.borrow_mut().const_unification_table().probe_value(target_vid).origin.span;
329-
let Generalization { value, needs_wf: _ } = generalize::generalize(
329+
// FIXME(generic_const_exprs): Occurs check failures for unevaluated
330+
// constants and generic expressions are not yet handled correctly.
331+
let Generalization { value_may_be_infer: value, needs_wf: _ } = generalize::generalize(
330332
self,
331333
&mut CombineDelegate { infcx: self, span, param_env },
332334
ct,
333335
target_vid,
334336
ty::Variance::Invariant,
335337
)?;
336338

337-
// FIXME(generic_const_exprs): Occurs check failures for unevaluated
338-
// constants and generic expressions are not yet handled correctly.
339-
let value = value.may_be_infer();
340-
341339
self.inner.borrow_mut().const_unification_table().union_value(
342340
target_vid,
343341
ConstVarValue {
@@ -449,7 +447,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
449447
// `'?2` and `?3` are fresh region/type inference
450448
// variables. (Down below, we will relate `a_ty <: b_ty`,
451449
// adding constraints like `'x: '?2` and `?1 <: ?3`.)
452-
let Generalization { value, needs_wf } = generalize::generalize(
450+
let Generalization { value_may_be_infer: b_ty, needs_wf } = generalize::generalize(
453451
self.infcx,
454452
&mut CombineDelegate {
455453
infcx: self.infcx,
@@ -461,7 +459,6 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
461459
ambient_variance,
462460
)?;
463461

464-
let b_ty = value.may_be_infer(); // we handle this further down.
465462
self.infcx.inner.borrow_mut().type_variables().instantiate(b_vid, b_ty);
466463

467464
if needs_wf {
@@ -501,6 +498,11 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
501498
}
502499
}
503500
}
501+
502+
// FIXME: This does not handle subtyping correctly, we should switch to
503+
// alias-relate in the new solver and could instead create a new inference
504+
// variable for `a_ty`, emitting `Projection(a_ty, a_infer)` and
505+
// `a_infer <: b_ty`.
504506
self.obligations.push(Obligation::new(
505507
self.tcx(),
506508
self.trace.cause.clone(),

Diff for: compiler/rustc_infer/src/infer/generalize.rs

+23-16
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ pub(super) fn generalize<'tcx, D: GeneralizerDelegate<'tcx>, T: Into<Term<'tcx>>
4747
};
4848

4949
assert!(!term.has_escaping_bound_vars());
50-
let value = generalizer.relate(term, term)?;
50+
let value_may_be_infer = generalizer.relate(term, term)?;
5151
let needs_wf = generalizer.needs_wf;
52-
Ok(Generalization { value: HandleProjection(value), needs_wf })
52+
Ok(Generalization { value_may_be_infer, needs_wf })
5353
}
5454

5555
/// Abstracts the handling of region vars between HIR and MIR/NLL typechecking
@@ -153,10 +153,11 @@ struct Generalizer<'me, 'tcx, D> {
153153

154154
cache: SsoHashMap<Ty<'tcx>, Ty<'tcx>>,
155155

156-
/// This is set once we're generalizing the arguments of an alias. In case
157-
/// we encounter an occurs check failure we generalize the alias to an
158-
/// inference variable instead of erroring. This is necessary to avoid
159-
/// incorrect errors when relating `?0` with `<?0 as Trait>::Assoc`.
156+
/// This is set once we're generalizing the arguments of an alias.
157+
///
158+
/// This is necessary to correctly handle
159+
/// `<T as Bar<<?0 as Foo>::Assoc>::Assoc == ?0`. This equality can
160+
/// hold by either normalizing the outer or the inner associated type.
160161
in_alias: bool,
161162

162163
/// See the field `needs_wf` in `Generalization`.
@@ -330,6 +331,12 @@ where
330331
}
331332

332333
ty::Alias(kind, data) => {
334+
// An occurs check failure inside of an alias does not mean
335+
// that the types definitely don't unify. We may be able
336+
// to normalize the alias after all.
337+
//
338+
// We handle this by lazily equating the alias and generalizing
339+
// it to an inference variable.
333340
let is_nested_alias = mem::replace(&mut self.in_alias, true);
334341
let result = match self.relate(data, data) {
335342
Ok(data) => Ok(Ty::new_alias(self.tcx(), kind, data)),
@@ -343,7 +350,7 @@ where
343350
self.for_universe.can_name(visitor.max_universe())
344351
&& !t.has_escaping_bound_vars();
345352
if !infer_replacement_is_complete {
346-
warn!("incomplete generalization of an alias type: {t:?}");
353+
warn!("may incompletely handle alias type: {t:?}");
347354
}
348355

349356
debug!("generalization failure in alias");
@@ -504,20 +511,20 @@ where
504511
}
505512
}
506513

507-
#[derive(Debug)]
508-
pub(super) struct HandleProjection<T>(T);
509-
impl<T> HandleProjection<T> {
510-
pub(super) fn may_be_infer(self) -> T {
511-
self.0
512-
}
513-
}
514-
515514
/// Result from a generalization operation. This includes
516515
/// not only the generalized type, but also a bool flag
517516
/// indicating whether further WF checks are needed.
518517
#[derive(Debug)]
519518
pub(super) struct Generalization<T> {
520-
pub(super) value: HandleProjection<T>,
519+
/// When generalizing `<?0 as Trait>::Assoc` or
520+
/// `<T as Bar<<?0 as Foo>::Assoc>>::Assoc`
521+
/// for `?0` generalization returns an inference
522+
/// variable.
523+
///
524+
/// This has to be handled wotj care as it can
525+
/// otherwise very easily result in infinite
526+
/// recursion.
527+
pub(super) value_may_be_infer: T,
521528

522529
/// If true, then the generalized type may not be well-formed,
523530
/// even if the source type is well-formed, so we should add an

Diff for: compiler/rustc_infer/src/infer/nll_relate/mod.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -214,17 +214,16 @@ where
214214
}
215215

216216
fn generalize(&mut self, ty: Ty<'tcx>, for_vid: ty::TyVid) -> RelateResult<'tcx, Ty<'tcx>> {
217-
let Generalization { value, needs_wf: _ } = generalize::generalize(
217+
let Generalization { value_may_be_infer: ty, needs_wf: _ } = generalize::generalize(
218218
self.infcx,
219219
&mut self.delegate,
220220
ty,
221221
for_vid,
222222
self.ambient_variance,
223223
)?;
224224

225-
let ty = value.may_be_infer();
226225
if ty.is_ty_var() {
227-
warn!("occurs check failure in MIR typeck");
226+
span_bug!(self.delegate.span(), "occurs check failure in MIR typeck");
228227
}
229228
Ok(ty)
230229
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
2+
WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!2_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
3+
WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
4+
WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!2_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
5+
WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
6+
WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!2_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
7+
WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
8+
WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!2_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
9+
error[E0119]: conflicting implementations of trait `Overlap<for<'a> fn(&'a (), ())>` for type `for<'a> fn(&'a (), ())`
10+
--> $DIR/associated-type.rs:31:1
11+
|
12+
LL | impl<T> Overlap<T> for T {
13+
| ------------------------ first implementation here
14+
...
15+
LL | / impl<T> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T
16+
LL | |
17+
LL | | where
18+
LL | | for<'a> *const T: ToUnit<'a>,
19+
| |_________________________________^ conflicting implementation for `for<'a> fn(&'a (), ())`
20+
|
21+
= note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
22+
23+
error: aborting due to previous error
24+
25+
For more information about this error, try `rustc --explain E0119`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
2+
WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!3_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
3+
WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
4+
WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!3_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
5+
WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
6+
WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!3_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
7+
WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
8+
WARN rustc_infer::infer::generalize may incompletely handle alias type: Alias(Projection, AliasTy { args: [*const ?1t, RePlaceholder(!3_BoundRegion { var: 0, kind: BrNamed(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), 'a) })], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit) })
9+
error[E0119]: conflicting implementations of trait `Overlap<for<'a> fn(&'a (), _)>` for type `for<'a> fn(&'a (), _)`
10+
--> $DIR/associated-type.rs:31:1
11+
|
12+
LL | impl<T> Overlap<T> for T {
13+
| ------------------------ first implementation here
14+
...
15+
LL | / impl<T> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T
16+
LL | |
17+
LL | | where
18+
LL | | for<'a> *const T: ToUnit<'a>,
19+
| |_________________________________^ conflicting implementation for `for<'a> fn(&'a (), _)`
20+
|
21+
= note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
22+
23+
error: aborting due to previous error
24+
25+
For more information about this error, try `rustc --explain E0119`.

Diff for: tests/ui/coherence/occurs-check/associated-type.rs

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// revisions: old next
2+
//[next] compile-flags: -Ztrait-solver=next
3+
4+
// A regression test for #105787
5+
6+
// Using the higher ranked projection hack to prevent us from replacing the projection
7+
// with an inference variable.
8+
trait ToUnit<'a> {
9+
type Unit;
10+
}
11+
12+
struct LocalTy;
13+
impl<'a> ToUnit<'a> for *const LocalTy {
14+
type Unit = ();
15+
}
16+
17+
impl<'a, T: Copy + ?Sized> ToUnit<'a> for *const T {
18+
type Unit = ();
19+
}
20+
21+
trait Overlap<T> {
22+
type Assoc;
23+
}
24+
25+
type Assoc<'a, T> = <*const T as ToUnit<'a>>::Unit;
26+
27+
impl<T> Overlap<T> for T {
28+
type Assoc = usize;
29+
}
30+
31+
impl<T> Overlap<for<'a> fn(&'a (), Assoc<'a, T>)> for T
32+
//~^ ERROR conflicting implementations of trait
33+
where
34+
for<'a> *const T: ToUnit<'a>,
35+
{
36+
type Assoc = Box<usize>;
37+
}
38+
39+
fn foo<T: Overlap<U>, U>(x: T::Assoc) -> T::Assoc {
40+
x
41+
}
42+
43+
fn main() {
44+
foo::<for<'a> fn(&'a (), ()), for<'a> fn(&'a (), ())>(3usize);
45+
}

Diff for: tests/ui/coherence/occurs-check/opaques.next.stderr

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0119]: conflicting implementations of trait `Trait<Alias<_>>` for type `Alias<_>`
2+
--> $DIR/opaques.rs:29:1
3+
|
4+
LL | impl<T> Trait<T> for T {
5+
| ---------------------- first implementation here
6+
...
7+
LL | impl<T> Trait<T> for defining_scope::Alias<T> {
8+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Alias<_>`
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0119`.

Diff for: tests/ui/coherence/occurs-check/opaques.rs

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//revisions: old next
2+
//[next] compile-flags: -Ztrait-solver=next
3+
4+
// A regression test for #105787
5+
6+
//[old] known-bug: #105787
7+
//[old] check-pass
8+
#![feature(type_alias_impl_trait)]
9+
mod defining_scope {
10+
use super::*;
11+
pub type Alias<T> = impl Sized;
12+
13+
pub fn cast<T>(x: Container<Alias<T>, T>) -> Container<T, T> {
14+
x
15+
}
16+
}
17+
18+
struct Container<T: Trait<U>, U> {
19+
x: <T as Trait<U>>::Assoc,
20+
}
21+
22+
trait Trait<T> {
23+
type Assoc;
24+
}
25+
26+
impl<T> Trait<T> for T {
27+
type Assoc = Box<u32>;
28+
}
29+
impl<T> Trait<T> for defining_scope::Alias<T> {
30+
//[next]~^ ERROR conflicting implementations of trait
31+
type Assoc = usize;
32+
}
33+
34+
fn main() {
35+
let x: Box<u32> = defining_scope::cast::<()>(Container { x: 0 }).x;
36+
println!("{}", *x);
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0271]: type mismatch resolving `<<T as Id<_>>::Id as Unnormalizable>::Assoc == _`
2+
--> $DIR/occurs-check-nested-alias.rs:31:9
3+
|
4+
LL | x = y;
5+
| ^ types differ
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0271`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// revisions: old next
2+
//[old] check-pass
3+
4+
// Need to emit an alias-relate instead of a `Projection` goal here.
5+
//[next] compile-flags: -Ztrait-solver=next
6+
//[next] known-bug: trait-system-refactor-initiative#8
7+
#![crate_type = "lib"]
8+
#![allow(unused)]
9+
trait Unnormalizable {
10+
type Assoc;
11+
}
12+
13+
trait Id<T> {
14+
type Id;
15+
}
16+
impl<T, U> Id<T> for U {
17+
type Id = U;
18+
}
19+
20+
struct Inv<T>(*mut T);
21+
22+
fn unconstrained<T>() -> T {
23+
todo!()
24+
}
25+
26+
fn create<T, U: Unnormalizable>(
27+
x: &U,
28+
) -> (Inv<T>, Inv<<<U as Id<T>>::Id as Unnormalizable>::Assoc>) {
29+
todo!()
30+
}
31+
32+
fn foo<T: Unnormalizable>() {
33+
let q = unconstrained();
34+
let (mut x, y) = create::<_, _>(&q);
35+
x = y;
36+
drop::<T>(q);
37+
}

0 commit comments

Comments
 (0)