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), } +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, + // 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/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::>(); + .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_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::>()) } -/// 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>>, + ret_coercion_span: RefCell>, yield_ty: Option>, @@ -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::() ) { - 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>), } @@ -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); @@ -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 { 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 { 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 { 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 { 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 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 for TokenTree { }; 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() -> *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..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::() } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +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::>>() } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +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_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 { | --------^^^^^^^^^^^^^^^^ | | | 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..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`.