Skip to content

Commit 51769af

Browse files
authored
Rollup merge of #100691 - compiler-errors:issue-100690, r=estebank
Make `same_type_modulo_infer` a proper `TypeRelation` Specifically, this fixes #100690 because we no longer consider a `ReLateBound` and a `ReVar` to be equal. `ReVar` can only be equal to free regions or static.
2 parents c4fa35b + 64bd8c1 commit 51769af

File tree

4 files changed

+150
-53
lines changed

4 files changed

+150
-53
lines changed

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

+79-53
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ use rustc_hir::lang_items::LangItem;
6666
use rustc_hir::Node;
6767
use rustc_middle::dep_graph::DepContext;
6868
use rustc_middle::ty::print::with_no_trimmed_paths;
69+
use rustc_middle::ty::relate::{self, RelateResult, TypeRelation};
6970
use rustc_middle::ty::{
7071
self, error::TypeError, Binder, List, Region, Subst, Ty, TyCtxt, TypeFoldable,
7172
TypeSuperVisitable, TypeVisitable,
@@ -2661,67 +2662,92 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
26612662
/// Float types, respectively). When comparing two ADTs, these rules apply recursively.
26622663
pub fn same_type_modulo_infer(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
26632664
let (a, b) = self.resolve_vars_if_possible((a, b));
2664-
match (a.kind(), b.kind()) {
2665-
(&ty::Adt(def_a, substs_a), &ty::Adt(def_b, substs_b)) => {
2666-
if def_a != def_b {
2667-
return false;
2668-
}
2665+
SameTypeModuloInfer(self).relate(a, b).is_ok()
2666+
}
2667+
}
26692668

2670-
substs_a
2671-
.types()
2672-
.zip(substs_b.types())
2673-
.all(|(a, b)| self.same_type_modulo_infer(a, b))
2674-
}
2675-
(&ty::FnDef(did_a, substs_a), &ty::FnDef(did_b, substs_b)) => {
2676-
if did_a != did_b {
2677-
return false;
2678-
}
2669+
struct SameTypeModuloInfer<'a, 'tcx>(&'a InferCtxt<'a, 'tcx>);
26792670

2680-
substs_a
2681-
.types()
2682-
.zip(substs_b.types())
2683-
.all(|(a, b)| self.same_type_modulo_infer(a, b))
2684-
}
2685-
(&ty::Int(_) | &ty::Uint(_), &ty::Infer(ty::InferTy::IntVar(_)))
2671+
impl<'tcx> TypeRelation<'tcx> for SameTypeModuloInfer<'_, 'tcx> {
2672+
fn tcx(&self) -> TyCtxt<'tcx> {
2673+
self.0.tcx
2674+
}
2675+
2676+
fn param_env(&self) -> ty::ParamEnv<'tcx> {
2677+
// Unused, only for consts which we treat as always equal
2678+
ty::ParamEnv::empty()
2679+
}
2680+
2681+
fn tag(&self) -> &'static str {
2682+
"SameTypeModuloInfer"
2683+
}
2684+
2685+
fn a_is_expected(&self) -> bool {
2686+
true
2687+
}
2688+
2689+
fn relate_with_variance<T: relate::Relate<'tcx>>(
2690+
&mut self,
2691+
_variance: ty::Variance,
2692+
_info: ty::VarianceDiagInfo<'tcx>,
2693+
a: T,
2694+
b: T,
2695+
) -> relate::RelateResult<'tcx, T> {
2696+
self.relate(a, b)
2697+
}
2698+
2699+
fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
2700+
match (a.kind(), b.kind()) {
2701+
(ty::Int(_) | ty::Uint(_), ty::Infer(ty::InferTy::IntVar(_)))
26862702
| (
2687-
&ty::Infer(ty::InferTy::IntVar(_)),
2688-
&ty::Int(_) | &ty::Uint(_) | &ty::Infer(ty::InferTy::IntVar(_)),
2703+
ty::Infer(ty::InferTy::IntVar(_)),
2704+
ty::Int(_) | ty::Uint(_) | ty::Infer(ty::InferTy::IntVar(_)),
26892705
)
2690-
| (&ty::Float(_), &ty::Infer(ty::InferTy::FloatVar(_)))
2706+
| (ty::Float(_), ty::Infer(ty::InferTy::FloatVar(_)))
26912707
| (
2692-
&ty::Infer(ty::InferTy::FloatVar(_)),
2693-
&ty::Float(_) | &ty::Infer(ty::InferTy::FloatVar(_)),
2708+
ty::Infer(ty::InferTy::FloatVar(_)),
2709+
ty::Float(_) | ty::Infer(ty::InferTy::FloatVar(_)),
26942710
)
2695-
| (&ty::Infer(ty::InferTy::TyVar(_)), _)
2696-
| (_, &ty::Infer(ty::InferTy::TyVar(_))) => true,
2697-
(&ty::Ref(_, ty_a, mut_a), &ty::Ref(_, ty_b, mut_b)) => {
2698-
mut_a == mut_b && self.same_type_modulo_infer(ty_a, ty_b)
2699-
}
2700-
(&ty::RawPtr(a), &ty::RawPtr(b)) => {
2701-
a.mutbl == b.mutbl && self.same_type_modulo_infer(a.ty, b.ty)
2702-
}
2703-
(&ty::Slice(a), &ty::Slice(b)) => self.same_type_modulo_infer(a, b),
2704-
(&ty::Array(a_ty, a_ct), &ty::Array(b_ty, b_ct)) => {
2705-
self.same_type_modulo_infer(a_ty, b_ty) && a_ct == b_ct
2706-
}
2707-
(&ty::Tuple(a), &ty::Tuple(b)) => {
2708-
if a.len() != b.len() {
2709-
return false;
2710-
}
2711-
std::iter::zip(a.iter(), b.iter()).all(|(a, b)| self.same_type_modulo_infer(a, b))
2712-
}
2713-
(&ty::FnPtr(a), &ty::FnPtr(b)) => {
2714-
let a = a.skip_binder().inputs_and_output;
2715-
let b = b.skip_binder().inputs_and_output;
2716-
if a.len() != b.len() {
2717-
return false;
2718-
}
2719-
std::iter::zip(a.iter(), b.iter()).all(|(a, b)| self.same_type_modulo_infer(a, b))
2720-
}
2721-
// FIXME(compiler-errors): This needs to be generalized more
2722-
_ => a == b,
2711+
| (ty::Infer(ty::InferTy::TyVar(_)), _)
2712+
| (_, ty::Infer(ty::InferTy::TyVar(_))) => Ok(a),
2713+
(ty::Infer(_), _) | (_, ty::Infer(_)) => Err(TypeError::Mismatch),
2714+
_ => relate::super_relate_tys(self, a, b),
27232715
}
27242716
}
2717+
2718+
fn regions(
2719+
&mut self,
2720+
a: ty::Region<'tcx>,
2721+
b: ty::Region<'tcx>,
2722+
) -> RelateResult<'tcx, ty::Region<'tcx>> {
2723+
if (a.is_var() && b.is_free_or_static()) || (b.is_var() && a.is_free_or_static()) || a == b
2724+
{
2725+
Ok(a)
2726+
} else {
2727+
Err(TypeError::Mismatch)
2728+
}
2729+
}
2730+
2731+
fn binders<T>(
2732+
&mut self,
2733+
a: ty::Binder<'tcx, T>,
2734+
b: ty::Binder<'tcx, T>,
2735+
) -> relate::RelateResult<'tcx, ty::Binder<'tcx, T>>
2736+
where
2737+
T: relate::Relate<'tcx>,
2738+
{
2739+
Ok(ty::Binder::dummy(self.relate(a.skip_binder(), b.skip_binder())?))
2740+
}
2741+
2742+
fn consts(
2743+
&mut self,
2744+
a: ty::Const<'tcx>,
2745+
_b: ty::Const<'tcx>,
2746+
) -> relate::RelateResult<'tcx, ty::Const<'tcx>> {
2747+
// FIXME(compiler-errors): This could at least do some first-order
2748+
// relation
2749+
Ok(a)
2750+
}
27252751
}
27262752

27272753
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {

compiler/rustc_middle/src/ty/sty.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1617,6 +1617,10 @@ impl<'tcx> Region<'tcx> {
16171617
_ => self.is_free(),
16181618
}
16191619
}
1620+
1621+
pub fn is_var(self) -> bool {
1622+
matches!(self.kind(), ty::ReVar(_))
1623+
}
16201624
}
16211625

16221626
/// Type utilities
+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// This code (probably) _should_ compile, but it currently does not because we
2+
// are not smart enough about implied bounds.
3+
4+
use std::io;
5+
6+
fn real_dispatch<T, F>(f: F) -> Result<(), io::Error>
7+
//~^ NOTE required by a bound in this
8+
where
9+
F: FnOnce(&mut UIView<T>) -> Result<(), io::Error> + Send + 'static,
10+
//~^ NOTE required by this bound in `real_dispatch`
11+
//~| NOTE required by a bound in `real_dispatch`
12+
{
13+
todo!()
14+
}
15+
16+
#[derive(Debug)]
17+
struct UIView<'a, T: 'a> {
18+
_phantom: std::marker::PhantomData<&'a mut T>,
19+
}
20+
21+
trait Handle<'a, T: 'a, V, R> {
22+
fn dispatch<F>(&self, f: F) -> Result<(), io::Error>
23+
where
24+
F: FnOnce(&mut V) -> R + Send + 'static;
25+
}
26+
27+
#[derive(Debug, Clone)]
28+
struct TUIHandle<T> {
29+
_phantom: std::marker::PhantomData<T>,
30+
}
31+
32+
impl<'a, T: 'a> Handle<'a, T, UIView<'a, T>, Result<(), io::Error>> for TUIHandle<T> {
33+
fn dispatch<F>(&self, f: F) -> Result<(), io::Error>
34+
where
35+
F: FnOnce(&mut UIView<'a, T>) -> Result<(), io::Error> + Send + 'static,
36+
{
37+
real_dispatch(f)
38+
//~^ ERROR expected a `FnOnce<(&mut UIView<'_, T>,)>` closure, found `F`
39+
//~| NOTE expected an `FnOnce<(&mut UIView<'_, T>,)>` closure, found `F`
40+
//~| NOTE expected a closure with arguments
41+
//~| NOTE required by a bound introduced by this call
42+
}
43+
}
44+
45+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error[E0277]: expected a `FnOnce<(&mut UIView<'_, T>,)>` closure, found `F`
2+
--> $DIR/issue-100690.rs:37:23
3+
|
4+
LL | real_dispatch(f)
5+
| ------------- ^ expected an `FnOnce<(&mut UIView<'_, T>,)>` closure, found `F`
6+
| |
7+
| required by a bound introduced by this call
8+
|
9+
= note: expected a closure with arguments `(&mut UIView<'a, T>,)`
10+
found a closure with arguments `(&mut UIView<'_, T>,)`
11+
note: required by a bound in `real_dispatch`
12+
--> $DIR/issue-100690.rs:9:8
13+
|
14+
LL | fn real_dispatch<T, F>(f: F) -> Result<(), io::Error>
15+
| ------------- required by a bound in this
16+
...
17+
LL | F: FnOnce(&mut UIView<T>) -> Result<(), io::Error> + Send + 'static,
18+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `real_dispatch`
19+
20+
error: aborting due to previous error
21+
22+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)