about summary refs log tree commit diff
diff options
context:
space:
mode:
authorleonardo.yvens <leoyvens@gmail.com>2018-02-08 17:36:17 -0200
committerleonardo.yvens <leoyvens@gmail.com>2018-02-08 17:36:17 -0200
commitd49d428f791b97c476c066deb9c2b3c20165199f (patch)
treeda9dd8704a3abc58e61f3532bffaa98e5d7a18a8
parentb813718f6dff49b851fcd18a5674640554bda2e5 (diff)
downloadrust-d49d428f791b97c476c066deb9c2b3c20165199f.tar.gz
rust-d49d428f791b97c476c066deb9c2b3c20165199f.zip
Revert checking casts before fallback.
This turns out to not be backwards compatible.
-rw-r--r--src/librustc_typeck/check/cast.rs11
-rw-r--r--src/librustc_typeck/check/mod.rs25
-rw-r--r--src/test/run-pass/cast-does-fallback.rs4
-rw-r--r--src/test/ui/issue-45730.rs4
-rw-r--r--src/test/ui/issue-45730.stderr8
5 files changed, 17 insertions, 35 deletions
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index dae5ba14bfb..48bd7b14fc9 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -38,7 +38,7 @@
 //! expression, `e as U2` is not necessarily so (in fact it will only be valid if
 //! `U1` coerces to `U2`).
 
-use super::{Diverges, Fallback, FnCtxt};
+use super::{Diverges, FnCtxt};
 
 use errors::DiagnosticBuilder;
 use hir::def_id::DefId;
@@ -290,9 +290,6 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
             }
             CastError::UnknownCastPtrKind |
             CastError::UnknownExprPtrKind => {
-                if fcx.is_tainted_by_errors() {
-                    return;
-                }
                 let unknown_cast_to = match e {
                     CastError::UnknownCastPtrKind => true,
                     CastError::UnknownExprPtrKind => false,
@@ -396,12 +393,6 @@ 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);
-        // For backwards compatibility we apply numeric fallback here. This means that in:
-        // `let x = 100; x as u8;`, we infer `x` to `i32` rather than `u8`.
-        if self.expr_ty.is_ty_infer() {
-            fcx.fallback_if_possible(self.expr_ty, Fallback::Numeric);
-            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 {:?})",
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 0395b3eb4aa..f50bd03a9e0 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -858,17 +858,19 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             fcx
         };
 
-        fcx.check_casts();
-
         // All type checking constraints were added, try to fallback unsolved variables.
         fcx.select_obligations_where_possible();
         for ty in &fcx.unsolved_variables() {
-            fcx.fallback_if_possible(ty, Fallback::Full);
+            fcx.fallback_if_possible(ty);
         }
         fcx.select_obligations_where_possible();
 
+        // Even though coercion casts provide type hints, we check casts after fallback for
+        // backwards compatibility. This makes fallback a stronger type hint than a cast coercion.
+        fcx.check_casts();
+
         // Closure and generater analysis may run after fallback
-        // because they doen't constrain other type variables.
+        // because they don't constrain other type variables.
         fcx.closure_analyze(body);
         assert!(fcx.deferred_call_resolutions.borrow().is_empty());
         fcx.resolve_generator_interiors(def_id);
@@ -1734,12 +1736,6 @@ enum TupleArgumentsFlag {
     TupleArguments,
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub enum Fallback {
-    Full,
-    Numeric
-}
-
 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     pub fn new(inh: &'a Inherited<'a, 'gcx, 'tcx>,
                param_env: ty::ParamEnv<'tcx>,
@@ -2149,7 +2145,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     // unconstrained floats with f64.
     // Fallback becomes very dubious if we have encountered type-checking errors.
     // In that case, fallback to TyError.
-    fn fallback_if_possible(&self, ty: Ty<'tcx>, fallback: Fallback) {
+    fn fallback_if_possible(&self, ty: Ty<'tcx>) {
         use rustc::ty::error::UnconstrainedNumeric::Neither;
         use rustc::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat};
 
@@ -2158,12 +2154,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             _ if self.is_tainted_by_errors() => self.tcx().types.err,
             UnconstrainedInt => self.tcx.types.i32,
             UnconstrainedFloat => self.tcx.types.f64,
-            Neither if self.type_var_diverges(ty) => {
-                match fallback {
-                    Fallback::Full => self.tcx.mk_diverging_default(),
-                    Fallback::Numeric => return,
-                }
-            }
+            Neither if self.type_var_diverges(ty) => self.tcx.mk_diverging_default(),
             Neither => return
         };
         debug!("default_type_parameters: defaulting `{:?}` to `{:?}`", ty, fallback);
diff --git a/src/test/run-pass/cast-does-fallback.rs b/src/test/run-pass/cast-does-fallback.rs
index 86d6e387b25..aa6752ffc35 100644
--- a/src/test/run-pass/cast-does-fallback.rs
+++ b/src/test/run-pass/cast-does-fallback.rs
@@ -9,6 +9,10 @@
 // except according to those terms.
 
 pub fn main() {
+    // Test that these type check correctly.
+    (&42u8 >> 4) as usize;
+    (&42u8 << 4) as usize;
+
     let cap = 512 * 512;
     cap as u8;
     // Assert `cap` did not get inferred to `u8` and overflowed.
diff --git a/src/test/ui/issue-45730.rs b/src/test/ui/issue-45730.rs
index 1fe0b1ae2d2..d733c8e6de2 100644
--- a/src/test/ui/issue-45730.rs
+++ b/src/test/ui/issue-45730.rs
@@ -11,13 +11,9 @@
 use std::fmt;
 fn main() {
     let x: *const _ = 0 as _; //~ ERROR cannot cast
-}
 
-fn a() {
     let x: *const _ = 0 as *const _; //~ ERROR cannot cast
     let y: Option<*const fmt::Debug> = Some(x) as _;
-}
 
-fn c() {
     let x = 0 as *const i32 as *const _ as *mut _; //~ ERROR cannot cast
 }
diff --git a/src/test/ui/issue-45730.stderr b/src/test/ui/issue-45730.stderr
index 13205eead43..94d39239117 100644
--- a/src/test/ui/issue-45730.stderr
+++ b/src/test/ui/issue-45730.stderr
@@ -9,9 +9,9 @@ error[E0641]: cannot cast to a pointer of an unknown kind
    = note: The type information given here is insufficient to check whether the pointer cast is valid
 
 error[E0641]: cannot cast to a pointer of an unknown kind
-  --> $DIR/issue-45730.rs:17:23
+  --> $DIR/issue-45730.rs:15:23
    |
-17 |     let x: *const _ = 0 as *const _; //~ ERROR cannot cast
+15 |     let x: *const _ = 0 as *const _; //~ ERROR cannot cast
    |                       ^^^^^--------
    |                            |
    |                            help: consider giving more type information
@@ -19,9 +19,9 @@ error[E0641]: cannot cast to a pointer of an unknown kind
    = note: The type information given here is insufficient to check whether the pointer cast is valid
 
 error[E0641]: cannot cast to a pointer of an unknown kind
-  --> $DIR/issue-45730.rs:22:13
+  --> $DIR/issue-45730.rs:18:13
    |
-22 |     let x = 0 as *const i32 as *const _ as *mut _; //~ ERROR cannot cast
+18 |     let x = 0 as *const i32 as *const _ as *mut _; //~ ERROR cannot cast
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------
    |                                            |
    |                                            help: consider giving more type information