Make coerce_never lint an error

Remove the coerce_never lint and make the behaviour an error.
This commit is contained in:
Andrew Cann 2018-02-01 15:23:04 +08:00
parent 32ddb30715
commit 59688e119e
12 changed files with 22 additions and 103 deletions

View File

@ -230,12 +230,6 @@ declare_lint! {
"detect mut variables which don't need to be mutable"
}
declare_lint! {
pub COERCE_NEVER,
Deny,
"detect coercion to !"
}
declare_lint! {
pub SINGLE_USE_LIFETIME,
Allow,
@ -310,7 +304,6 @@ impl LintPass for HardwiredLints {
DEPRECATED,
UNUSED_UNSAFE,
UNUSED_MUT,
COERCE_NEVER,
SINGLE_USE_LIFETIME,
TYVAR_BEHIND_RAW_POINTER,
ELIDED_LIFETIME_IN_PATH,

View File

@ -270,11 +270,6 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
reference: "issue #46205 <https://github.com/rust-lang/rust/issues/46205>",
epoch: None,
},
FutureIncompatibleInfo {
id: LintId::of(COERCE_NEVER),
reference: "issue #46325 <https://github.com/rust-lang/rust/issues/46325>",
epoch: None,
},
FutureIncompatibleInfo {
id: LintId::of(TYVAR_BEHIND_RAW_POINTER),
reference: "issue #46906 <https://github.com/rust-lang/rust/issues/46906>",

View File

@ -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::FnCtxt;
use errors::DiagnosticBuilder;
use hir::def_id::DefId;
@ -59,7 +59,6 @@ use util::common::ErrorReported;
pub struct CastCheck<'tcx> {
expr: &'tcx hir::Expr,
expr_ty: Ty<'tcx>,
expr_diverges: Diverges,
cast_ty: Ty<'tcx>,
cast_span: Span,
span: Span,
@ -183,7 +182,6 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
pub fn new(fcx: &FnCtxt<'a, 'gcx, 'tcx>,
expr: &'tcx hir::Expr,
expr_ty: Ty<'tcx>,
expr_diverges: Diverges,
cast_ty: Ty<'tcx>,
cast_span: Span,
span: Span)
@ -191,7 +189,6 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
let check = CastCheck {
expr,
expr_ty,
expr_diverges,
cast_ty,
cast_span,
span,
@ -437,7 +434,6 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
let f = self.expr_ty.fn_sig(fcx.tcx);
let res = fcx.try_coerce(self.expr,
self.expr_ty,
self.expr_diverges,
fcx.tcx.mk_fn_ptr(f));
if !res.is_ok() {
return Err(CastError::NonScalar);
@ -620,7 +616,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
}
fn try_coercion_cast(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> bool {
fcx.try_coerce(self.expr, self.expr_ty, self.expr_diverges, self.cast_ty).is_ok()
fcx.try_coerce(self.expr, self.expr_ty, self.cast_ty).is_ok()
}
}

View File

@ -66,7 +66,6 @@ use rustc::hir;
use rustc::hir::def_id::DefId;
use rustc::infer::{Coercion, InferResult, InferOk};
use rustc::infer::type_variable::TypeVariableOrigin;
use rustc::lint;
use rustc::traits::{self, ObligationCause, ObligationCauseCode};
use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability};
use rustc::ty::{self, TypeAndMut, Ty, ClosureSubsts};
@ -752,27 +751,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
pub fn try_coerce(&self,
expr: &hir::Expr,
expr_ty: Ty<'tcx>,
expr_diverges: Diverges,
target: Ty<'tcx>)
-> RelateResult<'tcx, Ty<'tcx>> {
let source = self.resolve_type_vars_with_obligations(expr_ty);
debug!("coercion::try({:?}: {:?} -> {:?})", expr, source, target);
// Special-ish case: we can coerce any type `T` into the `!`
// type, but only if the source expression diverges.
if target.is_never() && expr_diverges.always() {
debug!("permit coercion to `!` because expr diverges");
if self.can_eq(self.param_env, source, target).is_err() {
self.tcx.lint_node(
lint::builtin::COERCE_NEVER,
expr.id,
expr.span,
&format!("cannot coerce `{}` to !", source)
);
return Ok(target);
}
}
let cause = self.cause(expr.span, ObligationCauseCode::ExprAssignable);
let coerce = Coerce::new(self, cause);
let ok = self.commit_if_ok(|_| coerce.coerce(source, target))?;
@ -1123,7 +1106,7 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
if self.pushed == 0 {
// Special-case the first expression we are coercing.
// To be honest, I'm not entirely sure why we do this.
fcx.try_coerce(expression, expression_ty, expression_diverges, self.expected_ty)
fcx.try_coerce(expression, expression_ty, self.expected_ty)
} else {
match self.expressions {
Expressions::Dynamic(ref exprs) =>

View File

@ -100,7 +100,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
-> (Ty<'tcx>, Option<DiagnosticBuilder<'tcx>>) {
let expected = self.resolve_type_vars_with_obligations(expected);
let e = match self.try_coerce(expr, checked_ty, self.diverges.get(), expected) {
let e = match self.try_coerce(expr, checked_ty, expected) {
Ok(ty) => return (ty, None),
Err(e) => e
};

View File

@ -3944,7 +3944,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let t_cast = self.resolve_type_vars_if_possible(&t_cast);
let t_expr = self.check_expr_with_expectation(e, ExpectCastableToType(t_cast));
let t_cast = self.resolve_type_vars_if_possible(&t_cast);
let diverges = self.diverges.get();
// Eagerly check for some obvious errors.
if t_expr.references_error() || t_cast.references_error() {
@ -3952,7 +3951,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
} else {
// Defer other checks until we're done type checking.
let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
match cast::CastCheck::new(self, e, t_expr, diverges, t_cast, t.span, expr.span) {
match cast::CastCheck::new(self, e, t_expr, t_cast, t.span, expr.span) {
Ok(cast_check) => {
deferred_cast_checks.push(cast_check);
t_cast

View File

@ -10,11 +10,9 @@
fn foo(x: usize, y: !, z: usize) { }
#[deny(coerce_never)]
fn cast_a() {
let y = {return; 22} as !;
//~^ ERROR cannot coerce `i32` to !
//~| hard error
//~^ ERROR non-primitive cast
}
fn cast_b() {

View File

@ -8,17 +8,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![deny(coerce_never)]
fn foo(x: usize, y: !, z: usize) { }
fn call_foo_a() {
// FIXME(#40800) -- accepted because divergence happens **before**
// the coercion to `!`, but within same expression. Not clear that
// these are the rules we want.
foo(return, 22, 44);
//~^ ERROR cannot coerce `{integer}` to !
//~| hard error
//~^ ERROR mismatched types
}
fn call_foo_b() {
@ -38,8 +32,7 @@ fn call_foo_d() {
let b = 22;
let c = 44;
foo(a, b, c); // ... and hence a reference to `a` is expected to diverge.
//~^ ERROR cannot coerce `{integer}` to !
//~| hard error
//~^ ERROR mismatched types
}
fn call_foo_e() {
@ -79,8 +72,7 @@ fn tuple_a() {
fn tuple_b() {
// Divergence happens before coercion: OK
let x: (usize, !, usize) = (return, 44, 66);
//~^ ERROR cannot coerce `{integer}` to !
//~| hard error
//~^ ERROR mismatched types
}
fn tuple_c() {

View File

@ -8,12 +8,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[deny(coerce_never)]
fn assert_sizeof() -> ! {
unsafe {
::std::mem::transmute::<f64, [u8; 8]>(panic!())
//~^ ERROR cannot coerce `[u8; 8]` to !
//~| hard error
//~^ ERROR mismatched types
}
}

View File

@ -1,18 +0,0 @@
// Copyright 2016 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.
#[allow(coerce_never)]
fn assert_sizeof() -> ! {
unsafe {
::std::mem::transmute::<f64, [u8; 8]>(panic!())
}
}
fn main() { }

View File

@ -12,12 +12,9 @@
#![allow(unused_assignments)]
#![allow(dead_code)]
#![deny(unreachable_code)]
#![deny(coerce_never)]
fn foo() {
let x: ! = ! { return; 22 }; //~ ERROR unreachable
//~^ ERROR cannot coerce
//~| hard error
let x: ! = ! { return; }; //~ ERROR unreachable
//~| ERROR cannot apply unary operator `!` to type `!`
}

View File

@ -1,8 +1,14 @@
error: unreachable expression
--> $DIR/expr_unary.rs:18:28
error[E0600]: cannot apply unary operator `!` to type `!`
--> $DIR/expr_unary.rs:17:16
|
LL | let x: ! = ! { return; 22 }; //~ ERROR unreachable
| ^^
17 | let x: ! = ! { return; }; //~ ERROR unreachable
| ^^^^^^^^^^^^^
error: unreachable expression
--> $DIR/expr_unary.rs:17:16
|
LL | let x: ! = ! { return; }; //~ ERROR unreachable
| ^^^^^^^^^^^^^
|
note: lint level defined here
--> $DIR/expr_unary.rs:14:9
@ -10,26 +16,6 @@ note: lint level defined here
LL | #![deny(unreachable_code)]
| ^^^^^^^^^^^^^^^^
error: cannot coerce `{integer}` to !
--> $DIR/expr_unary.rs:18:28
|
LL | let x: ! = ! { return; 22 }; //~ ERROR unreachable
| ^^
|
note: lint level defined here
--> $DIR/expr_unary.rs:15:9
|
LL | #![deny(coerce_never)]
| ^^^^^^^^^^^^
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #46325 <https://github.com/rust-lang/rust/issues/46325>
error[E0600]: cannot apply unary operator `!` to type `!`
--> $DIR/expr_unary.rs:18:16
|
LL | let x: ! = ! { return; 22 }; //~ ERROR unreachable
| ^^^^^^^^^^^^^^^^
error: aborting due to 3 previous errors
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0600`.