Skip to content

Commit ab2dc84

Browse files
committed
Auto merge of #118247 - spastorino:type-equality-subtyping, r=<try>
Fix for TypeId exposes equality-by-subtyping vs normal-form-syntactic-equality unsoundness Fixes #97156 This PR revives #97427 idea, it sits on top of #118118 because the idea uncovered some problems with IATs. r? `@lcnr` This is ICEing yet for `tests/ui/traits/new-solver/escaping-bound-vars-in-writeback-normalization.rs` using the new trait solver. After #118118 and this ICE is fixed, we would need a rebase and a crater run. Opening as a WIP for now.
2 parents 49b3924 + d3841fb commit ab2dc84

16 files changed

+141
-29
lines changed

compiler/rustc_hir_analysis/src/check/intrinsic.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
138138
let name_str = intrinsic_name.as_str();
139139

140140
let bound_vars = tcx.mk_bound_variable_kinds(&[
141+
ty::BoundVariableKind::Region(ty::BrAnon),
141142
ty::BoundVariableKind::Region(ty::BrAnon),
142143
ty::BoundVariableKind::Region(ty::BrEnv),
143144
]);
@@ -151,7 +152,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
151152
let env_region = ty::Region::new_bound(
152153
tcx,
153154
ty::INNERMOST,
154-
ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrEnv },
155+
ty::BoundRegion { var: ty::BoundVar::from_u32(2), kind: ty::BrEnv },
155156
);
156157
let va_list_ty = tcx.type_of(did).instantiate(tcx, &[region.into()]);
157158
(Ty::new_ref(tcx, env_region, ty::TypeAndMut { ty: va_list_ty, mutbl }), va_list_ty)
@@ -446,9 +447,12 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
446447

447448
sym::raw_eq => {
448449
let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon };
449-
let param_ty =
450+
let param_ty_lhs =
451+
Ty::new_imm_ref(tcx, ty::Region::new_bound(tcx, ty::INNERMOST, br), param(0));
452+
let br = ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrAnon };
453+
let param_ty_rhs =
450454
Ty::new_imm_ref(tcx, ty::Region::new_bound(tcx, ty::INNERMOST, br), param(0));
451-
(1, vec![param_ty; 2], tcx.types.bool)
455+
(1, vec![param_ty_lhs, param_ty_rhs], tcx.types.bool)
452456
}
453457

454458
sym::black_box => (1, vec![param(0)], param(0)),

compiler/rustc_infer/src/infer/equate.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,8 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
165165
}
166166

167167
if a.skip_binder().has_escaping_bound_vars() || b.skip_binder().has_escaping_bound_vars() {
168-
self.fields.higher_ranked_sub(a, b, self.a_is_expected)?;
169-
self.fields.higher_ranked_sub(b, a, self.a_is_expected)?;
168+
self.fields.higher_ranked_equate(a, b, self.a_is_expected)?;
169+
self.fields.higher_ranked_equate(b, a, self.a_is_expected)?;
170170
} else {
171171
// Fast path for the common case.
172172
self.relate(a.skip_binder(), b.skip_binder())?;

compiler/rustc_infer/src/infer/higher_ranked/mod.rs

+34
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,40 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> {
5757
// placeholders which **must not** be named afterwards.
5858
Ok(())
5959
}
60+
61+
#[instrument(skip(self), level = "debug")]
62+
pub fn higher_ranked_equate<T>(
63+
&mut self,
64+
sub: Binder<'tcx, T>,
65+
sup: Binder<'tcx, T>,
66+
sub_is_expected: bool,
67+
) -> RelateResult<'tcx, ()>
68+
where
69+
T: Relate<'tcx>,
70+
{
71+
let span = self.trace.cause.span;
72+
// First, we instantiate each bound region in the supertype with a
73+
// fresh placeholder region. Note that this automatically creates
74+
// a new universe if needed.
75+
let sup_prime = self.infcx.instantiate_binder_with_placeholders(sup);
76+
77+
// Next, we instantiate each bound region in the subtype
78+
// with a fresh region variable. These region variables --
79+
// but no other preexisting region variables -- can name
80+
// the placeholders.
81+
let sub_prime = self.infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, sub);
82+
83+
debug!("a_prime={:?}", sub_prime);
84+
debug!("b_prime={:?}", sup_prime);
85+
86+
// Compare types now that bound regions have been replaced.
87+
let result = self.equate(sub_is_expected).relate(sub_prime, sup_prime)?;
88+
89+
debug!("OK result={result:?}");
90+
// NOTE: returning the result here would be dangerous as it contains
91+
// placeholders which **must not** be named afterwards.
92+
Ok(())
93+
}
6094
}
6195

6296
impl<'tcx> InferCtxt<'tcx> {

tests/ui/associated-inherent-types/issue-111404-1.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ impl<'a> Foo<fn(&'a ())> {
88
}
99

1010
fn bar(_: fn(Foo<for<'b> fn(Foo<fn(&'b ())>::Assoc)>::Assoc)) {}
11-
//~^ ERROR higher-ranked subtype error
12-
//~| ERROR higher-ranked subtype error
11+
//~^ ERROR mismatched types [E0308]
12+
//~| ERROR mismatched types [E0308]
1313

1414
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
1-
error: higher-ranked subtype error
2-
--> $DIR/issue-111404-1.rs:10:1
1+
error[E0308]: mismatched types
2+
--> $DIR/issue-111404-1.rs:10:11
33
|
44
LL | fn bar(_: fn(Foo<for<'b> fn(Foo<fn(&'b ())>::Assoc)>::Assoc)) {}
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
6+
|
7+
= note: expected struct `Foo<fn(&())>`
8+
found struct `Foo<for<'b> fn(&'b ())>`
69

7-
error: higher-ranked subtype error
8-
--> $DIR/issue-111404-1.rs:10:1
10+
error[E0308]: mismatched types
11+
--> $DIR/issue-111404-1.rs:10:11
912
|
1013
LL | fn bar(_: fn(Foo<for<'b> fn(Foo<fn(&'b ())>::Assoc)>::Assoc)) {}
11-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
1215
|
16+
= note: expected struct `Foo<fn(&())>`
17+
found struct `Foo<for<'b> fn(&'b ())>`
1318
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
1419

1520
error: aborting due to 2 previous errors
1621

22+
For more information about this error, try `rustc --explain E0308`.

tests/ui/coherence/coherence-fn-covariant-bound-vs-static.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// check-pass
2+
13
// Test that impls for these two types are considered ovelapping:
24
//
35
// * `for<'r> fn(fn(&'r u32))`
@@ -15,7 +17,8 @@ trait Trait {}
1517

1618
impl Trait for for<'r> fn(fn(&'r ())) {}
1719
impl<'a> Trait for fn(fn(&'a ())) {}
18-
//~^ ERROR conflicting implementations
20+
//~^ WARN conflicting implementations of trait `Trait` for type `for<'r> fn(fn(&'r ()))` [coherence_leak_check]
21+
//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
1922
//
2023
// Note in particular that we do NOT get a future-compatibility warning
2124
// here. This is because the new leak-check proposed in [MCP 295] does not

tests/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1-
error[E0119]: conflicting implementations of trait `Trait` for type `for<'r> fn(fn(&'r ()))`
2-
--> $DIR/coherence-fn-covariant-bound-vs-static.rs:17:1
1+
warning: conflicting implementations of trait `Trait` for type `for<'r> fn(fn(&'r ()))`
2+
--> $DIR/coherence-fn-covariant-bound-vs-static.rs:19:1
33
|
44
LL | impl Trait for for<'r> fn(fn(&'r ())) {}
55
| ------------------------------------- first implementation here
66
LL | impl<'a> Trait for fn(fn(&'a ())) {}
77
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'r> fn(fn(&'r ()))`
88
|
9+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
10+
= note: for more information, see issue #56105 <https://github.com/rust-lang/rust/issues/56105>
911
= note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
12+
= note: `#[warn(coherence_leak_check)]` on by default
1013

11-
error: aborting due to 1 previous error
14+
warning: 1 warning emitted
1215

13-
For more information about this error, try `rustc --explain E0119`.

tests/ui/coherence/coherence-fn-inputs.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// check-pass
2+
13
// Test that we consider these two types completely equal:
24
//
35
// * `for<'a, 'b> fn(&'a u32, &'b u32)`
@@ -13,7 +15,8 @@
1315
trait Trait {}
1416
impl Trait for for<'a, 'b> fn(&'a u32, &'b u32) {}
1517
impl Trait for for<'c> fn(&'c u32, &'c u32) {
16-
//~^ ERROR conflicting implementations
18+
//~^ WARN conflicting implementations of trait `Trait` for type `for<'a, 'b> fn(&'a u32, &'b u32)` [coherence_leak_check]
19+
//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
1720
//
1821
// Note in particular that we do NOT get a future-compatibility warning
1922
// here. This is because the new leak-check proposed in [MCP 295] does not

tests/ui/coherence/coherence-fn-inputs.stderr

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1-
error[E0119]: conflicting implementations of trait `Trait` for type `for<'a, 'b> fn(&'a u32, &'b u32)`
2-
--> $DIR/coherence-fn-inputs.rs:15:1
1+
warning: conflicting implementations of trait `Trait` for type `for<'a, 'b> fn(&'a u32, &'b u32)`
2+
--> $DIR/coherence-fn-inputs.rs:17:1
33
|
44
LL | impl Trait for for<'a, 'b> fn(&'a u32, &'b u32) {}
55
| ----------------------------------------------- first implementation here
66
LL | impl Trait for for<'c> fn(&'c u32, &'c u32) {
77
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a u32, &'b u32)`
88
|
9+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
10+
= note: for more information, see issue #56105 <https://github.com/rust-lang/rust/issues/56105>
911
= note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
12+
= note: `#[warn(coherence_leak_check)]` on by default
1013

11-
error: aborting due to 1 previous error
14+
warning: 1 warning emitted
1215

13-
For more information about this error, try `rustc --explain E0119`.

tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.stderr

+8-1
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,12 @@ LL | WHAT_A_TYPE => 0,
77
= note: the traits must be derived, manual `impl`s are not sufficient
88
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
99

10-
error: aborting due to 1 previous error
10+
error[E0277]: the trait bound `for<'a, 'b> fn(&'a (), &'b ()): WithAssoc<T>` is not satisfied
11+
--> $DIR/typeid-equality-by-subtyping.rs:44:51
12+
|
13+
LL | fn unsound<T>(x: <One as WithAssoc<T>>::Assoc) -> <Two as WithAssoc<T>>::Assoc
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `WithAssoc<T>` is not implemented for `for<'a, 'b> fn(&'a (), &'b ())`
15+
16+
error: aborting due to 2 previous errors
1117

18+
For more information about this error, try `rustc --explain E0277`.

tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
//
33
// In particular, we test this pattern in trait solving, where it is not connected
44
// to any part of the source code.
5-
//
6-
// check-pass
75

86
trait Trait<T> {}
97

@@ -34,4 +32,5 @@ fn main() {
3432
// This is because we can use `'static`.
3533

3634
foo::<()>();
35+
//~^ ERROR implementation of `Trait` is not general enough
3736
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error: implementation of `Trait` is not general enough
2+
--> $DIR/hrtb-exists-forall-trait-covariant.rs:34:5
3+
|
4+
LL | foo::<()>();
5+
| ^^^^^^^^^^^ implementation of `Trait` is not general enough
6+
|
7+
= note: `()` must implement `Trait<for<'b> fn(fn(&'b u32))>`
8+
= note: ...but it actually implements `Trait<fn(fn(&'0 u32))>`, for some specific lifetime `'0`
9+
10+
error: aborting due to 1 previous error
11+

tests/ui/lub-glb/old-lub-glb-hr-eq.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
// error. However, now that we handle subtyping correctly, we no
44
// longer get an error, because we recognize these two types as
55
// equivalent!
6-
//
7-
// check-pass
86

97
fn foo(x: fn(&u8, &u8), y: for<'a> fn(&'a u8, &'a u8)) {
108
// The two types above are actually equivalent. With the older
@@ -13,6 +11,7 @@ fn foo(x: fn(&u8, &u8), y: for<'a> fn(&'a u8, &'a u8)) {
1311
let z = match 22 {
1412
0 => x,
1513
_ => y,
14+
//~^ ERROR `match` arms have incompatible types [E0308]
1615
};
1716
}
1817

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0308]: `match` arms have incompatible types
2+
--> $DIR/old-lub-glb-hr-eq.rs:13:14
3+
|
4+
LL | let z = match 22 {
5+
| _____________-
6+
LL | | 0 => x,
7+
| | - this is found to be of type `for<'a, 'b> fn(&'a u8, &'b u8)`
8+
LL | | _ => y,
9+
| | ^ one type is more general than the other
10+
LL | |
11+
LL | | };
12+
| |_____- `match` arms have incompatible types
13+
|
14+
= note: expected fn pointer `for<'a, 'b> fn(&'a u8, &'b u8)`
15+
found fn pointer `for<'a> fn(&'a u8, &'a u8)`
16+
17+
error: aborting due to 1 previous error
18+
19+
For more information about this error, try `rustc --explain E0308`.

tests/ui/traits/new-solver/member-constraints-in-root-universe.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
// compile-flags: -Ztrait-solver=next
2-
// check-pass
32

43
trait Trait {
54
type Ty;
@@ -11,6 +10,8 @@ impl Trait for for<'a> fn(&'a u8, &'a u8) {
1110

1211
// argument is necessary to create universes before registering the hidden type.
1312
fn test<'a>(_: <fn(&u8, &u8) as Trait>::Ty) -> impl Sized {
13+
//~^ ERROR the type `<for<'a, 'b> fn(&'a u8, &'b u8) as Trait>::Ty` is not well-formed
14+
//~| ERROR the size for values of type `<for<'a, 'b> fn(&'a u8, &'b u8) as Trait>::Ty` cannot be known at compilation time [E0277]
1415
"hidden type is `&'?0 str` with '?0 member of ['static,]"
1516
}
1617

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error: the type `<for<'a, 'b> fn(&'a u8, &'b u8) as Trait>::Ty` is not well-formed
2+
--> $DIR/member-constraints-in-root-universe.rs:12:16
3+
|
4+
LL | fn test<'a>(_: <fn(&u8, &u8) as Trait>::Ty) -> impl Sized {
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
7+
error[E0277]: the size for values of type `<for<'a, 'b> fn(&'a u8, &'b u8) as Trait>::Ty` cannot be known at compilation time
8+
--> $DIR/member-constraints-in-root-universe.rs:12:13
9+
|
10+
LL | fn test<'a>(_: <fn(&u8, &u8) as Trait>::Ty) -> impl Sized {
11+
| ^ doesn't have a size known at compile-time
12+
|
13+
= help: the trait `Sized` is not implemented for `<for<'a, 'b> fn(&'a u8, &'b u8) as Trait>::Ty`
14+
= help: unsized fn params are gated as an unstable feature
15+
help: function arguments must have a statically known size, borrowed types always have a known size
16+
|
17+
LL | fn test<'a>(_: &<fn(&u8, &u8) as Trait>::Ty) -> impl Sized {
18+
| +
19+
20+
error: aborting due to 2 previous errors
21+
22+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)