diff --git a/Cargo.lock b/Cargo.lock
index 365d14c579bdb..5e6bde1db7cd5 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('_'));
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 156d55b9e2fe6..0fd5963c99d4a 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -1979,6 +1979,15 @@ pub enum FunctionRetTy {
Return(P<Ty>),
}
+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 {
@@ -2119,7 +2128,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/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/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<DefId>,
+ // maps from tuple struct constructors to tuple struct items
+ struct_constructors: FxHashMap<ast::NodeId, ast::NodeId>,
}
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<ast::NodeId>,
krate: &'k hir::Crate,
tcx: TyCtxt<'k, 'tcx, 'tcx>,
+ // see `MarkSymbolVisitor::struct_constructors`
+ struct_constructors: FxHashMap<ast::NodeId, ast::NodeId>,
}
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<ast::NodeId>
-{
+fn create_and_seed_worklist<'a, 'tcx>(
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ access_levels: &privacy::AccessLevels,
+ krate: &hir::Crate,
+) -> (Vec<ast::NodeId>, FxHashMap<ast::NodeId, ast::NodeId>) {
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<ast::NodeId> {
- 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<ast::NodeId> {
- 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<ast::NodeId>,
@@ -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 <ident> <generics> = <ty>;` where <ty> refers to a struct_ctor,
- // DefMap maps <ty> to `id` instead.
- fn symbol_is_live(&mut self,
- id: ast::NodeId,
- ctor_id: Option<ast::NodeId>)
- -> 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/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_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/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs
index 146bf53830656..64defaf78a487 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 },
);
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/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/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 794e5741d62ca..e543677ef0621 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -3213,23 +3213,43 @@ 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::<Vec<_>>();
+ .map(|suggestion| {
+ import_candidate_to_enum_paths(&suggestion)
+ }).collect::<Vec<_>>();
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_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,
+ );
}
}
if path.len() == 1 && this.self_type_is_available(span) {
@@ -5128,8 +5148,8 @@ fn path_names_to_string(path: &Path) -> String {
.collect::<Vec<_>>())
}
-/// 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 +5160,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/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 9a1f9784192c1..8b2be84942388 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -1169,7 +1169,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())
@@ -1210,13 +1209,14 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
(self.final_ty.unwrap_or(self.expected_ty), expression_ty)
};
+ let reason_label = "expected because of this statement";
let mut db;
match cause.code {
ObligationCauseCode::ReturnNoExpression => {
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);
@@ -1234,9 +1234,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/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/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index d45f8fd6de8d9..0665452e30a57 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -538,6 +538,7 @@ pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
err_count_on_creation: usize,
ret_coercion: Option<RefCell<DynamicCoerceMany<'gcx, 'tcx>>>,
+ ret_coercion_span: RefCell<Option<Span>>,
yield_ty: Option<Ty<'tcx>>,
@@ -1987,6 +1988,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)),
@@ -3440,7 +3442,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
len.assert_usize(self.tcx),
field.as_str().parse::<u64>()
) {
- 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 {
@@ -3454,11 +3458,13 @@ 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 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,
@@ -4168,11 +4174,30 @@ 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);
- 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/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/libsyntax/parse/lexer/tokentrees.rs b/src/libsyntax/parse/lexer/tokentrees.rs
index 6f9dc247a7897..265ff5f57e4c0 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`.
@@ -186,8 +186,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 013ecd3d343c2..b04495d751a85 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<Vec<TokenStream>>),
}
@@ -165,6 +164,14 @@ pub enum TokenStream {
#[cfg(target_arch = "x86_64")]
static_assert!(MEM_SIZE_OF_TOKEN_STREAM: mem::size_of::<TokenStream>() == 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<TokenTree> for TokenStream {
fn from(tt: TokenTree) -> TokenStream {
- TokenStream::Tree(tt)
+ TokenStream::Tree(tt, NonJoint)
}
}
@@ -232,7 +239,7 @@ impl Extend<TokenStream> 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);
@@ -369,8 +376,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!(),
}
}
@@ -381,8 +387,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;
@@ -395,27 +400,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<TokenTree> {
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(),
}
}
@@ -439,11 +442,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
@@ -493,8 +492,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),
}
@@ -516,9 +514,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;
@@ -540,7 +538,7 @@ impl Iterator for Cursor {
fn next(&mut self) -> Option<TokenTree> {
self.next_as_stream().map(|stream| match stream {
- TokenStream::Tree(tree) | TokenStream::JointTree(tree) => tree,
+ TokenStream::Tree(tree, _) => tree,
_ => unreachable!()
})
}
@@ -550,18 +548,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<TokenStream> {
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,
};
@@ -574,7 +569,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();
@@ -589,8 +584,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())
@@ -602,9 +597,8 @@ impl Cursor {
fn look_ahead(streams: &[TokenStream], mut n: usize) -> Result<TokenTree, usize> {
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,
@@ -617,10 +611,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() {
@@ -653,8 +645,7 @@ impl From<TokenStream> 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 ca960cbe41b5d..507ceb53432d6 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};
@@ -278,11 +278,7 @@ impl ToInternal<TokenStream> for TokenTree<Group, Punct, Ident, Literal> {
};
let tree = tokenstream::TokenTree::Token(span, token);
- if joint {
- tree.joint()
- } else {
- tree.into()
- }
+ TokenStream::Tree(tree, if joint { Joint } else { NonJoint })
}
}
diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs
index 9aafb9fc549fc..ae2259d525898 100644
--- a/src/libsyntax_pos/lib.rs
+++ b/src/libsyntax_pos/lib.rs
@@ -334,6 +334,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/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 fb6507fd22a4b..3b4e89f12e0ad 100644
--- a/src/test/codegen/packed.rs
+++ b/src/test/codegen/packed.rs
@@ -83,6 +83,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);
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<T>() -> *const T { 0 as *const T }
const unsafe fn ret_null_mut_ptr_no_unsafe<T>() -> *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::<String>() }
- //~^ ERROR calls to `const unsafe fn` in const fns are unstable
}
-const fn call_unsafe_generic_cell_const_fn() -> *const Vec<std::cell::Cell<u32>> {
+const fn call_unsafe_generic_cell_const_fn()
+ -> *const Vec<std::cell::Cell<u32>>
+{
unsafe { ret_null_mut_ptr_no_unsafe::<Vec<std::cell::Cell<u32>>>() }
- //~^ 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::<String>() }
+}
+const unsafe fn call_unsafe_generic_cell_const_unsafe_fn()
+ -> *const Vec<std::cell::Cell<u32>>
+{
+ unsafe { ret_null_mut_ptr_no_unsafe::<Vec<std::cell::Cell<u32>>>() }
+}
+
+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::<String>()
+}
+const unsafe fn call_unsafe_generic_cell_const_unsafe_fn_immediate()
+ -> *const Vec<std::cell::Cell<u32>>
+{
+ ret_null_mut_ptr_no_unsafe::<Vec<std::cell::Cell<u32>>>()
+}
+
+//------------------------------------------------------------------------------
+// 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..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,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:60: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:63: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:66: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:73:5
|
-LL | unsafe { ret_null_ptr_no_unsafe::<String>() }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+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:60:77
|
-LL | unsafe { ret_null_mut_ptr_no_unsafe::<Vec<std::cell::Cell<u32>>>() }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(min_const_unsafe_fn)]
-
-// ok
-const unsafe fn foo4() -> i32 { 42 }
-const unsafe fn foo5<T>() -> *const T { 0 as *const T }
-const unsafe fn foo6<T>() -> *mut T { 0 as *mut T }
-const fn no_unsafe() { unsafe {} }
-
-const fn foo8() -> i32 {
- unsafe { foo4() }
-}
-const fn foo9() -> *const String {
- unsafe { foo5::<String>() }
-}
-const fn foo10() -> *const Vec<std::cell::Cell<u32>> {
- unsafe { foo6::<Vec<std::cell::Cell<u32>>>() }
-}
-const unsafe fn foo8_3() -> i32 {
- unsafe { foo4() }
-}
-const unsafe fn foo9_3() -> *const String {
- unsafe { foo5::<String>() }
-}
-const unsafe fn foo10_3() -> *const Vec<std::cell::Cell<u32>> {
- unsafe { foo6::<Vec<std::cell::Cell<u32>>>() }
-}
-const unsafe fn foo8_2() -> i32 {
- foo4()
-}
-const unsafe fn foo9_2() -> *const String {
- foo5::<String>()
-}
-const unsafe fn foo10_2() -> *const Vec<std::cell::Cell<u32>> {
- foo6::<Vec<std::cell::Cell<u32>>>()
-}
-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_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.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")]
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`
| ^^^^^^^^^^^^
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..4180b1e295ab0
--- /dev/null
+++ b/src/test/ui/consts/static_mut_containing_mut_ref2.rs
@@ -0,0 +1,9 @@
+#![feature(const_let)]
+
+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
new file mode 100644
index 0000000000000..f0ae1545056b7
--- /dev/null
+++ b/src/test/ui/consts/static_mut_containing_mut_ref2.stderr
@@ -0,0 +1,16 @@
+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[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
+
+Some errors occurred: E0017, E0019.
+For more information about an error, try `rustc --explain E0017`.
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`.
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..496ce4fb378ae
--- /dev/null
+++ b/src/test/ui/dead-code-tuple-struct-field.rs
@@ -0,0 +1,12 @@
+// compile-pass
+
+#![deny(dead_code)]
+
+const LEN: usize = 4;
+
+#[derive(Debug)]
+struct Wrapper([u8; LEN]);
+
+fn main() {
+ println!("{:?}", Wrapper([0, 1, 2, 3]));
+}
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..264cfa449942c
--- /dev/null
+++ b/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.rs
@@ -0,0 +1,15 @@
+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 }
+//~^ 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/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/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/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
|
diff --git a/src/test/ui/issues/issue-11004.stderr b/src/test/ui/issues/issue-11004.stderr
index 215120c9c25ea..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 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/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<MyEnum, String> {
| --------^^^^^^^^^^^^^^^^
| |
| 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<foo::MyEnum, String> {
| --------^^^^^^^^^^^^^^^^^^^^^
| |
| 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<T> //~ 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<T>) //~ 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..652e1695a85a6 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
@@ -40,28 +41,29 @@ error[E0573]: expected type, found variant `Ok`
--> $DIR/issue-35675.rs:29:13
|
LL | fn foo() -> Ok {
- | ^^ not a type
- |
- = 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`?
+ | ^^
+ | |
+ | 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
|
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: 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`?
+ | ^^^^
+ | |
+ | not a type
+ | help: try using the variant's enum: `Option`
error: aborting due to 7 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..0b4ccdd5a56d4
--- /dev/null
+++ b/src/test/ui/parenthesised-deref-suggestion.rs
@@ -0,0 +1,11 @@
+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`
+
+ 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
new file mode 100644
index 0000000000000..71a2bf67f06ae
--- /dev/null
+++ b/src/test/ui/parenthesised-deref-suggestion.stderr
@@ -0,0 +1,21 @@
+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[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`.
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
diff --git a/src/test/ui/unsafe/unsafe-fn-autoderef.stderr b/src/test/ui/unsafe/unsafe-fn-autoderef.stderr
index 13fcbb347c94b..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 native pointer; try dereferencing it: `(*p).f`
+ | --^
+ | |
+ | help: `p` is a raw pointer; try dereferencing it: `(*p).f`
error: aborting due to previous error
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
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`.