Skip to content

Commit

Permalink
Make coerce_never lint an error
Browse files Browse the repository at this point in the history
Remove the coerce_never lint and make the behaviour an error.
  • Loading branch information
canndrew authored and nikomatsakis committed Feb 8, 2018
1 parent 32601f6 commit c3beef6
Show file tree
Hide file tree
Showing 12 changed files with 21 additions and 101 deletions.
7 changes: 0 additions & 7 deletions src/librustc/lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,12 +221,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,
Expand Down Expand Up @@ -287,7 +281,6 @@ impl LintPass for HardwiredLints {
DEPRECATED,
UNUSED_UNSAFE,
UNUSED_MUT,
COERCE_NEVER,
SINGLE_USE_LIFETIME,
TYVAR_BEHIND_RAW_POINTER,
ELIDED_LIFETIME_IN_PATH
Expand Down
4 changes: 0 additions & 4 deletions src/librustc_lint/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,10 +243,6 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
id: LintId::of(INCOHERENT_FUNDAMENTAL_IMPLS),
reference: "issue #46205 <https://github.com/rust-lang/rust/issues/46205>",
},
FutureIncompatibleInfo {
id: LintId::of(COERCE_NEVER),
reference: "issue #46325 <https://github.com/rust-lang/rust/issues/46325>",
},
FutureIncompatibleInfo {
id: LintId::of(TYVAR_BEHIND_RAW_POINTER),
reference: "issue #46906 <https://github.com/rust-lang/rust/issues/46906>",
Expand Down
8 changes: 2 additions & 6 deletions src/librustc_typeck/check/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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,
Expand Down Expand Up @@ -183,15 +182,13 @@ 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)
-> Result<CastCheck<'tcx>, ErrorReported> {
let check = CastCheck {
expr,
expr_ty,
expr_diverges,
cast_ty,
cast_span,
span,
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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()
}
}

Expand Down
19 changes: 1 addition & 18 deletions src/librustc_typeck/check/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
use rustc::ty::{self, TypeAndMut, Ty, ClosureSubsts};
Expand Down Expand Up @@ -736,27 +735,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))?;
Expand Down Expand Up @@ -1106,7 +1089,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) =>
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_typeck/check/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
};
Expand Down
3 changes: 1 addition & 2 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3948,15 +3948,14 @@ 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() {
tcx.types.err
} 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
Expand Down
4 changes: 1 addition & 3 deletions src/test/compile-fail/coerce-to-bang-cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
14 changes: 3 additions & 11 deletions src/test/compile-fail/coerce-to-bang.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 beacuse 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() {
Expand All @@ -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() {
Expand Down Expand Up @@ -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() {
Expand Down
4 changes: 1 addition & 3 deletions src/test/compile-fail/diverging-fn-tail-35849.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}

Expand Down
18 changes: 0 additions & 18 deletions src/test/run-pass/diverging-fn-tail-35849.rs

This file was deleted.

5 changes: 1 addition & 4 deletions src/test/ui/reachable/expr_unary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 `!`
}

Expand Down
34 changes: 10 additions & 24 deletions src/test/ui/reachable/expr_unary.stderr
Original file line number Diff line number Diff line change
@@ -1,34 +1,20 @@
error[E0600]: cannot apply unary operator `!` to type `!`
--> $DIR/expr_unary.rs:17:16
|
17 | let x: ! = ! { return; }; //~ ERROR unreachable
| ^^^^^^^^^^^^^

error: unreachable expression
--> $DIR/expr_unary.rs:18:28
--> $DIR/expr_unary.rs:17:16
|
18 | let x: ! = ! { return; 22 }; //~ ERROR unreachable
| ^^
17 | let x: ! = ! { return; }; //~ ERROR unreachable
| ^^^^^^^^^^^^^
|
note: lint level defined here
--> $DIR/expr_unary.rs:14:9
|
14 | #![deny(unreachable_code)]
| ^^^^^^^^^^^^^^^^

error: cannot coerce `{integer}` to !
--> $DIR/expr_unary.rs:18:28
|
18 | let x: ! = ! { return; 22 }; //~ ERROR unreachable
| ^^
|
note: lint level defined here
--> $DIR/expr_unary.rs:15:9
|
15 | #![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
|
18 | let x: ! = ! { return; 22 }; //~ ERROR unreachable
| ^^^^^^^^^^^^^^^^

error: aborting due to 3 previous errors
error: aborting due to 2 previous errors

0 comments on commit c3beef6

Please sign in to comment.