Make coerce_never lint an error
Remove the coerce_never lint and make the behaviour an error.
This commit is contained in:
parent
32ddb30715
commit
59688e119e
@ -230,12 +230,6 @@ declare_lint! {
|
|||||||
"detect mut variables which don't need to be mutable"
|
"detect mut variables which don't need to be mutable"
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_lint! {
|
|
||||||
pub COERCE_NEVER,
|
|
||||||
Deny,
|
|
||||||
"detect coercion to !"
|
|
||||||
}
|
|
||||||
|
|
||||||
declare_lint! {
|
declare_lint! {
|
||||||
pub SINGLE_USE_LIFETIME,
|
pub SINGLE_USE_LIFETIME,
|
||||||
Allow,
|
Allow,
|
||||||
@ -310,7 +304,6 @@ impl LintPass for HardwiredLints {
|
|||||||
DEPRECATED,
|
DEPRECATED,
|
||||||
UNUSED_UNSAFE,
|
UNUSED_UNSAFE,
|
||||||
UNUSED_MUT,
|
UNUSED_MUT,
|
||||||
COERCE_NEVER,
|
|
||||||
SINGLE_USE_LIFETIME,
|
SINGLE_USE_LIFETIME,
|
||||||
TYVAR_BEHIND_RAW_POINTER,
|
TYVAR_BEHIND_RAW_POINTER,
|
||||||
ELIDED_LIFETIME_IN_PATH,
|
ELIDED_LIFETIME_IN_PATH,
|
||||||
|
@ -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>",
|
reference: "issue #46205 <https://github.com/rust-lang/rust/issues/46205>",
|
||||||
epoch: None,
|
epoch: None,
|
||||||
},
|
},
|
||||||
FutureIncompatibleInfo {
|
|
||||||
id: LintId::of(COERCE_NEVER),
|
|
||||||
reference: "issue #46325 <https://github.com/rust-lang/rust/issues/46325>",
|
|
||||||
epoch: None,
|
|
||||||
},
|
|
||||||
FutureIncompatibleInfo {
|
FutureIncompatibleInfo {
|
||||||
id: LintId::of(TYVAR_BEHIND_RAW_POINTER),
|
id: LintId::of(TYVAR_BEHIND_RAW_POINTER),
|
||||||
reference: "issue #46906 <https://github.com/rust-lang/rust/issues/46906>",
|
reference: "issue #46906 <https://github.com/rust-lang/rust/issues/46906>",
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
//! expression, `e as U2` is not necessarily so (in fact it will only be valid if
|
//! expression, `e as U2` is not necessarily so (in fact it will only be valid if
|
||||||
//! `U1` coerces to `U2`).
|
//! `U1` coerces to `U2`).
|
||||||
|
|
||||||
use super::{Diverges, FnCtxt};
|
use super::FnCtxt;
|
||||||
|
|
||||||
use errors::DiagnosticBuilder;
|
use errors::DiagnosticBuilder;
|
||||||
use hir::def_id::DefId;
|
use hir::def_id::DefId;
|
||||||
@ -59,7 +59,6 @@ use util::common::ErrorReported;
|
|||||||
pub struct CastCheck<'tcx> {
|
pub struct CastCheck<'tcx> {
|
||||||
expr: &'tcx hir::Expr,
|
expr: &'tcx hir::Expr,
|
||||||
expr_ty: Ty<'tcx>,
|
expr_ty: Ty<'tcx>,
|
||||||
expr_diverges: Diverges,
|
|
||||||
cast_ty: Ty<'tcx>,
|
cast_ty: Ty<'tcx>,
|
||||||
cast_span: Span,
|
cast_span: Span,
|
||||||
span: Span,
|
span: Span,
|
||||||
@ -183,7 +182,6 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
|
|||||||
pub fn new(fcx: &FnCtxt<'a, 'gcx, 'tcx>,
|
pub fn new(fcx: &FnCtxt<'a, 'gcx, 'tcx>,
|
||||||
expr: &'tcx hir::Expr,
|
expr: &'tcx hir::Expr,
|
||||||
expr_ty: Ty<'tcx>,
|
expr_ty: Ty<'tcx>,
|
||||||
expr_diverges: Diverges,
|
|
||||||
cast_ty: Ty<'tcx>,
|
cast_ty: Ty<'tcx>,
|
||||||
cast_span: Span,
|
cast_span: Span,
|
||||||
span: Span)
|
span: Span)
|
||||||
@ -191,7 +189,6 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
|
|||||||
let check = CastCheck {
|
let check = CastCheck {
|
||||||
expr,
|
expr,
|
||||||
expr_ty,
|
expr_ty,
|
||||||
expr_diverges,
|
|
||||||
cast_ty,
|
cast_ty,
|
||||||
cast_span,
|
cast_span,
|
||||||
span,
|
span,
|
||||||
@ -437,7 +434,6 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
|
|||||||
let f = self.expr_ty.fn_sig(fcx.tcx);
|
let f = self.expr_ty.fn_sig(fcx.tcx);
|
||||||
let res = fcx.try_coerce(self.expr,
|
let res = fcx.try_coerce(self.expr,
|
||||||
self.expr_ty,
|
self.expr_ty,
|
||||||
self.expr_diverges,
|
|
||||||
fcx.tcx.mk_fn_ptr(f));
|
fcx.tcx.mk_fn_ptr(f));
|
||||||
if !res.is_ok() {
|
if !res.is_ok() {
|
||||||
return Err(CastError::NonScalar);
|
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 {
|
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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +66,6 @@ use rustc::hir;
|
|||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc::infer::{Coercion, InferResult, InferOk};
|
use rustc::infer::{Coercion, InferResult, InferOk};
|
||||||
use rustc::infer::type_variable::TypeVariableOrigin;
|
use rustc::infer::type_variable::TypeVariableOrigin;
|
||||||
use rustc::lint;
|
|
||||||
use rustc::traits::{self, ObligationCause, ObligationCauseCode};
|
use rustc::traits::{self, ObligationCause, ObligationCauseCode};
|
||||||
use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability};
|
use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability};
|
||||||
use rustc::ty::{self, TypeAndMut, Ty, ClosureSubsts};
|
use rustc::ty::{self, TypeAndMut, Ty, ClosureSubsts};
|
||||||
@ -752,27 +751,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
pub fn try_coerce(&self,
|
pub fn try_coerce(&self,
|
||||||
expr: &hir::Expr,
|
expr: &hir::Expr,
|
||||||
expr_ty: Ty<'tcx>,
|
expr_ty: Ty<'tcx>,
|
||||||
expr_diverges: Diverges,
|
|
||||||
target: Ty<'tcx>)
|
target: Ty<'tcx>)
|
||||||
-> RelateResult<'tcx, Ty<'tcx>> {
|
-> RelateResult<'tcx, Ty<'tcx>> {
|
||||||
let source = self.resolve_type_vars_with_obligations(expr_ty);
|
let source = self.resolve_type_vars_with_obligations(expr_ty);
|
||||||
debug!("coercion::try({:?}: {:?} -> {:?})", expr, source, target);
|
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 cause = self.cause(expr.span, ObligationCauseCode::ExprAssignable);
|
||||||
let coerce = Coerce::new(self, cause);
|
let coerce = Coerce::new(self, cause);
|
||||||
let ok = self.commit_if_ok(|_| coerce.coerce(source, target))?;
|
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 {
|
if self.pushed == 0 {
|
||||||
// Special-case the first expression we are coercing.
|
// Special-case the first expression we are coercing.
|
||||||
// To be honest, I'm not entirely sure why we do this.
|
// 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 {
|
} else {
|
||||||
match self.expressions {
|
match self.expressions {
|
||||||
Expressions::Dynamic(ref exprs) =>
|
Expressions::Dynamic(ref exprs) =>
|
||||||
|
@ -100,7 +100,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
-> (Ty<'tcx>, Option<DiagnosticBuilder<'tcx>>) {
|
-> (Ty<'tcx>, Option<DiagnosticBuilder<'tcx>>) {
|
||||||
let expected = self.resolve_type_vars_with_obligations(expected);
|
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),
|
Ok(ty) => return (ty, None),
|
||||||
Err(e) => e
|
Err(e) => e
|
||||||
};
|
};
|
||||||
|
@ -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_cast = self.resolve_type_vars_if_possible(&t_cast);
|
||||||
let t_expr = self.check_expr_with_expectation(e, ExpectCastableToType(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 t_cast = self.resolve_type_vars_if_possible(&t_cast);
|
||||||
let diverges = self.diverges.get();
|
|
||||||
|
|
||||||
// Eagerly check for some obvious errors.
|
// Eagerly check for some obvious errors.
|
||||||
if t_expr.references_error() || t_cast.references_error() {
|
if t_expr.references_error() || t_cast.references_error() {
|
||||||
@ -3952,7 +3951,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||||||
} else {
|
} else {
|
||||||
// Defer other checks until we're done type checking.
|
// Defer other checks until we're done type checking.
|
||||||
let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
|
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) => {
|
Ok(cast_check) => {
|
||||||
deferred_cast_checks.push(cast_check);
|
deferred_cast_checks.push(cast_check);
|
||||||
t_cast
|
t_cast
|
||||||
|
@ -10,11 +10,9 @@
|
|||||||
|
|
||||||
fn foo(x: usize, y: !, z: usize) { }
|
fn foo(x: usize, y: !, z: usize) { }
|
||||||
|
|
||||||
#[deny(coerce_never)]
|
|
||||||
fn cast_a() {
|
fn cast_a() {
|
||||||
let y = {return; 22} as !;
|
let y = {return; 22} as !;
|
||||||
//~^ ERROR cannot coerce `i32` to !
|
//~^ ERROR non-primitive cast
|
||||||
//~| hard error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cast_b() {
|
fn cast_b() {
|
||||||
|
@ -8,17 +8,11 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
#![deny(coerce_never)]
|
|
||||||
|
|
||||||
fn foo(x: usize, y: !, z: usize) { }
|
fn foo(x: usize, y: !, z: usize) { }
|
||||||
|
|
||||||
fn call_foo_a() {
|
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);
|
foo(return, 22, 44);
|
||||||
//~^ ERROR cannot coerce `{integer}` to !
|
//~^ ERROR mismatched types
|
||||||
//~| hard error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_foo_b() {
|
fn call_foo_b() {
|
||||||
@ -38,8 +32,7 @@ fn call_foo_d() {
|
|||||||
let b = 22;
|
let b = 22;
|
||||||
let c = 44;
|
let c = 44;
|
||||||
foo(a, b, c); // ... and hence a reference to `a` is expected to diverge.
|
foo(a, b, c); // ... and hence a reference to `a` is expected to diverge.
|
||||||
//~^ ERROR cannot coerce `{integer}` to !
|
//~^ ERROR mismatched types
|
||||||
//~| hard error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_foo_e() {
|
fn call_foo_e() {
|
||||||
@ -79,8 +72,7 @@ fn tuple_a() {
|
|||||||
fn tuple_b() {
|
fn tuple_b() {
|
||||||
// Divergence happens before coercion: OK
|
// Divergence happens before coercion: OK
|
||||||
let x: (usize, !, usize) = (return, 44, 66);
|
let x: (usize, !, usize) = (return, 44, 66);
|
||||||
//~^ ERROR cannot coerce `{integer}` to !
|
//~^ ERROR mismatched types
|
||||||
//~| hard error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tuple_c() {
|
fn tuple_c() {
|
||||||
|
@ -8,12 +8,10 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
#[deny(coerce_never)]
|
|
||||||
fn assert_sizeof() -> ! {
|
fn assert_sizeof() -> ! {
|
||||||
unsafe {
|
unsafe {
|
||||||
::std::mem::transmute::<f64, [u8; 8]>(panic!())
|
::std::mem::transmute::<f64, [u8; 8]>(panic!())
|
||||||
//~^ ERROR cannot coerce `[u8; 8]` to !
|
//~^ ERROR mismatched types
|
||||||
//~| hard error
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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() { }
|
|
@ -12,12 +12,9 @@
|
|||||||
#![allow(unused_assignments)]
|
#![allow(unused_assignments)]
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
#![deny(unreachable_code)]
|
#![deny(unreachable_code)]
|
||||||
#![deny(coerce_never)]
|
|
||||||
|
|
||||||
fn foo() {
|
fn foo() {
|
||||||
let x: ! = ! { return; 22 }; //~ ERROR unreachable
|
let x: ! = ! { return; }; //~ ERROR unreachable
|
||||||
//~^ ERROR cannot coerce
|
|
||||||
//~| hard error
|
|
||||||
//~| ERROR cannot apply unary operator `!` to type `!`
|
//~| ERROR cannot apply unary operator `!` to type `!`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,14 @@
|
|||||||
error: unreachable expression
|
error[E0600]: cannot apply unary operator `!` to type `!`
|
||||||
--> $DIR/expr_unary.rs:18:28
|
--> $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
|
note: lint level defined here
|
||||||
--> $DIR/expr_unary.rs:14:9
|
--> $DIR/expr_unary.rs:14:9
|
||||||
@ -10,26 +16,6 @@ note: lint level defined here
|
|||||||
LL | #![deny(unreachable_code)]
|
LL | #![deny(unreachable_code)]
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: cannot coerce `{integer}` to !
|
error: aborting due to 2 previous errors
|
||||||
--> $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
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0600`.
|
For more information about this error, try `rustc --explain E0600`.
|
||||||
|
Loading…
Reference in New Issue
Block a user