提交 27183a90 编写于 作者: M Matthew Jasper

Feature gate trivial bounds

上级 d0ec8ea1
......@@ -1475,6 +1475,14 @@ fn note_obligation_cause_code<T>(&self,
}
ObligationCauseCode::ReturnType(_) |
ObligationCauseCode::BlockTailExpression(_) => (),
ObligationCauseCode::TrivialBound => {
err.help("see issue #48214");
if tcx.sess.opts.unstable_features.is_nightly_build() {
err.help("add #![feature(trivial_bounds)] to the \
crate attributes to enable",
);
}
}
}
}
......
......@@ -243,6 +243,9 @@ pub enum ObligationCauseCode<'tcx> {
/// Block implicit return
BlockTailExpression(ast::NodeId),
/// #[feature(trivial_bounds)] is not enabled
TrivialBound,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
......
......@@ -243,6 +243,7 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
super::IntrinsicType => Some(super::IntrinsicType),
super::MethodReceiver => Some(super::MethodReceiver),
super::BlockTailExpression(id) => Some(super::BlockTailExpression(id)),
super::TrivialBound => Some(super::TrivialBound),
}
}
}
......
......@@ -46,6 +46,12 @@ fn with_fcx<F>(&'tcx mut self, f: F) where
let param_env = self.param_env;
self.inherited.enter(|inh| {
let fcx = FnCtxt::new(&inh, param_env, id);
if !inh.tcx.features().trivial_bounds {
// As predicates are cached rather than obligations, this
// needsto be called first so that they are checked with an
// empty param_env.
check_false_global_bounds(&fcx, span, id);
}
let wf_tys = f(&fcx, fcx.tcx.global_tcx());
fcx.select_all_obligations_or_error();
fcx.regionck_item(id, span, &wf_tys);
......@@ -660,6 +666,41 @@ fn reject_shadowing_type_parameters(tcx: TyCtxt, def_id: DefId) {
}
}
/// Feature gates RFC 2056 - trivial bounds, checking for global bounds that
/// aren't true.
fn check_false_global_bounds<'a, 'gcx, 'tcx>(
fcx: &FnCtxt<'a, 'gcx, 'tcx>,
span: Span,
id: ast::NodeId,
) {
use rustc::ty::TypeFoldable;
let empty_env = ty::ParamEnv::empty();
let def_id = fcx.tcx.hir.local_def_id(id);
let predicates = fcx.tcx.predicates_of(def_id).predicates;
// Check elaborated bounds
let implied_obligations = traits::elaborate_predicates(fcx.tcx, predicates);
for pred in implied_obligations {
// HAS_LOCAL_NAMES is used to match the existing behvaiour.
if !pred.has_type_flags(ty::TypeFlags::HAS_LOCAL_NAMES) {
let obligation = traits::Obligation::new(
traits::ObligationCause::new(
span,
id,
traits::TrivialBound,
),
empty_env,
pred,
);
fcx.register_predicate(obligation);
}
}
fcx.select_all_obligations_or_error();
}
pub struct CheckTypeWellFormedVisitor<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
......
......@@ -463,6 +463,9 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
// Allows use of the :literal macro fragment specifier (RFC 1576)
(active, macro_literal_matcher, "1.27.0", Some(35625), None),
// inconsistent bounds in where clauses
(active, trivial_bounds, "1.28.0", Some(48214), None),
);
declare_features! (
......
// Copyright 2018 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(unused)]
#![allow(type_alias_bounds)]
pub trait Foo {
fn test(&self);
}
fn generic_function<X: Foo>(x: X) {}
enum E where i32: Foo { V } //~ ERROR
struct S where i32: Foo; //~ ERROR
trait T where i32: Foo {} //~ ERROR
union U where i32: Foo { f: i32 } //~ ERROR
type Y where i32: Foo = (); // OK - bound is ignored
impl Foo for () where i32: Foo { //~ ERROR
fn test(&self) {
3i32.test();
Foo::test(&4i32);
generic_function(5i32);
}
}
fn f() where i32: Foo //~ ERROR
{
let s = S;
3i32.test();
Foo::test(&4i32);
generic_function(5i32);
}
fn use_op(s: String) -> String where String: ::std::ops::Neg<Output=String> { //~ ERROR
-s
}
fn use_for() where i32: Iterator { //~ ERROR
for _ in 2i32 {}
}
trait A {}
impl A for i32 {}
struct Dst<X: ?Sized> {
x: X,
}
struct TwoStrs(str, str) where str: Sized; //~ ERROR
fn unsized_local() where Dst<A>: Sized { //~ ERROR
let x: Dst<A> = *(Box::new(Dst { x: 1 }) as Box<Dst<A>>);
}
fn return_str() -> str where str: Sized { //~ ERROR
*"Sized".to_string().into_boxed_str()
}
// This is currently accepted because the function pointer isn't
// considered global.
fn global_hr(x: fn(&())) where fn(&()): Foo { // OK
x.test();
}
fn main() {}
error[E0277]: the trait bound `i32: Foo` is not satisfied
--> $DIR/feature-gate-trivial_bounds.rs:20:1
|
LL | enum E where i32: Foo { V } //~ ERROR
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32`
|
= help: see issue #48214
= help: add #![feature(trivial_bounds)] to the crate attributes to enable
error[E0277]: the trait bound `i32: Foo` is not satisfied
--> $DIR/feature-gate-trivial_bounds.rs:22:1
|
LL | struct S where i32: Foo; //~ ERROR
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32`
|
= help: see issue #48214
= help: add #![feature(trivial_bounds)] to the crate attributes to enable
error[E0277]: the trait bound `i32: Foo` is not satisfied
--> $DIR/feature-gate-trivial_bounds.rs:24:1
|
LL | trait T where i32: Foo {} //~ ERROR
| ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32`
|
= help: see issue #48214
= help: add #![feature(trivial_bounds)] to the crate attributes to enable
error[E0277]: the trait bound `i32: Foo` is not satisfied
--> $DIR/feature-gate-trivial_bounds.rs:26:1
|
LL | union U where i32: Foo { f: i32 } //~ ERROR
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32`
|
= help: see issue #48214
= help: add #![feature(trivial_bounds)] to the crate attributes to enable
error[E0277]: the trait bound `i32: Foo` is not satisfied
--> $DIR/feature-gate-trivial_bounds.rs:30:1
|
LL | / impl Foo for () where i32: Foo { //~ ERROR
LL | | fn test(&self) {
LL | | 3i32.test();
LL | | Foo::test(&4i32);
LL | | generic_function(5i32);
LL | | }
LL | | }
| |_^ the trait `Foo` is not implemented for `i32`
|
= help: see issue #48214
= help: add #![feature(trivial_bounds)] to the crate attributes to enable
error[E0277]: the trait bound `i32: Foo` is not satisfied
--> $DIR/feature-gate-trivial_bounds.rs:38:1
|
LL | / fn f() where i32: Foo //~ ERROR
LL | | {
LL | | let s = S;
LL | | 3i32.test();
LL | | Foo::test(&4i32);
LL | | generic_function(5i32);
LL | | }
| |_^ the trait `Foo` is not implemented for `i32`
|
= help: see issue #48214
= help: add #![feature(trivial_bounds)] to the crate attributes to enable
error[E0277]: the trait bound `std::string::String: std::ops::Neg` is not satisfied
--> $DIR/feature-gate-trivial_bounds.rs:46:1
|
LL | / fn use_op(s: String) -> String where String: ::std::ops::Neg<Output=String> { //~ ERROR
LL | | -s
LL | | }
| |_^ the trait `std::ops::Neg` is not implemented for `std::string::String`
|
= help: see issue #48214
= help: add #![feature(trivial_bounds)] to the crate attributes to enable
error[E0277]: the trait bound `i32: std::iter::Iterator` is not satisfied
--> $DIR/feature-gate-trivial_bounds.rs:50:1
|
LL | / fn use_for() where i32: Iterator { //~ ERROR
LL | | for _ in 2i32 {}
LL | | }
| |_^ `i32` is not an iterator; maybe try calling `.iter()` or a similar method
|
= help: the trait `std::iter::Iterator` is not implemented for `i32`
= help: see issue #48214
= help: add #![feature(trivial_bounds)] to the crate attributes to enable
error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
--> $DIR/feature-gate-trivial_bounds.rs:62:1
|
LL | struct TwoStrs(str, str) where str: Sized; //~ ERROR
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `str` does not have a constant size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `str`
= help: see issue #48214
= help: add #![feature(trivial_bounds)] to the crate attributes to enable
error[E0277]: the trait bound `A + 'static: std::marker::Sized` is not satisfied in `Dst<A + 'static>`
--> $DIR/feature-gate-trivial_bounds.rs:64:1
|
LL | / fn unsized_local() where Dst<A>: Sized { //~ ERROR
LL | | let x: Dst<A> = *(Box::new(Dst { x: 1 }) as Box<Dst<A>>);
LL | | }
| |_^ `A + 'static` does not have a constant size known at compile-time
|
= help: within `Dst<A + 'static>`, the trait `std::marker::Sized` is not implemented for `A + 'static`
= note: required because it appears within the type `Dst<A + 'static>`
= help: see issue #48214
= help: add #![feature(trivial_bounds)] to the crate attributes to enable
error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
--> $DIR/feature-gate-trivial_bounds.rs:68:1
|
LL | / fn return_str() -> str where str: Sized { //~ ERROR
LL | | *"Sized".to_string().into_boxed_str()
LL | | }
| |_^ `str` does not have a constant size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `str`
= help: see issue #48214
= help: add #![feature(trivial_bounds)] to the crate attributes to enable
error: aborting due to 11 previous errors
For more information about this error, try `rustc --explain E0277`.
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册