Correctly check comparison operators in MIR typeck
This commit is contained in:
parent
08dfbfb618
commit
9e19f3a27f
@ -2290,36 +2290,54 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
right,
|
||||
) => {
|
||||
let ty_left = left.ty(body, tcx);
|
||||
if let ty::RawPtr(_) | ty::FnPtr(_) = ty_left.kind {
|
||||
let ty_right = right.ty(body, tcx);
|
||||
let common_ty = self.infcx.next_ty_var(TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::MiscVariable,
|
||||
span: body.source_info(location).span,
|
||||
});
|
||||
self.sub_types(
|
||||
common_ty,
|
||||
ty_left,
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Boring,
|
||||
)
|
||||
.unwrap_or_else(|err| {
|
||||
bug!("Could not equate type variable with {:?}: {:?}", ty_left, err)
|
||||
});
|
||||
if let Err(terr) = self.sub_types(
|
||||
common_ty,
|
||||
ty_right,
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Boring,
|
||||
) {
|
||||
span_mirbug!(
|
||||
self,
|
||||
rvalue,
|
||||
"unexpected comparison types {:?} and {:?} yields {:?}",
|
||||
match ty_left.kind {
|
||||
// Types with regions are comparable if they have a common super-type.
|
||||
ty::RawPtr(_) | ty::FnPtr(_) => {
|
||||
let ty_right = right.ty(body, tcx);
|
||||
let common_ty = self.infcx.next_ty_var(TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::MiscVariable,
|
||||
span: body.source_info(location).span,
|
||||
});
|
||||
self.relate_types(
|
||||
common_ty,
|
||||
ty::Variance::Contravariant,
|
||||
ty_left,
|
||||
ty_right,
|
||||
terr
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Boring,
|
||||
)
|
||||
.unwrap_or_else(|err| {
|
||||
bug!("Could not equate type variable with {:?}: {:?}", ty_left, err)
|
||||
});
|
||||
if let Err(terr) = self.relate_types(
|
||||
common_ty,
|
||||
ty::Variance::Contravariant,
|
||||
ty_right,
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Boring,
|
||||
) {
|
||||
span_mirbug!(
|
||||
self,
|
||||
rvalue,
|
||||
"unexpected comparison types {:?} and {:?} yields {:?}",
|
||||
ty_left,
|
||||
ty_right,
|
||||
terr
|
||||
)
|
||||
}
|
||||
}
|
||||
// For types with no regions we can just check that the
|
||||
// both operands have the same type.
|
||||
ty::Int(_) | ty::Uint(_) | ty::Bool | ty::Char | ty::Float(_)
|
||||
if ty_left == right.ty(body, tcx) => {}
|
||||
// Other types are compared by trait methods, not by
|
||||
// `Rvalue::BinaryOp`.
|
||||
_ => span_mirbug!(
|
||||
self,
|
||||
rvalue,
|
||||
"unexpected comparison types {:?} and {:?}",
|
||||
ty_left,
|
||||
right.ty(body, tcx)
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,13 +21,13 @@ fn compare_fn_ptr<'a, 'b, 'c>(f: fn(&'c mut &'a i32), g: fn(&'c mut &'b i32)) {
|
||||
}
|
||||
|
||||
fn compare_hr_fn_ptr<'a>(f: fn(&'a i32), g: fn(&i32)) {
|
||||
f == g;
|
||||
//~^ ERROR higher-ranked subtype error
|
||||
// Ideally this should compile with the operands swapped as well, but HIR
|
||||
// type checking prevents it (and stops compilation) for now.
|
||||
f == g; // OK
|
||||
}
|
||||
|
||||
fn compare_const_fn_ptr<'a>(f: *const fn(&'a i32), g: *const fn(&i32)) {
|
||||
f == g;
|
||||
//~^ ERROR higher-ranked subtype error
|
||||
f == g; // OK
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -76,17 +76,5 @@ LL | f == g;
|
||||
|
||||
help: `'a` and `'b` must be the same: replace one with the other
|
||||
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/type-check-pointer-comparisons.rs:24:5
|
||||
|
|
||||
LL | f == g;
|
||||
| ^^^^^^
|
||||
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/type-check-pointer-comparisons.rs:29:5
|
||||
|
|
||||
LL | f == g;
|
||||
| ^^^^^^
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user