From 7719f534196c9fe5216161e313ad7624f1beadee Mon Sep 17 00:00:00 2001 From: "leonardo.yvens" Date: Fri, 16 Feb 2018 11:16:41 -0200 Subject: [PATCH 1/3] Replace `structurally_resolved_type` in casts check. The behaviour of `resolve_type_vars_if_possible` is simpler and infallible. --- src/librustc/ty/cast.rs | 3 +-- src/librustc_typeck/check/cast.rs | 10 +++------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/librustc/ty/cast.rs b/src/librustc/ty/cast.rs index c118b7a4692e5..3ba79d91964ab 100644 --- a/src/librustc/ty/cast.rs +++ b/src/librustc/ty/cast.rs @@ -20,7 +20,6 @@ use syntax::ast; pub enum IntTy { U(ast::UintTy), I, - Ivar, CEnum, Bool, Char @@ -64,7 +63,7 @@ impl<'tcx> CastTy<'tcx> { ty::TyBool => Some(CastTy::Int(IntTy::Bool)), ty::TyChar => Some(CastTy::Int(IntTy::Char)), ty::TyInt(_) => Some(CastTy::Int(IntTy::I)), - ty::TyInfer(ty::InferTy::IntVar(_)) => Some(CastTy::Int(IntTy::Ivar)), + ty::TyInfer(ty::InferTy::IntVar(_)) => Some(CastTy::Int(IntTy::I)), ty::TyInfer(ty::InferTy::FloatVar(_)) => Some(CastTy::Float), ty::TyUint(u) => Some(CastTy::Int(IntTy::U(u))), ty::TyFloat(_) => Some(CastTy::Float), diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index e4bad8349ea2b..31f418df902be 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -389,8 +389,8 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { } pub fn check(mut self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) { - self.expr_ty = fcx.structurally_resolved_type(self.span, self.expr_ty); - self.cast_ty = fcx.structurally_resolved_type(self.span, self.cast_ty); + self.expr_ty = fcx.resolve_type_vars_if_possible(&self.expr_ty); + self.cast_ty = fcx.resolve_type_vars_if_possible(&self.cast_ty); debug!("check_cast({}, {:?} as {:?})", self.expr.id, @@ -484,11 +484,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { ty::TypeVariants::TyInfer(t) => { match t { ty::InferTy::IntVar(_) | - ty::InferTy::FloatVar(_) | - ty::InferTy::FreshIntTy(_) | - ty::InferTy::FreshFloatTy(_) => { - Err(CastError::NeedDeref) - } + ty::InferTy::FloatVar(_) => Err(CastError::NeedDeref), _ => Err(CastError::NeedViaPtr), } } From 7353ef744e1ff4e8b511f77969eab316e8e06f5b Mon Sep 17 00:00:00 2001 From: "leonardo.yvens" Date: Sun, 18 Feb 2018 10:39:26 -0300 Subject: [PATCH 2/3] Replace `structurally_resolve_type` in unary expr check. `resolve_type_vars_with_obligations` is the same but doesn't error on unresolved type variables. In theory this could make more code compile because we don't error or could ommit an otherwise useful error. In practice I couldn't observe any effect. --- src/librustc_typeck/check/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 69879bbe85d6e..e5d3e84e840d2 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3639,7 +3639,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { needs); if !oprnd_t.references_error() { - oprnd_t = self.structurally_resolved_type(expr.span, oprnd_t); + oprnd_t = self.resolve_type_vars_with_obligations(&oprnd_t); match unop { hir::UnDeref => { if let Some(mt) = oprnd_t.builtin_deref(true) { From 0a5a5c3418c56546c574b7698d9158ef16aa174e Mon Sep 17 00:00:00 2001 From: "leonardo.yvens" Date: Thu, 22 Mar 2018 17:41:07 -0300 Subject: [PATCH 3/3] revert making casts atomic, test order dependency --- src/librustc_typeck/check/cast.rs | 4 ++-- src/librustc_typeck/check/mod.rs | 2 +- src/test/run-pass/cast.rs | 5 +++++ src/test/ui/order-dependent-cast-inference.rs | 18 ++++++++++++++++++ .../ui/order-dependent-cast-inference.stderr | 13 +++++++++++++ 5 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/order-dependent-cast-inference.rs create mode 100644 src/test/ui/order-dependent-cast-inference.stderr diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 31f418df902be..7ebacc92babf8 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -389,8 +389,8 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { } pub fn check(mut self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) { - self.expr_ty = fcx.resolve_type_vars_if_possible(&self.expr_ty); - self.cast_ty = fcx.resolve_type_vars_if_possible(&self.cast_ty); + self.expr_ty = fcx.structurally_resolved_type(self.span, self.expr_ty); + self.cast_ty = fcx.structurally_resolved_type(self.span, self.cast_ty); debug!("check_cast({}, {:?} as {:?})", self.expr.id, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index e5d3e84e840d2..69879bbe85d6e 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3639,7 +3639,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { needs); if !oprnd_t.references_error() { - oprnd_t = self.resolve_type_vars_with_obligations(&oprnd_t); + oprnd_t = self.structurally_resolved_type(expr.span, oprnd_t); match unop { hir::UnDeref => { if let Some(mt) = oprnd_t.builtin_deref(true) { diff --git a/src/test/run-pass/cast.rs b/src/test/run-pass/cast.rs index bb60626a4bf02..80fa5362a8be9 100644 --- a/src/test/run-pass/cast.rs +++ b/src/test/run-pass/cast.rs @@ -19,4 +19,9 @@ pub fn main() { assert_eq!(i as u8 as i8, 'Q' as u8 as i8); assert_eq!(0x51 as char, 'Q'); assert_eq!(0 as u32, false as u32); + + // Test that `_` is correctly inferred. + let x = &"hello"; + let mut y = x as *const _; + y = 0 as *const _; } diff --git a/src/test/ui/order-dependent-cast-inference.rs b/src/test/ui/order-dependent-cast-inference.rs new file mode 100644 index 0000000000000..afcd402343b25 --- /dev/null +++ b/src/test/ui/order-dependent-cast-inference.rs @@ -0,0 +1,18 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + // Tests case where inference fails due to the order in which casts are checked. + // Ideally this would compile, see #48270. + let x = &"hello"; + let mut y = 0 as *const _; + //~^ ERROR cannot cast to a pointer of an unknown kind + y = x as *const _; +} diff --git a/src/test/ui/order-dependent-cast-inference.stderr b/src/test/ui/order-dependent-cast-inference.stderr new file mode 100644 index 0000000000000..556acc87cffaf --- /dev/null +++ b/src/test/ui/order-dependent-cast-inference.stderr @@ -0,0 +1,13 @@ +error[E0641]: cannot cast to a pointer of an unknown kind + --> $DIR/order-dependent-cast-inference.rs:15:17 + | +LL | let mut y = 0 as *const _; + | ^^^^^-------- + | | + | help: consider giving more type information + | + = note: The type information given here is insufficient to check whether the pointer cast is valid + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0641`.