Skip to content

Commit

Permalink
Correctly check comparison operators in MIR typeck
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewjasper committed May 3, 2020
1 parent 08dfbfb commit 9e19f3a
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 44 deletions.
72 changes: 45 additions & 27 deletions src/librustc_mir/borrow_check/type_check/mod.rs
Expand Up @@ -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)
),
}
}

Expand Down
8 changes: 4 additions & 4 deletions src/test/ui/nll/type-check-pointer-comparisons.rs
Expand Up @@ -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() {}
14 changes: 1 addition & 13 deletions src/test/ui/nll/type-check-pointer-comparisons.stderr
Expand Up @@ -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

0 comments on commit 9e19f3a

Please sign in to comment.