Revert checking casts before fallback.
This turns out to not be backwards compatible.
This commit is contained in:
parent
b813718f6d
commit
d49d428f79
@ -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 {:?})",
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user