Skip to content

Commit

Permalink
hr type equality != bidirectional subtyping
Browse files Browse the repository at this point in the history
  • Loading branch information
lcnr committed May 27, 2022
1 parent 4f68efa commit 124673b
Show file tree
Hide file tree
Showing 62 changed files with 398 additions and 454 deletions.
8 changes: 2 additions & 6 deletions compiler/rustc_infer/src/infer/combine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -749,9 +749,7 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
}
}
}
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted })
if self.tcx().lazy_normalization() =>
{
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
assert_eq!(promoted, None);
let substs = self.relate_with_variance(
ty::Variance::Invariant,
Expand Down Expand Up @@ -980,9 +978,7 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
}
}
}
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted })
if self.tcx().lazy_normalization() =>
{
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
assert_eq!(promoted, None);
let substs = self.relate_with_variance(
ty::Variance::Invariant,
Expand Down
16 changes: 10 additions & 6 deletions compiler/rustc_infer/src/infer/equate.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use super::combine::{CombineFields, ConstEquateRelation, RelationDir};
use super::Subtype;

use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::TyVar;
Expand Down Expand Up @@ -151,13 +152,16 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
where
T: Relate<'tcx>,
{
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_late_bound_regions(a);
let b = self.tcx().anonymize_late_bound_regions(b);
if a.bound_vars() == b.bound_vars() {
let (a, b) = self
.fields
.infcx
.replace_bound_vars_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())?;
Ok(a)
Err(TypeError::Mismatch)
}
}
}
Expand Down
29 changes: 16 additions & 13 deletions compiler/rustc_trait_selection/src/traits/wf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -432,19 +432,22 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
GenericArgKind::Const(constant) => {
match constant.val() {
ty::ConstKind::Unevaluated(uv) => {
let obligations = self.nominal_obligations(uv.def.did, uv.substs);
self.out.extend(obligations);

let predicate =
ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv.shrink()))
.to_predicate(self.tcx());
let cause = self.cause(traits::MiscObligation);
self.out.push(traits::Obligation::with_depth(
cause,
self.recursion_depth,
self.param_env,
predicate,
));
if !uv.has_escaping_bound_vars() {
let obligations = self.nominal_obligations(uv.def.did, uv.substs);
self.out.extend(obligations);

let predicate = ty::Binder::dummy(
ty::PredicateKind::ConstEvaluatable(uv.shrink()),
)
.to_predicate(self.tcx());
let cause = self.cause(traits::MiscObligation);
self.out.push(traits::Obligation::with_depth(
cause,
self.recursion_depth,
self.param_env,
predicate,
));
}
}
ty::ConstKind::Infer(infer) => {
let resolved = self.infcx.shallow_resolve(infer);
Expand Down
19 changes: 13 additions & 6 deletions compiler/rustc_typeck/src/check/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,13 @@ 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(0)), ty::BoundVariableKind::Region(ty::BrEnv)]
.iter()
.copied(),
[
ty::BoundVariableKind::Region(ty::BrAnon(0)),
ty::BoundVariableKind::Region(ty::BrAnon(1)),
ty::BoundVariableKind::Region(ty::BrEnv),
]
.iter()
.copied(),
);
let mk_va_list_ty = |mutbl| {
tcx.lang_items().va_list().map(|did| {
Expand All @@ -127,7 +131,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
));
let env_region = tcx.mk_region(ty::ReLateBound(
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.bound_type_of(did).subst(tcx, &[region.into()]);
(tcx.mk_ref(env_region, ty::TypeAndMut { ty: va_list_ty, mutbl }), va_list_ty)
Expand Down Expand Up @@ -391,9 +395,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(0) };
let param_ty =
let param_ty_lhs =
tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)), param(0));
(1, vec![param_ty; 2], tcx.types.bool)
let br = ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrAnon(1) };
let param_ty_rhs =
tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)), param(0));
(1, vec![param_ty_lhs, param_ty_rhs], tcx.types.bool)
}

sym::black_box => (1, vec![param(0)], param(0)),
Expand Down
57 changes: 41 additions & 16 deletions src/test/ui/closure-expected-type/expect-fn-supply-fn.base.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -36,33 +36,58 @@ note: ...does not necessarily outlive the anonymous lifetime #1 defined here
LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {});
| ^^^^^^^^^^^^^^^^^^^^^^

error[E0308]: mismatched types
--> $DIR/expect-fn-supply-fn.rs:38:52
error[E0631]: type mismatch in closure arguments
--> $DIR/expect-fn-supply-fn.rs:36:5
|
LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {});
| ^^^^^^^^ one type is more general than the other
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------- found signature of `fn(for<'r> fn(&'r u32), _) -> _`
| |
| expected signature of `for<'a, 'r> fn(for<'a> fn(&'a u32), &'r i32) -> _`
|
= note: expected fn pointer `fn(&u32)`
found fn pointer `for<'r> fn(&'r u32)`
note: required by a bound in `with_closure_expecting_fn_with_free_region`
--> $DIR/expect-fn-supply-fn.rs:7:8
|
LL | fn with_closure_expecting_fn_with_free_region<F>(_: F)
| ------------------------------------------ required by a bound in this
LL | where
LL | F: for<'a> FnOnce(fn(&'a u32), &i32),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `with_closure_expecting_fn_with_free_region`

error[E0308]: mismatched types
--> $DIR/expect-fn-supply-fn.rs:45:53
error[E0631]: type mismatch in closure arguments
--> $DIR/expect-fn-supply-fn.rs:43:5
|
LL | with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {});
| ^^^^^^^^^^^ one type is more general than the other
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------- found signature of `fn(fn(&'x u32), _) -> _`
| |
| expected signature of `for<'r> fn(for<'s> fn(&'s u32), &'r i32) -> _`
|
= note: expected fn pointer `for<'r> fn(&'r u32)`
found fn pointer `fn(&'x u32)`
note: required by a bound in `with_closure_expecting_fn_with_bound_region`
--> $DIR/expect-fn-supply-fn.rs:13:8
|
LL | fn with_closure_expecting_fn_with_bound_region<F>(_: F)
| ------------------------------------------- required by a bound in this
LL | where
LL | F: FnOnce(fn(&u32), &i32),
| ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `with_closure_expecting_fn_with_bound_region`

error[E0308]: mismatched types
--> $DIR/expect-fn-supply-fn.rs:54:53
error[E0631]: type mismatch in closure arguments
--> $DIR/expect-fn-supply-fn.rs:52:5
|
LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| {
| ^^^^^^^ one type is more general than the other
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --------------- found signature of `for<'r> fn(for<'r> fn(&'r u32), _) -> _`
| |
| expected signature of `for<'r> fn(for<'s> fn(&'s u32), &'r i32) -> _`
|
note: required by a bound in `with_closure_expecting_fn_with_bound_region`
--> $DIR/expect-fn-supply-fn.rs:13:8
|
= note: expected fn pointer `for<'r> fn(&'r u32)`
found fn pointer `fn(&u32)`
LL | fn with_closure_expecting_fn_with_bound_region<F>(_: F)
| ------------------------------------------- required by a bound in this
LL | where
LL | F: FnOnce(fn(&u32), &i32),
| ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `with_closure_expecting_fn_with_bound_region`

error: aborting due to 5 previous errors

For more information about this error, try `rustc --explain E0308`.
Some errors have detailed explanations: E0308, E0631.
For more information about an error, try `rustc --explain E0308`.
85 changes: 44 additions & 41 deletions src/test/ui/closure-expected-type/expect-fn-supply-fn.nll.stderr
Original file line number Diff line number Diff line change
@@ -1,51 +1,54 @@
error: lifetime may not live long enough
--> $DIR/expect-fn-supply-fn.rs:20: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:20: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:38:49
error[E0631]: type mismatch in closure arguments
--> $DIR/expect-fn-supply-fn.rs:36:5
|
LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {});
| ^ one type is more general than the other
|
= note: expected fn pointer `for<'r> fn(&'r u32)`
found fn pointer `fn(&u32)`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---------------- found signature of `fn(for<'r> fn(&'r u32), _) -> _`
| |
| expected signature of `for<'a, 'r> fn(for<'a> fn(&'a u32), &'r i32) -> _`
|
note: required by a bound in `with_closure_expecting_fn_with_free_region`
--> $DIR/expect-fn-supply-fn.rs:7:8
|
LL | fn with_closure_expecting_fn_with_free_region<F>(_: F)
| ------------------------------------------ required by a bound in this
LL | where
LL | F: for<'a> FnOnce(fn(&'a u32), &i32),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `with_closure_expecting_fn_with_free_region`

error[E0308]: mismatched types
--> $DIR/expect-fn-supply-fn.rs:45:50
error[E0631]: type mismatch in closure arguments
--> $DIR/expect-fn-supply-fn.rs:43:5
|
LL | with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {});
| ^ one type is more general than the other
|
= note: expected fn pointer `fn(&'x u32)`
found fn pointer `for<'r> fn(&'r u32)`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------- found signature of `fn(fn(&'x u32), _) -> _`
| |
| expected signature of `for<'r> fn(for<'s> fn(&'s u32), &'r i32) -> _`
|
note: required by a bound in `with_closure_expecting_fn_with_bound_region`
--> $DIR/expect-fn-supply-fn.rs:13:8
|
LL | fn with_closure_expecting_fn_with_bound_region<F>(_: F)
| ------------------------------------------- required by a bound in this
LL | where
LL | F: FnOnce(fn(&u32), &i32),
| ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `with_closure_expecting_fn_with_bound_region`

error[E0308]: mismatched types
--> $DIR/expect-fn-supply-fn.rs:54:50
error[E0631]: type mismatch in closure arguments
--> $DIR/expect-fn-supply-fn.rs:52:5
|
LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| {
| ^ one type is more general than the other
|
= note: expected fn pointer `fn(&u32)`
found fn pointer `for<'r> fn(&'r u32)`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --------------- found signature of `for<'r> fn(for<'r> fn(&'r u32), _) -> _`
| |
| expected signature of `for<'r> fn(for<'s> fn(&'s u32), &'r i32) -> _`
|
note: required by a bound in `with_closure_expecting_fn_with_bound_region`
--> $DIR/expect-fn-supply-fn.rs:13:8
|
LL | fn with_closure_expecting_fn_with_bound_region<F>(_: F)
| ------------------------------------------- required by a bound in this
LL | where
LL | F: FnOnce(fn(&u32), &i32),
| ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `with_closure_expecting_fn_with_bound_region`

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`.
8 changes: 3 additions & 5 deletions src/test/ui/closure-expected-type/expect-fn-supply-fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ fn expect_free_supply_free_from_fn<'x>(x: &'x u32) {
with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {});
//[base]~^ ERROR mismatched types
//[base]~| ERROR mismatched types
//[nll]~^^^ ERROR lifetime may not live long enough
//[nll]~| ERROR lifetime may not live long enough
}

fn expect_free_supply_free_from_closure() {
Expand All @@ -36,14 +34,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 @@ -52,7 +50,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
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

This file was deleted.

10 changes: 3 additions & 7 deletions src/test/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() {}
Loading

0 comments on commit 124673b

Please sign in to comment.