diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index a94792a2f9f59..512d4d8c5b792 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -816,6 +816,8 @@ def bootstrap(help_triggered): env["BOOTSTRAP_PYTHON"] = sys.executable env["BUILD_DIR"] = build.build_dir env["RUSTC_BOOTSTRAP"] = '1' + env["CARGO"] = build.cargo() + env["RUSTC"] = build.rustc() run(args, env=env, verbose=build.verbose) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index e4d467c927245..b3ed10257bdac 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -23,7 +23,6 @@ use std::cmp; use num_cpus; use toml; -use util::exe; use cache::{INTERNER, Interned}; use flags::Flags; pub use flags::Subcommand; @@ -367,9 +366,8 @@ impl Config { config.src = Config::path_from_python("SRC"); config.out = Config::path_from_python("BUILD_DIR"); - let stage0_root = config.out.join(&config.build).join("stage0/bin"); - config.initial_rustc = stage0_root.join(exe("rustc", &config.build)); - config.initial_cargo = stage0_root.join(exe("cargo", &config.build)); + config.initial_rustc = Config::path_from_python("RUSTC"); + config.initial_cargo = Config::path_from_python("CARGO"); config } diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 414f17dfad400..f0be6efa31a02 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -204,7 +204,8 @@ const LLVM_TOOLS: &[&str] = &[ "llvm-objcopy", // used to transform ELFs into binary format which flashing tools consume "llvm-objdump", // used to disassemble programs "llvm-profdata", // used to inspect and merge files generated by profiles - "llvm-size", // prints the size of the linker sections of a program + "llvm-size", // used to prints the size of the linker sections of a program + "llvm-strip", // used to discard symbols from binary files to reduce their size ]; /// A structure representing a Rust compiler. diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs index 2aad3149bb211..8c950cd06d9e3 100644 --- a/src/liballoc/collections/btree/map.rs +++ b/src/liballoc/collections/btree/map.rs @@ -149,12 +149,11 @@ unsafe impl<#[may_dangle] K, #[may_dangle] V> Drop for BTreeMap { #[stable(feature = "rust1", since = "1.0.0")] impl Clone for BTreeMap { fn clone(&self) -> BTreeMap { - fn clone_subtree(node: node::NodeRef) - -> BTreeMap { - + fn clone_subtree<'a, K: Clone, V: Clone>( + node: node::NodeRef, K, V, marker::LeafOrInternal> + ) -> BTreeMap + where K: 'a, V: 'a, + { match node.force() { Leaf(leaf) => { let mut out_tree = BTreeMap { @@ -1080,7 +1079,11 @@ impl BTreeMap { /// Calculates the number of elements if it is incorrect. fn recalc_length(&mut self) { - fn dfs(node: NodeRef) -> usize { + fn dfs<'a, K, V>( + node: NodeRef, K, V, marker::LeafOrInternal> + ) -> usize + where K: 'a, V: 'a + { let mut res = node.len(); if let Internal(node) = node.force() { diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 5896322f111f8..0b279f66b88d6 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -91,7 +91,7 @@ macro_rules! step_impl_unsigned { #[inline] #[allow(unreachable_patterns)] fn add_usize(&self, n: usize) -> Option { - match <$t>::private_try_from(n) { + match <$t>::try_from(n) { Ok(n_as_t) => self.checked_add(n_as_t), Err(_) => None, } @@ -123,7 +123,7 @@ macro_rules! step_impl_signed { #[inline] #[allow(unreachable_patterns)] fn add_usize(&self, n: usize) -> Option { - match <$unsigned>::private_try_from(n) { + match <$unsigned>::try_from(n) { Ok(n_as_unsigned) => { // Wrapping in unsigned space handles cases like // `-120_i8.add_usize(200) == Some(80_i8)`, @@ -461,74 +461,3 @@ impl DoubleEndedIterator for ops::RangeInclusive { #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for ops::RangeInclusive {} - -/// Compensate removal of some impls per -/// https://github.com/rust-lang/rust/pull/49305#issuecomment-376293243 -trait PrivateTryFromUsize: Sized { - fn private_try_from(n: usize) -> Result; -} - -impl PrivateTryFromUsize for T where T: TryFrom { - #[inline] - fn private_try_from(n: usize) -> Result { - T::try_from(n).map_err(|_| ()) - } -} - -// no possible bounds violation -macro_rules! try_from_unbounded { - ($($target:ty),*) => {$( - impl PrivateTryFromUsize for $target { - #[inline] - fn private_try_from(value: usize) -> Result { - Ok(value as $target) - } - } - )*} -} - -// unsigned to signed (only positive bound) -#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))] -macro_rules! try_from_upper_bounded { - ($($target:ty),*) => {$( - impl PrivateTryFromUsize for $target { - #[inline] - fn private_try_from(u: usize) -> Result<$target, ()> { - if u > (<$target>::max_value() as usize) { - Err(()) - } else { - Ok(u as $target) - } - } - } - )*} -} - - -#[cfg(target_pointer_width = "16")] -mod ptr_try_from_impls { - use super::PrivateTryFromUsize; - - try_from_unbounded!(u16, u32, u64, u128); - try_from_unbounded!(i32, i64, i128); -} - -#[cfg(target_pointer_width = "32")] -mod ptr_try_from_impls { - use super::PrivateTryFromUsize; - - try_from_upper_bounded!(u16); - try_from_unbounded!(u32, u64, u128); - try_from_upper_bounded!(i32); - try_from_unbounded!(i64, i128); -} - -#[cfg(target_pointer_width = "64")] -mod ptr_try_from_impls { - use super::PrivateTryFromUsize; - - try_from_upper_bounded!(u16, u32); - try_from_unbounded!(u64, u128); - try_from_upper_bounded!(i32, i64); - try_from_unbounded!(i128); -} diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index e0d267a6ce0ec..260ebabf1fa4a 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -4213,6 +4213,21 @@ impl From for TryFromIntError { } } +// no possible bounds violation +macro_rules! try_from_unbounded { + ($source:ty, $($target:ty),*) => {$( + #[unstable(feature = "try_from", issue = "33417")] + impl TryFrom<$source> for $target { + type Error = TryFromIntError; + + #[inline] + fn try_from(value: $source) -> Result { + Ok(value as $target) + } + } + )*} +} + // only negative bounds macro_rules! try_from_lower_bounded { ($source:ty, $($target:ty),*) => {$( @@ -4311,20 +4326,27 @@ try_from_both_bounded!(i128, u64, u32, u16, u8); try_from_upper_bounded!(usize, isize); try_from_lower_bounded!(isize, usize); -try_from_upper_bounded!(usize, u8); -try_from_upper_bounded!(usize, i8, i16); -try_from_both_bounded!(isize, u8); -try_from_both_bounded!(isize, i8); - #[cfg(target_pointer_width = "16")] mod ptr_try_from_impls { use super::TryFromIntError; use convert::TryFrom; - // Fallible across platfoms, only implementation differs + try_from_upper_bounded!(usize, u8); + try_from_unbounded!(usize, u16, u32, u64, u128); + try_from_upper_bounded!(usize, i8, i16); + try_from_unbounded!(usize, i32, i64, i128); + + try_from_both_bounded!(isize, u8); try_from_lower_bounded!(isize, u16, u32, u64, u128); + try_from_both_bounded!(isize, i8); + try_from_unbounded!(isize, i16, i32, i64, i128); + + rev!(try_from_upper_bounded, usize, u32, u64, u128); rev!(try_from_lower_bounded, usize, i8, i16); rev!(try_from_both_bounded, usize, i32, i64, i128); + + rev!(try_from_upper_bounded, isize, u16, u32, u64, u128); + rev!(try_from_both_bounded, isize, i32, i64, i128); } #[cfg(target_pointer_width = "32")] @@ -4332,11 +4354,25 @@ mod ptr_try_from_impls { use super::TryFromIntError; use convert::TryFrom; - // Fallible across platfoms, only implementation differs - try_from_both_bounded!(isize, u16); + try_from_upper_bounded!(usize, u8, u16); + try_from_unbounded!(usize, u32, u64, u128); + try_from_upper_bounded!(usize, i8, i16, i32); + try_from_unbounded!(usize, i64, i128); + + try_from_both_bounded!(isize, u8, u16); try_from_lower_bounded!(isize, u32, u64, u128); + try_from_both_bounded!(isize, i8, i16); + try_from_unbounded!(isize, i32, i64, i128); + + rev!(try_from_unbounded, usize, u32); + rev!(try_from_upper_bounded, usize, u64, u128); rev!(try_from_lower_bounded, usize, i8, i16, i32); rev!(try_from_both_bounded, usize, i64, i128); + + rev!(try_from_unbounded, isize, u16); + rev!(try_from_upper_bounded, isize, u32, u64, u128); + rev!(try_from_unbounded, isize, i32); + rev!(try_from_both_bounded, isize, i64, i128); } #[cfg(target_pointer_width = "64")] @@ -4344,11 +4380,25 @@ mod ptr_try_from_impls { use super::TryFromIntError; use convert::TryFrom; - // Fallible across platfoms, only implementation differs - try_from_both_bounded!(isize, u16, u32); + try_from_upper_bounded!(usize, u8, u16, u32); + try_from_unbounded!(usize, u64, u128); + try_from_upper_bounded!(usize, i8, i16, i32, i64); + try_from_unbounded!(usize, i128); + + try_from_both_bounded!(isize, u8, u16, u32); try_from_lower_bounded!(isize, u64, u128); + try_from_both_bounded!(isize, i8, i16, i32); + try_from_unbounded!(isize, i64, i128); + + rev!(try_from_unbounded, usize, u32, u64); + rev!(try_from_upper_bounded, usize, u128); rev!(try_from_lower_bounded, usize, i8, i16, i32, i64); rev!(try_from_both_bounded, usize, i128); + + rev!(try_from_unbounded, isize, u16, u32); + rev!(try_from_upper_bounded, isize, u64, u128); + rev!(try_from_unbounded, isize, i32, i64); + rev!(try_from_both_bounded, isize, i128); } #[doc(hidden)] diff --git a/src/libcore/tests/num/mod.rs b/src/libcore/tests/num/mod.rs index 24fe96a2b8255..ab96d3126bb22 100644 --- a/src/libcore/tests/num/mod.rs +++ b/src/libcore/tests/num/mod.rs @@ -37,6 +37,15 @@ mod flt2dec; mod dec2flt; mod bignum; + +/// Adds the attribute to all items in the block. +macro_rules! cfg_block { + ($(#[$attr:meta]{$($it:item)*})*) => {$($( + #[$attr] + $it + )*)*} +} + /// Groups items that assume the pointer width is either 16/32/64, and has to be altered if /// support for larger/smaller pointer widths are added in the future. macro_rules! assume_usize_width { @@ -330,6 +339,42 @@ assume_usize_width! { test_impl_try_from_always_ok! { test_try_u16usize, u16, usize } test_impl_try_from_always_ok! { test_try_i16isize, i16, isize } + + test_impl_try_from_always_ok! { test_try_usizeu64, usize, u64 } + test_impl_try_from_always_ok! { test_try_usizeu128, usize, u128 } + test_impl_try_from_always_ok! { test_try_usizei128, usize, i128 } + + test_impl_try_from_always_ok! { test_try_isizei64, isize, i64 } + test_impl_try_from_always_ok! { test_try_isizei128, isize, i128 } + + cfg_block!( + #[cfg(target_pointer_width = "16")] { + test_impl_try_from_always_ok! { test_try_usizeu16, usize, u16 } + test_impl_try_from_always_ok! { test_try_isizei16, isize, i16 } + test_impl_try_from_always_ok! { test_try_usizeu32, usize, u32 } + test_impl_try_from_always_ok! { test_try_usizei32, usize, i32 } + test_impl_try_from_always_ok! { test_try_isizei32, isize, i32 } + test_impl_try_from_always_ok! { test_try_usizei64, usize, i64 } + } + + #[cfg(target_pointer_width = "32")] { + test_impl_try_from_always_ok! { test_try_u16isize, u16, isize } + test_impl_try_from_always_ok! { test_try_usizeu32, usize, u32 } + test_impl_try_from_always_ok! { test_try_isizei32, isize, i32 } + test_impl_try_from_always_ok! { test_try_u32usize, u32, usize } + test_impl_try_from_always_ok! { test_try_i32isize, i32, isize } + test_impl_try_from_always_ok! { test_try_usizei64, usize, i64 } + } + + #[cfg(target_pointer_width = "64")] { + test_impl_try_from_always_ok! { test_try_u16isize, u16, isize } + test_impl_try_from_always_ok! { test_try_u32usize, u32, usize } + test_impl_try_from_always_ok! { test_try_u32isize, u32, isize } + test_impl_try_from_always_ok! { test_try_i32isize, i32, isize } + test_impl_try_from_always_ok! { test_try_u64usize, u64, usize } + test_impl_try_from_always_ok! { test_try_i64isize, i64, isize } + } + ); } /// Conversions where max of $source can be represented as $target, @@ -378,6 +423,24 @@ assume_usize_width! { test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_isizeu64, isize, u64 } test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_isizeu128, isize, u128 } test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_isizeusize, isize, usize } + + cfg_block!( + #[cfg(target_pointer_width = "16")] { + test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_isizeu16, isize, u16 } + test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_isizeu32, isize, u32 } + } + + #[cfg(target_pointer_width = "32")] { + test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_isizeu32, isize, u32 } + + test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i32usize, i32, usize } + } + + #[cfg(target_pointer_width = "64")] { + test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i32usize, i32, usize } + test_impl_try_from_signed_to_unsigned_upper_ok! { test_try_i64usize, i64, usize } + } + ); } /// Conversions where max of $source can not be represented as $target, @@ -419,9 +482,29 @@ test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u128i64, u128, i64 } test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u128i128, u128, i128 } assume_usize_width! { + test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u64isize, u64, isize } + test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u128isize, u128, isize } + test_impl_try_from_unsigned_to_signed_upper_err! { test_try_usizei8, usize, i8 } test_impl_try_from_unsigned_to_signed_upper_err! { test_try_usizei16, usize, i16 } test_impl_try_from_unsigned_to_signed_upper_err! { test_try_usizeisize, usize, isize } + + cfg_block!( + #[cfg(target_pointer_width = "16")] { + test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u16isize, u16, isize } + test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u32isize, u32, isize } + } + + #[cfg(target_pointer_width = "32")] { + test_impl_try_from_unsigned_to_signed_upper_err! { test_try_u32isize, u32, isize } + test_impl_try_from_unsigned_to_signed_upper_err! { test_try_usizei32, usize, i32 } + } + + #[cfg(target_pointer_width = "64")] { + test_impl_try_from_unsigned_to_signed_upper_err! { test_try_usizei32, usize, i32 } + test_impl_try_from_unsigned_to_signed_upper_err! { test_try_usizei64, usize, i64 } + } + ); } /// Conversions where min/max of $source can not be represented as $target. @@ -481,6 +564,34 @@ test_impl_try_from_same_sign_err! { test_try_i128i64, i128, i64 } assume_usize_width! { test_impl_try_from_same_sign_err! { test_try_usizeu8, usize, u8 } + test_impl_try_from_same_sign_err! { test_try_u128usize, u128, usize } + test_impl_try_from_same_sign_err! { test_try_i128isize, i128, isize } + + cfg_block!( + #[cfg(target_pointer_width = "16")] { + test_impl_try_from_same_sign_err! { test_try_u32usize, u32, usize } + test_impl_try_from_same_sign_err! { test_try_u64usize, u64, usize } + + test_impl_try_from_same_sign_err! { test_try_i32isize, i32, isize } + test_impl_try_from_same_sign_err! { test_try_i64isize, i64, isize } + } + + #[cfg(target_pointer_width = "32")] { + test_impl_try_from_same_sign_err! { test_try_u64usize, u64, usize } + test_impl_try_from_same_sign_err! { test_try_usizeu16, usize, u16 } + + test_impl_try_from_same_sign_err! { test_try_i64isize, i64, isize } + test_impl_try_from_same_sign_err! { test_try_isizei16, isize, i16 } + } + + #[cfg(target_pointer_width = "64")] { + test_impl_try_from_same_sign_err! { test_try_usizeu16, usize, u16 } + test_impl_try_from_same_sign_err! { test_try_usizeu32, usize, u32 } + + test_impl_try_from_same_sign_err! { test_try_isizei16, isize, i16 } + test_impl_try_from_same_sign_err! { test_try_isizei32, isize, i32 } + } + ); } /// Conversions where neither the min nor the max of $source can be represented by @@ -525,6 +636,22 @@ test_impl_try_from_signed_to_unsigned_err! { test_try_i128u64, i128, u64 } assume_usize_width! { test_impl_try_from_signed_to_unsigned_err! { test_try_isizeu8, isize, u8 } test_impl_try_from_signed_to_unsigned_err! { test_try_i128usize, i128, usize } + + cfg_block! { + #[cfg(target_pointer_width = "16")] { + test_impl_try_from_signed_to_unsigned_err! { test_try_i32usize, i32, usize } + test_impl_try_from_signed_to_unsigned_err! { test_try_i64usize, i64, usize } + } + #[cfg(target_pointer_width = "32")] { + test_impl_try_from_signed_to_unsigned_err! { test_try_i64usize, i64, usize } + + test_impl_try_from_signed_to_unsigned_err! { test_try_isizeu16, isize, u16 } + } + #[cfg(target_pointer_width = "64")] { + test_impl_try_from_signed_to_unsigned_err! { test_try_isizeu16, isize, u16 } + test_impl_try_from_signed_to_unsigned_err! { test_try_isizeu32, isize, u32 } + } + } } macro_rules! test_float { diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 60e944e5affc3..a7ed854d01649 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -607,13 +607,6 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { } visitor.visit_lifetime(lifetime); } - TyImplTraitExistential(_, def_id, ref lifetimes) => { - // we are not recursing into the `existential` item, because it is already being visited - // as part of the surrounding module. The `NodeId` just exists so we don't have to look - // it up everywhere else in the compiler - visitor.visit_def_mention(Def::Existential(def_id)); - walk_list!(visitor, visit_lifetime, lifetimes); - } TyTypeof(ref expression) => { visitor.visit_anon_const(expression) } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index e59e50ae9e698..56df95336072a 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -103,6 +103,7 @@ pub struct LoweringContext<'a> { loop_scopes: Vec, is_in_loop_condition: bool, is_in_trait_impl: bool, + is_in_anon_const: bool, /// What to do when we encounter either an "anonymous lifetime /// reference". The term "anonymous" is meant to encompass both @@ -230,6 +231,7 @@ pub fn lower_crate( node_id_to_hir_id: IndexVec::new(), is_generator: false, is_in_trait_impl: false, + is_in_anon_const: false, lifetimes_to_define: Vec::new(), is_collecting_in_band_lifetimes: false, in_scope_lifetimes: Vec::new(), @@ -968,31 +970,30 @@ impl<'a> LoweringContext<'a> { } fn lower_loop_destination(&mut self, destination: Option<(NodeId, Label)>) -> hir::Destination { - match destination { - Some((id, label)) => { - let target_id = if let Def::Label(loop_id) = self.expect_full_def(id) { - Ok(self.lower_node_id(loop_id).node_id) - } else { - Err(hir::LoopIdError::UnresolvedLabel) - }; - hir::Destination { - label: self.lower_label(Some(label)), - target_id, + let target_id = if self.is_in_anon_const { + Err(hir::LoopIdError::OutsideLoopScope) + } else { + match destination { + Some((id, _)) => { + if let Def::Label(loop_id) = self.expect_full_def(id) { + Ok(self.lower_node_id(loop_id).node_id) + } else { + Err(hir::LoopIdError::UnresolvedLabel) + } } - } - None => { - let target_id = self.loop_scopes - .last() - .map(|innermost_loop_id| *innermost_loop_id) - .map(|id| Ok(self.lower_node_id(id).node_id)) - .unwrap_or(Err(hir::LoopIdError::OutsideLoopScope)) - .into(); - - hir::Destination { - label: None, - target_id, + None => { + self.loop_scopes + .last() + .map(|innermost_loop_id| *innermost_loop_id) + .map(|id| Ok(self.lower_node_id(id).node_id)) + .unwrap_or(Err(hir::LoopIdError::OutsideLoopScope)) + .into() } } + }; + hir::Destination { + label: self.lower_label(destination.map(|(_, label)| label)), + target_id, } } @@ -1306,13 +1307,20 @@ impl<'a> LoweringContext<'a> { lctx.items.insert(exist_ty_id.node_id, exist_ty_item); // `impl Trait` now just becomes `Foo<'a, 'b, ..>` - hir::TyImplTraitExistential( - hir::ItemId { - id: exist_ty_id.node_id - }, - DefId::local(exist_ty_def_index), - lifetimes, - ) + let path = P(hir::Path { + span: exist_ty_span, + def: Def::Existential(DefId::local(exist_ty_def_index)), + segments: hir_vec![hir::PathSegment { + infer_types: false, + ident: Ident::new(keywords::Invalid.name(), exist_ty_span), + args: Some(P(hir::GenericArgs { + parenthesized: false, + bindings: HirVec::new(), + args: lifetimes, + })) + }], + }); + hir::TyPath(hir::QPath::Resolved(None, path)) }) } @@ -1321,7 +1329,7 @@ impl<'a> LoweringContext<'a> { exist_ty_id: NodeId, parent_index: DefIndex, bounds: &hir::GenericBounds, - ) -> (HirVec, HirVec) { + ) -> (HirVec, HirVec) { // This visitor walks over impl trait bounds and creates defs for all lifetimes which // appear in the bounds, excluding lifetimes that are created within the bounds. // e.g. 'a, 'b, but not 'c in `impl for<'c> SomeTrait<'a, 'b, 'c>` @@ -1332,7 +1340,7 @@ impl<'a> LoweringContext<'a> { collect_elided_lifetimes: bool, currently_bound_lifetimes: Vec, already_defined_lifetimes: HashSet, - output_lifetimes: Vec, + output_lifetimes: Vec, output_lifetime_params: Vec, } @@ -1416,11 +1424,11 @@ impl<'a> LoweringContext<'a> { && !self.already_defined_lifetimes.contains(&name) { self.already_defined_lifetimes.insert(name); - self.output_lifetimes.push(hir::Lifetime { + self.output_lifetimes.push(hir::GenericArg::Lifetime(hir::Lifetime { id: self.context.next_id().node_id, span: lifetime.span, name, - }); + })); // We need to manually create the ids here, because the // definitions will go into the explicit `existential type` @@ -3440,13 +3448,22 @@ impl<'a> LoweringContext<'a> { } fn lower_anon_const(&mut self, c: &AnonConst) -> hir::AnonConst { - let LoweredNodeId { node_id, hir_id } = self.lower_node_id(c.id); + let was_in_loop_condition = self.is_in_loop_condition; + self.is_in_loop_condition = false; + let was_in_anon_const = self.is_in_anon_const; + self.is_in_anon_const = true; - hir::AnonConst { + let LoweredNodeId { node_id, hir_id } = self.lower_node_id(c.id); + let anon_const = hir::AnonConst { id: node_id, hir_id, body: self.lower_body(None, |this| this.lower_expr(&c.value)), - } + }; + + self.is_in_anon_const = was_in_anon_const; + self.is_in_loop_condition = was_in_loop_condition; + + anon_const } fn lower_expr(&mut self, e: &Expr) -> hir::Expr { diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index b0b81316148ea..8d83dd3279c64 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1692,18 +1692,6 @@ pub enum Ty_ { /// A trait object type `Bound1 + Bound2 + Bound3` /// where `Bound` is a trait or a lifetime. TyTraitObject(HirVec, Lifetime), - /// An existentially quantified (there exists a type satisfying) `impl - /// Bound1 + Bound2 + Bound3` type where `Bound` is a trait or a lifetime. - /// - /// The `Item` is the generated - /// `existential type Foo<'a, 'b>: MyTrait<'a, 'b>;`. - /// - /// The `HirVec` is the list of lifetimes applied as parameters - /// to the `abstract type`, e.g. the `'c` and `'d` in `-> Foo<'c, 'd>`. - /// This list is only a list of lifetimes and not type parameters - /// because all in-scope type parameters are captured by `impl Trait`, - /// so they are resolved directly through the parent `Generics`. - TyImplTraitExistential(ItemId, DefId, HirVec), /// Unused for now TyTypeof(AnonConst), /// TyInfer means the type should be inferred instead of it having been diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 255009c94c6ab..4d0969d898e91 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -420,15 +420,6 @@ impl<'a> State<'a> { self.print_lifetime(lifetime)?; } } - hir::TyImplTraitExistential(hir_id, _def_id, ref _lifetimes) => { - match self.ann.try_fetch_item(hir_id.id).map(|it| &it.node) { - None => self.word_space("impl {{Trait}}")?, - Some(&hir::ItemExistential(ref exist_ty)) => { - self.print_bounds("impl", &exist_ty.bounds)?; - }, - other => bug!("impl Trait pointed to {:#?}", other), - } - } hir::TyArray(ref ty, ref length) => { self.s.word("[")?; self.print_type(&ty)?; diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 0c7baea85ad8f..dd19d59578fc1 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -340,7 +340,6 @@ impl_stable_hash_for!(enum hir::Ty_ { TyTup(ts), TyPath(qpath), TyTraitObject(trait_refs, lifetime), - TyImplTraitExistential(existty, def_id, lifetimes), TyTypeof(body_id), TyErr, TyInfer diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index afc83771fe1c7..1377176bc7fb8 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -518,7 +518,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } else { err.span_label(arm_span, msg); } - } + }, + hir::MatchSource::TryDesugar => { // Issue #51632 + if let Ok(try_snippet) = self.tcx.sess.codemap().span_to_snippet(arm_span) { + err.span_suggestion_with_applicability( + arm_span, + "try wrapping with a success variant", + format!("Ok({})", try_snippet), + Applicability::MachineApplicable + ); + } + }, _ => { let msg = "match arm with an incompatible type"; if self.tcx.sess.codemap().is_multiline(arm_span) { @@ -1312,7 +1322,12 @@ impl<'tcx> ObligationCause<'tcx> { match self.code { CompareImplMethodObligation { .. } => Error0308("method not compatible with trait"), MatchExpressionArm { source, .. } => Error0308(match source { - hir::MatchSource::IfLetDesugar { .. } => "`if let` arms have incompatible types", + hir::MatchSource::IfLetDesugar { .. } => { + "`if let` arms have incompatible types" + }, + hir::MatchSource::TryDesugar => { + "try expression alternatives have incompatible types" + }, _ => "match arms have incompatible types", }), IfExpression => Error0308("if and else have incompatible types"), diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 6ccf09f4dfc4f..a83aa47fd4f13 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -840,6 +840,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { fn walk_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat, match_mode: MatchMode) { debug!("walk_pat(cmt_discr={:?}, pat={:?})", cmt_discr, pat); + let tcx = self.tcx(); let ExprUseVisitor { ref mc, ref mut delegate, param_env } = *self; return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |cmt_pat, pat| { if let PatKind::Binding(_, canonical_id, ..) = pat.node { @@ -849,34 +850,36 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { pat, match_mode, ); - let bm = *mc.tables.pat_binding_modes().get(pat.hir_id) - .expect("missing binding mode"); - debug!("walk_pat: pat.hir_id={:?} bm={:?}", pat.hir_id, bm); - - // pat_ty: the type of the binding being produced. - let pat_ty = return_if_err!(mc.node_ty(pat.hir_id)); - debug!("walk_pat: pat_ty={:?}", pat_ty); - - // Each match binding is effectively an assignment to the - // binding being produced. - let def = Def::Local(canonical_id); - if let Ok(ref binding_cmt) = mc.cat_def(pat.hir_id, pat.span, pat_ty, def) { - delegate.mutate(pat.id, pat.span, binding_cmt, MutateMode::Init); - } + if let Some(&bm) = mc.tables.pat_binding_modes().get(pat.hir_id) { + debug!("walk_pat: pat.hir_id={:?} bm={:?}", pat.hir_id, bm); + + // pat_ty: the type of the binding being produced. + let pat_ty = return_if_err!(mc.node_ty(pat.hir_id)); + debug!("walk_pat: pat_ty={:?}", pat_ty); + + // Each match binding is effectively an assignment to the + // binding being produced. + let def = Def::Local(canonical_id); + if let Ok(ref binding_cmt) = mc.cat_def(pat.hir_id, pat.span, pat_ty, def) { + delegate.mutate(pat.id, pat.span, binding_cmt, MutateMode::Init); + } - // It is also a borrow or copy/move of the value being matched. - match bm { - ty::BindByReference(m) => { - if let ty::TyRef(r, _, _) = pat_ty.sty { - let bk = ty::BorrowKind::from_mutbl(m); - delegate.borrow(pat.id, pat.span, &cmt_pat, r, bk, RefBinding); + // It is also a borrow or copy/move of the value being matched. + match bm { + ty::BindByReference(m) => { + if let ty::TyRef(r, _, _) = pat_ty.sty { + let bk = ty::BorrowKind::from_mutbl(m); + delegate.borrow(pat.id, pat.span, &cmt_pat, r, bk, RefBinding); + } + } + ty::BindByValue(..) => { + let mode = copy_or_move(mc, param_env, &cmt_pat, PatBindingMove); + debug!("walk_pat binding consuming pat"); + delegate.consume_pat(pat, &cmt_pat, mode); } } - ty::BindByValue(..) => { - let mode = copy_or_move(mc, param_env, &cmt_pat, PatBindingMove); - debug!("walk_pat binding consuming pat"); - delegate.consume_pat(pat, &cmt_pat, mode); - } + } else { + tcx.sess.delay_span_bug(pat.span, "missing binding mode"); } } })); diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index ed2b9c5068929..369f65c214aa1 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -625,122 +625,131 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { }; self.with(scope, |_, this| this.visit_ty(&mt.ty)); } - hir::TyImplTraitExistential(item_id, _, ref lifetimes) => { - // Resolve the lifetimes that are applied to the existential type. - // These are resolved in the current scope. - // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to - // `fn foo<'a>() -> MyAnonTy<'a> { ... }` - // ^ ^this gets resolved in the current scope - for lifetime in lifetimes { - self.visit_lifetime(lifetime); - - // Check for predicates like `impl for<'a> SomeTrait>` - // and ban them. Type variables instantiated inside binders aren't - // well-supported at the moment, so this doesn't work. - // In the future, this should be fixed and this error should be removed. - let def = self.map.defs.get(&lifetime.id).cloned(); - if let Some(Region::LateBound(_, def_id, _)) = def { - if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) { - // Ensure that the parent of the def is an item, not HRTB - let parent_id = self.tcx.hir.get_parent_node(node_id); - let parent_impl_id = hir::ImplItemId { node_id: parent_id }; - let parent_trait_id = hir::TraitItemId { node_id: parent_id }; - let krate = self.tcx.hir.forest.krate(); - if !(krate.items.contains_key(&parent_id) - || krate.impl_items.contains_key(&parent_impl_id) - || krate.trait_items.contains_key(&parent_trait_id)) - { - span_err!( - self.tcx.sess, - lifetime.span, - E0657, - "`impl Trait` can only capture lifetimes \ - bound at the fn or impl level" - ); - self.uninsert_lifetime_on_error(lifetime, def.unwrap()); + hir::TyPath(hir::QPath::Resolved(None, ref path)) => { + if let Def::Existential(exist_ty_did) = path.def { + assert!(exist_ty_did.is_local()); + // Resolve the lifetimes that are applied to the existential type. + // These are resolved in the current scope. + // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to + // `fn foo<'a>() -> MyAnonTy<'a> { ... }` + // ^ ^this gets resolved in the current scope + for lifetime in &path.segments[0].args.as_ref().unwrap().args { + if let hir::GenericArg::Lifetime(lifetime) = lifetime { + self.visit_lifetime(lifetime); + + // Check for predicates like `impl for<'a> Trait>` + // and ban them. Type variables instantiated inside binders aren't + // well-supported at the moment, so this doesn't work. + // In the future, this should be fixed and this error should be removed. + let def = self.map.defs.get(&lifetime.id).cloned(); + if let Some(Region::LateBound(_, def_id, _)) = def { + if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) { + // Ensure that the parent of the def is an item, not HRTB + let parent_id = self.tcx.hir.get_parent_node(node_id); + let parent_impl_id = hir::ImplItemId { node_id: parent_id }; + let parent_trait_id = hir::TraitItemId { node_id: parent_id }; + let krate = self.tcx.hir.forest.krate(); + if !(krate.items.contains_key(&parent_id) + || krate.impl_items.contains_key(&parent_impl_id) + || krate.trait_items.contains_key(&parent_trait_id)) + { + span_err!( + self.tcx.sess, + lifetime.span, + E0657, + "`impl Trait` can only capture lifetimes \ + bound at the fn or impl level" + ); + self.uninsert_lifetime_on_error(lifetime, def.unwrap()); + } + } } } } - } - // Resolve the lifetimes in the bounds to the lifetime defs in the generics. - // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to - // `abstract type MyAnonTy<'b>: MyTrait<'b>;` - // ^ ^ this gets resolved in the scope of - // the exist_ty generics - let (generics, bounds) = match self.tcx.hir.expect_item(item_id.id).node { - hir::ItemExistential(hir::ExistTy{ ref generics, ref bounds, .. }) => ( - generics, - bounds, - ), - ref i => bug!("impl Trait pointed to non-existential type?? {:#?}", i), - }; + let id = self.tcx.hir.as_local_node_id(exist_ty_did).unwrap(); + + // Resolve the lifetimes in the bounds to the lifetime defs in the generics. + // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to + // `abstract type MyAnonTy<'b>: MyTrait<'b>;` + // ^ ^ this gets resolved in the scope of + // the exist_ty generics + let (generics, bounds) = match self.tcx.hir.expect_item(id).node { + hir::ItemExistential(hir::ExistTy{ ref generics, ref bounds, .. }) => ( + generics, + bounds, + ), + ref i => bug!("impl Trait pointed to non-existential type?? {:#?}", i), + }; - // We want to start our early-bound indices at the end of the parent scope, - // not including any parent `impl Trait`s. - let mut index = self.next_early_index_for_abstract_type(); - debug!("visit_ty: index = {}", index); + // We want to start our early-bound indices at the end of the parent scope, + // not including any parent `impl Trait`s. + let mut index = self.next_early_index_for_abstract_type(); + debug!("visit_ty: index = {}", index); - let mut elision = None; - let mut lifetimes = FxHashMap(); - let mut type_count = 0; - for param in &generics.params { - match param.kind { - GenericParamKind::Lifetime { .. } => { - let (name, reg) = Region::early(&self.tcx.hir, &mut index, ¶m); - if let hir::ParamName::Plain(param_name) = name { - if param_name.name == keywords::UnderscoreLifetime.name() { - // Pick the elided lifetime "definition" if one exists - // and use it to make an elision scope. - elision = Some(reg); + let mut elision = None; + let mut lifetimes = FxHashMap(); + let mut type_count = 0; + for param in &generics.params { + match param.kind { + GenericParamKind::Lifetime { .. } => { + let (name, reg) = Region::early(&self.tcx.hir, &mut index, ¶m); + if let hir::ParamName::Plain(param_name) = name { + if param_name.name == keywords::UnderscoreLifetime.name() { + // Pick the elided lifetime "definition" if one exists + // and use it to make an elision scope. + elision = Some(reg); + } else { + lifetimes.insert(name, reg); + } } else { lifetimes.insert(name, reg); } - } else { - lifetimes.insert(name, reg); } - } - GenericParamKind::Type { .. } => { - type_count += 1; + GenericParamKind::Type { .. } => { + type_count += 1; + } } } - } - let next_early_index = index + type_count; + let next_early_index = index + type_count; - if let Some(elision_region) = elision { - let scope = Scope::Elision { - elide: Elide::Exact(elision_region), - s: self.scope, - }; - self.with(scope, |_old_scope, this| { + if let Some(elision_region) = elision { + let scope = Scope::Elision { + elide: Elide::Exact(elision_region), + s: self.scope, + }; + self.with(scope, |_old_scope, this| { + let scope = Scope::Binder { + lifetimes, + next_early_index, + s: this.scope, + track_lifetime_uses: true, + abstract_type_parent: false, + }; + this.with(scope, |_old_scope, this| { + this.visit_generics(generics); + for bound in bounds { + this.visit_param_bound(bound); + } + }); + }); + } else { let scope = Scope::Binder { lifetimes, next_early_index, - s: this.scope, + s: self.scope, track_lifetime_uses: true, abstract_type_parent: false, }; - this.with(scope, |_old_scope, this| { + self.with(scope, |_old_scope, this| { this.visit_generics(generics); for bound in bounds { this.visit_param_bound(bound); } }); - }); + } } else { - let scope = Scope::Binder { - lifetimes, - next_early_index, - s: self.scope, - track_lifetime_uses: true, - abstract_type_parent: false, - }; - self.with(scope, |_old_scope, this| { - this.visit_generics(generics); - for bound in bounds { - this.visit_param_bound(bound); - } - }); + intravisit::walk_ty(self, ty) } } _ => intravisit::walk_ty(self, ty), diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index f5c2a0c3f9f05..a32fdbb285d12 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1115,12 +1115,12 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { } tcx.layout_raw(param_env.and(normalized))? } - ty::TyParam(_) => { - return Err(LayoutError::Unknown(ty)); - } - ty::TyGeneratorWitness(..) | ty::TyInfer(_) | ty::TyError => { + ty::TyGeneratorWitness(..) | ty::TyInfer(_) => { bug!("LayoutDetails::compute: unexpected type `{}`", ty) } + ty::TyParam(_) | ty::TyError => { + return Err(LayoutError::Unknown(ty)); + } }) } diff --git a/src/librustc_borrowck/borrowck/unused.rs b/src/librustc_borrowck/borrowck/unused.rs index 294ae1e63a9ee..475ff0b744349 100644 --- a/src/librustc_borrowck/borrowck/unused.rs +++ b/src/librustc_borrowck/borrowck/unused.rs @@ -54,16 +54,16 @@ impl<'a, 'tcx> UnusedMutCx<'a, 'tcx> { // Skip anything that looks like `&foo` or `&mut foo`, only look // for by-value bindings - let bm = match self.bccx.tables.pat_binding_modes().get(hir_id) { - Some(&bm) => bm, - None => span_bug!(span, "missing binding mode"), - }; - match bm { - ty::BindByValue(hir::MutMutable) => {} - _ => return, + if let Some(&bm) = self.bccx.tables.pat_binding_modes().get(hir_id) { + match bm { + ty::BindByValue(hir::MutMutable) => {} + _ => return, + } + + mutables.entry(ident.name).or_insert(Vec::new()).push((hir_id, span)); + } else { + tcx.sess.delay_span_bug(span, "missing binding mode"); } - - mutables.entry(ident.name).or_insert(Vec::new()).push((hir_id, span)); }); } diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 07830d54d0c9e..741758cb954ba 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -331,6 +331,12 @@ pub fn initialize_available_targets() { LLVMInitializeAArch64TargetMC, LLVMInitializeAArch64AsmPrinter, LLVMInitializeAArch64AsmParser); + init_target!(llvm_component = "amdgpu", + LLVMInitializeAMDGPUTargetInfo, + LLVMInitializeAMDGPUTarget, + LLVMInitializeAMDGPUTargetMC, + LLVMInitializeAMDGPUAsmPrinter, + LLVMInitializeAMDGPUAsmParser); init_target!(llvm_component = "mips", LLVMInitializeMipsTargetInfo, LLVMInitializeMipsTarget, diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 44fc67dfa4379..f903dbd97a814 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -10,8 +10,10 @@ use borrow_check::WriteKind; use rustc::middle::region::ScopeTree; -use rustc::mir::{BorrowKind, Field, Local, LocalKind, Location, Operand}; -use rustc::mir::{Place, ProjectionElem, Rvalue, Statement, StatementKind}; +use rustc::mir::{BindingForm, BorrowKind, ClearCrossCrate, Field, Local}; +use rustc::mir::{LocalDecl, LocalKind, Location, Operand, Place}; +use rustc::mir::{ProjectionElem, Rvalue, Statement, StatementKind}; +use rustc::mir::VarBindingForm; use rustc::ty::{self, RegionKind}; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::sync::Lrc; @@ -622,42 +624,55 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { assigned_span: Span, err_place: &Place<'tcx>, ) { - let is_arg = if let Place::Local(local) = place { - if let LocalKind::Arg = self.mir.local_kind(*local) { - true + let (from_arg, local_decl) = if let Place::Local(local) = *err_place { + if let LocalKind::Arg = self.mir.local_kind(local) { + (true, Some(&self.mir.local_decls[local])) } else { - false + (false, Some(&self.mir.local_decls[local])) } } else { - false + (false, None) + }; + + // If root local is initialized immediately (everything apart from let + // PATTERN;) then make the error refer to that local, rather than the + // place being assigned later. + let (place_description, assigned_span) = match local_decl { + Some(LocalDecl { is_user_variable: Some(ClearCrossCrate::Clear), .. }) + | Some(LocalDecl { is_user_variable: Some(ClearCrossCrate::Set( + BindingForm::Var(VarBindingForm { + opt_match_place: None, .. + }))), ..}) + | Some(LocalDecl { is_user_variable: None, .. }) + | None => (self.describe_place(place), assigned_span), + Some(decl) => (self.describe_place(err_place), decl.source_info.span), }; let mut err = self.tcx.cannot_reassign_immutable( span, - &self.describe_place(place).unwrap_or("_".to_owned()), - is_arg, + place_description.as_ref().map(AsRef::as_ref).unwrap_or("_"), + from_arg, Origin::Mir, ); - let msg = if is_arg { + let msg = if from_arg { "cannot assign to immutable argument" } else { "cannot assign twice to immutable variable" }; if span != assigned_span { - if !is_arg { - let value_msg = match self.describe_place(place) { + if !from_arg { + let value_msg = match place_description { Some(name) => format!("`{}`", name), None => "value".to_owned(), }; err.span_label(assigned_span, format!("first assignment to {}", value_msg)); } } - if let Place::Local(local) = err_place { - let local_decl = &self.mir.local_decls[*local]; - if let Some(name) = local_decl.name { - if local_decl.can_be_made_mutable() { + if let Some(decl) = local_decl { + if let Some(name) = decl.name { + if decl.can_be_made_mutable() { err.span_label( - local_decl.source_info.span, + decl.source_info.span, format!("consider changing this to `mut {}`", name), ); } diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 4db5c8e9278e5..cdf0079e2ae83 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -541,13 +541,14 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, if let hir::PatKind::Binding(_, _, ident, _) = pat.node { decl.debug_name = ident.name; - let bm = *hir.tables.pat_binding_modes() - .get(pat.hir_id) - .expect("missing binding mode"); - if bm == ty::BindByValue(hir::MutMutable) { - decl.mutability = Mutability::Mut; + if let Some(&bm) = hir.tables.pat_binding_modes().get(pat.hir_id) { + if bm == ty::BindByValue(hir::MutMutable) { + decl.mutability = Mutability::Mut; + } else { + decl.mutability = Mutability::Not; + } } else { - decl.mutability = Mutability::Not; + tcx.sess.delay_span_bug(pat.span, "missing binding mode"); } } } diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index b9d6486d9174a..502091e519201 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -541,9 +541,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// Finds the breakable scope for a given label. This is used for /// resolving `break` and `continue`. pub fn find_breakable_scope(&self, - span: Span, - label: region::Scope) - -> &BreakableScope<'tcx> { + span: Span, + label: region::Scope) + -> &BreakableScope<'tcx> { // find the loop-scope with the correct id self.breakable_scopes.iter() .rev() diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index e04cdcfa02773..18ae7c7745915 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -309,33 +309,32 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { fn check_for_bindings_named_the_same_as_variants(cx: &MatchVisitor, pat: &Pat) { pat.walk(|p| { if let PatKind::Binding(_, _, ident, None) = p.node { - let bm = *cx.tables - .pat_binding_modes() - .get(p.hir_id) - .expect("missing binding mode"); - - if bm != ty::BindByValue(hir::MutImmutable) { - // Nothing to check. - return true; - } - let pat_ty = cx.tables.pat_ty(p); - if let ty::TyAdt(edef, _) = pat_ty.sty { - if edef.is_enum() && edef.variants.iter().any(|variant| { - variant.name == ident.name && variant.ctor_kind == CtorKind::Const - }) { - let ty_path = cx.tcx.item_path_str(edef.did); - let mut err = struct_span_warn!(cx.tcx.sess, p.span, E0170, - "pattern binding `{}` is named the same as one \ - of the variants of the type `{}`", - ident, ty_path); - err.span_suggestion_with_applicability( - p.span, - "to match on the variant, qualify the path", - format!("{}::{}", ty_path, ident), - Applicability::MachineApplicable - ); - err.emit(); + if let Some(&bm) = cx.tables.pat_binding_modes().get(p.hir_id) { + if bm != ty::BindByValue(hir::MutImmutable) { + // Nothing to check. + return true; } + let pat_ty = cx.tables.pat_ty(p); + if let ty::TyAdt(edef, _) = pat_ty.sty { + if edef.is_enum() && edef.variants.iter().any(|variant| { + variant.name == ident.name && variant.ctor_kind == CtorKind::Const + }) { + let ty_path = cx.tcx.item_path_str(edef.did); + let mut err = struct_span_warn!(cx.tcx.sess, p.span, E0170, + "pattern binding `{}` is named the same as one \ + of the variants of the type `{}`", + ident, ty_path); + err.span_suggestion_with_applicability( + p.span, + "to match on the variant, qualify the path", + format!("{}::{}", ty_path, ident), + Applicability::MachineApplicable + ); + err.emit(); + } + } + } else { + cx.tcx.sess.delay_span_bug(p.span, "missing binding mode"); } } true @@ -517,12 +516,12 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor, let mut by_ref_span = None; for pat in pats { pat.each_binding(|_, hir_id, span, _path| { - let bm = *cx.tables - .pat_binding_modes() - .get(hir_id) - .expect("missing binding mode"); - if let ty::BindByReference(..) = bm { - by_ref_span = Some(span); + if let Some(&bm) = cx.tables.pat_binding_modes().get(hir_id) { + if let ty::BindByReference(..) = bm { + by_ref_span = Some(span); + } + } else { + cx.tcx.sess.delay_span_bug(pat.span, "missing binding mode"); } }) } @@ -553,18 +552,18 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor, for pat in pats { pat.walk(|p| { if let PatKind::Binding(_, _, _, ref sub) = p.node { - let bm = *cx.tables - .pat_binding_modes() - .get(p.hir_id) - .expect("missing binding mode"); - match bm { - ty::BindByValue(..) => { - let pat_ty = cx.tables.node_id_to_type(p.hir_id); - if pat_ty.moves_by_default(cx.tcx, cx.param_env, pat.span) { - check_move(p, sub.as_ref().map(|p| &**p)); + if let Some(&bm) = cx.tables.pat_binding_modes().get(p.hir_id) { + match bm { + ty::BindByValue(..) => { + let pat_ty = cx.tables.node_id_to_type(p.hir_id); + if pat_ty.moves_by_default(cx.tcx, cx.param_env, pat.span) { + check_move(p, sub.as_ref().map(|p| &**p)); + } } + _ => {} } - _ => {} + } else { + cx.tcx.sess.delay_span_bug(pat.span, "missing binding mode"); } } true diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 4d0e3e826e878..636969e263222 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -743,8 +743,10 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { ); *self.const_to_pat(instance, val, expr.hir_id, lit.span).kind }, - Err(()) => { - self.errors.push(PatternError::FloatBug); + Err(e) => { + if e == LitToConstError::UnparseableFloat { + self.errors.push(PatternError::FloatBug); + } PatternKind::Wild }, } @@ -764,8 +766,10 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { ); *self.const_to_pat(instance, val, expr.hir_id, lit.span).kind }, - Err(()) => { - self.errors.push(PatternError::FloatBug); + Err(e) => { + if e == LitToConstError::UnparseableFloat { + self.errors.push(PatternError::FloatBug); + } PatternKind::Wild }, } @@ -1118,12 +1122,18 @@ pub fn compare_const_vals<'a, 'tcx>( fallback() } +#[derive(PartialEq)] +enum LitToConstError { + UnparseableFloat, + Propagated, +} + // FIXME: Combine with rustc_mir::hair::cx::const_eval_literal fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind, tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>, neg: bool) - -> Result<&'tcx ty::Const<'tcx>, ()> { + -> Result<&'tcx ty::Const<'tcx>, LitToConstError> { use syntax::ast::*; use rustc::mir::interpret::*; @@ -1152,7 +1162,10 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind, ty::TyInt(other) => Int::Signed(other), ty::TyUint(UintTy::Usize) => Int::Unsigned(tcx.sess.target.usize_ty), ty::TyUint(other) => Int::Unsigned(other), - _ => bug!(), + ty::TyError => { // Avoid ICE (#51963) + return Err(LitToConstError::Propagated); + } + _ => bug!("literal integer type with bad type ({:?})", ty.sty), }; // This converts from LitKind::Int (which is sign extended) to // Scalar::Bytes (which is zero extended) @@ -1182,14 +1195,14 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind, }) }, LitKind::Float(n, fty) => { - parse_float(n, fty, neg)? + parse_float(n, fty, neg).map_err(|_| LitToConstError::UnparseableFloat)? } LitKind::FloatUnsuffixed(n) => { let fty = match ty.sty { ty::TyFloat(fty) => fty, _ => bug!() }; - parse_float(n, fty, neg)? + parse_float(n, fty, neg).map_err(|_| LitToConstError::UnparseableFloat)? } LitKind::Bool(b) => ConstValue::Scalar(Scalar::Bits { bits: b as u128, diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs index 749c0d04ae91f..ea09bab5d1411 100644 --- a/src/librustc_mir/interpret/const_eval.rs +++ b/src/librustc_mir/interpret/const_eval.rs @@ -1,3 +1,6 @@ +use std::fmt; +use std::error::Error; + use rustc::hir; use rustc::mir::interpret::{ConstEvalErr}; use rustc::mir; @@ -15,9 +18,6 @@ use rustc::mir::interpret::{ }; use super::{Place, EvalContext, StackPopCleanup, ValTy, PlaceExtra, Memory, MemoryKind}; -use std::fmt; -use std::error::Error; - pub fn mk_borrowck_eval_cx<'a, 'mir, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance<'tcx>, @@ -152,7 +152,7 @@ fn eval_body_using_ecx<'a, 'mir, 'tcx>( let ptr = ecx.memory.allocate( layout.size, layout.align, - None, + MemoryKind::Stack, )?; let internally_mutable = !layout.ty.is_freeze(tcx, param_env, mir.span); let is_static = tcx.is_static(cid.instance.def_id()); @@ -486,7 +486,7 @@ pub fn const_variant_index<'a, 'tcx>( let (ptr, align) = match value { Value::ScalarPair(..) | Value::Scalar(_) => { let layout = ecx.layout_of(val.ty)?; - let ptr = ecx.memory.allocate(layout.size, layout.align, Some(MemoryKind::Stack))?.into(); + let ptr = ecx.memory.allocate(layout.size, layout.align, MemoryKind::Stack)?.into(); ecx.write_value_to_ptr(value, ptr, layout.align, val.ty)?; (ptr, layout.align) }, @@ -515,7 +515,7 @@ pub fn const_value_to_allocation_provider<'a, 'tcx>( ()); let value = ecx.const_to_value(val.val)?; let layout = ecx.layout_of(val.ty)?; - let ptr = ecx.memory.allocate(layout.size, layout.align, Some(MemoryKind::Stack))?; + let ptr = ecx.memory.allocate(layout.size, layout.align, MemoryKind::Stack)?; ecx.write_value_to_ptr(value, ptr.into(), layout.align, val.ty)?; let alloc = ecx.memory.get(ptr.alloc_id)?; Ok(tcx.intern_const_alloc(alloc.clone())) diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 15d8b9c36215a..031c75013a27b 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -1,4 +1,5 @@ use std::fmt::Write; +use std::mem; use rustc::hir::def_id::DefId; use rustc::hir::def::Def; @@ -9,14 +10,13 @@ use rustc::ty::subst::{Subst, Substs}; use rustc::ty::{self, Ty, TyCtxt, TypeAndMut}; use rustc::ty::query::TyCtxtAt; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; -use rustc::mir::interpret::FrameInfo; -use syntax::codemap::{self, Span}; -use syntax::ast::Mutability; use rustc::mir::interpret::{ - GlobalId, Value, Scalar, + FrameInfo, GlobalId, Value, Scalar, EvalResult, EvalErrorKind, Pointer, ConstValue, }; -use std::mem; + +use syntax::codemap::{self, Span}; +use syntax::ast::Mutability; use super::{Place, PlaceExtra, Memory, HasMemory, MemoryKind, @@ -206,7 +206,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M let layout = self.layout_of(ty)?; assert!(!layout.is_unsized(), "cannot alloc memory for unsized type"); - self.memory.allocate(layout.size, layout.align, Some(MemoryKind::Stack)) + self.memory.allocate(layout.size, layout.align, MemoryKind::Stack) } pub fn memory(&self) -> &Memory<'a, 'mir, 'tcx, M> { @@ -246,7 +246,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M } ConstValue::ByRef(alloc, offset) => { // FIXME: Allocate new AllocId for all constants inside - let id = self.memory.allocate_value(alloc.clone(), Some(MemoryKind::Stack))?; + let id = self.memory.allocate_value(alloc.clone(), MemoryKind::Stack)?; Ok(Value::ByRef(Pointer::new(id, offset).into(), alloc.align)) }, ConstValue::ScalarPair(a, b) => Ok(Value::ScalarPair(a, b)), diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index f5da65ae44db7..5cf734cce8a3f 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -6,12 +6,12 @@ use rustc::ty::Instance; use rustc::ty::ParamEnv; use rustc::ty::query::TyCtxtAt; use rustc::ty::layout::{self, Align, TargetDataLayout, Size}; -use syntax::ast::Mutability; - -use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use rustc::mir::interpret::{Pointer, AllocId, Allocation, AccessKind, Value, EvalResult, Scalar, EvalErrorKind, GlobalId, AllocType}; pub use rustc::mir::interpret::{write_target_uint, write_target_int, read_target_uint}; +use rustc_data_structures::fx::{FxHashSet, FxHashMap}; + +use syntax::ast::Mutability; use super::{EvalContext, Machine}; @@ -41,11 +41,6 @@ pub struct Memory<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> { /// Actual memory allocations (arbitrary bytes, may contain pointers into other allocations). alloc_map: FxHashMap, - /// Actual memory allocations (arbitrary bytes, may contain pointers into other allocations). - /// - /// Stores statics while they are being processed, before they are interned and thus frozen - uninitialized_statics: FxHashMap, - /// The current stack frame. Used to check accesses against locks. pub cur_frame: usize, @@ -58,7 +53,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { data, alloc_kind: FxHashMap::default(), alloc_map: FxHashMap::default(), - uninitialized_statics: FxHashMap::default(), tcx, cur_frame: usize::max_value(), } @@ -82,20 +76,12 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn allocate_value( &mut self, alloc: Allocation, - kind: Option>, + kind: MemoryKind, ) -> EvalResult<'tcx, AllocId> { let id = self.tcx.alloc_map.lock().reserve(); M::add_lock(self, id); - match kind { - Some(kind @ MemoryKind::Stack) | - Some(kind @ MemoryKind::Machine(_)) => { - self.alloc_map.insert(id, alloc); - self.alloc_kind.insert(id, kind); - }, - None => { - self.uninitialized_statics.insert(id, alloc); - }, - } + self.alloc_map.insert(id, alloc); + self.alloc_kind.insert(id, kind); Ok(id) } @@ -104,7 +90,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { &mut self, size: Size, align: Align, - kind: Option>, + kind: MemoryKind, ) -> EvalResult<'tcx, Pointer> { self.allocate_value(Allocation::undef(size, align), kind).map(Pointer::from) } @@ -132,7 +118,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { } // For simplicities' sake, we implement reallocate as "alloc, copy, dealloc" - let new_ptr = self.allocate(new_size, new_align, Some(kind))?; + let new_ptr = self.allocate(new_size, new_align, kind)?; self.copy( ptr.into(), old_align, @@ -168,12 +154,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { let alloc = match self.alloc_map.remove(&ptr.alloc_id) { Some(alloc) => alloc, - None => if self.uninitialized_statics.contains_key(&ptr.alloc_id) { - return err!(DeallocatedWrongMemoryKind( - "uninitializedstatic".to_string(), - format!("{:?}", kind), - )) - } else { + None => { return match self.tcx.alloc_map.lock().get(ptr.alloc_id) { Some(AllocType::Function(..)) => err!(DeallocatedWrongMemoryKind( "function".to_string(), @@ -299,24 +280,21 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn get(&self, id: AllocId) -> EvalResult<'tcx, &Allocation> { // normal alloc? match self.alloc_map.get(&id) { - Some(alloc) => Ok(alloc), + Some(alloc) => Ok(alloc), // uninitialized static alloc? - None => match self.uninitialized_statics.get(&id) { - Some(alloc) => Ok(alloc), - None => { - // static alloc? - let alloc = self.tcx.alloc_map.lock().get(id); - match alloc { - Some(AllocType::Memory(mem)) => Ok(mem), - Some(AllocType::Function(..)) => { - Err(EvalErrorKind::DerefFunctionPointer.into()) - } - Some(AllocType::Static(did)) => { - self.const_eval_static(did) - } - None => Err(EvalErrorKind::DanglingPointerDeref.into()), + None => { + // static alloc? + let alloc = self.tcx.alloc_map.lock().get(id); + match alloc { + Some(AllocType::Memory(mem)) => Ok(mem), + Some(AllocType::Function(..)) => { + Err(EvalErrorKind::DerefFunctionPointer.into()) + } + Some(AllocType::Static(did)) => { + self.const_eval_static(did) } - }, + None => Err(EvalErrorKind::DanglingPointerDeref.into()), + } }, } } @@ -329,17 +307,14 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { match self.alloc_map.get_mut(&id) { Some(alloc) => Ok(alloc), // uninitialized static alloc? - None => match self.uninitialized_statics.get_mut(&id) { - Some(alloc) => Ok(alloc), - None => { - // no alloc or immutable alloc? produce an error - match self.tcx.alloc_map.lock().get(id) { - Some(AllocType::Memory(..)) | - Some(AllocType::Static(..)) => err!(ModifiedConstantMemory), - Some(AllocType::Function(..)) => err!(DerefFunctionPointer), - None => err!(DanglingPointerDeref), - } - }, + None => { + // no alloc or immutable alloc? produce an error + match self.tcx.alloc_map.lock().get(id) { + Some(AllocType::Memory(..)) | + Some(AllocType::Static(..)) => err!(ModifiedConstantMemory), + Some(AllocType::Function(..)) => err!(DerefFunctionPointer), + None => err!(DanglingPointerDeref), + } }, } } @@ -390,27 +365,23 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { MemoryKind::Stack => " (stack)".to_owned(), MemoryKind::Machine(m) => format!(" ({:?})", m), }), - // uninitialized static alloc? - None => match self.uninitialized_statics.get(&id) { - Some(a) => (a, " (static in the process of initialization)".to_owned()), - None => { - // static alloc? - match self.tcx.alloc_map.lock().get(id) { - Some(AllocType::Memory(a)) => (a, "(immutable)".to_owned()), - Some(AllocType::Function(func)) => { - trace!("{} {}", msg, func); - continue; - } - Some(AllocType::Static(did)) => { - trace!("{} {:?}", msg, did); - continue; - } - None => { - trace!("{} (deallocated)", msg); - continue; - } + None => { + // static alloc? + match self.tcx.alloc_map.lock().get(id) { + Some(AllocType::Memory(a)) => (a, "(immutable)".to_owned()), + Some(AllocType::Function(func)) => { + trace!("{} {}", msg, func); + continue; } - }, + Some(AllocType::Static(did)) => { + trace!("{} {:?}", msg, did); + continue; + } + None => { + trace!("{} (deallocated)", msg); + continue; + } + } }, }; @@ -569,8 +540,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { Some(MemoryKind::Machine(_)) => bug!("machine didn't handle machine alloc"), Some(MemoryKind::Stack) => {}, } - let uninit = self.uninitialized_statics.remove(&alloc_id); - if let Some(mut alloc) = alloc.or(uninit) { + if let Some(mut alloc) = alloc { // ensure llvm knows not to put this into immutable memroy alloc.runtime_mutability = mutability; let alloc = self.tcx.intern_const_alloc(alloc); diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs index 373a0b0d0bfed..b6c7feda19fa8 100644 --- a/src/librustc_mir/interpret/traits.rs +++ b/src/librustc_mir/interpret/traits.rs @@ -1,9 +1,10 @@ use rustc::ty::{self, Ty}; use rustc::ty::layout::{Size, Align, LayoutOf}; +use rustc::mir::interpret::{Scalar, Value, Pointer, EvalResult}; + use syntax::ast::Mutability; -use rustc::mir::interpret::{Scalar, Value, Pointer, EvalResult}; -use super::{EvalContext, Machine}; +use super::{EvalContext, Machine, MemoryKind}; impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { /// Creates a dynamic vtable for the given type and vtable origin. This is used only for @@ -30,7 +31,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { let vtable = self.memory.allocate( ptr_size * (3 + methods.len() as u64), ptr_align, - None, + MemoryKind::Stack, )?; let drop = ::monomorphize::resolve_drop_in_place(*self.tcx, ty); diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs index c99f1e9da439f..eff0dbe1235ff 100644 --- a/src/librustc_passes/loops.rs +++ b/src/librustc_passes/loops.rs @@ -17,7 +17,7 @@ use rustc::hir::{self, Destination}; use syntax::ast; use syntax_pos::Span; -#[derive(Clone, Copy, PartialEq)] +#[derive(Clone, Copy, Debug, PartialEq)] enum LoopKind { Loop(hir::LoopSource), WhileLoop, @@ -34,12 +34,13 @@ impl LoopKind { } } -#[derive(Clone, Copy, PartialEq)] +#[derive(Clone, Copy, Debug, PartialEq)] enum Context { Normal, Loop(LoopKind), Closure, LabeledBlock, + AnonConst, } #[derive(Copy, Clone)] @@ -71,6 +72,10 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { self.with_context(Normal, |v| intravisit::walk_impl_item(v, i)); } + fn visit_anon_const(&mut self, c: &'hir hir::AnonConst) { + self.with_context(AnonConst, |v| intravisit::walk_anon_const(v, c)); + } + fn visit_expr(&mut self, e: &'hir hir::Expr) { match e.node { hir::ExprWhile(ref e, ref b, _) => { @@ -194,7 +199,7 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> { .span_label(span, "cannot break inside of a closure") .emit(); } - Normal => { + Normal | AnonConst => { struct_span_err!(self.sess, span, E0268, "`{}` outside of loop", name) .span_label(span, "cannot break outside of a loop") .emit(); diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index c55d57cb91631..3919ba13076f6 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -229,8 +229,12 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { hir::ItemUse(..) => {} // The interface is empty hir::ItemGlobalAsm(..) => {} - // Checked by visit_ty - hir::ItemExistential(..) => {} + hir::ItemExistential(..) => { + if item_level.is_some() { + // Reach the (potentially private) type and the API being exposed + self.reach(item.id).ty().predicates(); + } + } // Visit everything hir::ItemConst(..) | hir::ItemStatic(..) | hir::ItemFn(..) | hir::ItemTy(..) => { @@ -390,17 +394,6 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { module_id = self.tcx.hir.get_parent_node(module_id); } } - - fn visit_ty(&mut self, ty: &'tcx hir::Ty) { - if let hir::TyImplTraitExistential(item_id, _, _) = ty.node { - if self.get(item_id.id).is_some() { - // Reach the (potentially private) type and the API being exposed - self.reach(item_id.id).ty().predicates(); - } - } - - intravisit::walk_ty(self, ty); - } } impl<'b, 'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { @@ -1568,8 +1561,15 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> hir::ItemUse(..) => {} // No subitems hir::ItemGlobalAsm(..) => {} - // Checked in visit_ty - hir::ItemExistential(..) => {} + hir::ItemExistential(..) => { + // Check the traits being exposed, as they're separate, + // e.g. `impl Iterator` has two predicates, + // `X: Iterator` and `::Item == T`, + // where `X` is the `impl Iterator` itself, + // stored in `predicates_of`, not in the `Ty` itself. + + self.check(item.id, self.inner_visibility).predicates(); + } // Subitems of these items have inherited publicity hir::ItemConst(..) | hir::ItemStatic(..) | hir::ItemFn(..) | hir::ItemTy(..) => { @@ -1667,20 +1667,6 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> // handled in `visit_item` above } - fn visit_ty(&mut self, ty: &'tcx hir::Ty) { - if let hir::TyImplTraitExistential(ref exist_item, _, _) = ty.node { - // Check the traits being exposed, as they're separate, - // e.g. `impl Iterator` has two predicates, - // `X: Iterator` and `::Item == T`, - // where `X` is the `impl Iterator` itself, - // stored in `predicates_of`, not in the `Ty` itself. - - self.check(exist_item.id, self.inner_visibility).predicates(); - } - - intravisit::walk_ty(self, ty); - } - // Don't recurse into expressions in array sizes or const initializers fn visit_expr(&mut self, _: &'tcx hir::Expr) {} // Don't recurse into patterns in function arguments diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 762dc5d26f5a4..2e467d315bedd 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1095,6 +1095,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { hir::TyStr => tcx.mk_str() } } + Def::Existential(exist_ty_did) => { + assert!(exist_ty_did.is_local()); + let lifetimes = &path.segments[0].args.as_ref().unwrap().args; + self.impl_trait_ty_to_ty(exist_ty_did, lifetimes) + } Def::Err => { self.set_tainted_by_errors(); return self.tcx().types.err; @@ -1140,9 +1145,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { hir::TyTraitObject(ref bounds, ref lifetime) => { self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime) } - hir::TyImplTraitExistential(_, def_id, ref lifetimes) => { - self.impl_trait_ty_to_ty(def_id, lifetimes) - } hir::TyPath(hir::QPath::Resolved(ref maybe_qself, ref path)) => { debug!("ast_ty_to_ty: maybe_qself={:?} path={:?}", maybe_qself, path); let opt_self_ty = maybe_qself.as_ref().map(|qself| { @@ -1195,7 +1197,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { pub fn impl_trait_ty_to_ty( &self, def_id: DefId, - lifetimes: &[hir::Lifetime], + lifetimes: &[hir::GenericArg], ) -> Ty<'tcx> { debug!("impl_trait_ty_to_ty(def_id={:?}, lifetimes={:?})", def_id, lifetimes); let tcx = self.tcx(); @@ -1208,7 +1210,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // Our own parameters are the resolved lifetimes. match param.kind { GenericParamDefKind::Lifetime => { - self.ast_region_to_region(&lifetimes[i], None).into() + if let hir::GenericArg::Lifetime(lifetime) = &lifetimes[i] { + self.ast_region_to_region(lifetime, None).into() + } else { + bug!() + } } _ => bug!() } diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 08d8dd2e498b6..aee64ad3b550c 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -264,9 +264,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { (&ty::TyStr, &ty::TySlice(arr)) if arr == self.tcx.types.u8 => { if let hir::ExprLit(_) = expr.node { if let Ok(src) = cm.span_to_snippet(sp) { - return Some((sp, - "consider removing the leading `b`", - src[1..].to_string())); + if src.starts_with("b\"") { + return Some((sp, + "consider removing the leading `b`", + src[1..].to_string())); + } } } }, @@ -274,9 +276,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { (&ty::TySlice(arr), &ty::TyStr) if arr == self.tcx.types.u8 => { if let hir::ExprLit(_) = expr.node { if let Ok(src) = cm.span_to_snippet(sp) { - return Some((sp, - "consider adding a leading `b`", - format!("b{}", src))); + if src.starts_with("\"") { + return Some((sp, + "consider adding a leading `b`", + format!("b{}", src))); + } } } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index fa78b38dbb7a8..646c4f17568f0 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3827,7 +3827,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // this can only happen if the `break` was not // inside a loop at all, which is caught by the // loop-checking pass. - assert!(self.tcx.sess.err_count() > 0); + if self.tcx.sess.err_count() == 0 { + self.tcx.sess.delay_span_bug(expr.span, + "break was outside loop, but no error was emitted"); + } // We still need to assign a type to the inner expression to // prevent the ICE in #43162. @@ -3960,7 +3963,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // is nil. This makes sense because infinite loops // (which would have type !) are only possible iff we // permit break with a value [1]. - assert!(ctxt.coerce.is_some() || ctxt.may_break); // [1] + if ctxt.coerce.is_none() && !ctxt.may_break { + // [1] + self.tcx.sess.delay_span_bug(body.span, "no coercion, but loop may not break"); + } ctxt.coerce.map(|c| c.complete(self)).unwrap_or(self.tcx.mk_nil()) } hir::ExprMatch(ref discrim, ref arms, match_src) => { diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index e489c4d4a46be..68fcde0b1657a 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -1039,11 +1039,13 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { match sub_pat.node { // `ref x` pattern PatKind::Binding(..) => { - let bm = *mc.tables.pat_binding_modes().get(sub_pat.hir_id) - .expect("missing binding mode"); - if let ty::BindByReference(mutbl) = bm { - self.link_region_from_node_type(sub_pat.span, sub_pat.hir_id, - mutbl, &sub_cmt); + if let Some(&bm) = mc.tables.pat_binding_modes().get(sub_pat.hir_id) { + if let ty::BindByReference(mutbl) = bm { + self.link_region_from_node_type(sub_pat.span, sub_pat.hir_id, + mutbl, &sub_cmt); + } + } else { + self.tcx.sess.delay_span_bug(sub_pat.span, "missing binding mode"); } } _ => {} diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index f7d1e40794580..2445cae98607a 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -257,13 +257,11 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> { fn visit_pat(&mut self, p: &'gcx hir::Pat) { match p.node { hir::PatKind::Binding(..) => { - let bm = *self.fcx - .tables - .borrow() - .pat_binding_modes() - .get(p.hir_id) - .expect("missing binding mode"); - self.tables.pat_binding_modes_mut().insert(p.hir_id, bm); + if let Some(&bm) = self.fcx.tables.borrow().pat_binding_modes().get(p.hir_id) { + self.tables.pat_binding_modes_mut().insert(p.hir_id, bm); + } else { + self.tcx().sess.delay_span_bug(p.span, "missing binding mode"); + } } hir::PatKind::Struct(_, ref fields, _) => { for field in fields { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 852603ac51c35..4931cbfa5acc3 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -875,10 +875,6 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } - NodeTy(&hir::Ty { node: hir::TyImplTraitExistential(..), .. }) => { - bug!("impl Trait is desugared to existential type items"); - } - _ => &no_generics, }; diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index b8abb98edec48..f71d62d5a04e1 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2987,14 +2987,6 @@ impl Clean for hir::Ty { } } TyBareFn(ref barefn) => BareFunction(box barefn.clean(cx)), - TyImplTraitExistential(hir_id, _, _) => { - match cx.tcx.hir.expect_item(hir_id.id).node { - hir::ItemExistential(ref exist_ty) => { - ImplTrait(exist_ty.bounds.clean(cx)) - }, - ref other => panic!("impl Trait pointed to {:#?}", other), - } - }, TyInfer | TyErr => Infer, TyTypeof(..) => panic!("Unimplemented type {:?}", self.node), } diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs index 8ac52572810c6..aadd33b39542c 100644 --- a/src/libstd/io/cursor.rs +++ b/src/libstd/io/cursor.rs @@ -10,6 +10,7 @@ use io::prelude::*; +use core::convert::TryInto; use cmp; use io::{self, Initializer, SeekFrom, Error, ErrorKind}; @@ -259,26 +260,9 @@ fn slice_write(pos_mut: &mut u64, slice: &mut [u8], buf: &[u8]) -> io::Result Result { - if n <= (::max_value() as u64) { - Ok(n as usize) - } else { - Err(()) - } -} - -#[cfg(any(target_pointer_width = "64"))] -fn try_into(n: u64) -> Result { - Ok(n as usize) -} - // Resizing write implementation fn vec_write(pos_mut: &mut u64, vec: &mut Vec, buf: &[u8]) -> io::Result { - let pos: usize = try_into(*pos_mut).map_err(|_| { + let pos: usize = (*pos_mut).try_into().map_err(|_| { Error::new(ErrorKind::InvalidInput, "cursor position exceeds maximum possible vector length") })?; diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs index 4e98101266903..507e9d881717b 100644 --- a/src/libstd/sys/unix/ext/fs.rs +++ b/src/libstd/sys/unix/ext/fs.rs @@ -59,6 +59,78 @@ pub trait FileExt { #[stable(feature = "file_offset", since = "1.15.0")] fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result; + /// Reads the exact number of byte required to fill `buf` from the given offset. + /// + /// The offset is relative to the start of the file and thus independent + /// from the current cursor. + /// + /// The current file cursor is not affected by this function. + /// + /// Similar to [`Read::read_exact`] but uses [`read_at`] instead of `read`. + /// + /// [`Read::read_exact`]: ../../../../std/io/trait.Read.html#method.read_exact + /// [`read_at`]: #tymethod.read_at + /// + /// # Errors + /// + /// If this function encounters an error of the kind + /// [`ErrorKind::Interrupted`] then the error is ignored and the operation + /// will continue. + /// + /// If this function encounters an "end of file" before completely filling + /// the buffer, it returns an error of the kind [`ErrorKind::UnexpectedEof`]. + /// The contents of `buf` are unspecified in this case. + /// + /// If any other read error is encountered then this function immediately + /// returns. The contents of `buf` are unspecified in this case. + /// + /// If this function returns an error, it is unspecified how many bytes it + /// has read, but it will never read more than would be necessary to + /// completely fill the buffer. + /// + /// [`ErrorKind::Interrupted`]: ../../../../std/io/enum.ErrorKind.html#variant.Interrupted + /// [`ErrorKind::UnexpectedEof`]: ../../../../std/io/enum.ErrorKind.html#variant.UnexpectedEof + /// + /// # Examples + /// + /// ```no_run + /// #![feature(rw_exact_all_at)] + /// use std::io; + /// use std::fs::File; + /// use std::os::unix::prelude::FileExt; + /// + /// fn main() -> io::Result<()> { + /// let mut buf = [0u8; 8]; + /// let file = File::open("foo.txt")?; + /// + /// // We now read exactly 8 bytes from the offset 10. + /// file.read_exact_at(&mut buf, 10)?; + /// println!("read {} bytes: {:?}", buf.len(), buf); + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "rw_exact_all_at", issue = "51984")] + fn read_exact_at(&self, mut buf: &mut [u8], mut offset: u64) -> io::Result<()> { + while !buf.is_empty() { + match self.read_at(buf, offset) { + Ok(0) => break, + Ok(n) => { + let tmp = buf; + buf = &mut tmp[n..]; + offset += n as u64; + } + Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {} + Err(e) => return Err(e), + } + } + if !buf.is_empty() { + Err(io::Error::new(io::ErrorKind::UnexpectedEof, + "failed to fill whole buffer")) + } else { + Ok(()) + } + } + /// Writes a number of bytes starting from a given offset. /// /// Returns the number of bytes written. @@ -93,6 +165,61 @@ pub trait FileExt { /// ``` #[stable(feature = "file_offset", since = "1.15.0")] fn write_at(&self, buf: &[u8], offset: u64) -> io::Result; + + /// Attempts to write an entire buffer starting from a given offset. + /// + /// The offset is relative to the start of the file and thus independent + /// from the current cursor. + /// + /// The current file cursor is not affected by this function. + /// + /// This method will continuously call [`write_at`] until there is no more data + /// to be written or an error of non-[`ErrorKind::Interrupted`] kind is + /// returned. This method will not return until the entire buffer has been + /// successfully written or such an error occurs. The first error that is + /// not of [`ErrorKind::Interrupted`] kind generated from this method will be + /// returned. + /// + /// # Errors + /// + /// This function will return the first error of + /// non-[`ErrorKind::Interrupted`] kind that [`write_at`] returns. + /// + /// [`ErrorKind::Interrupted`]: ../../../../std/io/enum.ErrorKind.html#variant.Interrupted + /// [`write_at`]: #tymethod.write_at + /// + /// # Examples + /// + /// ```no_run + /// #![feature(rw_exact_all_at)] + /// use std::fs::File; + /// use std::io; + /// use std::os::unix::prelude::FileExt; + /// + /// fn main() -> io::Result<()> { + /// let file = File::open("foo.txt")?; + /// + /// // We now write at the offset 10. + /// file.write_all_at(b"sushi", 10)?; + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "rw_exact_all_at", issue = "51984")] + fn write_all_at(&self, mut buf: &[u8], mut offset: u64) -> io::Result<()> { + while !buf.is_empty() { + match self.write_at(buf, offset) { + Ok(0) => return Err(io::Error::new(io::ErrorKind::WriteZero, + "failed to write whole buffer")), + Ok(n) => { + buf = &buf[n..]; + offset += n as u64 + } + Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {} + Err(e) => return Err(e), + } + } + Ok(()) + } } #[stable(feature = "file_offset", since = "1.15.0")] diff --git a/src/test/compile-fail/immut-function-arguments.rs b/src/test/compile-fail/immut-function-arguments.rs index b32056fcb915a..61a074952efd2 100644 --- a/src/test/compile-fail/immut-function-arguments.rs +++ b/src/test/compile-fail/immut-function-arguments.rs @@ -13,12 +13,12 @@ fn f(y: Box) { *y = 5; //[ast]~ ERROR cannot assign - //[mir]~^ ERROR cannot assign twice + //[mir]~^ ERROR cannot assign } fn g() { let _frob = |q: Box| { *q = 2; }; //[ast]~ ERROR cannot assign - //[mir]~^ ERROR cannot assign twice + //[mir]~^ ERROR cannot assign } fn main() {} diff --git a/src/test/ui/array-break-length.rs b/src/test/ui/array-break-length.rs new file mode 100644 index 0000000000000..c3cfff0e1f642 --- /dev/null +++ b/src/test/ui/array-break-length.rs @@ -0,0 +1,19 @@ +// 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. + +fn main() { + loop { + |_: [_; break]| {} //~ ERROR: `break` outside of loop + } + + loop { + |_: [_; continue]| {} //~ ERROR: `continue` outside of loop + } +} diff --git a/src/test/ui/array-break-length.stderr b/src/test/ui/array-break-length.stderr new file mode 100644 index 0000000000000..114245b9cc77b --- /dev/null +++ b/src/test/ui/array-break-length.stderr @@ -0,0 +1,15 @@ +error[E0268]: `break` outside of loop + --> $DIR/array-break-length.rs:13:17 + | +LL | |_: [_; break]| {} //~ ERROR: `break` outside of loop + | ^^^^^ cannot break outside of a loop + +error[E0268]: `continue` outside of loop + --> $DIR/array-break-length.rs:17:17 + | +LL | |_: [_; continue]| {} //~ ERROR: `continue` outside of loop + | ^^^^^^^^ cannot break outside of a loop + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0268`. diff --git a/src/test/ui/closure-array-break-length.rs b/src/test/ui/closure-array-break-length.rs index 2e99921956ab2..8be5b925a399e 100644 --- a/src/test/ui/closure-array-break-length.rs +++ b/src/test/ui/closure-array-break-length.rs @@ -11,7 +11,7 @@ fn main() { |_: [_; continue]| {}; //~ ERROR: `continue` outside of loop - while |_: [_; continue]| {} {} //~ ERROR: `break` or `continue` with no label + while |_: [_; continue]| {} {} //~ ERROR: `continue` outside of loop - while |_: [_; break]| {} {} //~ ERROR: `break` or `continue` with no label + while |_: [_; break]| {} {} //~ ERROR: `break` outside of loop } diff --git a/src/test/ui/closure-array-break-length.stderr b/src/test/ui/closure-array-break-length.stderr index 139153992e274..f62b135437092 100644 --- a/src/test/ui/closure-array-break-length.stderr +++ b/src/test/ui/closure-array-break-length.stderr @@ -4,19 +4,18 @@ error[E0268]: `continue` outside of loop LL | |_: [_; continue]| {}; //~ ERROR: `continue` outside of loop | ^^^^^^^^ cannot break outside of a loop -error[E0590]: `break` or `continue` with no label in the condition of a `while` loop +error[E0268]: `continue` outside of loop --> $DIR/closure-array-break-length.rs:14:19 | -LL | while |_: [_; continue]| {} {} //~ ERROR: `break` or `continue` with no label - | ^^^^^^^^ unlabeled `continue` in the condition of a `while` loop +LL | while |_: [_; continue]| {} {} //~ ERROR: `continue` outside of loop + | ^^^^^^^^ cannot break outside of a loop -error[E0590]: `break` or `continue` with no label in the condition of a `while` loop +error[E0268]: `break` outside of loop --> $DIR/closure-array-break-length.rs:16:19 | -LL | while |_: [_; break]| {} {} //~ ERROR: `break` or `continue` with no label - | ^^^^^ unlabeled `break` in the condition of a `while` loop +LL | while |_: [_; break]| {} {} //~ ERROR: `break` outside of loop + | ^^^^^ cannot break outside of a loop error: aborting due to 3 previous errors -Some errors occurred: E0268, E0590. -For more information about an error, try `rustc --explain E0268`. +For more information about this error, try `rustc --explain E0268`. diff --git a/src/test/ui/command-line-diagnostics.nll.stderr b/src/test/ui/command-line-diagnostics.nll.stderr index 10dcf7d0e657a..46bb7c5af5744 100644 --- a/src/test/ui/command-line-diagnostics.nll.stderr +++ b/src/test/ui/command-line-diagnostics.nll.stderr @@ -2,8 +2,9 @@ error[E0384]: cannot assign twice to immutable variable `x` --> $DIR/command-line-diagnostics.rs:16:5 | LL | let x = 42; - | - -- first assignment to `x` + | - | | + | first assignment to `x` | consider changing this to `mut x` LL | x = 43; | ^^^^^^ cannot assign twice to immutable variable diff --git a/src/test/ui/did_you_mean/issue-35937.nll.stderr b/src/test/ui/did_you_mean/issue-35937.nll.stderr index 0c1dcb29d4d2c..7eaa4c7d5fea0 100644 --- a/src/test/ui/did_you_mean/issue-35937.nll.stderr +++ b/src/test/ui/did_you_mean/issue-35937.nll.stderr @@ -6,26 +6,24 @@ LL | let f = Foo { v: Vec::new() }; LL | f.v.push("cat".to_string()); //~ ERROR cannot borrow | ^^^ cannot borrow as mutable -error[E0384]: cannot assign twice to immutable variable `s.x` +error[E0384]: cannot assign twice to immutable variable `s` --> $DIR/issue-35937.rs:26:5 | LL | let s = S { x: 42 }; - | - ----------- first assignment to `s.x` + | - | | + | first assignment to `s` | consider changing this to `mut s` LL | s.x += 1; //~ ERROR cannot assign | ^^^^^^^^ cannot assign twice to immutable variable -error[E0384]: cannot assign twice to immutable variable `s.x` +error[E0384]: cannot assign to immutable argument `s` --> $DIR/issue-35937.rs:30:5 | LL | fn bar(s: S) { - | - - | | - | first assignment to `s.x` - | consider changing this to `mut s` + | - consider changing this to `mut s` LL | s.x += 1; //~ ERROR cannot assign - | ^^^^^^^^ cannot assign twice to immutable variable + | ^^^^^^^^ cannot assign to immutable argument error: aborting due to 3 previous errors diff --git a/src/test/ui/issue-51632-try-desugar-incompatible-types.fixed b/src/test/ui/issue-51632-try-desugar-incompatible-types.fixed new file mode 100644 index 0000000000000..016cff914bd2d --- /dev/null +++ b/src/test/ui/issue-51632-try-desugar-incompatible-types.fixed @@ -0,0 +1,25 @@ +// 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. + +// run-rustfix + +#![allow(dead_code)] + +fn missing_discourses() -> Result { + Ok(1) +} + +fn forbidden_narratives() -> Result { + Ok(missing_discourses()?) + //~^ ERROR try expression alternatives have incompatible types + //~| HELP try wrapping with a success variant +} + +fn main() {} diff --git a/src/test/ui/issue-51632-try-desugar-incompatible-types.rs b/src/test/ui/issue-51632-try-desugar-incompatible-types.rs new file mode 100644 index 0000000000000..315773a85f004 --- /dev/null +++ b/src/test/ui/issue-51632-try-desugar-incompatible-types.rs @@ -0,0 +1,25 @@ +// 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. + +// run-rustfix + +#![allow(dead_code)] + +fn missing_discourses() -> Result { + Ok(1) +} + +fn forbidden_narratives() -> Result { + missing_discourses()? + //~^ ERROR try expression alternatives have incompatible types + //~| HELP try wrapping with a success variant +} + +fn main() {} diff --git a/src/test/ui/issue-51632-try-desugar-incompatible-types.stderr b/src/test/ui/issue-51632-try-desugar-incompatible-types.stderr new file mode 100644 index 0000000000000..a50af5624c0cf --- /dev/null +++ b/src/test/ui/issue-51632-try-desugar-incompatible-types.stderr @@ -0,0 +1,15 @@ +error[E0308]: try expression alternatives have incompatible types + --> $DIR/issue-51632-try-desugar-incompatible-types.rs:20:5 + | +LL | missing_discourses()? + | ^^^^^^^^^^^^^^^^^^^^^ + | | + | expected enum `std::result::Result`, found isize + | help: try wrapping with a success variant: `Ok(missing_discourses()?)` + | + = note: expected type `std::result::Result` + found type `isize` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/issue-51714.rs b/src/test/ui/issue-51714.rs index 96c5b92ddfdcc..2b9d51f81b988 100644 --- a/src/test/ui/issue-51714.rs +++ b/src/test/ui/issue-51714.rs @@ -9,11 +9,16 @@ // except according to those terms. fn main() { - |_: [_; return || {}] | {} + |_: [_; return || {}] | {}; //~^ ERROR return statement outside of function body -} -fn foo() { [(); return || {}]; //~^ ERROR return statement outside of function body + + [(); return |ice| {}]; + //~^ ERROR return statement outside of function body + + [(); return while let Some(n) = Some(0) {}]; + //~^ ERROR return statement outside of function body + //~^^ ERROR irrefutable while-let pattern } diff --git a/src/test/ui/issue-51714.stderr b/src/test/ui/issue-51714.stderr index 746adea6b7ed7..ddc70bfb38e01 100644 --- a/src/test/ui/issue-51714.stderr +++ b/src/test/ui/issue-51714.stderr @@ -1,15 +1,34 @@ error[E0572]: return statement outside of function body --> $DIR/issue-51714.rs:12:14 | -LL | |_: [_; return || {}] | {} +LL | |_: [_; return || {}] | {}; | ^^^^^^^^^^^^ error[E0572]: return statement outside of function body - --> $DIR/issue-51714.rs:17:10 + --> $DIR/issue-51714.rs:15:10 | LL | [(); return || {}]; | ^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error[E0572]: return statement outside of function body + --> $DIR/issue-51714.rs:18:10 + | +LL | [(); return |ice| {}]; + | ^^^^^^^^^^^^^^^ + +error[E0572]: return statement outside of function body + --> $DIR/issue-51714.rs:21:10 + | +LL | [(); return while let Some(n) = Some(0) {}]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0165]: irrefutable while-let pattern + --> $DIR/issue-51714.rs:21:27 + | +LL | [(); return while let Some(n) = Some(0) {}]; + | ^^^^^^^ irrefutable pattern + +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0572`. +Some errors occurred: E0165, E0572. +For more information about an error, try `rustc --explain E0165`. diff --git a/src/test/ui/return-match-array-const.rs b/src/test/ui/return-match-array-const.rs new file mode 100644 index 0000000000000..45fc571d79d56 --- /dev/null +++ b/src/test/ui/return-match-array-const.rs @@ -0,0 +1,17 @@ +// 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. + +fn main() { + [(); return match 0 { n => n }]; //~ ERROR: return statement outside of function body + + [(); return match 0 { 0 => 0 }]; //~ ERROR: return statement outside of function body + + [(); return match () { 'a' => 0, _ => 0 }]; //~ ERROR: return statement outside of function body +} diff --git a/src/test/ui/return-match-array-const.stderr b/src/test/ui/return-match-array-const.stderr new file mode 100644 index 0000000000000..044dc8f51455f --- /dev/null +++ b/src/test/ui/return-match-array-const.stderr @@ -0,0 +1,21 @@ +error[E0572]: return statement outside of function body + --> $DIR/return-match-array-const.rs:12:10 + | +LL | [(); return match 0 { n => n }]; //~ ERROR: return statement outside of function body + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0572]: return statement outside of function body + --> $DIR/return-match-array-const.rs:14:10 + | +LL | [(); return match 0 { 0 => 0 }]; //~ ERROR: return statement outside of function body + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0572]: return statement outside of function body + --> $DIR/return-match-array-const.rs:16:10 + | +LL | [(); return match () { 'a' => 0, _ => 0 }]; //~ ERROR: return statement outside of function body + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0572`. diff --git a/src/test/ui/suggestions/issue-48364.rs b/src/test/ui/suggestions/issue-48364.rs new file mode 100644 index 0000000000000..82cb722a65600 --- /dev/null +++ b/src/test/ui/suggestions/issue-48364.rs @@ -0,0 +1,16 @@ +// 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. + +fn foo() -> bool { + b"".starts_with(stringify!(foo)) + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/src/test/ui/suggestions/issue-48364.stderr b/src/test/ui/suggestions/issue-48364.stderr new file mode 100644 index 0000000000000..b420654a32d8c --- /dev/null +++ b/src/test/ui/suggestions/issue-48364.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/issue-48364.rs:12:21 + | +LL | b"".starts_with(stringify!(foo)) + | ^^^^^^^^^^^^^^^ expected slice, found str + | + = note: expected type `&[u8]` + found type `&'static str` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/tools/miri b/src/tools/miri index 9143a69f4b3ef..5b7bb32b0e46d 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit 9143a69f4b3ef4bda77afddefe934be363e39f31 +Subproject commit 5b7bb32b0e46d195b80c4da09b560ac7fc92015d