Auto merge of #64269 - Centril:rollup-y4dm32c, r=Centril

Rollup of 5 pull requests

Successful merges:

 - #64052 (Rename test locals to work around LLDB bug)
 - #64066 (Support "soft" feature-gating using a lint)
 - #64177 (resolve: Do not afraid to set current module to enums and traits)
 - #64229 (Reduce span to function name in unreachable calls)
 - #64255 (Add methods for converting `bool` to `Option<T>`)

Failed merges:

r? @ghost
This commit is contained in:
bors 2019-09-07 22:08:30 +00:00
commit f7b05af814
30 changed files with 185 additions and 59 deletions

45
src/libcore/bool.rs Normal file
View File

@ -0,0 +1,45 @@
//! impl bool {}
#[cfg(not(boostrap_stdarch_ignore_this))]
#[lang = "bool"]
impl bool {
/// Returns `Some(t)` if the `bool` is `true`, or `None` otherwise.
///
/// # Examples
///
/// ```
/// #![feature(bool_to_option)]
///
/// assert_eq!(false.then(0), None);
/// assert_eq!(true.then(0), Some(0));
/// ```
#[unstable(feature = "bool_to_option", issue = "64260")]
#[inline]
pub fn then<T>(self, t: T) -> Option<T> {
if self {
Some(t)
} else {
None
}
}
/// Returns `Some(f())` if the `bool` is `true`, or `None` otherwise.
///
/// # Examples
///
/// ```
/// #![feature(bool_to_option)]
///
/// assert_eq!(false.then_with(|| 0), None);
/// assert_eq!(true.then_with(|| 0), Some(0));
/// ```
#[unstable(feature = "bool_to_option", issue = "64260")]
#[inline]
pub fn then_with<T, F: FnOnce() -> T>(self, f: F) -> Option<T> {
if self {
Some(f())
} else {
None
}
}
}

View File

@ -227,6 +227,7 @@ pub mod task;
pub mod alloc;
// note: does not need to be public
mod bool;
mod tuple;
mod unit;

View File

@ -1236,8 +1236,10 @@ pub(crate) mod builtin {
pub macro test($item:item) { /* compiler built-in */ }
/// Attribute macro applied to a function to turn it into a benchmark test.
#[unstable(feature = "test", issue = "50297",
reason = "`bench` is a part of custom test frameworks which are unstable")]
#[cfg_attr(not(boostrap_stdarch_ignore_this), unstable(soft, feature = "test", issue = "50297",
reason = "`bench` is a part of custom test frameworks which are unstable"))]
#[cfg_attr(boostrap_stdarch_ignore_this, unstable(feature = "test", issue = "50297",
reason = "`bench` is a part of custom test frameworks which are unstable"))]
#[allow_internal_unstable(test, rustc_attrs)]
#[rustc_builtin_macro]
pub macro bench($item:item) { /* compiler built-in */ }

View File

@ -0,0 +1,7 @@
#[test]
fn test_bool_to_option() {
assert_eq!(false.then(0), None);
assert_eq!(true.then(0), Some(0));
assert_eq!(false.then_with(|| 0), None);
assert_eq!(true.then_with(|| 0), Some(0));
}

View File

@ -1,3 +1,4 @@
#![feature(bool_to_option)]
#![feature(bound_cloned)]
#![feature(box_syntax)]
#![feature(cell_update)]
@ -40,6 +41,7 @@ mod any;
mod array;
mod ascii;
mod atomic;
mod bool;
mod cell;
mod char;
mod clone;

View File

@ -115,9 +115,10 @@ for ::syntax::attr::StabilityLevel {
hasher: &mut StableHasher<W>) {
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
::syntax::attr::StabilityLevel::Unstable { ref reason, ref issue } => {
::syntax::attr::StabilityLevel::Unstable { ref reason, ref issue, ref is_soft } => {
reason.hash_stable(hcx, hasher);
issue.hash_stable(hcx, hasher);
is_soft.hash_stable(hcx, hasher);
}
::syntax::attr::StabilityLevel::Stable { ref since } => {
since.hash_stable(hcx, hasher);

View File

@ -395,6 +395,12 @@ declare_lint! {
"reservation of a two-phased borrow conflicts with other shared borrows"
}
declare_lint! {
pub SOFT_UNSTABLE,
Deny,
"a feature gate that doesn't break dependent crates"
}
declare_lint_pass! {
/// Does nothing as a lint pass, but registers some `Lint`s
/// that are used by other parts of the compiler.
@ -460,6 +466,7 @@ declare_lint_pass! {
NESTED_IMPL_TRAIT,
MUTABLE_BORROW_RESERVATION_CONFLICT,
INDIRECT_STRUCTURAL_MATCH,
SOFT_UNSTABLE,
]
}

View File

@ -244,6 +244,7 @@ pub fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> LanguageItems {
language_item_table! {
// Variant name, Name, Method name, Target;
BoolImplItem, "bool", bool_impl, Target::Impl;
CharImplItem, "char", char_impl, Target::Impl;
StrImplItem, "str", str_impl, Target::Impl;
SliceImplItem, "slice", slice_impl, Target::Impl;

View File

@ -438,6 +438,7 @@ impl<'tcx> Index<'tcx> {
level: attr::StabilityLevel::Unstable {
reason: Some(Symbol::intern(reason)),
issue: 27812,
is_soft: false,
},
feature: sym::rustc_private,
rustc_depr: None,
@ -480,7 +481,7 @@ pub fn provide(providers: &mut Providers<'_>) {
}
pub fn report_unstable(
sess: &Session, feature: Symbol, reason: Option<Symbol>, issue: u32, span: Span
sess: &Session, feature: Symbol, reason: Option<Symbol>, issue: u32, is_soft: bool, span: Span
) {
let msg = match reason {
Some(r) => format!("use of unstable library feature '{}': {}", feature, r),
@ -505,7 +506,13 @@ pub fn report_unstable(
let error_id = (DiagnosticMessageId::StabilityId(issue), span_key, msg.clone());
let fresh = sess.one_time_diagnostics.borrow_mut().insert(error_id);
if fresh {
emit_feature_err(&sess.parse_sess, feature, span, GateIssue::Library(Some(issue)), &msg);
if is_soft {
sess.buffer_lint(lint::builtin::SOFT_UNSTABLE, CRATE_NODE_ID, span, &msg);
} else {
emit_feature_err(
&sess.parse_sess, feature, span, GateIssue::Library(Some(issue)), &msg
);
}
}
}
@ -621,6 +628,7 @@ pub enum EvalResult {
feature: Symbol,
reason: Option<Symbol>,
issue: u32,
is_soft: bool,
},
/// The item does not have the `#[stable]` or `#[unstable]` marker assigned.
Unmarked,
@ -720,7 +728,9 @@ impl<'tcx> TyCtxt<'tcx> {
}
match stability {
Some(&Stability { level: attr::Unstable { reason, issue }, feature, .. }) => {
Some(&Stability {
level: attr::Unstable { reason, issue, is_soft }, feature, ..
}) => {
if span.allows_unstable(feature) {
debug!("stability: skipping span={:?} since it is internal", span);
return EvalResult::Allow;
@ -744,7 +754,7 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
EvalResult::Deny { feature, reason, issue }
EvalResult::Deny { feature, reason, issue, is_soft }
}
Some(_) => {
// Stable APIs are always ok to call and deprecated APIs are
@ -767,8 +777,8 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn check_stability(self, def_id: DefId, id: Option<HirId>, span: Span) {
match self.eval_stability(def_id, id, span) {
EvalResult::Allow => {}
EvalResult::Deny { feature, reason, issue } =>
report_unstable(self.sess, feature, reason, issue, span),
EvalResult::Deny { feature, reason, issue, is_soft } =>
report_unstable(self.sess, feature, reason, issue, is_soft, span),
EvalResult::Unmarked => {
// The API could be uncallable for other reasons, for example when a private module
// was referenced.

View File

@ -435,7 +435,12 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
id: LintId::of(INDIRECT_STRUCTURAL_MATCH),
reference: "issue #62411 <https://github.com/rust-lang/rust/issues/62411>",
edition: None,
}
},
FutureIncompatibleInfo {
id: LintId::of(SOFT_UNSTABLE),
reference: "issue #64266 <https://github.com/rust-lang/rust/issues/64266>",
edition: None,
},
]);
// Register renamed and removed lints.

View File

@ -728,9 +728,10 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
expansion,
item.span);
self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion));
self.parent_scope.module = module;
for variant in &(*enum_definition).variants {
self.build_reduced_graph_for_variant(variant, module, vis);
self.build_reduced_graph_for_variant(variant, vis);
}
}
@ -818,10 +819,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
// Constructs the reduced graph for one variant. Variants exist in the
// type and value namespaces.
fn build_reduced_graph_for_variant(&mut self,
variant: &Variant,
parent: Module<'a>,
vis: ty::Visibility) {
fn build_reduced_graph_for_variant(&mut self, variant: &Variant, vis: ty::Visibility) {
let parent = self.parent_scope.module;
let expn_id = self.parent_scope.expansion;
let ident = variant.ident;
@ -1253,9 +1252,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
let expansion = self.parent_scope.expansion;
self.r.define(parent, item.ident, ns, (res, vis, item.span, expansion));
self.parent_scope.module = parent.parent.unwrap(); // nearest normal ancestor
visit::walk_trait_item(self, item);
self.parent_scope.module = parent;
}
fn visit_token(&mut self, t: Token) {

View File

@ -535,7 +535,11 @@ impl<'a> ModuleData<'a> {
}
fn nearest_item_scope(&'a self) -> Module<'a> {
if self.is_trait() { self.parent.unwrap() } else { self }
match self.kind {
ModuleKind::Def(DefKind::Enum, ..) | ModuleKind::Def(DefKind::Trait, ..) =>
self.parent.expect("enum or trait module without a parent"),
_ => self,
}
}
fn is_ancestor_of(&self, mut other: &Self) -> bool {
@ -1637,7 +1641,7 @@ impl<'a> Resolver<'a> {
}
if let ModuleKind::Block(..) = module.kind {
return Some(module.parent.unwrap());
return Some(module.parent.unwrap().nearest_item_scope());
}
None

View File

@ -774,10 +774,10 @@ impl<'a> Resolver<'a> {
fn check_stability_and_deprecation(&self, ext: &SyntaxExtension, path: &ast::Path) {
let span = path.span;
if let Some(stability) = &ext.stability {
if let StabilityLevel::Unstable { reason, issue } = stability.level {
if let StabilityLevel::Unstable { reason, issue, is_soft } = stability.level {
let feature = stability.feature;
if !self.active_features.contains(&feature) && !span.allows_unstable(feature) {
stability::report_unstable(self.session, feature, reason, issue, span);
stability::report_unstable(self.session, feature, reason, issue, is_soft, span);
}
}
if let Some(depr) = &stability.rustc_depr {

View File

@ -161,6 +161,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Warn for non-block expressions with diverging children.
match expr.node {
ExprKind::Block(..) | ExprKind::Loop(..) | ExprKind::Match(..) => {},
ExprKind::Call(ref callee, _) =>
self.warn_if_unreachable(expr.hir_id, callee.span, "call"),
ExprKind::MethodCall(_, ref span, _) =>
self.warn_if_unreachable(expr.hir_id, *span, "call"),
_ => self.warn_if_unreachable(expr.hir_id, expr.span, "expression"),
}

View File

@ -578,6 +578,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
ty::Param(p) => {
self.assemble_inherent_candidates_from_param(p);
}
ty::Bool => {
let lang_def_id = lang_items.bool_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);
}
ty::Char => {
let lang_def_id = lang_items.char_impl();
self.assemble_inherent_impl_for_primitive(lang_def_id);

View File

@ -67,6 +67,14 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
ty::Dynamic(ref data, ..) if data.principal_def_id().is_some() => {
self.check_def_id(item, data.principal_def_id().unwrap());
}
ty::Bool => {
self.check_primitive_impl(def_id,
lang_items.bool_impl(),
None,
"bool",
"bool",
item.span);
}
ty::Char => {
self.check_primitive_impl(def_id,
lang_items.char_impl(),

View File

@ -3977,7 +3977,7 @@ fn build_deref_target_impls(cx: &DocContext<'_>,
F32 => tcx.lang_items().f32_impl(),
F64 => tcx.lang_items().f64_impl(),
Char => tcx.lang_items().char_impl(),
Bool => None,
Bool => tcx.lang_items().bool_impl(),
Str => tcx.lang_items().str_impl(),
Slice => tcx.lang_items().slice_impl(),
Array => tcx.lang_items().slice_impl(),

View File

@ -679,6 +679,7 @@ fn primitive_impl(cx: &DocContext<'_>, path_str: &str) -> Option<DefId> {
"f32" => tcx.lang_items().f32_impl(),
"f64" => tcx.lang_items().f64_impl(),
"str" => tcx.lang_items().str_impl(),
"bool" => tcx.lang_items().bool_impl(),
"char" => tcx.lang_items().char_impl(),
_ => None,
}

View File

@ -53,6 +53,7 @@ pub fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate {
lang_items.f64_impl(),
lang_items.f32_runtime_impl(),
lang_items.f64_runtime_impl(),
lang_items.bool_impl(),
lang_items.char_impl(),
lang_items.str_impl(),
lang_items.slice_impl(),

View File

@ -154,23 +154,10 @@ pub struct Stability {
#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Copy, Clone, Debug, Eq, Hash)]
pub enum StabilityLevel {
// Reason for the current stability level and the relevant rust-lang issue
Unstable { reason: Option<Symbol>, issue: u32 },
Unstable { reason: Option<Symbol>, issue: u32, is_soft: bool },
Stable { since: Symbol },
}
impl Stability {
pub fn unstable(feature: Symbol, reason: Option<Symbol>, issue: u32) -> Stability {
Stability {
level: StabilityLevel::Unstable { reason, issue },
feature,
rustc_depr: None,
const_stability: None,
promotable: false,
allow_const_fn_ptr: false,
}
}
}
impl StabilityLevel {
pub fn is_unstable(&self) -> bool {
if let StabilityLevel::Unstable {..} = *self {
@ -356,19 +343,27 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
let mut feature = None;
let mut reason = None;
let mut issue = None;
let mut is_soft = false;
for meta in metas {
if let Some(mi) = meta.meta_item() {
match mi.name_or_empty() {
sym::feature => if !get(mi, &mut feature) { continue 'outer },
sym::reason => if !get(mi, &mut reason) { continue 'outer },
sym::issue => if !get(mi, &mut issue) { continue 'outer },
sym::soft => {
if !mi.is_word() {
let msg = "`soft` should not have any arguments";
sess.span_diagnostic.span_err(mi.span, msg);
}
is_soft = true;
}
_ => {
handle_errors(
sess,
meta.span(),
AttrError::UnknownMetaItem(
mi.path.to_string(),
&["feature", "reason", "issue"]
&["feature", "reason", "issue", "soft"]
),
);
continue 'outer
@ -400,7 +395,8 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
"incorrect 'issue'");
continue
}
}
},
is_soft,
},
feature,
rustc_depr: None,

View File

@ -626,6 +626,7 @@ symbols! {
size,
slice_patterns,
slicing_syntax,
soft,
Some,
specialization,
speed,

View File

@ -8,11 +8,11 @@
// gdb-command:run
// gdb-command:print *unique
// gdb-command:print *boxed_with_padding
// gdbg-check:$1 = {x = 99, y = 999, z = 9999, w = 99999}
// gdbr-check:$1 = boxed_struct::StructWithSomePadding {x: 99, y: 999, z: 9999, w: 99999}
// gdb-command:print *unique_dtor
// gdb-command:print *boxed_with_dtor
// gdbg-check:$2 = {x = 77, y = 777, z = 7777, w = 77777}
// gdbr-check:$2 = boxed_struct::StructWithDestructor {x: 77, y: 777, z: 7777, w: 77777}
@ -21,13 +21,13 @@
// lldb-command:run
// lldb-command:print *unique
// lldb-command:print *boxed_with_padding
// lldbg-check:[...]$0 = StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 }
// lldbr-check:(boxed_struct::StructWithSomePadding) *unique = StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 }
// lldbr-check:(boxed_struct::StructWithSomePadding) *boxed_with_padding = StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 }
// lldb-command:print *unique_dtor
// lldb-command:print *boxed_with_dtor
// lldbg-check:[...]$1 = StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 }
// lldbr-check:(boxed_struct::StructWithDestructor) *unique_dtor = StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 }
// lldbr-check:(boxed_struct::StructWithDestructor) *boxed_with_dtor = StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 }
#![allow(unused_variables)]
#![feature(box_syntax)]
@ -54,9 +54,9 @@ impl Drop for StructWithDestructor {
fn main() {
let unique: Box<_> = box StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 };
let boxed_with_padding: Box<_> = box StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 };
let unique_dtor: Box<_> = box StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 };
let boxed_with_dtor: Box<_> = box StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 };
zzz(); // #break
}

View File

@ -0,0 +1,5 @@
#[bench] //~ ERROR use of unstable library feature 'test'
//~| WARN this was previously accepted
fn bench() {}
fn main() {}

View File

@ -0,0 +1,12 @@
error: use of unstable library feature 'test': `bench` is a part of custom test frameworks which are unstable
--> $DIR/bench.rs:1:3
|
LL | #[bench]
| ^^^^^
|
= note: `#[deny(soft_unstable)]` on by default
= 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 #64266 <https://github.com/rust-lang/rust/issues/64266>
error: aborting due to previous error

View File

@ -11,11 +11,11 @@ LL | #![warn(unused)]
| ^^^^^^
= note: `#[warn(unreachable_code)]` implied by `#[warn(unused)]`
warning: unreachable expression
warning: unreachable call
--> $DIR/never-assign-dead-code.rs:10:5
|
LL | drop(x);
| ^^^^^^^
| ^^^^
warning: unused variable: `x`
--> $DIR/never-assign-dead-code.rs:9:9

View File

@ -10,11 +10,11 @@ note: lint level defined here
LL | #![deny(unreachable_code)]
| ^^^^^^^^^^^^^^^^
error: unreachable expression
error: unreachable call
--> $DIR/expr_call.rs:18:5
|
LL | bar(return);
| ^^^^^^^^^^^
| ^^^
error: aborting due to 2 previous errors

View File

@ -10,11 +10,11 @@ note: lint level defined here
LL | #![deny(unreachable_code)]
| ^^^^^^^^^^^^^^^^
error: unreachable expression
--> $DIR/expr_method.rs:21:5
error: unreachable call
--> $DIR/expr_method.rs:21:9
|
LL | Foo.bar(return);
| ^^^^^^^^^^^^^^^
| ^^^
error: aborting due to 2 previous errors

View File

@ -0,0 +1,14 @@
// check-pass
trait Trait {
fn method(&self) {
// Items inside a block turn it into a module internally.
struct S;
impl Trait for S {}
// OK, `Trait` is in scope here from method resolution point of view.
S.method();
}
}
fn main() {}

View File

@ -14,7 +14,7 @@ fn diverge_first() {
get_u8()); //~ ERROR unreachable expression
}
fn diverge_second() {
call( //~ ERROR unreachable expression
call( //~ ERROR unreachable call
get_u8(),
diverge());
}

View File

@ -10,13 +10,11 @@ note: lint level defined here
LL | #![deny(unreachable_code)]
| ^^^^^^^^^^^^^^^^
error: unreachable expression
error: unreachable call
--> $DIR/unreachable-in-call.rs:17:5
|
LL | / call(
LL | | get_u8(),
LL | | diverge());
| |__________________^
LL | call(
| ^^^^
error: aborting due to 2 previous errors