Skip to content

Commit

Permalink
Make type equality != bidirectional subtyping
Browse files Browse the repository at this point in the history
  • Loading branch information
spastorino committed Nov 24, 2023
1 parent f74f700 commit 3679fde
Show file tree
Hide file tree
Showing 63 changed files with 373 additions and 387 deletions.
10 changes: 7 additions & 3 deletions compiler/rustc_hir_analysis/src/check/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
let name_str = intrinsic_name.as_str();

let bound_vars = tcx.mk_bound_variable_kinds(&[
ty::BoundVariableKind::Region(ty::BrAnon),
ty::BoundVariableKind::Region(ty::BrAnon),
ty::BoundVariableKind::Region(ty::BrEnv),
]);
Expand All @@ -151,7 +152,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
let env_region = ty::Region::new_bound(
tcx,
ty::INNERMOST,
ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrEnv },
ty::BoundRegion { var: ty::BoundVar::from_u32(2), kind: ty::BrEnv },
);
let va_list_ty = tcx.type_of(did).instantiate(tcx, &[region.into()]);
(Ty::new_ref(tcx, env_region, ty::TypeAndMut { ty: va_list_ty, mutbl }), va_list_ty)
Expand Down Expand Up @@ -446,9 +447,12 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {

sym::raw_eq => {
let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon };
let param_ty =
let param_ty_lhs =
Ty::new_imm_ref(tcx, ty::Region::new_bound(tcx, ty::INNERMOST, br), param(0));
let br = ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrAnon };
let param_ty_rhs =
Ty::new_imm_ref(tcx, ty::Region::new_bound(tcx, ty::INNERMOST, br), param(0));
(1, vec![param_ty; 2], tcx.types.bool)
(1, vec![param_ty_lhs, param_ty_rhs], tcx.types.bool)
}

sym::black_box => (1, vec![param(0)], param(0)),
Expand Down
19 changes: 12 additions & 7 deletions compiler/rustc_infer/src/infer/equate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ use crate::traits::PredicateObligations;
use super::combine::{CombineFields, ObligationEmittingRelation};
use super::Subtype;

use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
use rustc_middle::ty::GenericArgsRef;
use rustc_middle::ty::TyVar;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
use rustc_middle::ty::{self, Ty, TyCtxt};

use rustc_hir::def_id::DefId;

Expand Down Expand Up @@ -164,14 +165,18 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
return Ok(a);
}

if a.skip_binder().has_escaping_bound_vars() || b.skip_binder().has_escaping_bound_vars() {
self.fields.higher_ranked_sub(a, b, self.a_is_expected)?;
self.fields.higher_ranked_sub(b, a, self.a_is_expected)?;
let a = self.tcx().anonymize_bound_vars(a);
let b = self.tcx().anonymize_bound_vars(b);

if a.bound_vars() == b.bound_vars() {
let (a, b) = self
.fields
.infcx
.instantiate_binder_with_placeholders(a.map_bound(|a| (a, b.skip_binder())));
Ok(ty::Binder::dummy(self.relate(a, b)?))
} else {
// Fast path for the common case.
self.relate(a.skip_binder(), b.skip_binder())?;
Err(TypeError::Mismatch)
}
Ok(a)
}
}

Expand Down
3 changes: 1 addition & 2 deletions tests/ui/associated-inherent-types/issue-109789.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ impl Other for u32 {}
// `try_report_trait_placeholder_mismatch`.

fn bar(_: Foo<for<'a> fn(&'a ())>::Assoc) {}
//~^ ERROR mismatched types
//~| ERROR mismatched types
//~^ ERROR associated type `Assoc` not found for `Foo<for<'a> fn(&'a ())>` in the current scope [E0220]

fn main() {}
27 changes: 10 additions & 17 deletions tests/ui/associated-inherent-types/issue-109789.stderr
Original file line number Diff line number Diff line change
@@ -1,22 +1,15 @@
error[E0308]: mismatched types
--> $DIR/issue-109789.rs:18:11
error[E0220]: associated type `Assoc` not found for `Foo<for<'a> fn(&'a ())>` in the current scope
--> $DIR/issue-109789.rs:18:36
|
LL | struct Foo<T>(T);
| ------------- associated item `Assoc` not found for this struct
...
LL | fn bar(_: Foo<for<'a> fn(&'a ())>::Assoc) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
| ^^^^^ associated item not found in `Foo<for<'a> fn(&'a ())>`
|
= note: expected struct `Foo<fn(&'static ())>`
found struct `Foo<for<'a> fn(&'a ())>`
= note: the associated type was found for
- `Foo<fn(&'static ())>`

error[E0308]: mismatched types
--> $DIR/issue-109789.rs:18:11
|
LL | fn bar(_: Foo<for<'a> fn(&'a ())>::Assoc) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected struct `Foo<fn(&'static ())>`
found struct `Foo<for<'a> fn(&'a ())>`
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: aborting due to 2 previous errors
error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
For more information about this error, try `rustc --explain E0220`.
25 changes: 25 additions & 0 deletions tests/ui/associated-inherent-types/issue-111404-1.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,33 @@
error[E0220]: associated type `Assoc` not found for `Foo<for<'b> fn(&'b ())>` in the current scope
--> $DIR/issue-111404-1.rs:10:55
|
LL | struct Foo<T>(T);
| ------------- associated item `Assoc` not found for this struct
...
LL | fn bar(_: fn(Foo<for<'b> fn(Foo<fn(&'b ())>::Assoc)>::Assoc)) {}
<<<<<<< HEAD
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error
||||||| parent of 9bb25a65025 (Make type equality != bidirectional subtyping)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: higher-ranked subtype error
--> $DIR/issue-111404-1.rs:10:1
|
LL | fn bar(_: fn(Foo<for<'b> fn(Foo<fn(&'b ())>::Assoc)>::Assoc)) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: aborting due to 2 previous errors
=======
| ^^^^^ associated item not found in `Foo<for<'b> fn(&'b ())>`
|
= note: the associated type was found for
- `Foo<fn(&'a ())>`

error: aborting due to previous error
>>>>>>> 9bb25a65025 (Make type equality != bidirectional subtyping)

For more information about this error, try `rustc --explain E0220`.
8 changes: 3 additions & 5 deletions tests/ui/closure-expected-type/expect-fn-supply-fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ fn expect_free_supply_free_from_fn<'x>(x: &'x u32) {
// Here, the type given for `'x` "obscures" a region from the
// expected signature that is bound at closure level.
with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {});
//~^ ERROR lifetime may not live long enough
//~| ERROR lifetime may not live long enough
}

fn expect_free_supply_free_from_closure() {
Expand All @@ -30,14 +28,14 @@ fn expect_free_supply_bound() {
// Here, we are given a function whose region is bound at closure level,
// but we expect one bound in the argument. Error results.
with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {});
//~^ ERROR mismatched types
//~^ ERROR type mismatch in closure arguments
}

fn expect_bound_supply_free_from_fn<'x>(x: &'x u32) {
// Here, we are given a `fn(&u32)` but we expect a `fn(&'x
// u32)`. In principle, this could be ok, but we demand equality.
with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {});
//~^ ERROR mismatched types
//~^ ERROR type mismatch in closure arguments
}

fn expect_bound_supply_free_from_closure() {
Expand All @@ -46,7 +44,7 @@ fn expect_bound_supply_free_from_closure() {
// the argument level.
type Foo<'a> = fn(&'a u32);
with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| {
//~^ ERROR mismatched types
//~^ ERROR type mismatch in closure arguments
});
}

Expand Down
97 changes: 59 additions & 38 deletions tests/ui/closure-expected-type/expect-fn-supply-fn.stderr
Original file line number Diff line number Diff line change
@@ -1,51 +1,72 @@
error: lifetime may not live long enough
--> $DIR/expect-fn-supply-fn.rs:16:49
|
LL | fn expect_free_supply_free_from_fn<'x>(x: &'x u32) {
| -- lifetime `'x` defined here
...
LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {});
| ^
| |
| has type `fn(&'1 u32)`
| requires that `'1` must outlive `'x`

error: lifetime may not live long enough
--> $DIR/expect-fn-supply-fn.rs:16:49
|
LL | fn expect_free_supply_free_from_fn<'x>(x: &'x u32) {
| -- lifetime `'x` defined here
...
LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {});
| ^ requires that `'x` must outlive `'static`

error[E0308]: mismatched types
--> $DIR/expect-fn-supply-fn.rs:32:49
error[E0631]: type mismatch in closure arguments
--> $DIR/expect-fn-supply-fn.rs:30:5
|
LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {});
| ^ one type is more general than the other
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------- found signature defined here
| |
| expected due to this
|
= note: expected closure signature `for<'a, 'b> fn(for<'a> fn(&'a u32), &'b i32) -> _`
found closure signature `fn(for<'a> fn(&'a u32), _) -> _`
note: required by a bound in `with_closure_expecting_fn_with_free_region`
--> $DIR/expect-fn-supply-fn.rs:3:8
|
LL | fn with_closure_expecting_fn_with_free_region<F>(_: F)
| ------------------------------------------ required by a bound in this function
LL | where
LL | F: for<'a> FnOnce(fn(&'a u32), &i32),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `with_closure_expecting_fn_with_free_region`
help: consider adjusting the signature so it borrows its argument
|
= note: expected fn pointer `fn(&u32)`
found fn pointer `for<'a> fn(&'a u32)`
LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), &y| {});
| +

error[E0308]: mismatched types
--> $DIR/expect-fn-supply-fn.rs:39:50
error[E0631]: type mismatch in closure arguments
--> $DIR/expect-fn-supply-fn.rs:37:5
|
LL | with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {});
| ^ one type is more general than the other
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------- found signature defined here
| |
| expected due to this
|
= note: expected fn pointer `for<'a> fn(&'a u32)`
found fn pointer `fn(&u32)`
= note: expected closure signature `for<'a> fn(for<'a> fn(&'a u32), &'a i32) -> _`
found closure signature `fn(fn(&'x u32), _) -> _`
note: required by a bound in `with_closure_expecting_fn_with_bound_region`
--> $DIR/expect-fn-supply-fn.rs:9:8
|
LL | fn with_closure_expecting_fn_with_bound_region<F>(_: F)
| ------------------------------------------- required by a bound in this function
LL | where
LL | F: FnOnce(fn(&u32), &i32),
| ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `with_closure_expecting_fn_with_bound_region`
help: consider adjusting the signature so it borrows its argument
|
LL | with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), &y| {});
| +

error[E0308]: mismatched types
--> $DIR/expect-fn-supply-fn.rs:48:50
error[E0631]: type mismatch in closure arguments
--> $DIR/expect-fn-supply-fn.rs:46:5
|
LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| {
| ^ one type is more general than the other
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --------------- found signature defined here
| |
| expected due to this
|
= note: expected closure signature `for<'a> fn(for<'a> fn(&'a u32), &'a i32) -> _`
found closure signature `for<'a> fn(for<'a> fn(&'a u32), _) -> _`
note: required by a bound in `with_closure_expecting_fn_with_bound_region`
--> $DIR/expect-fn-supply-fn.rs:9:8
|
LL | fn with_closure_expecting_fn_with_bound_region<F>(_: F)
| ------------------------------------------- required by a bound in this function
LL | where
LL | F: FnOnce(fn(&u32), &i32),
| ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `with_closure_expecting_fn_with_bound_region`
help: consider adjusting the signature so it borrows its argument
|
= note: expected fn pointer `for<'a> fn(&'a u32)`
found fn pointer `fn(&u32)`
LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, &y| {
| +

error: aborting due to 5 previous errors
error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0308`.
For more information about this error, try `rustc --explain E0631`.
4 changes: 3 additions & 1 deletion tests/ui/coherence/coherence-fn-covariant-bound-vs-static.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@
// * true if `exists<'r> { 'r: 'static }` (obviously true)
// * `fn(fn(&'static u32)) <: for<'r> fn(fn(&'r u32))`
// * true if `forall<'r> { 'static: 'r }` (also true)
//
// check-pass


trait Trait {}

impl Trait for for<'r> fn(fn(&'r ())) {}
impl<'a> Trait for fn(fn(&'a ())) {}
//~^ ERROR conflicting implementations
//
// Note in particular that we do NOT get a future-compatibility warning
// here. This is because the new leak-check proposed in [MCP 295] does not
Expand Down
13 changes: 0 additions & 13 deletions tests/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr

This file was deleted.

10 changes: 3 additions & 7 deletions tests/ui/coherence/coherence-fn-implied-bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,12 @@
// Note that while we would like to make this a hard error, we also
// give the same warning for `coherence-wasm-bindgen.rs`, which ought
// to be accepted.

#![deny(coherence_leak_check)]

//
// check-pass
trait Trait {}

impl Trait for for<'a, 'b> fn(&'a &'b u32, &'b &'a u32) -> &'b u32 {}

impl Trait for for<'c> fn(&'c &'c u32, &'c &'c u32) -> &'c u32 {
//~^ ERROR conflicting implementations
//~| WARNING this was previously accepted by the compiler
}
impl Trait for for<'c> fn(&'c &'c u32, &'c &'c u32) -> &'c u32 {}

fn main() {}
20 changes: 0 additions & 20 deletions tests/ui/coherence/coherence-fn-implied-bounds.stderr

This file was deleted.

12 changes: 3 additions & 9 deletions tests/ui/coherence/coherence-fn-inputs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,11 @@
//
// * `'c` can be the intersection of `'a` and `'b` (and there is always an intersection)
// * `'a` and `'b` can both be equal to `'c`
//
// check-pass

trait Trait {}
impl Trait for for<'a, 'b> fn(&'a u32, &'b u32) {}
impl Trait for for<'c> fn(&'c u32, &'c u32) {
//~^ ERROR conflicting implementations
//
// Note in particular that we do NOT get a future-compatibility warning
// here. This is because the new leak-check proposed in [MCP 295] does not
// "error" when these two types are equated.
//
// [MCP 295]: https://github.com/rust-lang/compiler-team/issues/295
}
impl Trait for for<'c> fn(&'c u32, &'c u32) {}

fn main() {}
13 changes: 0 additions & 13 deletions tests/ui/coherence/coherence-fn-inputs.stderr

This file was deleted.

Loading

0 comments on commit 3679fde

Please sign in to comment.