From e38e954a0d249f88d0a55504f70d6055e865a931 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Mon, 17 Dec 2018 15:57:38 +0900 Subject: [PATCH 01/29] Simplify MIR generation for logical ops --- src/librustc_mir/build/expr/into.rs | 53 +++++++++++++---------------- 1 file changed, 23 insertions(+), 30 deletions(-) diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 0e7305e076ede..a26b0055a048c 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -126,18 +126,17 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ExprKind::LogicalOp { op, lhs, rhs } => { // And: // - // [block: If(lhs)] -true-> [else_block: If(rhs)] -true-> [true_block] - // | | (false) - // +----------false-----------+------------------> [false_block] + // [block: If(lhs)] -true-> [else_block: dest = (rhs)] + // | (false) + // [shortcurcuit_block: dest = false] // // Or: // - // [block: If(lhs)] -false-> [else_block: If(rhs)] -true-> [true_block] - // | (true) | (false) - // [true_block] [false_block] + // [block: If(lhs)] -false-> [else_block: dest = (rhs)] + // | (true) + // [shortcurcuit_block: dest = true] - let (true_block, false_block, mut else_block, join_block) = ( - this.cfg.start_new_block(), + let (shortcircuit_block, mut else_block, join_block) = ( this.cfg.start_new_block(), this.cfg.start_new_block(), this.cfg.start_new_block(), @@ -145,47 +144,41 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let lhs = unpack!(block = this.as_local_operand(block, lhs)); let blocks = match op { - LogicalOp::And => (else_block, false_block), - LogicalOp::Or => (true_block, else_block), + LogicalOp::And => (else_block, shortcircuit_block), + LogicalOp::Or => (shortcircuit_block, else_block), }; let term = TerminatorKind::if_(this.hir.tcx(), lhs, blocks.0, blocks.1); this.cfg.terminate(block, source_info, term); - let rhs = unpack!(else_block = this.as_local_operand(else_block, rhs)); - let term = TerminatorKind::if_(this.hir.tcx(), rhs, true_block, false_block); - this.cfg.terminate(else_block, source_info, term); - this.cfg.push_assign_constant( - true_block, + shortcircuit_block, source_info, destination, Constant { span: expr_span, ty: this.hir.bool_ty(), user_ty: None, - literal: this.hir.true_literal(), + literal: match op { + LogicalOp::And => this.hir.false_literal(), + LogicalOp::Or => this.hir.true_literal(), + }, }, ); - - this.cfg.push_assign_constant( - false_block, + this.cfg.terminate( + shortcircuit_block, source_info, - destination, - Constant { - span: expr_span, - ty: this.hir.bool_ty(), - user_ty: None, - literal: this.hir.false_literal(), - }, + TerminatorKind::Goto { target: join_block }, ); - this.cfg.terminate( - true_block, + let rhs = unpack!(else_block = this.as_local_operand(else_block, rhs)); + this.cfg.push_assign( + else_block, source_info, - TerminatorKind::Goto { target: join_block }, + destination, + Rvalue::Use(rhs), ); this.cfg.terminate( - false_block, + else_block, source_info, TerminatorKind::Goto { target: join_block }, ); From f7314456d03d2bfed188baf3a988c77b40864dc8 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 18 Dec 2018 15:52:32 +0100 Subject: [PATCH 02/29] Mark tuple structs as live if their constructors are used --- src/librustc/hir/mod.rs | 2 +- src/librustc/middle/dead.rs | 80 ++++++++++----------- src/test/ui/dead-code-tuple-struct-field.rs | 22 ++++++ 3 files changed, 61 insertions(+), 43 deletions(-) create mode 100644 src/test/ui/dead-code-tuple-struct-field.rs diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 156d55b9e2fe6..3f5b614df9dc2 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -2119,7 +2119,7 @@ impl StructField { /// Id of the whole enum lives in `Item`. /// /// For structs: `NodeId` represents an Id of the structure's constructor, so it is not actually -/// used for `Struct`-structs (but still presents). Structures don't have an analogue of "Id of +/// used for `Struct`-structs (but still present). Structures don't have an analogue of "Id of /// the variant itself" from enum variants. /// Id of the whole struct lives in `Item`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 934d7c12be552..d2175c28309b1 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -25,6 +25,8 @@ use middle::privacy; use ty::{self, TyCtxt}; use util::nodemap::FxHashSet; +use rustc_data_structures::fx::FxHashMap; + use syntax::{ast, source_map}; use syntax::attr; use syntax_pos; @@ -55,12 +57,15 @@ struct MarkSymbolVisitor<'a, 'tcx: 'a> { in_pat: bool, inherited_pub_visibility: bool, ignore_variant_stack: Vec, + // maps from tuple struct constructors to tuple struct items + struct_constructors: FxHashMap, } impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { fn check_def_id(&mut self, def_id: DefId) { if let Some(node_id) = self.tcx.hir().as_local_node_id(def_id) { - if should_explore(self.tcx, node_id) { + if should_explore(self.tcx, node_id) || + self.struct_constructors.contains_key(&node_id) { self.worklist.push(node_id); } self.live_symbols.insert(node_id); @@ -137,19 +142,23 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { continue } - if let Some(ref node) = self.tcx.hir().find(id) { + // in the case of tuple struct constructors we want to check the item, not the generated + // tuple struct constructor function + let id = self.struct_constructors.get(&id).cloned().unwrap_or(id); + + if let Some(node) = self.tcx.hir().find(id) { self.live_symbols.insert(id); self.visit_node(node); } } } - fn visit_node(&mut self, node: &Node<'tcx>) { + fn visit_node(&mut self, node: Node<'tcx>) { let had_repr_c = self.repr_has_repr_c; self.repr_has_repr_c = false; let had_inherited_pub_visibility = self.inherited_pub_visibility; self.inherited_pub_visibility = false; - match *node { + match node { Node::Item(item) => { match item.node { hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => { @@ -337,6 +346,8 @@ struct LifeSeeder<'k, 'tcx: 'k> { worklist: Vec, krate: &'k hir::Crate, tcx: TyCtxt<'k, 'tcx, 'tcx>, + // see `MarkSymbolVisitor::struct_constructors` + struct_constructors: FxHashMap, } impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> { @@ -379,6 +390,9 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> { } } } + hir::ItemKind::Struct(ref variant_data, _) => { + self.struct_constructors.insert(variant_data.id(), item.id); + } _ => () } } @@ -392,11 +406,11 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> { } } -fn create_and_seed_worklist<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - access_levels: &privacy::AccessLevels, - krate: &hir::Crate) - -> Vec -{ +fn create_and_seed_worklist<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + access_levels: &privacy::AccessLevels, + krate: &hir::Crate, +) -> (Vec, FxHashMap) { let worklist = access_levels.map.iter().filter_map(|(&id, level)| { if level >= &privacy::AccessLevel::Reachable { Some(id) @@ -413,17 +427,18 @@ fn create_and_seed_worklist<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, worklist, krate, tcx, + struct_constructors: Default::default(), }; krate.visit_all_item_likes(&mut life_seeder); - return life_seeder.worklist; + (life_seeder.worklist, life_seeder.struct_constructors) } fn find_live<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, access_levels: &privacy::AccessLevels, krate: &hir::Crate) -> FxHashSet { - let worklist = create_and_seed_worklist(tcx, access_levels, krate); + let (worklist, struct_constructors) = create_and_seed_worklist(tcx, access_levels, krate); let mut symbol_visitor = MarkSymbolVisitor { worklist, tcx, @@ -433,20 +448,12 @@ fn find_live<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, in_pat: false, inherited_pub_visibility: false, ignore_variant_stack: vec![], + struct_constructors, }; symbol_visitor.mark_live_symbols(); symbol_visitor.live_symbols } -fn get_struct_ctor_id(item: &hir::Item) -> Option { - match item.node { - hir::ItemKind::Struct(ref struct_def, _) if !struct_def.is_struct() => { - Some(struct_def.id()) - } - _ => None - } -} - struct DeadVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, live_symbols: FxHashSet, @@ -464,46 +471,35 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> { | hir::ItemKind::Union(..) => true, _ => false }; - let ctor_id = get_struct_ctor_id(item); - should_warn && !self.symbol_is_live(item.id, ctor_id) + should_warn && !self.symbol_is_live(item.id) } fn should_warn_about_field(&mut self, field: &hir::StructField) -> bool { let field_type = self.tcx.type_of(self.tcx.hir().local_def_id(field.id)); !field.is_positional() - && !self.symbol_is_live(field.id, None) + && !self.symbol_is_live(field.id) && !field_type.is_phantom_data() && !has_allow_dead_code_or_lang_attr(self.tcx, field.id, &field.attrs) } fn should_warn_about_variant(&mut self, variant: &hir::VariantKind) -> bool { - !self.symbol_is_live(variant.data.id(), None) + !self.symbol_is_live(variant.data.id()) && !has_allow_dead_code_or_lang_attr(self.tcx, variant.data.id(), &variant.attrs) } fn should_warn_about_foreign_item(&mut self, fi: &hir::ForeignItem) -> bool { - !self.symbol_is_live(fi.id, None) + !self.symbol_is_live(fi.id) && !has_allow_dead_code_or_lang_attr(self.tcx, fi.id, &fi.attrs) } // id := node id of an item's definition. - // ctor_id := `Some` if the item is a struct_ctor (tuple struct), - // `None` otherwise. - // If the item is a struct_ctor, then either its `id` or - // `ctor_id` (unwrapped) is in the live_symbols set. More specifically, - // DefMap maps the ExprKind::Path of a struct_ctor to the node referred by - // `ctor_id`. On the other hand, in a statement like - // `type = ;` where refers to a struct_ctor, - // DefMap maps to `id` instead. - fn symbol_is_live(&mut self, - id: ast::NodeId, - ctor_id: Option) - -> bool { - if self.live_symbols.contains(&id) - || ctor_id.map_or(false, |ctor| self.live_symbols.contains(&ctor)) - { + fn symbol_is_live( + &mut self, + id: ast::NodeId, + ) -> bool { + if self.live_symbols.contains(&id) { return true; } // If it's a type whose items are live, then it's live, too. @@ -611,7 +607,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> { fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) { match impl_item.node { hir::ImplItemKind::Const(_, body_id) => { - if !self.symbol_is_live(impl_item.id, None) { + if !self.symbol_is_live(impl_item.id) { self.warn_dead_code(impl_item.id, impl_item.span, impl_item.ident.name, @@ -621,7 +617,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> { self.visit_nested_body(body_id) } hir::ImplItemKind::Method(_, body_id) => { - if !self.symbol_is_live(impl_item.id, None) { + if !self.symbol_is_live(impl_item.id) { let span = self.tcx.sess.source_map().def_span(impl_item.span); self.warn_dead_code(impl_item.id, span, impl_item.ident.name, "method", "used"); } diff --git a/src/test/ui/dead-code-tuple-struct-field.rs b/src/test/ui/dead-code-tuple-struct-field.rs new file mode 100644 index 0000000000000..f4989fa1037d3 --- /dev/null +++ b/src/test/ui/dead-code-tuple-struct-field.rs @@ -0,0 +1,22 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-pass + +#![deny(dead_code)] + +const LEN: usize = 4; + +#[derive(Debug)] +struct Wrapper([u8; LEN]); + +fn main() { + println!("{:?}", Wrapper([0, 1, 2, 3])); +} From c2402dca85716aa4b452352bec11ff949c5a1cbb Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 18 Dec 2018 22:58:49 +0000 Subject: [PATCH 03/29] Replace "native pointer" in error message with "raw pointer" --- src/librustc_typeck/check/mod.rs | 2 +- src/test/ui/issues/issue-11004.stderr | 4 ++-- src/test/ui/unsafe/unsafe-fn-autoderef.stderr | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 957c8d9f19f0e..cb14078fb93ca 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3387,7 +3387,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } ty::RawPtr(..) => { let base = self.tcx.hir().node_to_pretty_string(base.id); - let msg = format!("`{}` is a native pointer; try dereferencing it", base); + let msg = format!("`{}` is a raw pointer; try dereferencing it", base); let suggestion = format!("(*{}).{}", base, field); err.span_suggestion_with_applicability( field.span, diff --git a/src/test/ui/issues/issue-11004.stderr b/src/test/ui/issues/issue-11004.stderr index 215120c9c25ea..46b4c4bdba201 100644 --- a/src/test/ui/issues/issue-11004.stderr +++ b/src/test/ui/issues/issue-11004.stderr @@ -2,13 +2,13 @@ error[E0609]: no field `x` on type `*mut A` --> $DIR/issue-11004.rs:17:21 | LL | let x : i32 = n.x; //~ no field `x` on type `*mut A` - | ^ help: `n` is a native pointer; try dereferencing it: `(*n).x` + | ^ help: `n` is a raw pointer; try dereferencing it: `(*n).x` error[E0609]: no field `y` on type `*mut A` --> $DIR/issue-11004.rs:18:21 | LL | let y : f64 = n.y; //~ no field `y` on type `*mut A` - | ^ help: `n` is a native pointer; try dereferencing it: `(*n).y` + | ^ help: `n` is a raw pointer; try dereferencing it: `(*n).y` error: aborting due to 2 previous errors diff --git a/src/test/ui/unsafe/unsafe-fn-autoderef.stderr b/src/test/ui/unsafe/unsafe-fn-autoderef.stderr index 13fcbb347c94b..81f15b2931df3 100644 --- a/src/test/ui/unsafe/unsafe-fn-autoderef.stderr +++ b/src/test/ui/unsafe/unsafe-fn-autoderef.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `f` on type `*const Rec` --> $DIR/unsafe-fn-autoderef.rs:29:14 | LL | return p.f; //~ ERROR no field `f` on type `*const Rec` - | ^ help: `p` is a native pointer; try dereferencing it: `(*p).f` + | ^ help: `p` is a raw pointer; try dereferencing it: `(*p).f` error: aborting due to previous error From d6969ac2fbc07d646a6c46631c9c96165a1774fe Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 18 Dec 2018 23:42:42 +0000 Subject: [PATCH 04/29] Fix string for raw pointer deref suggestion --- src/librustc_typeck/check/mod.rs | 6 ++++-- src/test/ui/issues/issue-11004.stderr | 8 ++++++-- src/test/ui/parenthesised-deref-suggestion.rs | 8 ++++++++ src/test/ui/parenthesised-deref-suggestion.stderr | 12 ++++++++++++ src/test/ui/unsafe/unsafe-fn-autoderef.stderr | 4 +++- 5 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/parenthesised-deref-suggestion.rs create mode 100644 src/test/ui/parenthesised-deref-suggestion.stderr diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index cb14078fb93ca..500bdbf6acd85 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3386,11 +3386,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } ty::RawPtr(..) => { - let base = self.tcx.hir().node_to_pretty_string(base.id); + let base = self.tcx.sess.source_map() + .span_to_snippet(base.span) + .unwrap_or_else(|_| self.tcx.hir().node_to_pretty_string(base.id)); let msg = format!("`{}` is a raw pointer; try dereferencing it", base); let suggestion = format!("(*{}).{}", base, field); err.span_suggestion_with_applicability( - field.span, + expr.span, &msg, suggestion, Applicability::MaybeIncorrect, diff --git a/src/test/ui/issues/issue-11004.stderr b/src/test/ui/issues/issue-11004.stderr index 46b4c4bdba201..eb5b568b34738 100644 --- a/src/test/ui/issues/issue-11004.stderr +++ b/src/test/ui/issues/issue-11004.stderr @@ -2,13 +2,17 @@ error[E0609]: no field `x` on type `*mut A` --> $DIR/issue-11004.rs:17:21 | LL | let x : i32 = n.x; //~ no field `x` on type `*mut A` - | ^ help: `n` is a raw pointer; try dereferencing it: `(*n).x` + | --^ + | | + | help: `n` is a raw pointer; try dereferencing it: `(*n).x` error[E0609]: no field `y` on type `*mut A` --> $DIR/issue-11004.rs:18:21 | LL | let y : f64 = n.y; //~ no field `y` on type `*mut A` - | ^ help: `n` is a raw pointer; try dereferencing it: `(*n).y` + | --^ + | | + | help: `n` is a raw pointer; try dereferencing it: `(*n).y` error: aborting due to 2 previous errors diff --git a/src/test/ui/parenthesised-deref-suggestion.rs b/src/test/ui/parenthesised-deref-suggestion.rs new file mode 100644 index 0000000000000..bcbb51ccd6b65 --- /dev/null +++ b/src/test/ui/parenthesised-deref-suggestion.rs @@ -0,0 +1,8 @@ +struct Session { + opts: u8, +} + +fn main() { + let sess: &Session = &Session { opts: 0 }; + (sess as *const Session).opts; //~ ERROR no field `opts` on type `*const Session` +} diff --git a/src/test/ui/parenthesised-deref-suggestion.stderr b/src/test/ui/parenthesised-deref-suggestion.stderr new file mode 100644 index 0000000000000..2e122f38f3855 --- /dev/null +++ b/src/test/ui/parenthesised-deref-suggestion.stderr @@ -0,0 +1,12 @@ +error[E0609]: no field `opts` on type `*const Session` + --> $DIR/parenthesised-deref-suggestion.rs:7:30 + | +LL | (sess as *const Session).opts; //~ ERROR no field `opts` on type `*const Session` + | ^^^^ +help: `(sess as *const Session)` is a raw pointer; try dereferencing it + | +LL | (*(sess as *const Session)).opts; //~ ERROR no field `opts` on type `*const Session` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0609`. diff --git a/src/test/ui/unsafe/unsafe-fn-autoderef.stderr b/src/test/ui/unsafe/unsafe-fn-autoderef.stderr index 81f15b2931df3..7525f67051567 100644 --- a/src/test/ui/unsafe/unsafe-fn-autoderef.stderr +++ b/src/test/ui/unsafe/unsafe-fn-autoderef.stderr @@ -2,7 +2,9 @@ error[E0609]: no field `f` on type `*const Rec` --> $DIR/unsafe-fn-autoderef.rs:29:14 | LL | return p.f; //~ ERROR no field `f` on type `*const Rec` - | ^ help: `p` is a raw pointer; try dereferencing it: `(*p).f` + | --^ + | | + | help: `p` is a raw pointer; try dereferencing it: `(*p).f` error: aborting due to previous error From 030987481b339616954d36b4c421e86077f00e75 Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 18 Dec 2018 23:43:00 +0000 Subject: [PATCH 05/29] Fix string for array access suggestion --- src/librustc_typeck/check/mod.rs | 4 +++- src/test/ui/parenthesised-deref-suggestion.rs | 3 +++ src/test/ui/parenthesised-deref-suggestion.stderr | 9 +++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 500bdbf6acd85..2f6de21d884f5 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3372,7 +3372,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { len.assert_usize(self.tcx), field.as_str().parse::() ) { - let base = self.tcx.hir().node_to_pretty_string(base.id); + let base = self.tcx.sess.source_map() + .span_to_snippet(base.span) + .unwrap_or_else(|_| self.tcx.hir().node_to_pretty_string(base.id)); let help = "instead of using tuple indexing, use array indexing"; let suggestion = format!("{}[{}]", base, field); let applicability = if len < user_index { diff --git a/src/test/ui/parenthesised-deref-suggestion.rs b/src/test/ui/parenthesised-deref-suggestion.rs index bcbb51ccd6b65..0b4ccdd5a56d4 100644 --- a/src/test/ui/parenthesised-deref-suggestion.rs +++ b/src/test/ui/parenthesised-deref-suggestion.rs @@ -5,4 +5,7 @@ struct Session { fn main() { let sess: &Session = &Session { opts: 0 }; (sess as *const Session).opts; //~ ERROR no field `opts` on type `*const Session` + + let x = [0u32]; + (x as [u32; 1]).0; //~ ERROR no field `0` on type `[u32; 1]` } diff --git a/src/test/ui/parenthesised-deref-suggestion.stderr b/src/test/ui/parenthesised-deref-suggestion.stderr index 2e122f38f3855..71a2bf67f06ae 100644 --- a/src/test/ui/parenthesised-deref-suggestion.stderr +++ b/src/test/ui/parenthesised-deref-suggestion.stderr @@ -7,6 +7,15 @@ help: `(sess as *const Session)` is a raw pointer; try dereferencing it | LL | (*(sess as *const Session)).opts; //~ ERROR no field `opts` on type `*const Session` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0609]: no field `0` on type `[u32; 1]` + --> $DIR/parenthesised-deref-suggestion.rs:10:21 + | +LL | (x as [u32; 1]).0; //~ ERROR no field `0` on type `[u32; 1]` + | ----------------^ + | | + | help: instead of using tuple indexing, use array indexing: `(x as [u32; 1])[0]` + error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0609`. From e7c5146c5d801c020f13c81b8b550f465c33d03a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 20 Dec 2018 09:50:14 +1100 Subject: [PATCH 06/29] Remove `TokenStream::JointTree`. This is done by adding a new `IsJoint` field to `TokenStream::Tree`, which simplifies a lot of `match` statements. And likewise for `CursorKind`. The commit also adds a new method `TokenTree:stream()` which can replace a choice between `.into()` and `.joint()`. --- src/libsyntax/parse/lexer/tokentrees.rs | 5 +- src/libsyntax/tokenstream.rs | 93 +++++++++++-------------- src/libsyntax_ext/proc_macro_server.rs | 8 +-- 3 files changed, 46 insertions(+), 60 deletions(-) diff --git a/src/libsyntax/parse/lexer/tokentrees.rs b/src/libsyntax/parse/lexer/tokentrees.rs index 0906c25cab361..72abcb03410ec 100644 --- a/src/libsyntax/parse/lexer/tokentrees.rs +++ b/src/libsyntax/parse/lexer/tokentrees.rs @@ -11,7 +11,7 @@ use print::pprust::token_to_string; use parse::lexer::StringReader; use parse::{token, PResult}; -use tokenstream::{DelimSpan, TokenStream, TokenTree}; +use tokenstream::{DelimSpan, IsJoint::*, TokenStream, TokenTree}; impl<'a> StringReader<'a> { // Parse a stream of tokens into a list of `TokenTree`s, up to an `Eof`. @@ -178,8 +178,7 @@ impl<'a> StringReader<'a> { let raw = self.span_src_raw; self.real_token(); let is_joint = raw.hi() == self.span_src_raw.lo() && token::is_op(&self.token); - - Ok(if is_joint { tt.joint() } else { tt.into() }) + Ok(TokenStream::Tree(tt, if is_joint { Joint } else { NonJoint })) } } } diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index c11ef33f931d8..620035413a553 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -123,7 +123,7 @@ impl TokenTree { } pub fn joint(self) -> TokenStream { - TokenStream::JointTree(self) + TokenStream::Tree(self, Joint) } /// Returns the opening delimiter as a token tree. @@ -156,8 +156,7 @@ impl TokenTree { #[derive(Clone, Debug)] pub enum TokenStream { Empty, - Tree(TokenTree), - JointTree(TokenTree), + Tree(TokenTree, IsJoint), Stream(Lrc>), } @@ -165,6 +164,14 @@ pub enum TokenStream { #[cfg(target_arch = "x86_64")] static_assert!(MEM_SIZE_OF_TOKEN_STREAM: mem::size_of::() == 32); +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum IsJoint { + Joint, + NonJoint +} + +use self::IsJoint::*; + impl TokenStream { /// Given a `TokenStream` with a `Stream` of only two arguments, return a new `TokenStream` /// separating the two arguments with a comma for diagnostic suggestions. @@ -176,16 +183,16 @@ impl TokenStream { while let Some((pos, ts)) = iter.next() { if let Some((_, next)) = iter.peek() { let sp = match (&ts, &next) { - (TokenStream::Tree(TokenTree::Token(_, token::Token::Comma)), _) | - (_, TokenStream::Tree(TokenTree::Token(_, token::Token::Comma))) => { - continue; - } - (TokenStream::Tree(TokenTree::Token(sp, _)), _) => *sp, - (TokenStream::Tree(TokenTree::Delimited(sp, ..)), _) => sp.entire(), + (TokenStream::Tree(TokenTree::Token(_, token::Token::Comma), NonJoint), _) | + (_, TokenStream::Tree(TokenTree::Token(_, token::Token::Comma), NonJoint)) + => continue, + (TokenStream::Tree(TokenTree::Token(sp, _), NonJoint), _) => *sp, + (TokenStream::Tree(TokenTree::Delimited(sp, ..), NonJoint), _) => + sp.entire(), _ => continue, }; let sp = sp.shrink_to_hi(); - let comma = TokenStream::Tree(TokenTree::Token(sp, token::Comma)); + let comma = TokenStream::Tree(TokenTree::Token(sp, token::Comma), NonJoint); suggestion = Some((pos, comma, sp)); } } @@ -204,7 +211,7 @@ impl TokenStream { impl From for TokenStream { fn from(tt: TokenTree) -> TokenStream { - TokenStream::Tree(tt) + TokenStream::Tree(tt, NonJoint) } } @@ -232,7 +239,7 @@ impl Extend for TokenStream { vec.reserve(iter.size_hint().0); vec } - TokenStream::Tree(_) | TokenStream::JointTree(_) => { + TokenStream::Tree(..) => { let mut vec = Vec::new(); vec.reserve(1 + iter.size_hint().0); vec.push(this); @@ -367,8 +374,7 @@ impl TokenStream { /// Returns true if the token tree is a joint operation w.r.t. `proc_macro::TokenNode`. pub fn as_tree(self) -> (TokenTree, bool /* joint? */) { match self { - TokenStream::Tree(tree) => (tree, false), - TokenStream::JointTree(tree) => (tree, true), + TokenStream::Tree(tree, is_joint) => (tree, is_joint == Joint), _ => unreachable!(), } } @@ -379,8 +385,7 @@ impl TokenStream { let mut i = 0; while let Some(stream) = trees.next_as_stream() { result.push(match stream { - TokenStream::Tree(tree) => f(i, tree).into(), - TokenStream::JointTree(tree) => f(i, tree).joint(), + TokenStream::Tree(tree, is_joint) => TokenStream::Tree(f(i, tree), is_joint), _ => unreachable!() }); i += 1; @@ -393,27 +398,25 @@ impl TokenStream { let mut result = Vec::new(); while let Some(stream) = trees.next_as_stream() { result.push(match stream { - TokenStream::Tree(tree) => f(tree).into(), - TokenStream::JointTree(tree) => f(tree).joint(), + TokenStream::Tree(tree, is_joint) => TokenStream::Tree(f(tree), is_joint), _ => unreachable!() }); } TokenStream::new(result) } - fn first_tree_and_joint(&self) -> Option<(TokenTree, bool)> { + fn first_tree_and_joint(&self) -> Option<(TokenTree, IsJoint)> { match self { TokenStream::Empty => None, - TokenStream::Tree(ref tree) => Some((tree.clone(), false)), - TokenStream::JointTree(ref tree) => Some((tree.clone(), true)), + TokenStream::Tree(ref tree, is_joint) => Some((tree.clone(), *is_joint)), TokenStream::Stream(ref stream) => stream.first().unwrap().first_tree_and_joint(), } } fn last_tree_if_joint(&self) -> Option { match self { - TokenStream::Empty | TokenStream::Tree(..) => None, - TokenStream::JointTree(ref tree) => Some(tree.clone()), + TokenStream::Empty | TokenStream::Tree(_, NonJoint) => None, + TokenStream::Tree(ref tree, Joint) => Some(tree.clone()), TokenStream::Stream(ref stream) => stream.last().unwrap().last_tree_if_joint(), } } @@ -437,11 +440,7 @@ impl TokenStreamBuilder { self.push_all_but_last_tree(&last_stream); let glued_span = last_span.to(span); let glued_tt = TokenTree::Token(glued_span, glued_tok); - let glued_tokenstream = if is_joint { - glued_tt.joint() - } else { - glued_tt.into() - }; + let glued_tokenstream = TokenStream::Tree(glued_tt, is_joint); self.0.push(glued_tokenstream); self.push_all_but_first_tree(&stream); return @@ -491,8 +490,7 @@ pub struct Cursor(CursorKind); #[derive(Clone)] enum CursorKind { Empty, - Tree(TokenTree, bool /* consumed? */), - JointTree(TokenTree, bool /* consumed? */), + Tree(TokenTree, IsJoint, bool /* consumed? */), Stream(StreamCursor), } @@ -514,9 +512,9 @@ impl StreamCursor { self.index += 1; let next = self.stream[self.index - 1].clone(); match next { - TokenStream::Tree(..) | TokenStream::JointTree(..) => return Some(next), - TokenStream::Stream(stream) => self.insert(stream), TokenStream::Empty => {} + TokenStream::Tree(..) => return Some(next), + TokenStream::Stream(stream) => self.insert(stream), } } else if let Some((stream, index)) = self.stack.pop() { self.stream = stream; @@ -538,7 +536,7 @@ impl Iterator for Cursor { fn next(&mut self) -> Option { self.next_as_stream().map(|stream| match stream { - TokenStream::Tree(tree) | TokenStream::JointTree(tree) => tree, + TokenStream::Tree(tree, _) => tree, _ => unreachable!() }) } @@ -548,18 +546,15 @@ impl Cursor { fn new(stream: TokenStream) -> Self { Cursor(match stream { TokenStream::Empty => CursorKind::Empty, - TokenStream::Tree(tree) => CursorKind::Tree(tree, false), - TokenStream::JointTree(tree) => CursorKind::JointTree(tree, false), + TokenStream::Tree(tree, is_joint) => CursorKind::Tree(tree, is_joint, false), TokenStream::Stream(stream) => CursorKind::Stream(StreamCursor::new(stream)), }) } pub fn next_as_stream(&mut self) -> Option { let (stream, consumed) = match self.0 { - CursorKind::Tree(ref tree, ref mut consumed @ false) => - (tree.clone().into(), consumed), - CursorKind::JointTree(ref tree, ref mut consumed @ false) => - (tree.clone().joint(), consumed), + CursorKind::Tree(ref tree, ref is_joint, ref mut consumed @ false) => + (TokenStream::Tree(tree.clone(), *is_joint), consumed), CursorKind::Stream(ref mut cursor) => return cursor.next_as_stream(), _ => return None, }; @@ -572,7 +567,7 @@ impl Cursor { match self.0 { _ if stream.is_empty() => return, CursorKind::Empty => *self = stream.trees(), - CursorKind::Tree(_, consumed) | CursorKind::JointTree(_, consumed) => { + CursorKind::Tree(_, _, consumed) => { *self = TokenStream::new(vec![self.original_stream(), stream]).trees(); if consumed { self.next(); @@ -587,8 +582,8 @@ impl Cursor { pub fn original_stream(&self) -> TokenStream { match self.0 { CursorKind::Empty => TokenStream::empty(), - CursorKind::Tree(ref tree, _) => tree.clone().into(), - CursorKind::JointTree(ref tree, _) => tree.clone().joint(), + CursorKind::Tree(ref tree, ref is_joint, _) => + TokenStream::Tree(tree.clone(), *is_joint), CursorKind::Stream(ref cursor) => TokenStream::Stream( cursor.stack.get(0).cloned().map(|(stream, _)| stream) .unwrap_or_else(|| cursor.stream.clone()) @@ -600,9 +595,8 @@ impl Cursor { fn look_ahead(streams: &[TokenStream], mut n: usize) -> Result { for stream in streams { n = match stream { - TokenStream::Tree(ref tree) | TokenStream::JointTree(ref tree) - if n == 0 => return Ok(tree.clone()), - TokenStream::Tree(..) | TokenStream::JointTree(..) => n - 1, + TokenStream::Tree(ref tree, _) if n == 0 => return Ok(tree.clone()), + TokenStream::Tree(..) => n - 1, TokenStream::Stream(ref stream) => match look_ahead(stream, n) { Ok(tree) => return Ok(tree), Err(n) => n, @@ -615,10 +609,8 @@ impl Cursor { match self.0 { CursorKind::Empty | - CursorKind::Tree(_, true) | - CursorKind::JointTree(_, true) => Err(n), - CursorKind::Tree(ref tree, false) | - CursorKind::JointTree(ref tree, false) => look_ahead(&[tree.clone().into()], n), + CursorKind::Tree(_, _, true) => Err(n), + CursorKind::Tree(ref tree, _, false) => look_ahead(&[tree.clone().into()], n), CursorKind::Stream(ref cursor) => { look_ahead(&cursor.stream[cursor.index ..], n).or_else(|mut n| { for &(ref stream, index) in cursor.stack.iter().rev() { @@ -651,8 +643,7 @@ impl From for ThinTokenStream { fn from(stream: TokenStream) -> ThinTokenStream { ThinTokenStream(match stream { TokenStream::Empty => None, - TokenStream::Tree(tree) => Some(Lrc::new(vec![tree.into()])), - TokenStream::JointTree(tree) => Some(Lrc::new(vec![tree.joint()])), + TokenStream::Tree(..) => Some(Lrc::new(vec![stream])), TokenStream::Stream(stream) => Some(stream), }) } diff --git a/src/libsyntax_ext/proc_macro_server.rs b/src/libsyntax_ext/proc_macro_server.rs index a04d6c92b7817..fa41022b7b675 100644 --- a/src/libsyntax_ext/proc_macro_server.rs +++ b/src/libsyntax_ext/proc_macro_server.rs @@ -21,7 +21,7 @@ use syntax::ast; use syntax::ext::base::ExtCtxt; use syntax::parse::lexer::comments; use syntax::parse::{self, token, ParseSess}; -use syntax::tokenstream::{self, DelimSpan, TokenStream}; +use syntax::tokenstream::{self, DelimSpan, IsJoint::*, TokenStream}; use syntax_pos::hygiene::{SyntaxContext, Transparency}; use syntax_pos::symbol::{keywords, Symbol}; use syntax_pos::{BytePos, FileName, MultiSpan, Pos, SourceFile, Span}; @@ -297,11 +297,7 @@ impl ToInternal for TokenTree { }; let tree = tokenstream::TokenTree::Token(span, token); - if joint { - tree.joint() - } else { - tree.into() - } + TokenStream::Tree(tree, if joint { Joint } else { NonJoint }) } } From 405d8b0bb3d749e3baad25f68455873b66b219be Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 20 Dec 2018 14:31:40 +0100 Subject: [PATCH 07/29] Copyrite --- src/test/ui/dead-code-tuple-struct-field.rs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/test/ui/dead-code-tuple-struct-field.rs b/src/test/ui/dead-code-tuple-struct-field.rs index f4989fa1037d3..496ce4fb378ae 100644 --- a/src/test/ui/dead-code-tuple-struct-field.rs +++ b/src/test/ui/dead-code-tuple-struct-field.rs @@ -1,13 +1,3 @@ -// Copyright 2014 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - // compile-pass #![deny(dead_code)] From 59f643fc5f7f9de0896680ec41fc64087311bead Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 20 Dec 2018 14:00:30 -0800 Subject: [PATCH 08/29] Point to return span when writing `return;` on non-() fn --- src/librustc/hir/mod.rs | 9 +++++++++ src/librustc_typeck/check/coercion.rs | 3 +-- src/librustc_typeck/check/mod.rs | 19 ++++++++++++++++++- src/test/ui/error-codes/E0069.stderr | 4 +++- src/test/ui/ret-non-nil.stderr | 4 +++- .../return/return-unit-from-diverging.stderr | 4 +++- 6 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 156d55b9e2fe6..58733a83b253b 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1979,6 +1979,15 @@ pub enum FunctionRetTy { Return(P), } +impl fmt::Display for FunctionRetTy { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Return(ref ty) => print::to_string(print::NO_ANN, |s| s.print_type(ty)).fmt(f), + DefaultReturn(_) => "()".fmt(f), + } + } +} + impl FunctionRetTy { pub fn span(&self) -> Span { match *self { diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 8d844fe3a69e4..0b99a30b67dc8 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -1143,7 +1143,6 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E> // `expression_ty` will be unit). // // Another example is `break` with no argument expression. - assert!(expression_ty.is_unit()); assert!(expression_ty.is_unit(), "if let hack without unit type"); fcx.at(cause, fcx.param_env) .eq_exp(label_expression_as_expected, expression_ty, self.merged_ty()) @@ -1190,7 +1189,7 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E> db = struct_span_err!( fcx.tcx.sess, cause.span, E0069, "`return;` in a function whose return type is not `()`"); - db.span_label(cause.span, "return type is not ()"); + db.span_label(cause.span, "return type is not `()`"); } ObligationCauseCode::BlockTailExpression(blk_id) => { db = fcx.report_mismatched_types(cause, expected, found, err); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 8901f4b6b291b..d40afbbc3025b 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4103,7 +4103,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } else { let mut coercion = self.ret_coercion.as_ref().unwrap().borrow_mut(); let cause = self.cause(expr.span, ObligationCauseCode::ReturnNoExpression); - coercion.coerce_forced_unit(self, &cause, &mut |_| (), true); + if let Some((fn_decl, _)) = self.get_fn_decl(expr.id) { + coercion.coerce_forced_unit( + self, + &cause, + &mut |db| { + db.span_label( + fn_decl.output.span(), + format!( + "expected `{}` because of this return type", + fn_decl.output, + ), + ); + }, + true, + ); + } else { + coercion.coerce_forced_unit(self, &cause, &mut |_| (), true); + } } tcx.types.never } diff --git a/src/test/ui/error-codes/E0069.stderr b/src/test/ui/error-codes/E0069.stderr index 0ba1ed456635f..12b778f42e22c 100644 --- a/src/test/ui/error-codes/E0069.stderr +++ b/src/test/ui/error-codes/E0069.stderr @@ -1,8 +1,10 @@ error[E0069]: `return;` in a function whose return type is not `()` --> $DIR/E0069.rs:12:5 | +LL | fn foo() -> u8 { + | -- expected `u8` because of this return type LL | return; - | ^^^^^^ return type is not () + | ^^^^^^ return type is not `()` error: aborting due to previous error diff --git a/src/test/ui/ret-non-nil.stderr b/src/test/ui/ret-non-nil.stderr index 01f126bd11ea2..e0fdc8c67edf7 100644 --- a/src/test/ui/ret-non-nil.stderr +++ b/src/test/ui/ret-non-nil.stderr @@ -2,7 +2,9 @@ error[E0069]: `return;` in a function whose return type is not `()` --> $DIR/ret-non-nil.rs:15:19 | LL | fn g() -> isize { return; } - | ^^^^^^ return type is not () + | ----- ^^^^^^ return type is not `()` + | | + | expected `isize` because of this return type error: aborting due to previous error diff --git a/src/test/ui/return/return-unit-from-diverging.stderr b/src/test/ui/return/return-unit-from-diverging.stderr index 38d4ca37366ff..5a9f0877cc6b6 100644 --- a/src/test/ui/return/return-unit-from-diverging.stderr +++ b/src/test/ui/return/return-unit-from-diverging.stderr @@ -1,8 +1,10 @@ error[E0069]: `return;` in a function whose return type is not `()` --> $DIR/return-unit-from-diverging.rs:15:5 | +LL | fn fail() -> ! { + | - expected `!` because of this return type LL | return; //~ ERROR in a function whose return type is not - | ^^^^^^ return type is not () + | ^^^^^^ return type is not `()` error: aborting due to previous error From cdbccf50a7746a07c44a404c270f188f64c5abf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 20 Dec 2018 16:52:52 -0800 Subject: [PATCH 09/29] Point at coercion source on type errors for fn returning `impl Trait` --- src/librustc_typeck/check/coercion.rs | 15 +++++++++++++++ src/librustc_typeck/check/mod.rs | 4 ++++ src/libsyntax_pos/lib.rs | 7 +++++++ src/test/ui/impl-trait/equality.stderr | 3 +++ 4 files changed, 29 insertions(+) diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 0b99a30b67dc8..c7adf2982272c 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -1183,6 +1183,11 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E> (self.final_ty.unwrap_or(self.expected_ty), expression_ty) }; + let reason_label = if label_expression_as_expected { + "found because of this statement" + } else { + "expected because of this statement" + }; let mut db; match cause.code { ObligationCauseCode::ReturnNoExpression => { @@ -1207,9 +1212,19 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E> cause.span, blk_id, ); + if let Some(sp) = fcx.ret_coercion_span.borrow().as_ref() { + if !sp.overlaps(cause.span) { + db.span_label(*sp, reason_label); + } + } } _ => { db = fcx.report_mismatched_types(cause, expected, found, err); + if let Some(sp) = fcx.ret_coercion_span.borrow().as_ref() { + if !sp.overlaps(cause.span) { + db.span_label(*sp, reason_label); + } + } } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index d40afbbc3025b..50cf5ef1655fa 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -535,6 +535,7 @@ pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { err_count_on_creation: usize, ret_coercion: Option>>, + ret_coercion_span: RefCell>, yield_ty: Option>, @@ -1984,6 +1985,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { param_env, err_count_on_creation: inh.tcx.sess.err_count(), ret_coercion: None, + ret_coercion_span: RefCell::new(None), yield_ty: None, ps: RefCell::new(UnsafetyState::function(hir::Unsafety::Normal, ast::CRATE_NODE_ID)), @@ -4099,9 +4101,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { struct_span_err!(self.tcx.sess, expr.span, E0572, "return statement outside of function body").emit(); } else if let Some(ref e) = *expr_opt { + *self.ret_coercion_span.borrow_mut() = Some(e.span); self.check_return_expr(e); } else { let mut coercion = self.ret_coercion.as_ref().unwrap().borrow_mut(); + *self.ret_coercion_span.borrow_mut() = Some(expr.span); let cause = self.cause(expr.span, ObligationCauseCode::ReturnNoExpression); if let Some((fn_decl, _)) = self.get_fn_decl(expr.id) { coercion.coerce_forced_unit( diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 8b7ffa499cd71..514dea7fb1704 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -331,6 +331,13 @@ impl Span { span.lo <= other.lo && other.hi <= span.hi } + /// Return `true` if `self` touches `other`. + pub fn overlaps(self, other: Span) -> bool { + let span = self.data(); + let other = other.data(); + span.lo < other.hi && other.lo < span.hi + } + /// Return true if the spans are equal with regards to the source text. /// /// Use this instead of `==` when either span could be generated code, diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr index e277d4e28cb2b..f1d2071bbdb9e 100644 --- a/src/test/ui/impl-trait/equality.stderr +++ b/src/test/ui/impl-trait/equality.stderr @@ -1,6 +1,9 @@ error[E0308]: mismatched types --> $DIR/equality.rs:25:5 | +LL | return 1_i32; + | ----- expected because of this statement +LL | } LL | 0_u32 | ^^^^^ expected i32, found u32 | From f8e508cde4854cc4da4333a33696f0e67d366d78 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 17 Dec 2018 14:20:42 +0100 Subject: [PATCH 10/29] Fix a recently introduces regression --- src/librustc_mir/transform/qualify_consts.rs | 2 +- .../consts/static_mut_containing_mut_ref.rs | 7 +++++++ .../consts/static_mut_containing_mut_ref2.rs | 8 ++++++++ .../static_mut_containing_mut_ref2.stderr | 9 +++++++++ src/test/ui/write-to-static-mut-in-static.rs | 4 ++-- .../ui/write-to-static-mut-in-static.stderr | 20 ++++++++++++++++--- 6 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/consts/static_mut_containing_mut_ref.rs create mode 100644 src/test/ui/consts/static_mut_containing_mut_ref2.rs create mode 100644 src/test/ui/consts/static_mut_containing_mut_ref2.stderr diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index b854f029e5106..646a671d4a2ce 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -518,7 +518,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { // Only allow statics (not consts) to refer to other statics. if self.mode == Mode::Static || self.mode == Mode::StaticMut { - if context.is_mutating_use() { + if self.mode == Mode::Static && context.is_mutating_use() { // this is not strictly necessary as miri will also bail out // For interior mutability we can't really catch this statically as that // goes through raw pointers and intermediate temporaries, so miri has diff --git a/src/test/ui/consts/static_mut_containing_mut_ref.rs b/src/test/ui/consts/static_mut_containing_mut_ref.rs new file mode 100644 index 0000000000000..27e1a111163b1 --- /dev/null +++ b/src/test/ui/consts/static_mut_containing_mut_ref.rs @@ -0,0 +1,7 @@ +// compile-pass + +static mut STDERR_BUFFER_SPACE: [u8; 42] = [0u8; 42]; + +pub static mut STDERR_BUFFER: *mut [u8] = unsafe { &mut STDERR_BUFFER_SPACE }; + +fn main() {} diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.rs b/src/test/ui/consts/static_mut_containing_mut_ref2.rs new file mode 100644 index 0000000000000..aa9bfb4aeab2d --- /dev/null +++ b/src/test/ui/consts/static_mut_containing_mut_ref2.rs @@ -0,0 +1,8 @@ +#![feature(const_let)] + +static mut STDERR_BUFFER_SPACE: u8 = 0; + +pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; +//~^ references in statics may only refer to immutable values + +fn main() {} diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.stderr b/src/test/ui/consts/static_mut_containing_mut_ref2.stderr new file mode 100644 index 0000000000000..72923431c90ed --- /dev/null +++ b/src/test/ui/consts/static_mut_containing_mut_ref2.stderr @@ -0,0 +1,9 @@ +error[E0017]: references in statics may only refer to immutable values + --> $DIR/static_mut_containing_mut_ref2.rs:5:46 + | +LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ statics require immutable values + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0017`. diff --git a/src/test/ui/write-to-static-mut-in-static.rs b/src/test/ui/write-to-static-mut-in-static.rs index 191f09b54ee73..983b5d48e60fc 100644 --- a/src/test/ui/write-to-static-mut-in-static.rs +++ b/src/test/ui/write-to-static-mut-in-static.rs @@ -12,10 +12,10 @@ pub static mut A: u32 = 0; pub static mut B: () = unsafe { A = 1; }; -//~^ ERROR cannot mutate statics in the initializer of another static +//~^ ERROR could not evaluate static initializer pub static mut C: u32 = unsafe { C = 1; 0 }; -//~^ ERROR cannot mutate statics in the initializer of another static +//~^ ERROR cycle detected pub static D: u32 = D; diff --git a/src/test/ui/write-to-static-mut-in-static.stderr b/src/test/ui/write-to-static-mut-in-static.stderr index 673a71b4642f3..335f849fb2472 100644 --- a/src/test/ui/write-to-static-mut-in-static.stderr +++ b/src/test/ui/write-to-static-mut-in-static.stderr @@ -1,14 +1,28 @@ -error: cannot mutate statics in the initializer of another static +error[E0080]: could not evaluate static initializer --> $DIR/write-to-static-mut-in-static.rs:14:33 | LL | pub static mut B: () = unsafe { A = 1; }; - | ^^^^^ + | ^^^^^ tried to modify a static's initial value from another static's initializer -error: cannot mutate statics in the initializer of another static +error[E0391]: cycle detected when const-evaluating `C` --> $DIR/write-to-static-mut-in-static.rs:17:34 | LL | pub static mut C: u32 = unsafe { C = 1; 0 }; | ^^^^^ + | +note: ...which requires const-evaluating `C`... + --> $DIR/write-to-static-mut-in-static.rs:17:1 + | +LL | pub static mut C: u32 = unsafe { C = 1; 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which again requires const-evaluating `C`, completing the cycle +note: cycle used when const-evaluating + checking `C` + --> $DIR/write-to-static-mut-in-static.rs:17:1 + | +LL | pub static mut C: u32 = unsafe { C = 1; 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors +Some errors occurred: E0080, E0391. +For more information about an error, try `rustc --explain E0080`. From b9d74fc3ceec744ac6dbfb6b0d8d1003b54668e8 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 17 Dec 2018 14:36:10 +0100 Subject: [PATCH 11/29] Also test projections --- src/test/ui/consts/static_mut_containing_mut_ref2.rs | 2 +- src/test/ui/consts/static_mut_containing_mut_ref3.rs | 8 ++++++++ src/test/ui/consts/static_mut_containing_mut_ref3.stderr | 9 +++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/consts/static_mut_containing_mut_ref3.rs create mode 100644 src/test/ui/consts/static_mut_containing_mut_ref3.stderr diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.rs b/src/test/ui/consts/static_mut_containing_mut_ref2.rs index aa9bfb4aeab2d..aeb69b2652cbf 100644 --- a/src/test/ui/consts/static_mut_containing_mut_ref2.rs +++ b/src/test/ui/consts/static_mut_containing_mut_ref2.rs @@ -3,6 +3,6 @@ static mut STDERR_BUFFER_SPACE: u8 = 0; pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; -//~^ references in statics may only refer to immutable values +//~^ ERROR references in statics may only refer to immutable values fn main() {} diff --git a/src/test/ui/consts/static_mut_containing_mut_ref3.rs b/src/test/ui/consts/static_mut_containing_mut_ref3.rs new file mode 100644 index 0000000000000..0bc7faa9afdec --- /dev/null +++ b/src/test/ui/consts/static_mut_containing_mut_ref3.rs @@ -0,0 +1,8 @@ +#![feature(const_let)] + +static mut FOO: (u8, u8) = (42, 43); + +static mut BAR: () = unsafe { FOO.0 = 99; }; +//~^ ERROR could not evaluate static initializer + +fn main() {} diff --git a/src/test/ui/consts/static_mut_containing_mut_ref3.stderr b/src/test/ui/consts/static_mut_containing_mut_ref3.stderr new file mode 100644 index 0000000000000..cae53c6fee9dd --- /dev/null +++ b/src/test/ui/consts/static_mut_containing_mut_ref3.stderr @@ -0,0 +1,9 @@ +error[E0080]: could not evaluate static initializer + --> $DIR/static_mut_containing_mut_ref3.rs:5:31 + | +LL | static mut BAR: () = unsafe { FOO.0 = 99; }; + | ^^^^^^^^^^ tried to modify a static's initial value from another static's initializer + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. From 3414be0b3eb6192c13865e794817de396eeccd4b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 21 Dec 2018 11:33:29 +0100 Subject: [PATCH 12/29] fix deprecation warnings in liballoc benches --- Cargo.lock | 1 + src/liballoc/Cargo.toml | 1 + src/liballoc/benches/btree/map.rs | 4 ++-- src/liballoc/benches/lib.rs | 1 + src/liballoc/benches/slice.rs | 3 ++- src/liballoc/benches/str.rs | 8 ++++---- 6 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7e03474565d85..06d01ab78f3a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,6 +18,7 @@ dependencies = [ "compiler_builtins 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/src/liballoc/Cargo.toml b/src/liballoc/Cargo.toml index b2eb3566c04a7..861c7cecb8879 100644 --- a/src/liballoc/Cargo.toml +++ b/src/liballoc/Cargo.toml @@ -15,6 +15,7 @@ compiler_builtins = { version = "0.1.0", features = ['rustc-dep-of-std'] } [dev-dependencies] rand = "0.6" +rand_xorshift = "0.1" [[test]] name = "collectionstests" diff --git a/src/liballoc/benches/btree/map.rs b/src/liballoc/benches/btree/map.rs index 20b9091a07bfc..6e2b5e06b7a91 100644 --- a/src/liballoc/benches/btree/map.rs +++ b/src/liballoc/benches/btree/map.rs @@ -12,7 +12,7 @@ use std::iter::Iterator; use std::vec::Vec; use std::collections::BTreeMap; -use rand::{Rng, thread_rng}; +use rand::{Rng, seq::SliceRandom, thread_rng}; use test::{Bencher, black_box}; macro_rules! map_insert_rand_bench { @@ -78,7 +78,7 @@ macro_rules! map_find_rand_bench { map.insert(k, k); } - rng.shuffle(&mut keys); + keys.shuffle(&mut rng); // measure let mut i = 0; diff --git a/src/liballoc/benches/lib.rs b/src/liballoc/benches/lib.rs index b4f4fd74f3a39..9502a7dc3c075 100644 --- a/src/liballoc/benches/lib.rs +++ b/src/liballoc/benches/lib.rs @@ -13,6 +13,7 @@ #![feature(test)] extern crate rand; +extern crate rand_xorshift; extern crate test; mod btree; diff --git a/src/liballoc/benches/slice.rs b/src/liballoc/benches/slice.rs index 490320f57cbf7..fc58899406332 100644 --- a/src/liballoc/benches/slice.rs +++ b/src/liballoc/benches/slice.rs @@ -12,8 +12,9 @@ use rand::{thread_rng}; use std::mem; use std::ptr; -use rand::{Rng, SeedableRng, XorShiftRng}; +use rand::{Rng, SeedableRng}; use rand::distributions::{Standard, Alphanumeric}; +use rand_xorshift::XorShiftRng; use test::{Bencher, black_box}; #[bench] diff --git a/src/liballoc/benches/str.rs b/src/liballoc/benches/str.rs index 38c94d4d8b5f3..c5e1576d24e26 100644 --- a/src/liballoc/benches/str.rs +++ b/src/liballoc/benches/str.rs @@ -274,11 +274,11 @@ make_test!(split_a_str, s, s.split("a").count()); make_test!(trim_ascii_char, s, { s.trim_matches(|c: char| c.is_ascii()) }); -make_test!(trim_left_ascii_char, s, { - s.trim_left_matches(|c: char| c.is_ascii()) +make_test!(trim_start_ascii_char, s, { + s.trim_start_matches(|c: char| c.is_ascii()) }); -make_test!(trim_right_ascii_char, s, { - s.trim_right_matches(|c: char| c.is_ascii()) +make_test!(trim_end_ascii_char, s, { + s.trim_end_matches(|c: char| c.is_ascii()) }); make_test!(find_underscore_char, s, s.find('_')); From 6ed596ebe245df1a8de8a609222c8e217508f6dd Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 21 Dec 2018 13:39:45 +0100 Subject: [PATCH 13/29] Update tests to changes on master --- src/test/ui/consts/static_mut_containing_mut_ref2.rs | 1 + .../ui/consts/static_mut_containing_mut_ref2.stderr | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.rs b/src/test/ui/consts/static_mut_containing_mut_ref2.rs index aeb69b2652cbf..4180b1e295ab0 100644 --- a/src/test/ui/consts/static_mut_containing_mut_ref2.rs +++ b/src/test/ui/consts/static_mut_containing_mut_ref2.rs @@ -4,5 +4,6 @@ static mut STDERR_BUFFER_SPACE: u8 = 0; pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; //~^ ERROR references in statics may only refer to immutable values +//~| ERROR static contains unimplemented expression type fn main() {} diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.stderr b/src/test/ui/consts/static_mut_containing_mut_ref2.stderr index 72923431c90ed..f0ae1545056b7 100644 --- a/src/test/ui/consts/static_mut_containing_mut_ref2.stderr +++ b/src/test/ui/consts/static_mut_containing_mut_ref2.stderr @@ -4,6 +4,13 @@ error[E0017]: references in statics may only refer to immutable values LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ statics require immutable values -error: aborting due to previous error +error[E0019]: static contains unimplemented expression type + --> $DIR/static_mut_containing_mut_ref2.rs:5:45 + | +LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0017`. +Some errors occurred: E0017, E0019. +For more information about an error, try `rustc --explain E0017`. From 097d39d8ecb2d8aa828393c66e85716081188793 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 21 Dec 2018 23:12:15 +0100 Subject: [PATCH 14/29] Fix alignment for array indexing We need to reduce the alignment with the used offset. If the offset isn't known, we need to reduce with the element size to support arbitrary offsets. --- src/librustc_codegen_ssa/mir/place.rs | 13 ++++++-- src/librustc_codegen_ssa/mir/rvalue.rs | 3 +- src/test/codegen/issue-56927.rs | 44 ++++++++++++++++++++++++++ src/test/codegen/packed.rs | 36 +++++++++++++++++++++ 4 files changed, 93 insertions(+), 3 deletions(-) create mode 100644 src/test/codegen/issue-56927.rs diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index 90aa9f6cbc763..5fad4a24b262e 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -335,11 +335,20 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> { bx: &mut Bx, llindex: V ) -> Self { + // Statically compute the offset if we can, otherwise just use the element size, + // as this will yield the lowest alignment. + let layout = self.layout.field(bx, 0); + let offset = if bx.is_const_integral(llindex) { + layout.size.checked_mul(bx.const_to_uint(llindex), bx).unwrap_or(layout.size) + } else { + layout.size + }; + PlaceRef { llval: bx.inbounds_gep(self.llval, &[bx.cx().const_usize(0), llindex]), llextra: None, - layout: self.layout.field(bx.cx(), 0), - align: self.align + layout, + align: self.align.restrict_for_offset(offset), } } diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index c932ffd1c1bda..052342dd7597b 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -131,8 +131,9 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let keep_going = header_bx.icmp(IntPredicate::IntNE, current, end); header_bx.cond_br(keep_going, body_bx.llbb(), next_bx.llbb()); + let align = dest.align.restrict_for_offset(dest.layout.field(bx.cx(), 0).size); cg_elem.val.store(&mut body_bx, - PlaceRef::new_sized(current, cg_elem.layout, dest.align)); + PlaceRef::new_sized(current, cg_elem.layout, align)); let next = body_bx.inbounds_gep(current, &[bx.cx().const_usize(1)]); body_bx.br(header_bx.llbb()); diff --git a/src/test/codegen/issue-56927.rs b/src/test/codegen/issue-56927.rs new file mode 100644 index 0000000000000..0544ff86aacfa --- /dev/null +++ b/src/test/codegen/issue-56927.rs @@ -0,0 +1,44 @@ +// compile-flags: -C no-prepopulate-passes + +#![crate_type="rlib"] +use std::usize; + +#[repr(align(16))] +pub struct S { + arr: [u32; 4], +} + +// CHECK-LABEL: @test1 +// CHECK: store i32 0, i32* %{{.+}}, align 16 +// CHECK: store i32 1, i32* %{{.+}}, align 4 +// CHECK: store i32 2, i32* %{{.+}}, align 8 +// CHECK: store i32 3, i32* %{{.+}}, align 4 +#[no_mangle] +pub fn test1(s: &mut S) { + s.arr[0] = 0; + s.arr[1] = 1; + s.arr[2] = 2; + s.arr[3] = 3; +} + +// CHECK-LABEL: @test2 +// CHECK: store i32 4, i32* %{{.+}}, align 4 +#[allow(const_err)] +#[no_mangle] +pub fn test2(s: &mut S) { + s.arr[usize::MAX / 4 + 1] = 4; +} + +// CHECK-LABEL: @test3 +// CHECK: store i32 5, i32* %{{.+}}, align 4 +#[no_mangle] +pub fn test3(s: &mut S, i: usize) { + s.arr[i] = 5; +} + +// CHECK-LABEL: @test4 +// CHECK: store i32 6, i32* %{{.+}}, align 4 +#[no_mangle] +pub fn test4(s: &mut S) { + s.arr = [6; 4]; +} diff --git a/src/test/codegen/packed.rs b/src/test/codegen/packed.rs index b50f5b6f16fed..e60051de559b5 100644 --- a/src/test/codegen/packed.rs +++ b/src/test/codegen/packed.rs @@ -84,6 +84,42 @@ pub fn call_pkd2(f: fn() -> Array) -> BigPacked2 { BigPacked2 { dealign: 0, data: f() } } +// CHECK-LABEL: @write_packed_array1 +// CHECK: store i32 0, i32* %{{.+}}, align 1 +// CHECK: store i32 1, i32* %{{.+}}, align 1 +// CHECK: store i32 2, i32* %{{.+}}, align 1 +#[no_mangle] +pub fn write_packed_array1(p: &mut BigPacked1) { + p.data.0[0] = 0; + p.data.0[1] = 1; + p.data.0[2] = 2; +} + +// CHECK-LABEL: @write_packed_array2 +// CHECK: store i32 0, i32* %{{.+}}, align 2 +// CHECK: store i32 1, i32* %{{.+}}, align 2 +// CHECK: store i32 2, i32* %{{.+}}, align 2 +#[no_mangle] +pub fn write_packed_array2(p: &mut BigPacked2) { + p.data.0[0] = 0; + p.data.0[1] = 1; + p.data.0[2] = 2; +} + +// CHECK-LABEL: @repeat_packed_array1 +// CHECK: store i32 42, i32* %{{.+}}, align 1 +#[no_mangle] +pub fn repeat_packed_array1(p: &mut BigPacked1) { + p.data.0 = [42; 8]; +} + +// CHECK-LABEL: @repeat_packed_array2 +// CHECK: store i32 42, i32* %{{.+}}, align 2 +#[no_mangle] +pub fn repeat_packed_array2(p: &mut BigPacked2) { + p.data.0 = [42; 8]; +} + #[repr(packed)] #[derive(Copy, Clone)] pub struct Packed1Pair(u8, u32); From 20d694a95f0110fe253bfca7e9929bfdc6440c7e Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Mon, 17 Dec 2018 17:19:32 -0800 Subject: [PATCH 15/29] Update Pin API to match the one proposed for stabilization Remove pin::Unpin reexport and add Unpin to the prelude. Change Pin associated functions to methods. Rename get_mut_unchecked_ to get_unchecked_mut Remove impl Unpin for Pin Mark Pin repr(transparent) --- src/libcore/future/future.rs | 2 +- src/libcore/option.rs | 2 +- src/libcore/pin.rs | 33 ++++++++++++++------------------- src/libcore/prelude/v1.rs | 2 +- src/libstd/future.rs | 2 +- 5 files changed, 18 insertions(+), 23 deletions(-) diff --git a/src/libcore/future/future.rs b/src/libcore/future/future.rs index 5dee1d6dd3a39..da3aa8449bafb 100644 --- a/src/libcore/future/future.rs +++ b/src/libcore/future/future.rs @@ -120,7 +120,7 @@ impl<'a, F: ?Sized + Future + Unpin> Future for &'a mut F { impl

Future for Pin

where - P: ops::DerefMut, + P: Unpin + ops::DerefMut, P::Target: Future, { type Output = <

::Target as Future>::Output; diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 44d632ece055c..0d7ddfc20b6d3 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -285,7 +285,7 @@ impl Option { #[unstable(feature = "pin", issue = "49150")] pub fn as_pin_mut<'a>(self: Pin<&'a mut Option>) -> Option> { unsafe { - Pin::get_mut_unchecked(self).as_mut().map(|x| Pin::new_unchecked(x)) + Pin::get_unchecked_mut(self).as_mut().map(|x| Pin::new_unchecked(x)) } } diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index 521ce9b5f6b69..0436a709b31b7 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -100,12 +100,9 @@ #![unstable(feature = "pin", issue = "49150")] use fmt; -use marker::Sized; +use marker::{Sized, Unpin}; use ops::{Deref, DerefMut, Receiver, CoerceUnsized, DispatchFromDyn}; -#[doc(inline)] -pub use marker::Unpin; - /// A pinned pointer. /// /// This is a wrapper around a kind of pointer which makes that pointer "pin" its @@ -121,6 +118,7 @@ pub use marker::Unpin; // cannot move the value behind `pointer`. #[unstable(feature = "pin", issue = "49150")] #[fundamental] +#[repr(transparent)] #[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)] pub struct Pin

{ pointer: P, @@ -200,10 +198,10 @@ impl<'a, T: ?Sized> Pin<&'a T> { /// because it is one of the fields of that value), and also that you do /// not move out of the argument you receive to the interior function. #[unstable(feature = "pin", issue = "49150")] - pub unsafe fn map_unchecked(this: Pin<&'a T>, func: F) -> Pin<&'a U> where + pub unsafe fn map_unchecked(self: Pin<&'a T>, func: F) -> Pin<&'a U> where F: FnOnce(&T) -> &U, { - let pointer = &*this.pointer; + let pointer = &*self.pointer; let new_pointer = func(pointer); Pin::new_unchecked(new_pointer) } @@ -217,8 +215,8 @@ impl<'a, T: ?Sized> Pin<&'a T> { /// with the same lifetime as the original `Pin`. #[unstable(feature = "pin", issue = "49150")] #[inline(always)] - pub fn get_ref(this: Pin<&'a T>) -> &'a T { - this.pointer + pub fn get_ref(self: Pin<&'a T>) -> &'a T { + self.pointer } } @@ -226,8 +224,8 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { /// Convert this `Pin<&mut T>` into a `Pin<&T>` with the same lifetime. #[unstable(feature = "pin", issue = "49150")] #[inline(always)] - pub fn into_ref(this: Pin<&'a mut T>) -> Pin<&'a T> { - Pin { pointer: this.pointer } + pub fn into_ref(self: Pin<&'a mut T>) -> Pin<&'a T> { + Pin { pointer: self.pointer } } /// Get a mutable reference to the data inside of this `Pin`. @@ -241,10 +239,10 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { /// with the same lifetime as the original `Pin`. #[unstable(feature = "pin", issue = "49150")] #[inline(always)] - pub fn get_mut(this: Pin<&'a mut T>) -> &'a mut T + pub fn get_mut(self: Pin<&'a mut T>) -> &'a mut T where T: Unpin, { - this.pointer + self.pointer } /// Get a mutable reference to the data inside of this `Pin`. @@ -259,8 +257,8 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { /// instead. #[unstable(feature = "pin", issue = "49150")] #[inline(always)] - pub unsafe fn get_mut_unchecked(this: Pin<&'a mut T>) -> &'a mut T { - this.pointer + pub unsafe fn get_unchecked_mut(self: Pin<&'a mut T>) -> &'a mut T { + self.pointer } /// Construct a new pin by mapping the interior value. @@ -275,10 +273,10 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { /// because it is one of the fields of that value), and also that you do /// not move out of the argument you receive to the interior function. #[unstable(feature = "pin", issue = "49150")] - pub unsafe fn map_unchecked_mut(this: Pin<&'a mut T>, func: F) -> Pin<&'a mut U> where + pub unsafe fn map_unchecked_mut(self: Pin<&'a mut T>, func: F) -> Pin<&'a mut U> where F: FnOnce(&mut T) -> &mut U, { - let pointer = Pin::get_mut_unchecked(this); + let pointer = Pin::get_unchecked_mut(self); let new_pointer = func(pointer); Pin::new_unchecked(new_pointer) } @@ -342,6 +340,3 @@ impl<'a, P, U> DispatchFromDyn> for Pin

where P: DispatchFromDyn, {} - -#[unstable(feature = "pin", issue = "49150")] -impl

Unpin for Pin

{} diff --git a/src/libcore/prelude/v1.rs b/src/libcore/prelude/v1.rs index 45f629a64424c..a1e6034b20821 100644 --- a/src/libcore/prelude/v1.rs +++ b/src/libcore/prelude/v1.rs @@ -19,7 +19,7 @@ // Re-exported core operators #[stable(feature = "core_prelude", since = "1.4.0")] #[doc(no_inline)] -pub use marker::{Copy, Send, Sized, Sync}; +pub use marker::{Copy, Send, Sized, Sync, Unpin}; #[stable(feature = "core_prelude", since = "1.4.0")] #[doc(no_inline)] pub use ops::{Drop, Fn, FnMut, FnOnce}; diff --git a/src/libstd/future.rs b/src/libstd/future.rs index d5e6cab948b8f..3379be79186ef 100644 --- a/src/libstd/future.rs +++ b/src/libstd/future.rs @@ -43,7 +43,7 @@ impl> !Unpin for GenFuture {} impl> Future for GenFuture { type Output = T::Return; fn poll(self: Pin<&mut Self>, lw: &LocalWaker) -> Poll { - set_task_waker(lw, || match unsafe { Pin::get_mut_unchecked(self).0.resume() } { + set_task_waker(lw, || match unsafe { Pin::get_unchecked_mut(self).0.resume() } { GeneratorState::Yielded(()) => Poll::Pending, GeneratorState::Complete(x) => Poll::Ready(x), }) From 610bcaf6f35b076749f5b09c2c0ec6f01f974eeb Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Mon, 17 Dec 2018 18:14:07 -0800 Subject: [PATCH 16/29] Stabilize Pin --- src/liballoc/boxed.rs | 6 +-- src/liballoc/lib.rs | 1 - src/liballoc/rc.rs | 4 +- src/liballoc/sync.rs | 4 +- src/libcore/marker.rs | 10 ++--- src/libcore/option.rs | 4 +- src/libcore/pin.rs | 40 +++++++++---------- src/libstd/lib.rs | 3 +- .../compile-fail/must_use-in-stdlib-traits.rs | 2 +- .../arbitrary_self_types_stdlib_pointers.rs | 2 +- src/test/run-pass/async-await.rs | 2 +- src/test/run-pass/futures-api.rs | 2 +- 12 files changed, 39 insertions(+), 41 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index f1581310b48fc..6a63bee2795ea 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -111,7 +111,7 @@ impl Box { box x } - #[unstable(feature = "pin", issue = "49150")] + #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub fn pinned(x: T) -> Pin> { (box x).into() @@ -446,7 +446,7 @@ impl From for Box { } } -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] impl From> for Pin> { fn from(boxed: Box) -> Self { // It's not possible to move or replace the insides of a `Pin>` @@ -813,7 +813,7 @@ impl AsMut for Box { * implementation of `Unpin` (where `T: Unpin`) would be valid/safe, and * could have a method to project a Pin from it. */ -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] impl Unpin for Box { } #[unstable(feature = "generator_trait", issue = "43122")] diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index e00e430fab6ef..368e2cc00aae1 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -100,7 +100,6 @@ #![feature(nll)] #![feature(optin_builtin_traits)] #![feature(pattern)] -#![feature(pin)] #![feature(ptr_internals)] #![feature(ptr_offset_from)] #![feature(rustc_attrs)] diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 3fc70f4ac37a1..a8574e82c270e 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -325,7 +325,7 @@ impl Rc { } } - #[unstable(feature = "pin", issue = "49150")] + #[stable(feature = "pin", since = "1.33.0")] pub fn pinned(value: T) -> Pin> { unsafe { Pin::new_unchecked(Rc::new(value)) } } @@ -1931,5 +1931,5 @@ impl AsRef for Rc { } } -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] impl Unpin for Rc { } diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 5573701660812..ac709a15aaa3c 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -303,7 +303,7 @@ impl Arc { Arc { ptr: Box::into_raw_non_null(x), phantom: PhantomData } } - #[unstable(feature = "pin", issue = "49150")] + #[stable(feature = "pin", since = "1.33.0")] pub fn pinned(data: T) -> Pin> { unsafe { Pin::new_unchecked(Arc::new(data)) } } @@ -2047,5 +2047,5 @@ impl AsRef for Arc { } } -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] impl Unpin for Arc { } diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index d3d16127ed5fe..181623f4932ee 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -637,23 +637,23 @@ unsafe impl Freeze for &mut T {} /// [`replace`]: ../../std/mem/fn.replace.html /// [`Pin`]: ../pin/struct.Pin.html /// [`pin module`]: ../../std/pin/index.html -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] pub auto trait Unpin {} /// A marker type which does not implement `Unpin`. /// /// If a type contains a `PhantomPinned`, it will not implement `Unpin` by default. -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct PhantomPinned; -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] impl !Unpin for PhantomPinned {} -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] impl<'a, T: ?Sized + 'a> Unpin for &'a T {} -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] impl<'a, T: ?Sized + 'a> Unpin for &'a mut T {} /// Implementations of `Copy` for primitive types. diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 0d7ddfc20b6d3..2f248d5276c77 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -273,7 +273,7 @@ impl Option { /// Converts from `Pin<&Option>` to `Option>` #[inline] - #[unstable(feature = "pin", issue = "49150")] + #[stable(feature = "pin", since = "1.33.0")] pub fn as_pin_ref<'a>(self: Pin<&'a Option>) -> Option> { unsafe { Pin::get_ref(self).as_ref().map(|x| Pin::new_unchecked(x)) @@ -282,7 +282,7 @@ impl Option { /// Converts from `Pin<&mut Option>` to `Option>` #[inline] - #[unstable(feature = "pin", issue = "49150")] + #[stable(feature = "pin", since = "1.33.0")] pub fn as_pin_mut<'a>(self: Pin<&'a mut Option>) -> Option> { unsafe { Pin::get_unchecked_mut(self).as_mut().map(|x| Pin::new_unchecked(x)) diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index 0436a709b31b7..b55d6a3b9bca0 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -97,7 +97,7 @@ //! // std::mem::swap(&mut *still_unmoved, &mut *new_unmoved); //! ``` -#![unstable(feature = "pin", issue = "49150")] +#![stable(feature = "pin", since = "1.33.0")] use fmt; use marker::{Sized, Unpin}; @@ -116,7 +116,7 @@ use ops::{Deref, DerefMut, Receiver, CoerceUnsized, DispatchFromDyn}; // // Note: the derives below are allowed because they all only use `&P`, so they // cannot move the value behind `pointer`. -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] #[fundamental] #[repr(transparent)] #[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)] @@ -130,7 +130,7 @@ where { /// Construct a new `Pin` around a pointer to some data of a type that /// implements `Unpin`. - #[unstable(feature = "pin", issue = "49150")] + #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub fn new(pointer: P) -> Pin

{ // Safety: the value pointed to is `Unpin`, and so has no requirements @@ -152,14 +152,14 @@ impl Pin

{ /// /// If `pointer` dereferences to an `Unpin` type, `Pin::new` should be used /// instead. - #[unstable(feature = "pin", issue = "49150")] + #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub unsafe fn new_unchecked(pointer: P) -> Pin

{ Pin { pointer } } /// Get a pinned shared reference from this pinned pointer. - #[unstable(feature = "pin", issue = "49150")] + #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub fn as_ref(self: &Pin

) -> Pin<&P::Target> { unsafe { Pin::new_unchecked(&*self.pointer) } @@ -168,14 +168,14 @@ impl Pin

{ impl Pin

{ /// Get a pinned mutable reference from this pinned pointer. - #[unstable(feature = "pin", issue = "49150")] + #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub fn as_mut(self: &mut Pin

) -> Pin<&mut P::Target> { unsafe { Pin::new_unchecked(&mut *self.pointer) } } /// Assign a new value to the memory behind the pinned reference. - #[unstable(feature = "pin", issue = "49150")] + #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub fn set(mut self: Pin

, value: P::Target) where @@ -197,7 +197,7 @@ impl<'a, T: ?Sized> Pin<&'a T> { /// will not move so long as the argument value does not move (for example, /// because it is one of the fields of that value), and also that you do /// not move out of the argument you receive to the interior function. - #[unstable(feature = "pin", issue = "49150")] + #[stable(feature = "pin", since = "1.33.0")] pub unsafe fn map_unchecked(self: Pin<&'a T>, func: F) -> Pin<&'a U> where F: FnOnce(&T) -> &U, { @@ -213,7 +213,7 @@ impl<'a, T: ?Sized> Pin<&'a T> { /// that lives for as long as the borrow of the `Pin`, not the lifetime of /// the `Pin` itself. This method allows turning the `Pin` into a reference /// with the same lifetime as the original `Pin`. - #[unstable(feature = "pin", issue = "49150")] + #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub fn get_ref(self: Pin<&'a T>) -> &'a T { self.pointer @@ -222,7 +222,7 @@ impl<'a, T: ?Sized> Pin<&'a T> { impl<'a, T: ?Sized> Pin<&'a mut T> { /// Convert this `Pin<&mut T>` into a `Pin<&T>` with the same lifetime. - #[unstable(feature = "pin", issue = "49150")] + #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub fn into_ref(self: Pin<&'a mut T>) -> Pin<&'a T> { Pin { pointer: self.pointer } @@ -237,7 +237,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { /// that lives for as long as the borrow of the `Pin`, not the lifetime of /// the `Pin` itself. This method allows turning the `Pin` into a reference /// with the same lifetime as the original `Pin`. - #[unstable(feature = "pin", issue = "49150")] + #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub fn get_mut(self: Pin<&'a mut T>) -> &'a mut T where T: Unpin, @@ -255,7 +255,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { /// /// If the underlying data is `Unpin`, `Pin::get_mut` should be used /// instead. - #[unstable(feature = "pin", issue = "49150")] + #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub unsafe fn get_unchecked_mut(self: Pin<&'a mut T>) -> &'a mut T { self.pointer @@ -272,7 +272,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { /// will not move so long as the argument value does not move (for example, /// because it is one of the fields of that value), and also that you do /// not move out of the argument you receive to the interior function. - #[unstable(feature = "pin", issue = "49150")] + #[stable(feature = "pin", since = "1.33.0")] pub unsafe fn map_unchecked_mut(self: Pin<&'a mut T>, func: F) -> Pin<&'a mut U> where F: FnOnce(&mut T) -> &mut U, { @@ -282,7 +282,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { } } -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] impl Deref for Pin

{ type Target = P::Target; fn deref(&self) -> &P::Target { @@ -290,7 +290,7 @@ impl Deref for Pin

{ } } -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] impl DerefMut for Pin

where P::Target: Unpin @@ -303,21 +303,21 @@ where #[unstable(feature = "receiver_trait", issue = "0")] impl Receiver for Pin

{} -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] impl fmt::Debug for Pin

{ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&self.pointer, f) } } -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] impl fmt::Display for Pin

{ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.pointer, f) } } -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] impl fmt::Pointer for Pin

{ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Pointer::fmt(&self.pointer, f) @@ -329,13 +329,13 @@ impl fmt::Pointer for Pin

{ // `Deref` is unsound. Any such impl would probably be unsound // for other reasons, though, so we just need to take care not to allow such // impls to land in std. -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] impl CoerceUnsized> for Pin

where P: CoerceUnsized, {} -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] impl<'a, P, U> DispatchFromDyn> for Pin

where P: DispatchFromDyn, diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 9042cb3c72d60..436cb100e0875 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -281,7 +281,6 @@ #![feature(optin_builtin_traits)] #![feature(panic_internals)] #![feature(panic_unwind)] -#![feature(pin)] #![feature(prelude_import)] #![feature(ptr_internals)] #![feature(raw)] @@ -433,7 +432,7 @@ pub use alloc_crate::borrow; pub use alloc_crate::fmt; #[stable(feature = "rust1", since = "1.0.0")] pub use alloc_crate::format; -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] pub use core::pin; #[stable(feature = "rust1", since = "1.0.0")] pub use alloc_crate::slice; diff --git a/src/test/compile-fail/must_use-in-stdlib-traits.rs b/src/test/compile-fail/must_use-in-stdlib-traits.rs index 4bb5c59722ad1..7e446fdaeaf41 100644 --- a/src/test/compile-fail/must_use-in-stdlib-traits.rs +++ b/src/test/compile-fail/must_use-in-stdlib-traits.rs @@ -1,5 +1,5 @@ #![deny(unused_must_use)] -#![feature(futures_api, pin, arbitrary_self_types)] +#![feature(arbitrary_self_types, futures_api)] use std::iter::Iterator; use std::future::Future; diff --git a/src/test/run-pass/arbitrary_self_types_stdlib_pointers.rs b/src/test/run-pass/arbitrary_self_types_stdlib_pointers.rs index 6ec70bb8c09c8..e5ee2233b766d 100644 --- a/src/test/run-pass/arbitrary_self_types_stdlib_pointers.rs +++ b/src/test/run-pass/arbitrary_self_types_stdlib_pointers.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(pin)] +#![feature(arbitrary_self_types)] #![feature(rustc_attrs)] use std::{ diff --git a/src/test/run-pass/async-await.rs b/src/test/run-pass/async-await.rs index 59da758035466..996709fa86c33 100644 --- a/src/test/run-pass/async-await.rs +++ b/src/test/run-pass/async-await.rs @@ -10,7 +10,7 @@ // edition:2018 -#![feature(arbitrary_self_types, async_await, await_macro, futures_api, pin)] +#![feature(arbitrary_self_types, async_await, await_macro, futures_api)] use std::pin::Pin; use std::future::Future; diff --git a/src/test/run-pass/futures-api.rs b/src/test/run-pass/futures-api.rs index 18865e4a07622..ac67488924993 100644 --- a/src/test/run-pass/futures-api.rs +++ b/src/test/run-pass/futures-api.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(arbitrary_self_types, futures_api, pin)] +#![feature(arbitrary_self_types, futures_api)] #![allow(unused)] use std::future::Future; From 3005bf360d11dbda5d32b9b75647df07bfa1372d Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Tue, 18 Dec 2018 10:20:53 -0800 Subject: [PATCH 17/29] Pin stabilization: fix doctests --- src/libcore/marker.rs | 1 - src/libcore/pin.rs | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 181623f4932ee..74055a4f8a9b0 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -621,7 +621,6 @@ unsafe impl Freeze for &mut T {} /// So this, for example, can only be done on types implementing `Unpin`: /// /// ```rust -/// #![feature(pin)] /// use std::mem::replace; /// use std::pin::Pin; /// diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index b55d6a3b9bca0..9073e6e31b1da 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -43,8 +43,6 @@ //! # Examples //! //! ```rust -//! #![feature(pin)] -//! //! use std::pin::Pin; //! use std::marker::PhantomPinned; //! use std::ptr::NonNull; @@ -78,7 +76,7 @@ //! // we know this is safe because modifying a field doesn't move the whole struct //! unsafe { //! let mut_ref: Pin<&mut Self> = Pin::as_mut(&mut boxed); -//! Pin::get_mut_unchecked(mut_ref).slice = slice; +//! Pin::get_unchecked_mut(mut_ref).slice = slice; //! } //! boxed //! } From 684fe9a6b2b39e6b8a1089eecd0334ef484fcc56 Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Tue, 18 Dec 2018 10:25:02 -0800 Subject: [PATCH 18/29] Rename Box/Arc/Rc::pinned to ::pin --- src/liballoc/boxed.rs | 4 +++- src/liballoc/rc.rs | 4 +++- src/liballoc/sync.rs | 4 +++- src/libcore/pin.rs | 2 +- src/test/run-pass/async-await.rs | 2 +- 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 6a63bee2795ea..7438f3e6c9df5 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -111,9 +111,11 @@ impl Box { box x } + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then + /// `x` will be pinned in memory and unable to be moved. #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] - pub fn pinned(x: T) -> Pin> { + pub fn pin(x: T) -> Pin> { (box x).into() } } diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index a8574e82c270e..14cbb204f5fa9 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -325,8 +325,10 @@ impl Rc { } } + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then + /// `value` will be pinned in memory and unable to be moved. #[stable(feature = "pin", since = "1.33.0")] - pub fn pinned(value: T) -> Pin> { + pub fn pin(value: T) -> Pin> { unsafe { Pin::new_unchecked(Rc::new(value)) } } diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index ac709a15aaa3c..c1a1e6f1591d2 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -303,8 +303,10 @@ impl Arc { Arc { ptr: Box::into_raw_non_null(x), phantom: PhantomData } } + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then + /// `data` will be pinned in memory and unable to be moved. #[stable(feature = "pin", since = "1.33.0")] - pub fn pinned(data: T) -> Pin> { + pub fn pin(data: T) -> Pin> { unsafe { Pin::new_unchecked(Arc::new(data)) } } diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index 9073e6e31b1da..4f4ca4047e460 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -70,7 +70,7 @@ //! slice: NonNull::dangling(), //! _pin: PhantomPinned, //! }; -//! let mut boxed = Box::pinned(res); +//! let mut boxed = Box::pin(res); //! //! let slice = NonNull::from(&boxed.data); //! // we know this is safe because modifying a field doesn't move the whole struct diff --git a/src/test/run-pass/async-await.rs b/src/test/run-pass/async-await.rs index 996709fa86c33..d9eb801a20668 100644 --- a/src/test/run-pass/async-await.rs +++ b/src/test/run-pass/async-await.rs @@ -138,7 +138,7 @@ where F: FnOnce(u8) -> Fut, Fut: Future, { - let mut fut = Box::pinned(f(9)); + let mut fut = Box::pin(f(9)); let counter = Arc::new(Counter { wakes: AtomicUsize::new(0) }); let waker = local_waker_from_nonlocal(counter.clone()); assert_eq!(0, counter.wakes.load(atomic::Ordering::SeqCst)); From 861df06e077bb17c2d22ab978e37ee2c5350ff9b Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Tue, 18 Dec 2018 14:23:24 -0800 Subject: [PATCH 19/29] Fix Unpin docs link --- src/libcore/pin.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index 4f4ca4047e460..d8508631bf9c3 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -36,7 +36,7 @@ //! are always freely movable, even if the data they point to isn't. //! //! [`Pin`]: struct.Pin.html -//! [`Unpin`]: trait.Unpin.html +//! [`Unpin`]: ../../std/marker/trait.Unpin.html //! [`swap`]: ../../std/mem/fn.swap.html //! [`Box`]: ../../std/boxed/struct.Box.html //! From 6dd0d2d9bbc021fad2ca41ee4401306863af914c Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 22 Dec 2018 14:39:45 +0100 Subject: [PATCH 20/29] Fix a comment --- src/librustc_mir/monomorphize/collector.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index a6239a8115a36..8ab9cb42b8243 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -139,7 +139,7 @@ //! //! #### Boxes //! Since `Box` expression have special compiler support, no explicit calls to -//! `exchange_malloc()` and `exchange_free()` may show up in MIR, even if the +//! `exchange_malloc()` and `box_free()` may show up in MIR, even if the //! compiler will generate them. We have to observe `Rvalue::Box` expressions //! and Box-typed drop-statements for that purpose. //! From 3986c964481a048100565c8d30b1937ec2eb516d Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Sun, 18 Nov 2018 22:21:38 -0800 Subject: [PATCH 21/29] enum type instead of variant suggestion unification MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Weirdly, we were deciding between a help note and a structured suggestion based on whether the import candidate span was a dummy—but we weren't using that span in any case! The dummy-ness of the span (which appears to be a matter of this-crate vs. other-crate definition) isn't the right criterion by which we should decide whether it's germane to mention that "there is an enum variant"; instead, let's use the someness of `def` (which is used as the `has_unexpected_resolution` argument to `error_code`). Since `import_candidate_to_paths` has no other callers, we are free to stop returning the span and rename the function. By using `span_suggestions_`, we leverage the max-suggestions output limit already built in to the emitter, thus resolving #56028. In the matter of message wording, "you can" is redundant (and perhaps too informal); prefer the imperative. --- src/librustc_resolve/lib.rs | 46 +++++++++++-------- .../issue-56028-there-is-an-enum-variant.rs | 13 ++++++ ...ssue-56028-there-is-an-enum-variant.stderr | 38 +++++++++++++++ src/test/ui/enum/enum-variant-type-2.stderr | 2 +- src/test/ui/issues/issue-17546.stderr | 4 +- src/test/ui/issues/issue-30535.stderr | 7 +-- src/test/ui/issues/issue-35075.stderr | 18 ++++---- src/test/ui/issues/issue-35675.stderr | 32 ++++++++----- .../ui/variants/variant-used-as-type.stderr | 16 +++---- 9 files changed, 122 insertions(+), 54 deletions(-) create mode 100644 src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.rs create mode 100644 src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 794e5741d62ca..8f329283b1a28 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -3213,23 +3213,33 @@ impl<'a> Resolver<'a> { let enum_candidates = this.lookup_import_candidates(ident, ns, is_enum_variant); let mut enum_candidates = enum_candidates.iter() - .map(|suggestion| import_candidate_to_paths(&suggestion)).collect::>(); + .map(|suggestion| { + import_candidate_to_enum_paths(&suggestion) + }).collect::>(); enum_candidates.sort(); - for (sp, variant_path, enum_path) in enum_candidates { - if sp.is_dummy() { - let msg = format!("there is an enum variant `{}`, \ - try using `{}`?", - variant_path, - enum_path); - err.help(&msg); + + if !enum_candidates.is_empty() { + // contextualize for E0412 "cannot find type", but don't belabor the point + // (that it's a variant) for E0573 "expected type, found variant" + let preamble = if def.is_none() { + let others = match enum_candidates.len() { + 1 => String::new(), + 2 => " and 1 other".to_owned(), + n => format!(" and {} others", n) + }; + format!("there is an enum variant `{}`{}; ", + enum_candidates[0].0, others) } else { - err.span_suggestion_with_applicability( - span, - "you can try using the variant's enum", - enum_path, - Applicability::MachineApplicable, - ); - } + String::new() + }; + let msg = format!("{}try using the variant's enum", preamble); + + err.span_suggestions_with_applicability( + span, + &msg, + enum_candidates.into_iter().map(|(_variant, enum_ty)| enum_ty), + Applicability::MachineApplicable, + ); } } if path.len() == 1 && this.self_type_is_available(span) { @@ -5128,8 +5138,8 @@ fn path_names_to_string(path: &Path) -> String { .collect::>()) } -/// Get the path for an enum and the variant from an `ImportSuggestion` for an enum variant. -fn import_candidate_to_paths(suggestion: &ImportSuggestion) -> (Span, String, String) { +/// Get the stringified path for an enum from an `ImportSuggestion` for an enum variant. +fn import_candidate_to_enum_paths(suggestion: &ImportSuggestion) -> (String, String) { let variant_path = &suggestion.path; let variant_path_string = path_names_to_string(variant_path); @@ -5140,7 +5150,7 @@ fn import_candidate_to_paths(suggestion: &ImportSuggestion) -> (Span, String, St }; let enum_path_string = path_names_to_string(&enum_path); - (suggestion.path.span, variant_path_string, enum_path_string) + (variant_path_string, enum_path_string) } diff --git a/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.rs b/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.rs new file mode 100644 index 0000000000000..ec41c41141616 --- /dev/null +++ b/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.rs @@ -0,0 +1,13 @@ +enum PutDown { Set } +enum AffixHeart { Set } +enum CauseToBe { Set } +enum Determine { Set } +enum TableDishesAction { Set } +enum Solidify { Set } +enum UnorderedCollection { Set } + +fn setup() -> Set { Set } + +fn main() { + setup(); +} diff --git a/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr b/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr new file mode 100644 index 0000000000000..6107ca32a5d75 --- /dev/null +++ b/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr @@ -0,0 +1,38 @@ +error[E0412]: cannot find type `Set` in this scope + --> $DIR/issue-56028-there-is-an-enum-variant.rs:9:15 + | +LL | fn setup() -> Set { Set } + | ^^^ not found in this scope +help: there is an enum variant `AffixHeart::Set` and 7 others; try using the variant's enum + | +LL | fn setup() -> AffixHeart { Set } + | ^^^^^^^^^^ +LL | fn setup() -> CauseToBe { Set } + | ^^^^^^^^^ +LL | fn setup() -> Determine { Set } + | ^^^^^^^^^ +LL | fn setup() -> PutDown { Set } + | ^^^^^^^ +and 3 other candidates + +error[E0425]: cannot find value `Set` in this scope + --> $DIR/issue-56028-there-is-an-enum-variant.rs:9:21 + | +LL | fn setup() -> Set { Set } + | ^^^ not found in this scope +help: possible candidates are found in other modules, you can import them into scope + | +LL | use AffixHeart::Set; + | +LL | use CauseToBe::Set; + | +LL | use Determine::Set; + | +LL | use PutDown::Set; + | +and 3 other candidates + +error: aborting due to 2 previous errors + +Some errors occurred: E0412, E0425. +For more information about an error, try `rustc --explain E0412`. diff --git a/src/test/ui/enum/enum-variant-type-2.stderr b/src/test/ui/enum/enum-variant-type-2.stderr index 7a786af71bb3f..eb869f5539f36 100644 --- a/src/test/ui/enum/enum-variant-type-2.stderr +++ b/src/test/ui/enum/enum-variant-type-2.stderr @@ -5,7 +5,7 @@ LL | fn foo(x: Foo::Bar) {} //~ ERROR expected type, found variant `Foo::Bar` | ^^^^^^^^ | | | not a type - | help: you can try using the variant's enum: `Foo` + | help: try using the variant's enum: `Foo` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-17546.stderr b/src/test/ui/issues/issue-17546.stderr index 39f7d5fcc04bc..a8ab5e8eb7745 100644 --- a/src/test/ui/issues/issue-17546.stderr +++ b/src/test/ui/issues/issue-17546.stderr @@ -5,7 +5,7 @@ LL | fn new() -> NoResult { | --------^^^^^^^^^^^^^^^^ | | | did you mean `Result`? - | help: you can try using the variant's enum: `foo::MyEnum` + | help: try using the variant's enum: `foo::MyEnum` error[E0573]: expected type, found variant `Result` --> $DIR/issue-17546.rs:32:17 @@ -48,7 +48,7 @@ LL | fn newer() -> NoResult { | --------^^^^^^^^^^^^^^^^^^^^^ | | | did you mean `Result`? - | help: you can try using the variant's enum: `foo::MyEnum` + | help: try using the variant's enum: `foo::MyEnum` error: aborting due to 4 previous errors diff --git a/src/test/ui/issues/issue-30535.stderr b/src/test/ui/issues/issue-30535.stderr index c3838fdb9cf07..35ef227acfce6 100644 --- a/src/test/ui/issues/issue-30535.stderr +++ b/src/test/ui/issues/issue-30535.stderr @@ -2,9 +2,10 @@ error[E0573]: expected type, found variant `foo::Foo::FooV` --> $DIR/issue-30535.rs:16:8 | LL | _: foo::Foo::FooV //~ ERROR expected type, found variant `foo::Foo::FooV` - | ^^^^^^^^^^^^^^ not a type - | - = help: there is an enum variant `foo::Foo::FooV`, try using `foo::Foo`? + | ^^^^^^^^^^^^^^ + | | + | not a type + | help: try using the variant's enum: `foo::Foo` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-35075.stderr b/src/test/ui/issues/issue-35075.stderr index 9b2f17f038b8f..ead07a5f0c8fe 100644 --- a/src/test/ui/issues/issue-35075.stderr +++ b/src/test/ui/issues/issue-35075.stderr @@ -2,19 +2,21 @@ error[E0412]: cannot find type `Foo` in this scope --> $DIR/issue-35075.rs:12:12 | LL | inner: Foo //~ ERROR cannot find type `Foo` in this scope - | ^^^--- - | | - | not found in this scope - | help: you can try using the variant's enum: `Baz` + | ^^^ not found in this scope +help: there is an enum variant `Baz::Foo`; try using the variant's enum + | +LL | inner: Baz //~ ERROR cannot find type `Foo` in this scope + | ^^^ error[E0412]: cannot find type `Foo` in this scope --> $DIR/issue-35075.rs:16:9 | LL | Foo(Foo) //~ ERROR cannot find type `Foo` in this scope - | ^^^--- - | | - | not found in this scope - | help: you can try using the variant's enum: `Baz` + | ^^^ not found in this scope +help: there is an enum variant `Baz::Foo`; try using the variant's enum + | +LL | Foo(Baz) //~ ERROR cannot find type `Foo` in this scope + | ^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-35675.stderr b/src/test/ui/issues/issue-35675.stderr index fef8de3a28d9e..2f07ee7124d07 100644 --- a/src/test/ui/issues/issue-35675.stderr +++ b/src/test/ui/issues/issue-35675.stderr @@ -2,10 +2,11 @@ error[E0412]: cannot find type `Apple` in this scope --> $DIR/issue-35675.rs:17:29 | LL | fn should_return_fruit() -> Apple { + | ^^^^^ not found in this scope +help: there is an enum variant `Fruit::Apple`; try using the variant's enum + | +LL | fn should_return_fruit() -> Fruit { | ^^^^^ - | | - | not found in this scope - | help: you can try using the variant's enum: `Fruit` error[E0425]: cannot find function `Apple` in this scope --> $DIR/issue-35675.rs:19:5 @@ -24,7 +25,7 @@ LL | fn should_return_fruit_too() -> Fruit::Apple { | ^^^^^^^^^^^^ | | | not a type - | help: you can try using the variant's enum: `Fruit` + | help: try using the variant's enum: `Fruit` error[E0425]: cannot find function `Apple` in this scope --> $DIR/issue-35675.rs:25:5 @@ -41,27 +42,34 @@ error[E0573]: expected type, found variant `Ok` | LL | fn foo() -> Ok { | ^^ not a type +help: try using the variant's enum | - = help: there is an enum variant `std::prelude::v1::Ok`, try using `std::prelude::v1`? - = help: there is an enum variant `std::result::Result::Ok`, try using `std::result::Result`? +LL | fn foo() -> std::prelude::v1 { + | ^^^^^^^^^^^^^^^^ +LL | fn foo() -> std::result::Result { + | ^^^^^^^^^^^^^^^^^^^ error[E0412]: cannot find type `Variant3` in this scope --> $DIR/issue-35675.rs:34:13 | LL | fn bar() -> Variant3 { - | ^^^^^^^^ - | | - | not found in this scope - | help: you can try using the variant's enum: `x::Enum` + | ^^^^^^^^ not found in this scope +help: there is an enum variant `x::Enum::Variant3`; try using the variant's enum + | +LL | fn bar() -> x::Enum { + | ^^^^^^^ error[E0573]: expected type, found variant `Some` --> $DIR/issue-35675.rs:38:13 | LL | fn qux() -> Some { | ^^^^ not a type +help: try using the variant's enum | - = help: there is an enum variant `std::prelude::v1::Option::Some`, try using `std::prelude::v1::Option`? - = help: there is an enum variant `std::prelude::v1::Some`, try using `std::prelude::v1`? +LL | fn qux() -> std::prelude::v1::Option { + | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn qux() -> std::prelude::v1 { + | ^^^^^^^^^^^^^^^^ error: aborting due to 7 previous errors diff --git a/src/test/ui/variants/variant-used-as-type.stderr b/src/test/ui/variants/variant-used-as-type.stderr index 972fe8a8a616b..c72729923ef6d 100644 --- a/src/test/ui/variants/variant-used-as-type.stderr +++ b/src/test/ui/variants/variant-used-as-type.stderr @@ -3,28 +3,24 @@ error[E0573]: expected type, found variant `Ty::A` | LL | B(Ty::A), | ^^^^^ not a type -help: you can try using the variant's enum - | -LL | B(Ty), - | ^^ -help: you can try using the variant's enum +help: try using the variant's enum | LL | B(E), | ^ +LL | B(Ty), + | ^^ error[E0573]: expected type, found variant `E::A` --> $DIR/variant-used-as-type.rs:27:6 | LL | impl E::A {} | ^^^^ not a type -help: you can try using the variant's enum - | -LL | impl Ty {} - | ^^ -help: you can try using the variant's enum +help: try using the variant's enum | LL | impl E {} | ^ +LL | impl Ty {} + | ^^ error: aborting due to 2 previous errors From 64ad3e2c423f701b856a6780380a0dbb03f90c22 Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Fri, 23 Nov 2018 12:57:03 -0800 Subject: [PATCH 22/29] adjust enum type instead of variant suggestions for prelude enums The present author regrets not thinking of a more eloquent way to do this. --- src/librustc_resolve/lib.rs | 12 +++++++++- src/librustc_typeck/check/demand.rs | 1 + .../issue-56028-there-is-an-enum-variant.rs | 2 ++ src/test/ui/issues/issue-35675.stderr | 22 +++++++------------ 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 8f329283b1a28..e543677ef0621 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -3237,7 +3237,17 @@ impl<'a> Resolver<'a> { err.span_suggestions_with_applicability( span, &msg, - enum_candidates.into_iter().map(|(_variant, enum_ty)| enum_ty), + enum_candidates.into_iter() + .map(|(_variant_path, enum_ty_path)| enum_ty_path) + // variants reëxported in prelude doesn't mean `prelude::v1` is the + // type name! FIXME: is there a more principled way to do this that + // would work for other reëxports? + .filter(|enum_ty_path| enum_ty_path != "std::prelude::v1") + // also say `Option` rather than `std::prelude::v1::Option` + .map(|enum_ty_path| { + // FIXME #56861: DRYer prelude filtering + enum_ty_path.trim_start_matches("std::prelude::v1::").to_owned() + }), Applicability::MachineApplicable, ); } diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index db4b68611c51b..996b57f558cc5 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -123,6 +123,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let sole_field_ty = sole_field.ty(self.tcx, substs); if self.can_coerce(expr_ty, sole_field_ty) { let variant_path = self.tcx.item_path_str(variant.did); + // FIXME #56861: DRYer prelude filtering Some(variant_path.trim_start_matches("std::prelude::v1::").to_string()) } else { None diff --git a/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.rs b/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.rs index ec41c41141616..264cfa449942c 100644 --- a/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.rs +++ b/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.rs @@ -7,6 +7,8 @@ enum Solidify { Set } enum UnorderedCollection { Set } fn setup() -> Set { Set } +//~^ ERROR cannot find type `Set` in this scope +//~| ERROR cannot find value `Set` in this scope fn main() { setup(); diff --git a/src/test/ui/issues/issue-35675.stderr b/src/test/ui/issues/issue-35675.stderr index 2f07ee7124d07..652e1695a85a6 100644 --- a/src/test/ui/issues/issue-35675.stderr +++ b/src/test/ui/issues/issue-35675.stderr @@ -41,13 +41,10 @@ error[E0573]: expected type, found variant `Ok` --> $DIR/issue-35675.rs:29:13 | LL | fn foo() -> Ok { - | ^^ not a type -help: try using the variant's enum - | -LL | fn foo() -> std::prelude::v1 { - | ^^^^^^^^^^^^^^^^ -LL | fn foo() -> std::result::Result { - | ^^^^^^^^^^^^^^^^^^^ + | ^^ + | | + | not a type + | help: try using the variant's enum: `std::result::Result` error[E0412]: cannot find type `Variant3` in this scope --> $DIR/issue-35675.rs:34:13 @@ -63,13 +60,10 @@ error[E0573]: expected type, found variant `Some` --> $DIR/issue-35675.rs:38:13 | LL | fn qux() -> Some { - | ^^^^ not a type -help: try using the variant's enum - | -LL | fn qux() -> std::prelude::v1::Option { - | ^^^^^^^^^^^^^^^^^^^^^^^^ -LL | fn qux() -> std::prelude::v1 { - | ^^^^^^^^^^^^^^^^ + | ^^^^ + | | + | not a type + | help: try using the variant's enum: `Option` error: aborting due to 7 previous errors From 2820dc868a35c02adb9225492d575c7d5e72338c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 22 Dec 2018 19:20:13 -0800 Subject: [PATCH 23/29] Remove dead code --- src/librustc_typeck/check/coercion.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index c7adf2982272c..58cbb0ea538f1 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -1183,11 +1183,7 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E> (self.final_ty.unwrap_or(self.expected_ty), expression_ty) }; - let reason_label = if label_expression_as_expected { - "found because of this statement" - } else { - "expected because of this statement" - }; + let reason_label = "expected because of this statement"; let mut db; match cause.code { ObligationCauseCode::ReturnNoExpression => { From b42a3acaeca0f14df7d35b87d0045b4d58c95b55 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 22 Dec 2018 18:06:20 +0100 Subject: [PATCH 24/29] stabilize min_const_unsafe_fn in 1.33. --- src/librustc/ich/impls_mir.rs | 1 - src/librustc/mir/mod.rs | 3 - src/librustc_mir/transform/check_unsafety.rs | 29 +-------- src/libstd/lib.rs | 1 - src/libsyntax/feature_gate.rs | 5 +- src/test/run-pass-fulldeps/newtype_index.rs | 2 +- src/test/rustdoc/const-display.rs | 1 - .../min_const_fn/min_const_fn_unsafe.rs | 51 +++++++++++++--- .../min_const_fn/min_const_fn_unsafe.stderr | 49 +++++++-------- .../min_const_fn_unsafe_feature_gate.rs | 61 ------------------- .../min_const_fn_unsafe_feature_gate.stderr | 44 ------------- .../min_const_unsafe_fn_libstd_stability.rs | 1 - .../min_const_unsafe_fn_libstd_stability2.rs | 1 - 13 files changed, 72 insertions(+), 177 deletions(-) delete mode 100644 src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.rs delete mode 100644 src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.stderr diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs index d82020f59a10e..6852e2c69618b 100644 --- a/src/librustc/ich/impls_mir.rs +++ b/src/librustc/ich/impls_mir.rs @@ -47,7 +47,6 @@ impl_stable_hash_for!(enum mir::BorrowKind { impl_stable_hash_for!(enum mir::UnsafetyViolationKind { General, GeneralAndConstFn, - GatedConstFnCall, ExternStatic(lint_node_id), BorrowPacked(lint_node_id), }); diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index dc14450e8d22d..120350a573b6e 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2792,9 +2792,6 @@ impl Location { #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub enum UnsafetyViolationKind { General, - /// Right now function calls to `const unsafe fn` are only permitted behind a feature gate - /// Also, even `const unsafe fn` need an `unsafe` block to do the allowed operations. - GatedConstFnCall, /// Permitted in const fn and regular fns GeneralAndConstFn, ExternStatic(ast::NodeId), diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index f6b7f817aad53..89d9c03f74e3e 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -23,7 +23,6 @@ use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext}; use syntax::ast; use syntax::symbol::Symbol; -use syntax::feature_gate::{emit_feature_err, GateIssue}; use std::ops::Bound; @@ -97,7 +96,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { if let hir::Unsafety::Unsafe = sig.unsafety() { self.require_unsafe("call to unsafe function", "consult the function's documentation for information on how to avoid \ - undefined behavior", UnsafetyViolationKind::GatedConstFnCall) + undefined behavior", UnsafetyViolationKind::GeneralAndConstFn) } } } @@ -325,11 +324,6 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { // compat lint violation.kind = UnsafetyViolationKind::General; }, - UnsafetyViolationKind::GatedConstFnCall => { - // safe code can't call unsafe const fns, this `UnsafetyViolationKind` - // is only relevant for `Safety::ExplicitUnsafe` in `unsafe const fn`s - violation.kind = UnsafetyViolationKind::General; - } } if !self.violations.contains(&violation) { self.violations.push(violation) @@ -346,19 +340,8 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { } // only some unsafety is allowed in const fn if self.min_const_fn { - let min_const_unsafe_fn = self.tcx.features().min_const_unsafe_fn; for violation in violations { match violation.kind { - UnsafetyViolationKind::GatedConstFnCall if min_const_unsafe_fn => { - // these function calls to unsafe functions are allowed - // if `#![feature(min_const_unsafe_fn)]` is active - }, - UnsafetyViolationKind::GatedConstFnCall => { - // without the feature gate, we report errors - if !self.violations.contains(&violation) { - self.violations.push(violation.clone()) - } - } // these unsafe things are stable in const fn UnsafetyViolationKind::GeneralAndConstFn => {}, // these things are forbidden in const fns @@ -620,16 +603,6 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { .note(&details.as_str()[..]) .emit(); } - UnsafetyViolationKind::GatedConstFnCall => { - emit_feature_err( - &tcx.sess.parse_sess, - "min_const_unsafe_fn", - source_info.span, - GateIssue::Language, - "calls to `const unsafe fn` in const fns are unstable", - ); - - } UnsafetyViolationKind::ExternStatic(lint_node_id) => { tcx.lint_node_note(SAFE_EXTERN_STATICS, lint_node_id, diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 0d3de34fe6438..99a682832286e 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -273,7 +273,6 @@ #![feature(libc)] #![feature(link_args)] #![feature(linkage)] -#![cfg_attr(not(stage0), feature(min_const_unsafe_fn))] #![feature(needs_panic_runtime)] #![feature(never_type)] #![feature(nll)] diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 941a3a288da5c..2238e429a58e0 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -486,9 +486,6 @@ declare_features! ( // `extern crate self as foo;` puts local crate root into extern prelude under name `foo`. (active, extern_crate_self, "1.31.0", Some(56409), None), - - // Allows calling `const unsafe fn` inside `unsafe` blocks in `const fn` functions. - (active, min_const_unsafe_fn, "1.31.0", Some(55607), None), ); declare_features! ( @@ -694,6 +691,8 @@ declare_features! ( (accepted, underscore_imports, "1.33.0", Some(48216), None), // Allows `#[repr(packed(N))]` attribute on structs. (accepted, repr_packed, "1.33.0", Some(33158), None), + // Allows calling `const unsafe fn` inside `unsafe` blocks in `const fn` functions. + (accepted, min_const_unsafe_fn, "1.33.0", Some(55607), None), ); // If you change this, please modify `src/doc/unstable-book` as well. You must diff --git a/src/test/run-pass-fulldeps/newtype_index.rs b/src/test/run-pass-fulldeps/newtype_index.rs index 0fd7ccd55fb2d..3cd622a33b173 100644 --- a/src/test/run-pass-fulldeps/newtype_index.rs +++ b/src/test/run-pass-fulldeps/newtype_index.rs @@ -1,4 +1,4 @@ -#![feature(rustc_attrs, rustc_private, step_trait, min_const_unsafe_fn)] +#![feature(rustc_attrs, rustc_private, step_trait)] #[macro_use] extern crate rustc_data_structures; extern crate rustc_serialize; diff --git a/src/test/rustdoc/const-display.rs b/src/test/rustdoc/const-display.rs index 8ac0d07ceefe4..f38fab91de7c4 100644 --- a/src/test/rustdoc/const-display.rs +++ b/src/test/rustdoc/const-display.rs @@ -15,7 +15,6 @@ issue = "0")] #![feature(rustc_const_unstable, const_fn, foo, foo2)] -#![feature(min_const_unsafe_fn)] #![feature(staged_api)] // @has 'foo/fn.foo.html' '//pre' 'pub unsafe fn foo() -> u32' diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs index 92e99c6228a9b..da875fe7a6b77 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs +++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs @@ -8,27 +8,62 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// gate-test-min_const_unsafe_fn +//------------------------------------------------------------------------------ +// OK +//------------------------------------------------------------------------------ -// ok const unsafe fn ret_i32_no_unsafe() -> i32 { 42 } const unsafe fn ret_null_ptr_no_unsafe() -> *const T { 0 as *const T } const unsafe fn ret_null_mut_ptr_no_unsafe() -> *mut T { 0 as *mut T } const fn no_unsafe() { unsafe {} } -// not ok const fn call_unsafe_const_fn() -> i32 { - unsafe { ret_i32_no_unsafe() } //~ ERROR calls to `const unsafe fn` in const fns are unstable + unsafe { ret_i32_no_unsafe() } } const fn call_unsafe_generic_const_fn() -> *const String { unsafe { ret_null_ptr_no_unsafe::() } - //~^ ERROR calls to `const unsafe fn` in const fns are unstable } -const fn call_unsafe_generic_cell_const_fn() -> *const Vec> { +const fn call_unsafe_generic_cell_const_fn() + -> *const Vec> +{ unsafe { ret_null_mut_ptr_no_unsafe::>>() } - //~^ ERROR calls to `const unsafe fn` in const fns } -const unsafe fn deref_forbidden(x: *mut usize) -> usize { *x } + +const unsafe fn call_unsafe_const_unsafe_fn() -> i32 { + unsafe { ret_i32_no_unsafe() } +} +const unsafe fn call_unsafe_generic_const_unsafe_fn() -> *const String { + unsafe { ret_null_ptr_no_unsafe::() } +} +const unsafe fn call_unsafe_generic_cell_const_unsafe_fn() + -> *const Vec> +{ + unsafe { ret_null_mut_ptr_no_unsafe::>>() } +} + +const unsafe fn call_unsafe_const_unsafe_fn_immediate() -> i32 { + ret_i32_no_unsafe() +} +const unsafe fn call_unsafe_generic_const_unsafe_fn_immediate() -> *const String { + ret_null_ptr_no_unsafe::() +} +const unsafe fn call_unsafe_generic_cell_const_unsafe_fn_immediate() + -> *const Vec> +{ + ret_null_mut_ptr_no_unsafe::>>() +} + +//------------------------------------------------------------------------------ +// NOT OK +//------------------------------------------------------------------------------ + +const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe +//~^ dereferencing raw pointers in constant functions + +const unsafe fn bad_const_unsafe_deref_raw(x: *mut usize) -> usize { *x } +//~^ dereferencing raw pointers in constant functions + +const unsafe fn bad_const_unsafe_deref_raw_ref(x: *mut usize) -> &'static usize { &*x } //~^ dereferencing raw pointers in constant functions fn main() {} diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr index fafc89d149368..1ce23bc21bb3e 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr @@ -1,43 +1,44 @@ error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911) - --> $DIR/min_const_fn_unsafe.rs:31:59 + --> $DIR/min_const_fn_unsafe.rs:54:77 | -LL | const unsafe fn deref_forbidden(x: *mut usize) -> usize { *x } - | ^^ +LL | const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe + | ^^^ | = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable -error[E0658]: unions in const fn are unstable (see issue #51909) - --> $DIR/min_const_fn_unsafe.rs:38:5 +error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911) + --> $DIR/min_const_fn_unsafe.rs:57:70 | -LL | Foo { x: () }.y - | ^^^^^^^^^^^^^^^ +LL | const unsafe fn bad_const_unsafe_deref_raw(x: *mut usize) -> usize { *x } + | ^^ | - = help: add #![feature(const_fn_union)] to the crate attributes to enable + = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable -error[E0658]: calls to `const unsafe fn` in const fns are unstable (see issue #55607) - --> $DIR/min_const_fn_unsafe.rs:21:14 +error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911) + --> $DIR/min_const_fn_unsafe.rs:60:83 | -LL | unsafe { ret_i32_no_unsafe() } //~ ERROR calls to `const unsafe fn` in const fns are unstable - | ^^^^^^^^^^^^^^^^^^^ +LL | const unsafe fn bad_const_unsafe_deref_raw_ref(x: *mut usize) -> &'static usize { &*x } + | ^^^ | - = help: add #![feature(min_const_unsafe_fn)] to the crate attributes to enable + = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable -error[E0658]: calls to `const unsafe fn` in const fns are unstable (see issue #55607) - --> $DIR/min_const_fn_unsafe.rs:24:14 +error[E0658]: unions in const fn are unstable (see issue #51909) + --> $DIR/min_const_fn_unsafe.rs:67:5 | -LL | unsafe { ret_null_ptr_no_unsafe::() } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | Foo { x: () }.y + | ^^^^^^^^^^^^^^^ | - = help: add #![feature(min_const_unsafe_fn)] to the crate attributes to enable + = help: add #![feature(const_fn_union)] to the crate attributes to enable -error[E0658]: calls to `const unsafe fn` in const fns are unstable (see issue #55607) - --> $DIR/min_const_fn_unsafe.rs:28:14 +error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block + --> $DIR/min_const_fn_unsafe.rs:54:77 | -LL | unsafe { ret_null_mut_ptr_no_unsafe::>>() } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe + | ^^^ dereference of raw pointer | - = help: add #![feature(min_const_unsafe_fn)] to the crate attributes to enable + = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors occurred: E0133, E0658. +For more information about an error, try `rustc --explain E0133`. diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.rs b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.rs deleted file mode 100644 index 67a4820612642..0000000000000 --- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.rs +++ /dev/null @@ -1,61 +0,0 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![feature(min_const_unsafe_fn)] - -// ok -const unsafe fn foo4() -> i32 { 42 } -const unsafe fn foo5() -> *const T { 0 as *const T } -const unsafe fn foo6() -> *mut T { 0 as *mut T } -const fn no_unsafe() { unsafe {} } - -const fn foo8() -> i32 { - unsafe { foo4() } -} -const fn foo9() -> *const String { - unsafe { foo5::() } -} -const fn foo10() -> *const Vec> { - unsafe { foo6::>>() } -} -const unsafe fn foo8_3() -> i32 { - unsafe { foo4() } -} -const unsafe fn foo9_3() -> *const String { - unsafe { foo5::() } -} -const unsafe fn foo10_3() -> *const Vec> { - unsafe { foo6::>>() } -} -const unsafe fn foo8_2() -> i32 { - foo4() -} -const unsafe fn foo9_2() -> *const String { - foo5::() -} -const unsafe fn foo10_2() -> *const Vec> { - foo6::>>() -} -const unsafe fn foo30_3(x: *mut usize) -> usize { *x } -//~^ dereferencing raw pointers in constant functions - -const unsafe fn foo30_4(x: *mut usize) -> &'static usize { &*x } -//~^ dereferencing raw pointers in constant functions - -const fn foo30_5(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe -//~^ dereferencing raw pointers in constant functions - -fn main() {} - -const unsafe fn no_union() { - union Foo { x: (), y: () } - Foo { x: () }.y - //~^ unions in const fn -} diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.stderr deleted file mode 100644 index 63bf9a53e509c..0000000000000 --- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.stderr +++ /dev/null @@ -1,44 +0,0 @@ -error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911) - --> $DIR/min_const_fn_unsafe_feature_gate.rs:46:51 - | -LL | const unsafe fn foo30_3(x: *mut usize) -> usize { *x } - | ^^ - | - = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable - -error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911) - --> $DIR/min_const_fn_unsafe_feature_gate.rs:49:60 - | -LL | const unsafe fn foo30_4(x: *mut usize) -> &'static usize { &*x } - | ^^^ - | - = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable - -error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911) - --> $DIR/min_const_fn_unsafe_feature_gate.rs:52:62 - | -LL | const fn foo30_5(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe - | ^^^ - | - = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable - -error[E0658]: unions in const fn are unstable (see issue #51909) - --> $DIR/min_const_fn_unsafe_feature_gate.rs:59:5 - | -LL | Foo { x: () }.y - | ^^^^^^^^^^^^^^^ - | - = help: add #![feature(const_fn_union)] to the crate attributes to enable - -error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block - --> $DIR/min_const_fn_unsafe_feature_gate.rs:52:62 - | -LL | const fn foo30_5(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe - | ^^^ dereference of raw pointer - | - = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior - -error: aborting due to 5 previous errors - -Some errors occurred: E0133, E0658. -For more information about an error, try `rustc --explain E0133`. diff --git a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs index f559c23ff0f54..33fcea9818959 100644 --- a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs +++ b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs @@ -14,7 +14,6 @@ issue = "0")] #![feature(rustc_const_unstable, const_fn, foo, foo2)] -#![feature(min_const_unsafe_fn)] #![feature(staged_api)] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs index 131bc97c85a2a..68205edd63bc9 100644 --- a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs +++ b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs @@ -14,7 +14,6 @@ issue = "0")] #![feature(rustc_const_unstable, const_fn, foo, foo2)] -#![feature(min_const_unsafe_fn)] #![feature(staged_api)] #[stable(feature = "rust1", since = "1.0.0")] From bd1d5bc629ef43eb1574c0904b024bc0f9666616 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 22 Dec 2018 18:58:06 +0100 Subject: [PATCH 25/29] stabilize min_const_unsafe_fn --bless tests. --- src/test/ui/consts/const-size_of-cycle.stderr | 4 ---- .../ui/consts/min_const_fn/min_const_fn_unsafe.stderr | 10 +++++----- .../min_const_unsafe_fn_libstd_stability.stderr | 8 ++++---- .../min_const_unsafe_fn_libstd_stability2.stderr | 6 +++--- 4 files changed, 12 insertions(+), 16 deletions(-) diff --git a/src/test/ui/consts/const-size_of-cycle.stderr b/src/test/ui/consts/const-size_of-cycle.stderr index e824657f8afda..68f81f408f70a 100644 --- a/src/test/ui/consts/const-size_of-cycle.stderr +++ b/src/test/ui/consts/const-size_of-cycle.stderr @@ -5,10 +5,6 @@ LL | bytes: [u8; std::mem::size_of::()] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: ...which requires const-evaluating `Foo::bytes::{{constant}}`... - --> $SRC_DIR/libcore/mem.rs:LL:COL - | -LL | intrinsics::size_of::() - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires computing layout of `Foo`... note: ...which requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All }, value: [u8; _] }`... note: ...which requires const-evaluating + checking `Foo::bytes::{{constant}}`... diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr index 1ce23bc21bb3e..68b782bf0e7ea 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr @@ -1,5 +1,5 @@ error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911) - --> $DIR/min_const_fn_unsafe.rs:54:77 + --> $DIR/min_const_fn_unsafe.rs:60:77 | LL | const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe | ^^^ @@ -7,7 +7,7 @@ LL | const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911) - --> $DIR/min_const_fn_unsafe.rs:57:70 + --> $DIR/min_const_fn_unsafe.rs:63:70 | LL | const unsafe fn bad_const_unsafe_deref_raw(x: *mut usize) -> usize { *x } | ^^ @@ -15,7 +15,7 @@ LL | const unsafe fn bad_const_unsafe_deref_raw(x: *mut usize) -> usize { *x } = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable error[E0658]: dereferencing raw pointers in constant functions is unstable (see issue #51911) - --> $DIR/min_const_fn_unsafe.rs:60:83 + --> $DIR/min_const_fn_unsafe.rs:66:83 | LL | const unsafe fn bad_const_unsafe_deref_raw_ref(x: *mut usize) -> &'static usize { &*x } | ^^^ @@ -23,7 +23,7 @@ LL | const unsafe fn bad_const_unsafe_deref_raw_ref(x: *mut usize) -> &'static u = help: add #![feature(const_raw_ptr_deref)] to the crate attributes to enable error[E0658]: unions in const fn are unstable (see issue #51909) - --> $DIR/min_const_fn_unsafe.rs:67:5 + --> $DIR/min_const_fn_unsafe.rs:73:5 | LL | Foo { x: () }.y | ^^^^^^^^^^^^^^^ @@ -31,7 +31,7 @@ LL | Foo { x: () }.y = help: add #![feature(const_fn_union)] to the crate attributes to enable error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block - --> $DIR/min_const_fn_unsafe.rs:54:77 + --> $DIR/min_const_fn_unsafe.rs:60:77 | LL | const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe | ^^^ dereference of raw pointer diff --git a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr index 37be2889173f8..2a0ef0e6b9651 100644 --- a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr @@ -1,23 +1,23 @@ error: can only call other `min_const_fn` within a `min_const_fn` - --> $DIR/min_const_unsafe_fn_libstd_stability.rs:26:41 + --> $DIR/min_const_unsafe_fn_libstd_stability.rs:25:41 | LL | const unsafe fn bar() -> u32 { unsafe { foo() } } //~ ERROR can only call other `min_const_fn` | ^^^^^ error: can only call other `min_const_fn` within a `min_const_fn` - --> $DIR/min_const_unsafe_fn_libstd_stability.rs:33:42 + --> $DIR/min_const_unsafe_fn_libstd_stability.rs:32:42 | LL | const unsafe fn bar2() -> u32 { unsafe { foo2() } } //~ ERROR can only call other `min_const_fn` | ^^^^^^ error: only int, `bool` and `char` operations are stable in const fn - --> $DIR/min_const_unsafe_fn_libstd_stability.rs:37:33 + --> $DIR/min_const_unsafe_fn_libstd_stability.rs:36:33 | LL | const unsafe fn bar3() -> u32 { (5f32 + 6f32) as u32 } //~ ERROR only int, `bool` and `char` op | ^^^^^^^^^^^^^ error: can only call other `min_const_fn` within a `min_const_fn` - --> $DIR/min_const_unsafe_fn_libstd_stability.rs:45:48 + --> $DIR/min_const_unsafe_fn_libstd_stability.rs:44:48 | LL | const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } } //~ ERROR can only call other | ^^^^^^^^^^^^ diff --git a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr index 0b58dc1294be0..6153301518563 100644 --- a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr @@ -1,17 +1,17 @@ error: can only call other `min_const_fn` within a `min_const_fn` - --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:26:32 + --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:25:32 | LL | const unsafe fn bar() -> u32 { foo() } //~ ERROR can only call other `min_const_fn` | ^^^^^ error: can only call other `min_const_fn` within a `min_const_fn` - --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:33:33 + --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:32:33 | LL | const unsafe fn bar2() -> u32 { foo2() } //~ ERROR can only call other `min_const_fn` | ^^^^^^ error: can only call other `min_const_fn` within a `min_const_fn` - --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:41:39 + --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:40:39 | LL | const unsafe fn bar2_gated() -> u32 { foo2_gated() } //~ ERROR can only call other `min_const_fn` | ^^^^^^^^^^^^ From 7ae6fb215250d7515cc1ff7545c37d589104eda0 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 22 Dec 2018 21:06:32 +0100 Subject: [PATCH 26/29] stabilize min_const_unsafe_fn -- revert const-size_of-cycle changes --- src/test/ui/consts/const-size_of-cycle.stderr | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/test/ui/consts/const-size_of-cycle.stderr b/src/test/ui/consts/const-size_of-cycle.stderr index 68f81f408f70a..e824657f8afda 100644 --- a/src/test/ui/consts/const-size_of-cycle.stderr +++ b/src/test/ui/consts/const-size_of-cycle.stderr @@ -5,6 +5,10 @@ LL | bytes: [u8; std::mem::size_of::()] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: ...which requires const-evaluating `Foo::bytes::{{constant}}`... + --> $SRC_DIR/libcore/mem.rs:LL:COL + | +LL | intrinsics::size_of::() + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires computing layout of `Foo`... note: ...which requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All }, value: [u8; _] }`... note: ...which requires const-evaluating + checking `Foo::bytes::{{constant}}`... From db542b884d80bd4fa79862f62e07951a4a9d7045 Mon Sep 17 00:00:00 2001 From: John Paul Adrian Glaubitz Date: Sun, 23 Dec 2018 13:29:40 +0100 Subject: [PATCH 27/29] test: Ignore ui/target-feature-gate on s390x --- src/test/ui/target-feature-gate.rs | 1 + src/test/ui/target-feature-gate.stderr | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/ui/target-feature-gate.rs b/src/test/ui/target-feature-gate.rs index cb0938b861c05..9f3a7b5e92462 100644 --- a/src/test/ui/target-feature-gate.rs +++ b/src/test/ui/target-feature-gate.rs @@ -19,6 +19,7 @@ // ignore-powerpc64le // ignore-sparc // ignore-sparc64 +// ignore-s390x // gate-test-sse4a_target_feature // gate-test-powerpc_target_feature // gate-test-avx512_target_feature diff --git a/src/test/ui/target-feature-gate.stderr b/src/test/ui/target-feature-gate.stderr index d7154324d12fe..73da67a9b8fc9 100644 --- a/src/test/ui/target-feature-gate.stderr +++ b/src/test/ui/target-feature-gate.stderr @@ -1,5 +1,5 @@ error[E0658]: the target feature `avx512bw` is currently unstable (see issue #44839) - --> $DIR/target-feature-gate.rs:36:18 + --> $DIR/target-feature-gate.rs:37:18 | LL | #[target_feature(enable = "avx512bw")] | ^^^^^^^^^^^^^^^^^^^ From ecdbcada5de5c4e3d5d46920658f3c4688923659 Mon Sep 17 00:00:00 2001 From: John Paul Adrian Glaubitz Date: Sun, 23 Dec 2018 13:32:03 +0100 Subject: [PATCH 28/29] test: Ignore codegen/x86_mmx.rs on s390x --- src/test/codegen/x86_mmx.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/codegen/x86_mmx.rs b/src/test/codegen/x86_mmx.rs index 4424c30e0f875..0fd3d5424383f 100644 --- a/src/test/codegen/x86_mmx.rs +++ b/src/test/codegen/x86_mmx.rs @@ -18,6 +18,7 @@ // ignore-powerpc64le // ignore-sparc // ignore-sparc64 +// ignore-s390x // compile-flags: -O #![feature(repr_simd)] From 2c0f011ca28dbe2941369315bd78a1dbbb7f950e Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Thu, 29 Nov 2018 14:12:40 +0100 Subject: [PATCH 29/29] Improve docs for collecting into `Option`s Changes the original example to use more idiomatic formatting as well as `.checked_add`. Also adds a second example to show a case where the `.collect` returns `None`. --- src/libcore/option.rs | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 44d632ece055c..dbad29229eb8d 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -1253,20 +1253,42 @@ impl> FromIterator> for Option { /// returned. Should no [`None`][Option::None] occur, a container with the /// values of each [`Option`] is returned. /// - /// Here is an example which increments every integer in a vector, - /// checking for overflow: + /// # Examples + /// + /// Here is an example which increments every integer in a vector. + /// `We use the checked variant of `add` that returns `None` when the + /// calculation would result in an overflow. /// /// ``` - /// use std::u16; + /// let items = vec![0_u16, 1, 2]; + /// + /// let res: Option> = items + /// .iter() + /// .map(|x| x.checked_add(1)) + /// .collect(); /// - /// let v = vec![1, 2]; - /// let res: Option> = v.iter().map(|&x: &u16| - /// if x == u16::MAX { None } - /// else { Some(x + 1) } - /// ).collect(); - /// assert!(res == Some(vec![2, 3])); + /// assert_eq!(res, Some(vec![1, 2, 3])); /// ``` /// + /// As you can see, this will return the expected, valid items. + /// + /// Here is another example that tries to subtract one from another list + /// of integers, this time checking for underflow: + /// + /// ``` + /// let items = vec![2_u16, 1, 0]; + /// + /// let res: Option> = items + /// .iter() + /// .map(|x| x.checked_sub(1)) + /// .collect(); + /// + /// assert_eq!(res, None); + /// ``` + /// + /// Since the last element is zero, it would underflow. Thus, the resulting + /// value is `None`. + /// /// [`Iterator`]: ../iter/trait.Iterator.html #[inline] fn from_iter>>(iter: I) -> Option {