Be more explicit about how and why we need fallback in targets of casts
This commit is contained in:
parent
02084f3304
commit
4c0ff95e6e
3 changed files with 34 additions and 21 deletions
|
|
@ -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, FnCtxt};
|
||||
use super::{Diverges, Fallback, FnCtxt};
|
||||
|
||||
use errors::DiagnosticBuilder;
|
||||
use hir::def_id::DefId;
|
||||
|
|
@ -392,7 +392,13 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
|
|||
}
|
||||
|
||||
pub fn check(mut self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) {
|
||||
self.expr_ty = fcx.resolved_type(self.span, self.expr_ty);
|
||||
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.apply_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 {:?})",
|
||||
|
|
|
|||
|
|
@ -1724,6 +1724,12 @@ 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>,
|
||||
|
|
@ -2133,7 +2139,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
// unconstrained floats with f64.
|
||||
// Defaulting inference variables becomes very dubious if we have
|
||||
// encountered type-checking errors. In that case, fallback to TyError.
|
||||
fn apply_fallback_if_possible(&self, ty: Ty<'tcx>) {
|
||||
fn apply_fallback_if_possible(&self, ty: Ty<'tcx>, fallback: Fallback) {
|
||||
use rustc::ty::error::UnconstrainedNumeric::Neither;
|
||||
use rustc::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat};
|
||||
|
||||
|
|
@ -2142,7 +2148,8 @@ 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) => self.tcx.mk_diverging_default(),
|
||||
Neither if self.type_var_diverges(ty) && fallback == Fallback::Full
|
||||
=> self.tcx.mk_diverging_default(),
|
||||
Neither => return
|
||||
};
|
||||
debug!("default_type_parameters: defaulting `{:?}` to `{:?}`", ty, fallback);
|
||||
|
|
@ -2159,7 +2166,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
self.select_obligations_where_possible();
|
||||
|
||||
for ty in &self.unsolved_variables() {
|
||||
self.apply_fallback_if_possible(ty);
|
||||
self.apply_fallback_if_possible(ty, Fallback::Full);
|
||||
}
|
||||
|
||||
let mut fulfillment_cx = self.fulfillment_cx.borrow_mut();
|
||||
|
|
@ -4937,22 +4944,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
// Same as `structurally_resolved_type` but also resolves numeric vars, with fallback.
|
||||
pub fn resolved_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
let mut ty = self.resolve_type_vars_with_obligations(ty);
|
||||
if !ty.is_ty_infer() {
|
||||
return ty;
|
||||
} else {
|
||||
self.apply_fallback_if_possible(ty);
|
||||
ty = self.resolve_type_vars_with_obligations(ty);
|
||||
if !ty.is_ty_infer() {
|
||||
ty
|
||||
} else { // Fallback failed, error.
|
||||
self.must_be_known_in_context(sp, ty)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn must_be_known_in_context(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
if !self.is_tainted_by_errors() {
|
||||
type_error_struct!(self.tcx.sess, sp, ty, E0619,
|
||||
|
|
|
|||
16
src/test/run-pass/cast-does-fallback.rs
Normal file
16
src/test/run-pass/cast-does-fallback.rs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright 2017 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
pub fn main() {
|
||||
let cap = 512 * 512;
|
||||
cap as u8;
|
||||
// Assert `cap` did not get inferred to `u8` and overflowed.
|
||||
assert_ne!(cap, 0);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue