diff --git a/config.toml.example b/config.toml.example index 23943d34b7ca8..24293fc864c5f 100644 --- a/config.toml.example +++ b/config.toml.example @@ -90,6 +90,11 @@ # with clang-cl, so this is special in that it only compiles LLVM with clang-cl #clang-cl = '/path/to/clang-cl.exe' +# Pass extra compiler and linker flags to the LLVM CMake build. +#cflags = "-fextra-flag" +#cxxflags = "-fextra-flag" +#ldflags = "-Wl,extra-flag" + # Use libc++ when building LLVM instead of libstdc++. This is the default on # platforms already use libc++ as the default C++ library, but this option # allows you to use libc++ even on platforms when it's not. You need to ensure diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 9421817ae6d8e..a2989f0cffa6e 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -82,6 +82,9 @@ pub struct Config { pub lldb_enabled: bool, pub llvm_tools_enabled: bool, + pub llvm_cflags: Option, + pub llvm_cxxflags: Option, + pub llvm_ldflags: Option, pub llvm_use_libcxx: bool, // rust codegen options @@ -254,6 +257,9 @@ struct Llvm { link_shared: Option, version_suffix: Option, clang_cl: Option, + cflags: Option, + cxxflags: Option, + ldflags: Option, use_libcxx: Option, } @@ -516,6 +522,10 @@ impl Config { config.llvm_link_jobs = llvm.link_jobs; config.llvm_version_suffix = llvm.version_suffix.clone(); config.llvm_clang_cl = llvm.clang_cl.clone(); + + config.llvm_cflags = llvm.cflags.clone(); + config.llvm_cxxflags = llvm.cxxflags.clone(); + config.llvm_ldflags = llvm.ldflags.clone(); set(&mut config.llvm_use_libcxx, llvm.use_libcxx); } diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index b0c3c9702498d..7b70236dfe8e6 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -64,6 +64,10 @@ def v(*args): o("missing-tools", "dist.missing-tools", "allow failures when building tools") o("use-libcxx", "llvm.use_libcxx", "build LLVM with libc++") +o("cflags", "llvm.cflags", "build LLVM with these extra compiler flags") +o("cxxflags", "llvm.cxxflags", "build LLVM with these extra compiler flags") +o("ldflags", "llvm.ldflags", "build LLVM with these extra linker flags") + # Optimization and debugging options. These may be overridden by the release # channel, etc. o("optimize", "rust.optimize", "build optimized rust code") diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index cb9c86df55080..f5bacd63e6803 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -358,7 +358,11 @@ fn configure_cmake(builder: &Builder, } cfg.build_arg("-j").build_arg(builder.jobs().to_string()); - cfg.define("CMAKE_C_FLAGS", builder.cflags(target, GitRepo::Llvm).join(" ")); + let mut cflags = builder.cflags(target, GitRepo::Llvm).join(" "); + if let Some(ref s) = builder.config.llvm_cxxflags { + cflags.push_str(&format!(" {}", s)); + } + cfg.define("CMAKE_C_FLAGS", cflags); let mut cxxflags = builder.cflags(target, GitRepo::Llvm).join(" "); if builder.config.llvm_static_stdcpp && !target.contains("windows") && @@ -366,6 +370,9 @@ fn configure_cmake(builder: &Builder, { cxxflags.push_str(" -static-libstdc++"); } + if let Some(ref s) = builder.config.llvm_cxxflags { + cxxflags.push_str(&format!(" {}", s)); + } cfg.define("CMAKE_CXX_FLAGS", cxxflags); if let Some(ar) = builder.ar(target) { if ar.is_absolute() { @@ -383,6 +390,12 @@ fn configure_cmake(builder: &Builder, } } + if let Some(ref s) = builder.config.llvm_ldflags { + cfg.define("CMAKE_SHARED_LINKER_FLAGS", s); + cfg.define("CMAKE_MODULE_LINKER_FLAGS", s); + cfg.define("CMAKE_EXE_LINKER_FLAGS", s); + } + if env::var_os("SCCACHE_ERROR_LOG").is_some() { cfg.env("RUST_LOG", "sccache=warn"); } diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 86f28a957cd2c..d43a5c1032ce0 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -91,6 +91,8 @@ use self::Ordering::*; /// For example, let's tweak our previous code a bit: /// /// ``` +/// // The derive implements == comparisons +/// #[derive(PartialEq)] /// enum BookFormat { /// Paperback, /// Hardback, @@ -102,31 +104,34 @@ use self::Ordering::*; /// format: BookFormat, /// } /// +/// // Implement == comparisons /// impl PartialEq for Book { /// fn eq(&self, other: &BookFormat) -> bool { -/// match (&self.format, other) { -/// (BookFormat::Paperback, BookFormat::Paperback) => true, -/// (BookFormat::Hardback, BookFormat::Hardback) => true, -/// (BookFormat::Ebook, BookFormat::Ebook) => true, -/// (_, _) => false, -/// } +/// self.format == *other +/// } +/// } +/// +/// // Implement == comparisons +/// impl PartialEq for BookFormat { +/// fn eq(&self, other: &Book) -> bool { +/// *self == other.format /// } /// } /// /// let b1 = Book { isbn: 3, format: BookFormat::Paperback }; /// /// assert!(b1 == BookFormat::Paperback); -/// assert!(b1 != BookFormat::Ebook); +/// assert!(BookFormat::Ebook != b1); /// ``` /// /// By changing `impl PartialEq for Book` to `impl PartialEq for Book`, -/// we've changed what type we can use on the right side of the `==` operator. -/// This lets us use it in the `assert!` statements at the bottom. +/// we allow `BookFormat`s to be compared with `Book`s. /// /// You can also combine these implementations to let the `==` operator work with /// two different types: /// /// ``` +/// #[derive(PartialEq)] /// enum BookFormat { /// Paperback, /// Hardback, @@ -140,12 +145,13 @@ use self::Ordering::*; /// /// impl PartialEq for Book { /// fn eq(&self, other: &BookFormat) -> bool { -/// match (&self.format, other) { -/// (&BookFormat::Paperback, &BookFormat::Paperback) => true, -/// (&BookFormat::Hardback, &BookFormat::Hardback) => true, -/// (&BookFormat::Ebook, &BookFormat::Ebook) => true, -/// (_, _) => false, -/// } +/// self.format == *other +/// } +/// } +/// +/// impl PartialEq for BookFormat { +/// fn eq(&self, other: &Book) -> bool { +/// *self == other.format /// } /// } /// @@ -159,7 +165,7 @@ use self::Ordering::*; /// let b2 = Book { isbn: 3, format: BookFormat::Ebook }; /// /// assert!(b1 == BookFormat::Paperback); -/// assert!(b1 != BookFormat::Ebook); +/// assert!(BookFormat::Ebook != b1); /// assert!(b1 == b2); /// ``` /// diff --git a/src/libcore/ffi.rs b/src/libcore/ffi.rs index 0717a88b6b8f3..644380c69f2c7 100644 --- a/src/libcore/ffi.rs +++ b/src/libcore/ffi.rs @@ -12,24 +12,27 @@ use ::fmt; /// and `*mut c_void` is equivalent to C's `void*`. That said, this is /// *not* the same as C's `void` return type, which is Rust's `()` type. /// -/// Ideally, this type would be equivalent to [`!`], but currently it may -/// be more ideal to use `c_void` for FFI purposes. +/// To model pointers to opaque types in FFI, until `extern type` is +/// stabilized, it is recommended to use a newtype wrapper around an empty +/// byte array. See the [Nomicon] for details. /// -/// [`!`]: ../../std/primitive.never.html /// [pointer]: ../../std/primitive.pointer.html +/// [Nomicon]: https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs // N.B., for LLVM to recognize the void pointer type and by extension // functions like malloc(), we need to have it represented as i8* in // LLVM bitcode. The enum used here ensures this and prevents misuse -// of the "raw" type by only having private variants.. We need two +// of the "raw" type by only having private variants. We need two // variants, because the compiler complains about the repr attribute -// otherwise. +// otherwise and we need at least one variant as otherwise the enum +// would be uninhabited and at least dereferencing such pointers would +// be UB. #[repr(u8)] #[stable(feature = "raw_os", since = "1.1.0")] pub enum c_void { - #[unstable(feature = "c_void_variant", reason = "should not have to exist", + #[unstable(feature = "c_void_variant", reason = "temporary implementation detail", issue = "0")] #[doc(hidden)] __variant1, - #[unstable(feature = "c_void_variant", reason = "should not have to exist", + #[unstable(feature = "c_void_variant", reason = "temporary implementation detail", issue = "0")] #[doc(hidden)] __variant2, } @@ -49,7 +52,7 @@ impl fmt::Debug for c_void { #[unstable(feature = "c_variadic", reason = "the `c_variadic` feature has not been properly tested on \ all supported platforms", - issue = "27745")] + issue = "44930")] extern { type VaListImpl; } @@ -74,7 +77,7 @@ impl fmt::Debug for VaListImpl { #[unstable(feature = "c_variadic", reason = "the `c_variadic` feature has not been properly tested on \ all supported platforms", - issue = "27745")] + issue = "44930")] struct VaListImpl { stack: *mut (), gr_top: *mut (), @@ -90,7 +93,7 @@ struct VaListImpl { #[unstable(feature = "c_variadic", reason = "the `c_variadic` feature has not been properly tested on \ all supported platforms", - issue = "27745")] + issue = "44930")] struct VaListImpl { gpr: u8, fpr: u8, @@ -106,7 +109,7 @@ struct VaListImpl { #[unstable(feature = "c_variadic", reason = "the `c_variadic` feature has not been properly tested on \ all supported platforms", - issue = "27745")] + issue = "44930")] struct VaListImpl { gp_offset: i32, fp_offset: i32, @@ -120,7 +123,7 @@ struct VaListImpl { #[unstable(feature = "c_variadic", reason = "the `c_variadic` feature has not been properly tested on \ all supported platforms", - issue = "27745")] + issue = "44930")] #[repr(transparent)] pub struct VaList<'a>(&'a mut VaListImpl); @@ -140,7 +143,7 @@ mod sealed_trait { #[unstable(feature = "c_variadic", reason = "the `c_variadic` feature has not been properly tested on \ all supported platforms", - issue = "27745")] + issue = "44930")] pub trait VaArgSafe {} } @@ -150,7 +153,7 @@ macro_rules! impl_va_arg_safe { #[unstable(feature = "c_variadic", reason = "the `c_variadic` feature has not been properly tested on \ all supported platforms", - issue = "27745")] + issue = "44930")] impl sealed_trait::VaArgSafe for $t {} )+ } @@ -163,12 +166,12 @@ impl_va_arg_safe!{f64} #[unstable(feature = "c_variadic", reason = "the `c_variadic` feature has not been properly tested on \ all supported platforms", - issue = "27745")] + issue = "44930")] impl sealed_trait::VaArgSafe for *mut T {} #[unstable(feature = "c_variadic", reason = "the `c_variadic` feature has not been properly tested on \ all supported platforms", - issue = "27745")] + issue = "44930")] impl sealed_trait::VaArgSafe for *const T {} impl<'a> VaList<'a> { @@ -176,7 +179,7 @@ impl<'a> VaList<'a> { #[unstable(feature = "c_variadic", reason = "the `c_variadic` feature has not been properly tested on \ all supported platforms", - issue = "27745")] + issue = "44930")] pub unsafe fn arg(&mut self) -> T { va_arg(self) } @@ -185,7 +188,7 @@ impl<'a> VaList<'a> { #[unstable(feature = "c_variadic", reason = "the `c_variadic` feature has not been properly tested on \ all supported platforms", - issue = "27745")] + issue = "44930")] pub unsafe fn copy(&self, f: F) -> R where F: for<'copy> FnOnce(VaList<'copy>) -> R { #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 6827364c0f805..41caa1788fbb8 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -10,9 +10,9 @@ use ops; use str::FromStr; macro_rules! impl_nonzero_fmt { - ( ( $( $Trait: ident ),+ ) for $Ty: ident ) => { + ( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => { $( - #[stable(feature = "nonzero", since = "1.28.0")] + #[$stability] impl fmt::$Trait for $Ty { #[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -31,7 +31,7 @@ macro_rules! doc_comment { } macro_rules! nonzero_integers { - ( $( $Ty: ident($Int: ty); )+ ) => { + ( $( #[$stability: meta] $Ty: ident($Int: ty); )+ ) => { $( doc_comment! { concat!("An integer that is known not to equal zero. @@ -41,10 +41,10 @@ For example, `Option<", stringify!($Ty), ">` is the same size as `", stringify!( ```rust use std::mem::size_of; -assert_eq!(size_of::>(), size_of::<", stringify!($Int), +assert_eq!(size_of::>(), size_of::<", stringify!($Int), ">()); ```"), - #[stable(feature = "nonzero", since = "1.28.0")] + #[$stability] #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] #[repr(transparent)] #[rustc_layout_scalar_valid_range_start(1)] @@ -57,14 +57,14 @@ assert_eq!(size_of::>(), size_of::<", st /// # Safety /// /// The value must not be zero. - #[stable(feature = "nonzero", since = "1.28.0")] + #[$stability] #[inline] pub const unsafe fn new_unchecked(n: $Int) -> Self { $Ty(n) } /// Create a non-zero if the given value is not zero. - #[stable(feature = "nonzero", since = "1.28.0")] + #[$stability] #[inline] pub fn new(n: $Int) -> Option { if n != 0 { @@ -75,7 +75,7 @@ assert_eq!(size_of::>(), size_of::<", st } /// Returns the value as a primitive type. - #[stable(feature = "nonzero", since = "1.28.0")] + #[$stability] #[inline] pub const fn get(self) -> $Int { self.0 @@ -91,19 +91,25 @@ assert_eq!(size_of::>(), size_of::<", st } impl_nonzero_fmt! { - (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty + #[$stability] (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty } )+ } } nonzero_integers! { - NonZeroU8(u8); - NonZeroU16(u16); - NonZeroU32(u32); - NonZeroU64(u64); - NonZeroU128(u128); - NonZeroUsize(usize); + #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU8(u8); + #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU16(u16); + #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU32(u32); + #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU64(u64); + #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU128(u128); + #[stable(feature = "nonzero", since = "1.28.0")] NonZeroUsize(usize); + #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI8(i8); + #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI16(i16); + #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI32(i32); + #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI64(i64); + #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI128(i128); + #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroIsize(isize); } /// Provides intentionally-wrapped arithmetic on `T`. diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index 762e07549a52a..7c09a36d89883 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -99,6 +99,7 @@ use fmt; use marker::{Sized, Unpin}; +use cmp::{self, PartialEq, PartialOrd}; use ops::{Deref, DerefMut, Receiver, CoerceUnsized, DispatchFromDyn}; /// A pinned pointer. @@ -112,16 +113,57 @@ use ops::{Deref, DerefMut, Receiver, CoerceUnsized, DispatchFromDyn}; /// [`Unpin`]: ../../std/marker/trait.Unpin.html /// [`pin` module]: ../../std/pin/index.html // -// Note: the derives below are allowed because they all only use `&P`, so they -// cannot move the value behind `pointer`. +// Note: the derives below, and the explicit `PartialEq` and `PartialOrd` +// implementations, are allowed because they all only use `&P`, so they cannot move +// the value behind `pointer`. #[stable(feature = "pin", since = "1.33.0")] #[fundamental] #[repr(transparent)] -#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)] +#[derive(Copy, Clone, Hash, Eq, Ord)] pub struct Pin

{ pointer: P, } +#[stable(feature = "pin_partialeq_partialord_impl_applicability", since = "1.34.0")] +impl PartialEq> for Pin

+where + P: PartialEq, +{ + fn eq(&self, other: &Pin) -> bool { + self.pointer == other.pointer + } + + fn ne(&self, other: &Pin) -> bool { + self.pointer != other.pointer + } +} + +#[stable(feature = "pin_partialeq_partialord_impl_applicability", since = "1.34.0")] +impl PartialOrd> for Pin

+where + P: PartialOrd, +{ + fn partial_cmp(&self, other: &Pin) -> Option { + self.pointer.partial_cmp(&other.pointer) + } + + fn lt(&self, other: &Pin) -> bool { + self.pointer < other.pointer + } + + fn le(&self, other: &Pin) -> bool { + self.pointer <= other.pointer + } + + fn gt(&self, other: &Pin) -> bool { + self.pointer > other.pointer + } + + fn ge(&self, other: &Pin) -> bool { + self.pointer >= other.pointer + } +} + impl Pin

where P::Target: Unpin, diff --git a/src/libcore/tests/nonzero.rs b/src/libcore/tests/nonzero.rs index c813bf20cb61a..4532568ee0c16 100644 --- a/src/libcore/tests/nonzero.rs +++ b/src/libcore/tests/nonzero.rs @@ -1,4 +1,4 @@ -use core::num::NonZeroU32; +use core::num::{NonZeroU32, NonZeroI32}; use core::option::Option; use core::option::Option::{Some, None}; use std::mem::size_of; @@ -13,6 +13,7 @@ fn test_create_nonzero_instance() { #[test] fn test_size_nonzero_in_option() { assert_eq!(size_of::(), size_of::>()); + assert_eq!(size_of::(), size_of::>()); } #[test] @@ -118,3 +119,10 @@ fn test_from_nonzero() { let num: u32 = nz.into(); assert_eq!(num, 1u32); } + +#[test] +fn test_from_signed_nonzero() { + let nz = NonZeroI32::new(1).unwrap(); + let num: i32 = nz.into(); + assert_eq!(num, 1i32); +} diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 501ef01d74c6e..7384af108edbb 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -600,7 +600,7 @@ impl DepGraph { DepKind::Hir | DepKind::HirBody | DepKind::CrateMetadata => { - if dep_node.extract_def_id(tcx).is_none() { + if dep_dep_node.extract_def_id(tcx).is_none() { // If the node does not exist anymore, we // just fail to mark green. return None diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index f633703be56d4..041291e80eee9 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -35,11 +35,9 @@ use syntax::ast::{NodeId, CRATE_NODE_ID, Ident, Name, Attribute}; use syntax_pos::Span; use hir::*; use hir::def::Def; -use hir::map::{self, Map}; +use hir::map::Map; use super::itemlikevisit::DeepVisitor; -use std::cmp; - #[derive(Copy, Clone)] pub enum FnKind<'a> { /// `#[xxx] pub async/const/extern "Abi" fn foo()` @@ -1133,57 +1131,3 @@ pub fn walk_defaultness<'v, V: Visitor<'v>>(_: &mut V, _: &'v Defaultness) { // the right thing to do, should content be added in the future, // would be to walk it. } - -#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct IdRange { - pub min: NodeId, - pub max: NodeId, -} - -impl IdRange { - pub fn max() -> IdRange { - IdRange { - min: NodeId::MAX, - max: NodeId::from_u32(0), - } - } - - pub fn empty(&self) -> bool { - self.min >= self.max - } - - pub fn contains(&self, id: NodeId) -> bool { - id >= self.min && id < self.max - } - - pub fn add(&mut self, id: NodeId) { - self.min = cmp::min(self.min, id); - self.max = cmp::max(self.max, NodeId::from_u32(id.as_u32() + 1)); - } -} - - -pub struct IdRangeComputingVisitor<'a, 'hir: 'a> { - result: IdRange, - map: &'a map::Map<'hir>, -} - -impl<'a, 'hir> IdRangeComputingVisitor<'a, 'hir> { - pub fn new(map: &'a map::Map<'hir>) -> IdRangeComputingVisitor<'a, 'hir> { - IdRangeComputingVisitor { result: IdRange::max(), map: map } - } - - pub fn result(&self) -> IdRange { - self.result - } -} - -impl<'a, 'hir> Visitor<'hir> for IdRangeComputingVisitor<'a, 'hir> { - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'hir> { - NestedVisitorMap::OnlyBodies(&self.map) - } - - fn visit_id(&mut self, id: NodeId) { - self.result.add(id); - } -} diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 8badcbfc1b301..8cdc493e6fda7 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -3775,7 +3775,7 @@ impl<'a> LoweringContext<'a> { let ohs = P(self.lower_expr(ohs)); hir::ExprKind::Unary(op, ohs) } - ExprKind::Lit(ref l) => hir::ExprKind::Lit(P((*l).clone())), + ExprKind::Lit(ref l) => hir::ExprKind::Lit((*l).clone()), ExprKind::Cast(ref expr, ref ty) => { let expr = P(self.lower_expr(expr)); hir::ExprKind::Cast(expr, self.lower_ty(ty, ImplTraitContext::disallowed())) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index fc4bd05476f6c..aaef1c722be96 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -19,7 +19,7 @@ use syntax_pos::{Span, DUMMY_SP, symbol::InternedString}; use syntax::source_map::{self, Spanned}; use rustc_target::spec::abi::Abi; use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, DUMMY_NODE_ID, AsmDialect}; -use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy}; +use syntax::ast::{Attribute, Label, Lit, StrStyle, FloatTy, IntTy, UintTy}; use syntax::attr::InlineAttr; use syntax::ext::hygiene::SyntaxContext; use syntax::ptr::P; @@ -142,17 +142,6 @@ pub const DUMMY_HIR_ID: HirId = HirId { pub const DUMMY_ITEM_LOCAL_ID: ItemLocalId = ItemLocalId::MAX; -#[derive(Clone, RustcEncodable, RustcDecodable, Copy)] -pub struct Label { - pub ident: Ident, -} - -impl fmt::Debug for Label { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "label({:?})", self.ident) - } -} - #[derive(Clone, RustcEncodable, RustcDecodable, Copy)] pub struct Lifetime { pub id: NodeId, @@ -1466,7 +1455,7 @@ pub enum ExprKind { /// A unary operation (For example: `!x`, `*x`) Unary(UnOp, P), /// A literal (For example: `1`, `"foo"`) - Lit(P), + Lit(Lit), /// A cast (`foo as f64`) Cast(P, P), Type(P, P), diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 8ff60e5f56225..f48059b328ff3 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -153,7 +153,7 @@ impl_stable_hash_for!(enum hir::LifetimeName { Error, }); -impl_stable_hash_for!(struct hir::Label { +impl_stable_hash_for!(struct ast::Label { ident }); diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index c8d137a42b2e8..a0bd4f01cd231 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -368,6 +368,12 @@ declare_lint! { report_in_external_macro: true } +declare_lint! { + pub AMBIGUOUS_ASSOCIATED_ITEMS, + Warn, + "ambiguous associated items" +} + /// Does nothing as a lint pass, but registers some `Lint`s /// that are used by other parts of the compiler. #[derive(Copy, Clone)] @@ -433,6 +439,7 @@ impl LintPass for HardwiredLints { parser::QUESTION_MARK_MACRO_SEP, parser::ILL_FORMED_ATTRIBUTE_INPUT, DEPRECATED_IN_FUTURE, + AMBIGUOUS_ASSOCIATED_ITEMS, ) } } diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 66303ab71b25f..72963cb7e7fb4 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -39,7 +39,6 @@ use syntax_pos::{MultiSpan, Span}; use errors::{Applicability, DiagnosticBuilder, DiagnosticId}; use rustc::hir; -use rustc::hir::intravisit::{self, Visitor}; use dataflow::{DataFlowContext, BitwiseOperator, DataFlowOperator, KillFrom}; @@ -157,12 +156,6 @@ fn build_borrowck_dataflow_data<'a, 'c, 'tcx, F>(this: &mut BorrowckCtxt<'a, 'tc where F: FnOnce(&mut BorrowckCtxt<'a, 'tcx>) -> &'c cfg::CFG { // Check the body of fn items. - let tcx = this.tcx; - let id_range = { - let mut visitor = intravisit::IdRangeComputingVisitor::new(&tcx.hir()); - visitor.visit_body(this.body); - visitor.result() - }; let (all_loans, move_data) = gather_loans::gather_loans_in_fn(this, body_id); @@ -184,7 +177,6 @@ fn build_borrowck_dataflow_data<'a, 'c, 'tcx, F>(this: &mut BorrowckCtxt<'a, 'tc Some(this.body), cfg, LoanDataFlowOperator, - id_range, all_loans.len()); for (loan_idx, loan) in all_loans.iter().enumerate() { loan_dfcx.add_gen(loan.gen_scope.item_local_id(), loan_idx); @@ -198,7 +190,6 @@ fn build_borrowck_dataflow_data<'a, 'c, 'tcx, F>(this: &mut BorrowckCtxt<'a, 'tc let flowed_moves = move_data::FlowedMoveData::new(move_data, this, cfg, - id_range, this.body); Some(AnalysisData { all_loans, diff --git a/src/librustc_borrowck/borrowck/move_data.rs b/src/librustc_borrowck/borrowck/move_data.rs index c5bee87e90fe4..56c9f928eb03a 100644 --- a/src/librustc_borrowck/borrowck/move_data.rs +++ b/src/librustc_borrowck/borrowck/move_data.rs @@ -15,7 +15,6 @@ use std::rc::Rc; use std::usize; use syntax_pos::Span; use rustc::hir; -use rustc::hir::intravisit::IdRange; #[derive(Default)] pub struct MoveData<'tcx> { @@ -559,7 +558,6 @@ impl<'a, 'tcx> FlowedMoveData<'a, 'tcx> { pub fn new(move_data: MoveData<'tcx>, bccx: &BorrowckCtxt<'a, 'tcx>, cfg: &cfg::CFG, - id_range: IdRange, body: &hir::Body) -> FlowedMoveData<'a, 'tcx> { let tcx = bccx.tcx; @@ -570,7 +568,6 @@ impl<'a, 'tcx> FlowedMoveData<'a, 'tcx> { Some(body), cfg, MoveDataFlowOperator, - id_range, move_data.moves.borrow().len()); let mut dfcx_assign = DataFlowContext::new(tcx, @@ -578,7 +575,6 @@ impl<'a, 'tcx> FlowedMoveData<'a, 'tcx> { Some(body), cfg, AssignDataFlowOperator, - id_range, move_data.var_assignments.borrow().len()); move_data.add_gen_kills(bccx, diff --git a/src/librustc_borrowck/dataflow.rs b/src/librustc_borrowck/dataflow.rs index 56e25bd89c9ad..8cf620567405c 100644 --- a/src/librustc_borrowck/dataflow.rs +++ b/src/librustc_borrowck/dataflow.rs @@ -15,7 +15,7 @@ use rustc_data_structures::graph::implementation::OUTGOING; use rustc::util::nodemap::FxHashMap; use rustc::hir; -use rustc::hir::intravisit::{self, IdRange}; +use rustc::hir::intravisit; use rustc::hir::print as pprust; @@ -230,16 +230,15 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { body: Option<&hir::Body>, cfg: &cfg::CFG, oper: O, - id_range: IdRange, bits_per_id: usize) -> DataFlowContext<'a, 'tcx, O> { let usize_bits = mem::size_of::() * 8; let words_per_id = (bits_per_id + usize_bits - 1) / usize_bits; let num_nodes = cfg.graph.all_nodes().len(); - debug!("DataFlowContext::new(analysis_name: {}, id_range={:?}, \ + debug!("DataFlowContext::new(analysis_name: {}, \ bits_per_id={}, words_per_id={}) \ num_nodes: {}", - analysis_name, id_range, bits_per_id, words_per_id, + analysis_name, bits_per_id, words_per_id, num_nodes); let entry = if oper.initial_value() { usize::MAX } else {0}; diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index a074441f8a179..3e25f98ccd27c 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -135,10 +135,11 @@ impl CodeSuggestion { if let Some(line) = line_opt { if let Some(lo) = line.char_indices().map(|(i, _)| i).nth(lo) { let hi_opt = hi_opt.and_then(|hi| line.char_indices().map(|(i, _)| i).nth(hi)); - buf.push_str(match hi_opt { - Some(hi) => &line[lo..hi], - None => &line[lo..], - }); + match hi_opt { + Some(hi) if hi > lo => buf.push_str(&line[lo..hi]), + Some(_) => (), + None => buf.push_str(&line[lo..]), + } } if let None = hi_opt { buf.push('\n'); diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 2d764d11c66aa..71c859d8dbea7 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -341,6 +341,11 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { reference: "issue #57571 ", edition: None, }, + FutureIncompatibleInfo { + id: LintId::of(AMBIGUOUS_ASSOCIATED_ITEMS), + reference: "issue #57644 ", + edition: None, + }, ]); // Register renamed and removed lints. diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs index d35d64957b7b4..1f00086e32fe1 100644 --- a/src/librustc_metadata/native_libs.rs +++ b/src/librustc_metadata/native_libs.rs @@ -163,7 +163,7 @@ impl<'a, 'tcx> Collector<'a, 'tcx> { !self.tcx.features().static_nobundle { feature_gate::emit_feature_err(&self.tcx.sess.parse_sess, "static_nobundle", - span.unwrap(), + span.unwrap_or_else(|| syntax_pos::DUMMY_SP), GateIssue::Language, "kind=\"static-nobundle\" is feature gated"); } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 4890369e13f20..c0d7248fab7f3 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -13,7 +13,7 @@ extern crate rustc_typeck; extern crate syntax_pos; extern crate rustc_data_structures; -use rustc::hir::{self, Node, PatKind}; +use rustc::hir::{self, Node, PatKind, AssociatedItemKind}; use rustc::hir::def::Def; use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefId}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; @@ -548,7 +548,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { let mut reach = self.reach(trait_item_ref.id.node_id, item_level); reach.generics().predicates(); - if trait_item_ref.kind == hir::AssociatedItemKind::Type && + if trait_item_ref.kind == AssociatedItemKind::Type && !trait_item_ref.defaultness.has_value() { // No type to visit. } else { @@ -1333,11 +1333,11 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { if self.item_is_public(&impl_item_ref.id.node_id, &impl_item_ref.vis) { let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); match impl_item_ref.kind { - hir::AssociatedItemKind::Const => { + AssociatedItemKind::Const => { found_pub_static = true; intravisit::walk_impl_item(self, impl_item); } - hir::AssociatedItemKind::Method { has_self: false } => { + AssociatedItemKind::Method { has_self: false } => { found_pub_static = true; intravisit::walk_impl_item(self, impl_item); } @@ -1558,6 +1558,24 @@ impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> { in_assoc_ty: false, } } + + fn check_trait_or_impl_item(&self, node_id: ast::NodeId, assoc_item_kind: AssociatedItemKind, + defaultness: hir::Defaultness, vis: ty::Visibility) { + let mut check = self.check(node_id, vis); + + let (check_ty, is_assoc_ty) = match assoc_item_kind { + AssociatedItemKind::Const | AssociatedItemKind::Method { .. } => (true, false), + AssociatedItemKind::Type => (defaultness.has_value(), true), + // `ty()` for existential types is the underlying type, + // it's not a part of interface, so we skip it. + AssociatedItemKind::Existential => (false, true), + }; + check.in_assoc_ty = is_assoc_ty; + check.generics().predicates(); + if check_ty { + check.ty(); + } + } } impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> { @@ -1592,16 +1610,8 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> self.check(item.id, item_visibility).generics().predicates(); for trait_item_ref in trait_item_refs { - let mut check = self.check(trait_item_ref.id.node_id, item_visibility); - check.in_assoc_ty = trait_item_ref.kind == hir::AssociatedItemKind::Type; - check.generics().predicates(); - - if trait_item_ref.kind == hir::AssociatedItemKind::Type && - !trait_item_ref.defaultness.has_value() { - // No type to visit. - } else { - check.ty(); - } + self.check_trait_or_impl_item(trait_item_ref.id.node_id, trait_item_ref.kind, + trait_item_ref.defaultness, item_visibility); } } hir::ItemKind::TraitAlias(..) => { @@ -1647,9 +1657,8 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> } else { impl_vis }; - let mut check = self.check(impl_item.id, impl_item_vis); - check.in_assoc_ty = impl_item_ref.kind == hir::AssociatedItemKind::Type; - check.generics().predicates().ty(); + self.check_trait_or_impl_item(impl_item_ref.id.node_id, impl_item_ref.kind, + impl_item_ref.defaultness, impl_item_vis); } } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index b41193723069c..c11a2cd01c167 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -3318,7 +3318,12 @@ impl<'a> Resolver<'a> { if let Some(def) = def { match (def, source) { (Def::Macro(..), _) => { - err.span_label(span, format!("did you mean `{}!(...)`?", path_str)); + err.span_suggestion_with_applicability( + span, + "use `!` to invoke the macro", + format!("{}!", path_str), + Applicability::MaybeIncorrect, + ); return (err, candidates); } (Def::TyAlias(..), PathSource::Trait(_)) => { @@ -3330,13 +3335,22 @@ impl<'a> Resolver<'a> { } (Def::Mod(..), PathSource::Expr(Some(parent))) => match parent.node { ExprKind::Field(_, ident) => { - err.span_label(parent.span, format!("did you mean `{}::{}`?", - path_str, ident)); + err.span_suggestion_with_applicability( + parent.span, + "use the path separator to refer to an item", + format!("{}::{}", path_str, ident), + Applicability::MaybeIncorrect, + ); return (err, candidates); } ExprKind::MethodCall(ref segment, ..) => { - err.span_label(parent.span, format!("did you mean `{}::{}(...)`?", - path_str, segment.ident)); + let span = parent.span.with_hi(segment.ident.span.hi()); + err.span_suggestion_with_applicability( + span, + "use the path separator to refer to an item", + format!("{}::{}", path_str, segment.ident), + Applicability::MaybeIncorrect, + ); return (err, candidates); } _ => {} diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 8e5eaa18b9de0..534279e981d62 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -10,6 +10,7 @@ use hir::HirVec; use lint; use middle::resolve_lifetime as rl; use namespace::Namespace; +use rustc::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable}; use rustc::ty::{GenericParamDef, GenericParamDefKind}; @@ -1278,29 +1279,50 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } // Create a type from a path to an associated type. - // For a path `A::B::C::D`, `ty` and `ty_path_def` are the type and def for `A::B::C` + // For a path `A::B::C::D`, `qself_ty` and `qself_def` are the type and def for `A::B::C` // and item_segment is the path segment for `D`. We return a type and a def for // the whole path. - // Will fail except for `T::A` and `Self::A`; i.e., if `ty`/`ty_path_def` are not a type + // Will fail except for `T::A` and `Self::A`; i.e., if `qself_ty`/`qself_def` are not a type // parameter or `Self`. - pub fn associated_path_def_to_ty(&self, - ref_id: ast::NodeId, - span: Span, - ty: Ty<'tcx>, - ty_path_def: Def, - item_segment: &hir::PathSegment) - -> (Ty<'tcx>, Def) - { + pub fn associated_path_to_ty( + &self, + ref_id: ast::NodeId, + span: Span, + qself_ty: Ty<'tcx>, + qself_def: Def, + assoc_segment: &hir::PathSegment, + permit_variants: bool, + ) -> (Ty<'tcx>, Def) { let tcx = self.tcx(); - let assoc_name = item_segment.ident; + let assoc_ident = assoc_segment.ident; - debug!("associated_path_def_to_ty: {:?}::{}", ty, assoc_name); + debug!("associated_path_to_ty: {:?}::{}", qself_ty, assoc_ident); - self.prohibit_generics(slice::from_ref(item_segment)); + self.prohibit_generics(slice::from_ref(assoc_segment)); + + // Check if we have an enum variant. + let mut variant_resolution = None; + if let ty::Adt(adt_def, _) = qself_ty.sty { + if adt_def.is_enum() { + let variant_def = adt_def.variants.iter().find(|vd| { + tcx.hygienic_eq(assoc_ident, vd.ident, adt_def.did) + }); + if let Some(variant_def) = variant_def { + let def = Def::Variant(variant_def.did); + if permit_variants { + check_type_alias_enum_variants_enabled(tcx, span); + tcx.check_stability(variant_def.did, Some(ref_id), span); + return (qself_ty, def); + } else { + variant_resolution = Some(def); + } + } + } + } // Find the type of the associated item, and the trait where the associated // item is declared. - let bound = match (&ty.sty, ty_path_def) { + let bound = match (&qself_ty.sty, qself_def) { (_, Def::SelfTy(Some(_), Some(impl_def_id))) => { // `Self` in an impl of a trait -- we have a concrete self type and a // trait reference. @@ -1313,77 +1335,61 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { }; let candidates = traits::supertraits(tcx, ty::Binder::bind(trait_ref)) - .filter(|r| self.trait_defines_associated_type_named(r.def_id(), assoc_name)); + .filter(|r| self.trait_defines_associated_type_named(r.def_id(), assoc_ident)); - match self.one_bound_for_assoc_type(candidates, "Self", assoc_name, span) { + match self.one_bound_for_assoc_type(candidates, "Self", assoc_ident, span) { Ok(bound) => bound, Err(ErrorReported) => return (tcx.types.err, Def::Err), } } (&ty::Param(_), Def::SelfTy(Some(param_did), None)) | (&ty::Param(_), Def::TyParam(param_did)) => { - match self.find_bound_for_assoc_item(param_did, assoc_name, span) { + match self.find_bound_for_assoc_item(param_did, assoc_ident, span) { Ok(bound) => bound, Err(ErrorReported) => return (tcx.types.err, Def::Err), } } - (&ty::Adt(adt_def, _substs), Def::Enum(_did)) => { - let ty_str = ty.to_string(); - // Incorrect enum variant. - let mut err = tcx.sess.struct_span_err( - span, - &format!("no variant `{}` on enum `{}`", &assoc_name.as_str(), ty_str), - ); - // Check if it was a typo. - let input = adt_def.variants.iter().map(|variant| &variant.ident.name); - if let Some(suggested_name) = find_best_match_for_name( - input, - &assoc_name.as_str(), - None, - ) { - err.span_suggestion_with_applicability( + _ => { + if variant_resolution.is_some() { + // Variant in type position + let msg = format!("expected type, found variant `{}`", assoc_ident); + tcx.sess.span_err(span, &msg); + } else if qself_ty.is_enum() { + // Report as incorrect enum variant rather than ambiguous type. + let mut err = tcx.sess.struct_span_err( span, - "did you mean", - format!("{}::{}", ty_str, suggested_name.to_string()), - Applicability::MaybeIncorrect, + &format!("no variant `{}` on enum `{}`", &assoc_ident.as_str(), qself_ty), ); - } else { - err.span_label(span, "unknown variant"); - } - err.emit(); - return (tcx.types.err, Def::Err); - } - _ => { - // Check if we have an enum variant. - match ty.sty { - ty::Adt(adt_def, _) if adt_def.is_enum() => { - let variant_def = adt_def.variants.iter().find(|vd| { - tcx.hygienic_eq(assoc_name, vd.ident, adt_def.did) - }); - if let Some(variant_def) = variant_def { - check_type_alias_enum_variants_enabled(tcx, span); - - let def = Def::Variant(variant_def.did); - tcx.check_stability(def.def_id(), Some(ref_id), span); - return (ty, def); - } - }, - _ => (), - } - - // Don't print `TyErr` to the user. - if !ty.references_error() { + // Check if it was a typo. + let adt_def = qself_ty.ty_adt_def().expect("enum is not an ADT"); + if let Some(suggested_name) = find_best_match_for_name( + adt_def.variants.iter().map(|variant| &variant.ident.name), + &assoc_ident.as_str(), + None, + ) { + err.span_suggestion_with_applicability( + span, + "did you mean", + format!("{}::{}", qself_ty, suggested_name), + Applicability::MaybeIncorrect, + ); + } else { + err.span_label(span, "unknown variant"); + } + err.emit(); + } else if !qself_ty.references_error() { + // Don't print `TyErr` to the user. self.report_ambiguous_associated_type(span, - &ty.to_string(), + &qself_ty.to_string(), "Trait", - &assoc_name.as_str()); + &assoc_ident.as_str()); } return (tcx.types.err, Def::Err); } }; let trait_did = bound.def_id(); - let (assoc_ident, def_scope) = tcx.adjust_ident(assoc_name, trait_did, ref_id); + let (assoc_ident, def_scope) = tcx.adjust_ident(assoc_ident, trait_did, ref_id); let item = tcx.associated_items(trait_did).find(|i| { Namespace::from(i.kind) == Namespace::Type && i.ident.modern() == assoc_ident @@ -1394,11 +1400,35 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { let def = Def::AssociatedTy(item.def_id); if !item.vis.is_accessible_from(def_scope, tcx) { - let msg = format!("{} `{}` is private", def.kind_name(), assoc_name); + let msg = format!("{} `{}` is private", def.kind_name(), assoc_ident); tcx.sess.span_err(span, &msg); } tcx.check_stability(item.def_id, Some(ref_id), span); + if let Some(variant_def) = variant_resolution { + let mut err = tcx.struct_span_lint_node( + AMBIGUOUS_ASSOCIATED_ITEMS, + ref_id, + span, + "ambiguous associated item", + ); + + let mut could_refer_to = |def: Def, also| { + let note_msg = format!("`{}` could{} refer to {} defined here", + assoc_ident, also, def.kind_name()); + err.span_note(tcx.def_span(def.def_id()), ¬e_msg); + }; + could_refer_to(variant_def, ""); + could_refer_to(def, " also"); + + err.span_suggestion_with_applicability( + span, + "use fully-qualified syntax", + format!("<{} as {}>::{}", qself_ty, "Trait", assoc_ident), + Applicability::HasPlaceholders, + ).emit(); + } + (ty, def) } @@ -1773,7 +1803,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } else { Def::Err }; - self.associated_path_def_to_ty(ast_ty.id, ast_ty.span, ty, def, segment).0 + self.associated_path_to_ty(ast_ty.id, ast_ty.span, ty, def, segment, false).0 } hir::TyKind::Array(ref ty, ref length) => { let length_def_id = tcx.hir().local_def_id(length.id); diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 02687df6a94fc..e71dc019471bd 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -408,45 +408,36 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let tcx = self.tcx; - let mode = probe::Mode::Path; - match self.probe_for_name(span, mode, method_name, IsSuggestion(false), - self_ty, expr_id, ProbeScope::TraitsInScope) { - Ok(pick) => { - debug!("resolve_ufcs: pick={:?}", pick); - if let Some(import_id) = pick.import_id { - let import_def_id = tcx.hir().local_def_id(import_id); - debug!("resolve_ufcs: used_trait_import: {:?}", import_def_id); - Lrc::get_mut(&mut self.tables.borrow_mut().used_trait_imports) - .unwrap().insert(import_def_id); + // Check if we have an enum variant. + if let ty::Adt(adt_def, _) = self_ty.sty { + if adt_def.is_enum() { + let variant_def = adt_def.variants.iter().find(|vd| { + tcx.hygienic_eq(method_name, vd.ident, adt_def.did) + }); + if let Some(variant_def) = variant_def { + check_type_alias_enum_variants_enabled(tcx, span); + + let def = Def::VariantCtor(variant_def.did, variant_def.ctor_kind); + tcx.check_stability(def.def_id(), Some(expr_id), span); + return Ok(def); } - - let def = pick.item.def(); - debug!("resolve_ufcs: def={:?}", def); - tcx.check_stability(def.def_id(), Some(expr_id), span); - - Ok(def) } - Err(err) => { - // Check if we have an enum variant. - match self_ty.sty { - ty::Adt(adt_def, _) if adt_def.is_enum() => { - let variant_def = adt_def.variants.iter().find(|vd| { - tcx.hygienic_eq(method_name, vd.ident, adt_def.did) - }); - if let Some(variant_def) = variant_def { - check_type_alias_enum_variants_enabled(tcx, span); - - let def = Def::VariantCtor(variant_def.did, variant_def.ctor_kind); - tcx.check_stability(def.def_id(), Some(expr_id), span); - return Ok(def); - } - }, - _ => (), - } + } - Err(err) - } + let pick = self.probe_for_name(span, probe::Mode::Path, method_name, IsSuggestion(false), + self_ty, expr_id, ProbeScope::TraitsInScope)?; + debug!("resolve_ufcs: pick={:?}", pick); + if let Some(import_id) = pick.import_id { + let import_def_id = tcx.hir().local_def_id(import_id); + debug!("resolve_ufcs: used_trait_import: {:?}", import_def_id); + Lrc::get_mut(&mut self.tables.borrow_mut().used_trait_imports) + .unwrap().insert(import_def_id); } + + let def = pick.item.def(); + debug!("resolve_ufcs: def={:?}", def); + tcx.check_stability(def.def_id(), Some(expr_id), span); + Ok(def) } /// Find item with name `item_name` defined in impl/trait `def_id` diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 1b07385d4d1f4..22300f2ae11ed 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4724,8 +4724,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } else { Def::Err }; - let (ty, def) = AstConv::associated_path_def_to_ty(self, node_id, path_span, - ty, def, segment); + let (ty, def) = AstConv::associated_path_to_ty(self, node_id, path_span, + ty, def, segment, true); // Write back the new resolution. let hir_id = self.tcx.hir().node_to_hir_id(node_id); diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 3a64c56fc8eeb..06846d4ed0c9b 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1076,7 +1076,7 @@ themePicker.onblur = handleThemeButtonsBlur; all_sources.sort(); let mut w = try_err!(File::create(&dst), &dst); try_err!(writeln!(&mut w, - "var N = null;var sourcesIndex = {{}};\n{}", + "var N = null;var sourcesIndex = {{}};\n{}\ncreateSourceSidebar();", all_sources.join("\n")), &dst); } diff --git a/src/librustdoc/html/static/source-script.js b/src/librustdoc/html/static/source-script.js index 0affe1c6812f5..c5d6fa16f550e 100644 --- a/src/librustdoc/html/static/source-script.js +++ b/src/librustdoc/html/static/source-script.js @@ -137,5 +137,3 @@ function createSourceSidebar() { main.insertBefore(sidebar, main.firstChild); } - -createSourceSidebar(); diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index 1390be700634d..52a30967a2310 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -82,12 +82,6 @@ pre { border-bottom-color: #ddd; } -:target { background: #494a3d; } - -:target > .in-band { - background: #494a3d; -} - .content .method .where, .content .fn .where, .content .where.fmt-newline { @@ -252,7 +246,7 @@ a.test-arrow:hover{ color: #999; } -:target > code { +:target > code, :target > .in-band { background-color: #494a3d; } diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index 2b04dd2388d45..d20fea666e61d 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -84,12 +84,6 @@ pre { border-bottom-color: #ddd; } -:target { background: #FDFFD3; } - -:target > .in-band { - background: #FDFFD3; -} - .content .method .where, .content .fn .where, .content .where.fmt-newline { @@ -247,7 +241,7 @@ a.test-arrow:hover{ color: #999; } -:target > code { +:target > code, :target > .in-band { background: #FDFFD3; } diff --git a/src/libstd/ffi/mod.rs b/src/libstd/ffi/mod.rs index 62081e713f139..7a38f0ebd5a57 100644 --- a/src/libstd/ffi/mod.rs +++ b/src/libstd/ffi/mod.rs @@ -169,7 +169,7 @@ pub use core::ffi::c_void; #[unstable(feature = "c_variadic", reason = "the `c_variadic` feature has not been properly tested on \ all supported platforms", - issue = "27745")] + issue = "44930")] pub use core::ffi::VaList; mod c_str; diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 119b3f7f9f296..3538816c1124c 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -1121,7 +1121,9 @@ impl Permissions { /// writing. /// /// This operation does **not** modify the filesystem. To modify the - /// filesystem use the `fs::set_permissions` function. + /// filesystem use the [`fs::set_permissions`] function. + /// + /// [`fs::set_permissions`]: fn.set_permissions.html /// /// # Examples /// @@ -1639,10 +1641,15 @@ pub fn hard_link, Q: AsRef>(src: P, dst: Q) -> io::Result<( /// /// The `dst` path will be a symbolic link pointing to the `src` path. /// On Windows, this will be a file symlink, not a directory symlink; -/// for this reason, the platform-specific `std::os::unix::fs::symlink` -/// and `std::os::windows::fs::{symlink_file, symlink_dir}` should be +/// for this reason, the platform-specific [`std::os::unix::fs::symlink`] +/// and [`std::os::windows::fs::symlink_file`] or [`symlink_dir`] should be /// used instead to make the intent explicit. /// +/// [`std::os::unix::fs::symlink`]: ../os/unix/fs/fn.symlink.html +/// [`std::os::windows::fs::symlink_file`]: ../os/windows/fs/fn.symlink_file.html +/// [`symlink_dir`]: ../os/windows/fs/fn.symlink_dir.html +/// +/// /// # Examples /// /// ```no_run @@ -1795,7 +1802,7 @@ pub fn create_dir>(path: P) -> io::Result<()> { /// * If any directory in the path specified by `path` /// does not already exist and it could not be created otherwise. The specific /// error conditions for when a directory is being created (after it is -/// determined to not exist) are outlined by `fs::create_dir`. +/// determined to not exist) are outlined by [`fs::create_dir`]. /// /// Notable exception is made for situations where any of the directories /// specified in the `path` could not be created as it was being created concurrently. @@ -1803,6 +1810,8 @@ pub fn create_dir>(path: P) -> io::Result<()> { /// concurrently from multiple threads or processes is guaranteed not to fail /// due to a race condition with itself. /// +/// [`fs::create_dir`]: fn.create_dir.html +/// /// # Examples /// /// ```no_run @@ -1868,7 +1877,10 @@ pub fn remove_dir>(path: P) -> io::Result<()> { /// /// # Errors /// -/// See `file::remove_file` and `fs::remove_dir`. +/// See [`fs::remove_file`] and [`fs::remove_dir`]. +/// +/// [`fs::remove_file`]: fn.remove_file.html +/// [`fs::remove_dir`]: fn.remove_dir.html /// /// # Examples /// diff --git a/src/libstd/prelude/mod.rs b/src/libstd/prelude/mod.rs index ec8318f3728eb..bf689bad559d3 100644 --- a/src/libstd/prelude/mod.rs +++ b/src/libstd/prelude/mod.rs @@ -44,8 +44,8 @@ //! The current version of the prelude (version 1) lives in //! [`std::prelude::v1`], and re-exports the following. //! -//! * [`std::marker`]::{[`Copy`], [`Send`], [`Sized`], [`Sync`]}. The marker -//! traits indicate fundamental properties of types. +//! * [`std::marker`]::{[`Copy`], [`Send`], [`Sized`], [`Sync`], [`Unpin`]}. The +//! marker traits indicate fundamental properties of types. //! * [`std::ops`]::{[`Drop`], [`Fn`], [`FnMut`], [`FnOnce`]}. Various //! operations for both destructors and overloading `()`. //! * [`std::mem`]::[`drop`][`mem::drop`], a convenience function for explicitly @@ -108,6 +108,7 @@ //! [`Sync`]: ../marker/trait.Sync.html //! [`ToOwned`]: ../borrow/trait.ToOwned.html //! [`ToString`]: ../string/trait.ToString.html +//! [`Unpin`]: ../marker/trait.Unpin.html //! [`Vec`]: ../vec/struct.Vec.html //! [`Clone::clone`]: ../clone/trait.Clone.html#tymethod.clone //! [`mem::drop`]: ../mem/fn.drop.html diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 24202ca8fbdc0..9a129e7e8fcd8 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -435,7 +435,8 @@ fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[quoted::TokenTree]) -> bool { match *seq_tt { TokenTree::MetaVarDecl(_, _, id) => id.name == "vis", TokenTree::Sequence(_, ref sub_seq) => - sub_seq.op == quoted::KleeneOp::ZeroOrMore, + sub_seq.op == quoted::KleeneOp::ZeroOrMore + || sub_seq.op == quoted::KleeneOp::ZeroOrOne, _ => false, } }) { @@ -543,7 +544,10 @@ impl FirstSets { } // Reverse scan: Sequence comes before `first`. - if subfirst.maybe_empty || seq_rep.op == quoted::KleeneOp::ZeroOrMore { + if subfirst.maybe_empty + || seq_rep.op == quoted::KleeneOp::ZeroOrMore + || seq_rep.op == quoted::KleeneOp::ZeroOrOne + { // If sequence is potentially empty, then // union them (preserving first emptiness). first.add_all(&TokenSet { maybe_empty: true, ..subfirst }); @@ -591,8 +595,10 @@ impl FirstSets { assert!(first.maybe_empty); first.add_all(subfirst); - if subfirst.maybe_empty || - seq_rep.op == quoted::KleeneOp::ZeroOrMore { + if subfirst.maybe_empty + || seq_rep.op == quoted::KleeneOp::ZeroOrMore + || seq_rep.op == quoted::KleeneOp::ZeroOrOne + { // continue scanning for more first // tokens, but also make sure we // restore empty-tracking state diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 823c786bded26..5b430d13516b4 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5234,22 +5234,13 @@ impl<'a> Parser<'a> { kind: ast::GenericParamKind::Lifetime, }); if let Some(sp) = seen_ty_param { - let param_span = self.prev_span; - let ate_comma = self.eat(&token::Comma); - let remove_sp = if ate_comma { - param_span.until(self.span) - } else { - last_comma_span.unwrap_or(param_span).to(param_span) - }; - bad_lifetime_pos.push(param_span); - - if let Ok(snippet) = self.sess.source_map().span_to_snippet(param_span) { + let remove_sp = last_comma_span.unwrap_or(self.prev_span).to(self.prev_span); + bad_lifetime_pos.push(self.prev_span); + if let Ok(snippet) = self.sess.source_map().span_to_snippet(self.prev_span) { suggestions.push((remove_sp, String::new())); - suggestions.push((sp.shrink_to_lo(), format!("{}, ", snippet))); - } - if ate_comma { - last_comma_span = Some(self.prev_span); - continue + suggestions.push(( + sp.shrink_to_lo(), + format!("{}, ", snippet))); } } } else if self.check_ident() { diff --git a/src/test/incremental/change_name_of_static_in_fn.rs b/src/test/incremental/change_name_of_static_in_fn.rs new file mode 100644 index 0000000000000..5b27b6808ead2 --- /dev/null +++ b/src/test/incremental/change_name_of_static_in_fn.rs @@ -0,0 +1,17 @@ + +// revisions:rpass1 rpass2 rpass3 + +// See issue #57692. + +#![allow(warnings)] + +fn main() { + #[cfg(rpass1)] + { + static map: u64 = 0; + } + #[cfg(not(rpass1))] + { + static MAP: u64 = 0; + } +} diff --git a/src/test/ui/feature-gate/feature-gate-static-nobundle-2.rs b/src/test/ui/feature-gate/feature-gate-static-nobundle-2.rs new file mode 100644 index 0000000000000..92844f9306d28 --- /dev/null +++ b/src/test/ui/feature-gate/feature-gate-static-nobundle-2.rs @@ -0,0 +1,6 @@ +//~ ERROR kind="static-nobundle" is feature gated +// Test the behavior of rustc when non-existent library is statically linked + +// compile-flags: -l static-nobundle=nonexistent + +fn main() {} diff --git a/src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr b/src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr new file mode 100644 index 0000000000000..419c21901a02f --- /dev/null +++ b/src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr @@ -0,0 +1,7 @@ +error[E0658]: kind="static-nobundle" is feature gated (see issue #37403) + | + = help: add #![feature(static_nobundle)] to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/imports/issue-57539.rs b/src/test/ui/imports/issue-57539.rs new file mode 100644 index 0000000000000..90b74eb464779 --- /dev/null +++ b/src/test/ui/imports/issue-57539.rs @@ -0,0 +1,8 @@ +// edition:2018 + +mod core { + use core; //~ ERROR `core` is ambiguous + use crate::*; +} + +fn main() {} diff --git a/src/test/ui/imports/issue-57539.stderr b/src/test/ui/imports/issue-57539.stderr new file mode 100644 index 0000000000000..3f745fd8204bf --- /dev/null +++ b/src/test/ui/imports/issue-57539.stderr @@ -0,0 +1,18 @@ +error[E0659]: `core` is ambiguous (name vs any other name during import resolution) + --> $DIR/issue-57539.rs:4:9 + | +LL | use core; //~ ERROR `core` is ambiguous + | ^^^^ ambiguous name + | + = note: `core` could refer to a built-in extern crate + = help: use `::core` to refer to this extern crate unambiguously +note: `core` could also refer to the module imported here + --> $DIR/issue-57539.rs:5:9 + | +LL | use crate::*; + | ^^^^^^^^ + = help: use `self::core` to refer to this module unambiguously + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/issues/issue-5067.rs b/src/test/ui/issues/issue-5067.rs index 526a68311462e..616fd09907a2b 100644 --- a/src/test/ui/issues/issue-5067.rs +++ b/src/test/ui/issues/issue-5067.rs @@ -1,37 +1,59 @@ #![allow(unused_macros)] +// Tests that repetition matchers cannot match the empty token tree (since that would be +// ambiguous). + +// edition:2018 + macro_rules! foo { ( $()* ) => {}; //~^ ERROR repetition matches empty token tree ( $()+ ) => {}; //~^ ERROR repetition matches empty token tree - + ( $()? ) => {}; + //~^ ERROR repetition matches empty token tree ( $(),* ) => {}; // PASS ( $(),+ ) => {}; // PASS - + // `?` cannot have a separator... ( [$()*] ) => {}; //~^ ERROR repetition matches empty token tree ( [$()+] ) => {}; //~^ ERROR repetition matches empty token tree - + ( [$()?] ) => {}; + //~^ ERROR repetition matches empty token tree ( [$(),*] ) => {}; // PASS ( [$(),+] ) => {}; // PASS - + // `?` cannot have a separator... ( $($()* $(),* $(a)* $(a),* )* ) => {}; //~^ ERROR repetition matches empty token tree ( $($()* $(),* $(a)* $(a),* )+ ) => {}; //~^ ERROR repetition matches empty token tree - + ( $($()* $(),* $(a)* $(a),* )? ) => {}; + //~^ ERROR repetition matches empty token tree + ( $($()? $(),* $(a)? $(a),* )* ) => {}; + //~^ ERROR repetition matches empty token tree + ( $($()? $(),* $(a)? $(a),* )+ ) => {}; + //~^ ERROR repetition matches empty token tree + ( $($()? $(),* $(a)? $(a),* )? ) => {}; + //~^ ERROR repetition matches empty token tree ( $(a $(),* $(a)* $(a),* )* ) => {}; // PASS ( $($(a)+ $(),* $(a)* $(a),* )+ ) => {}; // PASS + ( $($(a)+ $(),* $(a)* $(a),* )? ) => {}; // PASS + + ( $(a $(),* $(a)? $(a),* )* ) => {}; // PASS + ( $($(a)+ $(),* $(a)? $(a),* )+ ) => {}; // PASS + ( $($(a)+ $(),* $(a)? $(a),* )? ) => {}; // PASS ( $(a $()+)* ) => {}; //~^ ERROR repetition matches empty token tree ( $(a $()*)+ ) => {}; //~^ ERROR repetition matches empty token tree + ( $(a $()+)? ) => {}; + //~^ ERROR repetition matches empty token tree + ( $(a $()?)+ ) => {}; + //~^ ERROR repetition matches empty token tree } - // --- Original Issue --- // macro_rules! make_vec { @@ -43,11 +65,10 @@ fn main() { let _ = make_vec![a 1, a 2, a 3]; } - // --- Minified Issue --- // macro_rules! m { - ( $()* ) => {} + ( $()* ) => {}; //~^ ERROR repetition matches empty token tree } diff --git a/src/test/ui/issues/issue-5067.stderr b/src/test/ui/issues/issue-5067.stderr index 433b7c8c04907..7ffc6071407c5 100644 --- a/src/test/ui/issues/issue-5067.stderr +++ b/src/test/ui/issues/issue-5067.stderr @@ -1,62 +1,110 @@ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:4:8 + --> $DIR/issue-5067.rs:9:8 | LL | ( $()* ) => {}; | ^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:6:8 + --> $DIR/issue-5067.rs:11:8 | LL | ( $()+ ) => {}; | ^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:12:9 + --> $DIR/issue-5067.rs:13:8 + | +LL | ( $()? ) => {}; + | ^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:18:9 | LL | ( [$()*] ) => {}; | ^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:14:9 + --> $DIR/issue-5067.rs:20:9 | LL | ( [$()+] ) => {}; | ^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:20:8 + --> $DIR/issue-5067.rs:22:9 + | +LL | ( [$()?] ) => {}; + | ^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:27:8 | LL | ( $($()* $(),* $(a)* $(a),* )* ) => {}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:22:8 + --> $DIR/issue-5067.rs:29:8 | LL | ( $($()* $(),* $(a)* $(a),* )+ ) => {}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:28:12 + --> $DIR/issue-5067.rs:31:8 + | +LL | ( $($()* $(),* $(a)* $(a),* )? ) => {}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:33:8 + | +LL | ( $($()? $(),* $(a)? $(a),* )* ) => {}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:35:8 + | +LL | ( $($()? $(),* $(a)? $(a),* )+ ) => {}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:37:8 + | +LL | ( $($()? $(),* $(a)? $(a),* )? ) => {}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:47:12 | LL | ( $(a $()+)* ) => {}; | ^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:30:12 + --> $DIR/issue-5067.rs:49:12 | LL | ( $(a $()*)+ ) => {}; | ^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:38:18 + --> $DIR/issue-5067.rs:51:12 + | +LL | ( $(a $()+)? ) => {}; + | ^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:53:12 + | +LL | ( $(a $()?)+ ) => {}; + | ^^ + +error: repetition matches empty token tree + --> $DIR/issue-5067.rs:60:18 | LL | (a $e1:expr $($(, a $e2:expr)*)*) => ([$e1 $($(, $e2)*)*]); | ^^^^^^^^^^^^^^^^^^ error: repetition matches empty token tree - --> $DIR/issue-5067.rs:50:8 + --> $DIR/issue-5067.rs:71:8 | -LL | ( $()* ) => {} +LL | ( $()* ) => {}; | ^^ -error: aborting due to 10 previous errors +error: aborting due to 18 previous errors diff --git a/src/test/ui/issues/issue-57597.rs b/src/test/ui/issues/issue-57597.rs new file mode 100644 index 0000000000000..ebeb3fe07adb4 --- /dev/null +++ b/src/test/ui/issues/issue-57597.rs @@ -0,0 +1,80 @@ +// Regression test for #57597. +// +// Make sure that nested matchers work correctly rather than causing an infinite loop or crash. + +// edition:2018 + +macro_rules! foo1 { + ($($($i:ident)?)+) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo2 { + ($($($i:ident)?)*) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo3 { + ($($($i:ident)?)?) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo4 { + ($($($($i:ident)?)?)?) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo5 { + ($($($($i:ident)*)?)?) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo6 { + ($($($($i:ident)?)*)?) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo7 { + ($($($($i:ident)?)?)*) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo8 { + ($($($($i:ident)*)*)?) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo9 { + ($($($($i:ident)?)*)*) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo10 { + ($($($($i:ident)?)*)+) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo11 { + ($($($($i:ident)+)?)*) => {}; + //~^ ERROR repetition matches empty token tree +} + +macro_rules! foo12 { + ($($($($i:ident)+)*)?) => {}; + //~^ ERROR repetition matches empty token tree +} + +fn main() { + foo1!(); + foo2!(); + foo3!(); + foo4!(); + foo5!(); + foo6!(); + foo7!(); + foo8!(); + foo9!(); + foo10!(); + foo11!(); + foo12!(); +} diff --git a/src/test/ui/issues/issue-57597.stderr b/src/test/ui/issues/issue-57597.stderr new file mode 100644 index 0000000000000..0a02ac8c499b6 --- /dev/null +++ b/src/test/ui/issues/issue-57597.stderr @@ -0,0 +1,74 @@ +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:8:7 + | +LL | ($($($i:ident)?)+) => {}; + | ^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:13:7 + | +LL | ($($($i:ident)?)*) => {}; + | ^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:18:7 + | +LL | ($($($i:ident)?)?) => {}; + | ^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:23:7 + | +LL | ($($($($i:ident)?)?)?) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:28:7 + | +LL | ($($($($i:ident)*)?)?) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:33:7 + | +LL | ($($($($i:ident)?)*)?) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:38:7 + | +LL | ($($($($i:ident)?)?)*) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:43:7 + | +LL | ($($($($i:ident)*)*)?) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:48:7 + | +LL | ($($($($i:ident)?)*)*) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:53:7 + | +LL | ($($($($i:ident)?)*)+) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:58:7 + | +LL | ($($($($i:ident)+)?)*) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: repetition matches empty token tree + --> $DIR/issue-57597.rs:63:7 + | +LL | ($($($($i:ident)+)*)?) => {}; + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 12 previous errors + diff --git a/src/test/ui/lifetime-before-type-params.rs b/src/test/ui/lifetime-before-type-params.rs new file mode 100644 index 0000000000000..9b905d4883a16 --- /dev/null +++ b/src/test/ui/lifetime-before-type-params.rs @@ -0,0 +1,9 @@ +#![allow(unused)] +fn first() {} +//~^ ERROR lifetime parameters must be declared prior to type parameters +fn second<'a, T, 'b>() {} +//~^ ERROR lifetime parameters must be declared prior to type parameters +fn third() {} +//~^ ERROR lifetime parameters must be declared prior to type parameters +fn fourth<'a, T, 'b, U, 'c, V>() {} +//~^ ERROR lifetime parameters must be declared prior to type parameters diff --git a/src/test/ui/lifetime-before-type-params.stderr b/src/test/ui/lifetime-before-type-params.stderr new file mode 100644 index 0000000000000..7ac8dffdfbe0c --- /dev/null +++ b/src/test/ui/lifetime-before-type-params.stderr @@ -0,0 +1,47 @@ +error: lifetime parameters must be declared prior to type parameters + --> $DIR/lifetime-before-type-params.rs:2:13 + | +LL | fn first() {} + | ^^ ^^ +help: move the lifetime parameter prior to the first type parameter + | +LL | fn first<'a, 'b, T>() {} + | ^^^ ^^^ -- + +error: lifetime parameters must be declared prior to type parameters + --> $DIR/lifetime-before-type-params.rs:4:18 + | +LL | fn second<'a, T, 'b>() {} + | ^^ +help: move the lifetime parameter prior to the first type parameter + | +LL | fn second<'a, 'b, T>() {} + | ^^^ -- + +error: lifetime parameters must be declared prior to type parameters + --> $DIR/lifetime-before-type-params.rs:6:16 + | +LL | fn third() {} + | ^^ +help: move the lifetime parameter prior to the first type parameter + | +LL | fn third<'a, T, U>() {} + | ^^^ -- + +error: lifetime parameters must be declared prior to type parameters + --> $DIR/lifetime-before-type-params.rs:8:18 + | +LL | fn fourth<'a, T, 'b, U, 'c, V>() {} + | ^^ ^^ +help: move the lifetime parameter prior to the first type parameter + | +LL | fn fourth<'a, 'b, 'c, T, U, V>() {} + | ^^^ ^^^ -- -- + +error[E0601]: `main` function not found in crate `lifetime_before_type_params` + | + = note: consider adding a `main` function to `$DIR/lifetime-before-type-params.rs` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/privacy/private-in-public-assoc-ty.rs b/src/test/ui/privacy/private-in-public-assoc-ty.rs index c6e86ed64ae73..81d23959fd4ad 100644 --- a/src/test/ui/privacy/private-in-public-assoc-ty.rs +++ b/src/test/ui/privacy/private-in-public-assoc-ty.rs @@ -1,7 +1,7 @@ // Private types and traits are not allowed in interfaces of associated types. // This test also ensures that the checks are performed even inside private modules. -#![feature(associated_type_defaults)] +#![feature(associated_type_defaults, existential_type)] mod m { struct Priv; @@ -23,10 +23,17 @@ mod m { type Alias4 = Priv; //~^ ERROR private type `m::Priv` in public interface + + type Exist; + fn infer_exist() -> Self::Exist; } impl PubTr for u8 { type Alias1 = Priv; //~^ ERROR private type `m::Priv` in public interface + + existential type Exist: PrivTr; + //~^ ERROR private trait `m::PrivTr` in public interface + fn infer_exist() -> Self::Exist { Priv } } } diff --git a/src/test/ui/privacy/private-in-public-assoc-ty.stderr b/src/test/ui/privacy/private-in-public-assoc-ty.stderr index 6740277c9a7c1..0e5dab1a08c37 100644 --- a/src/test/ui/privacy/private-in-public-assoc-ty.stderr +++ b/src/test/ui/privacy/private-in-public-assoc-ty.stderr @@ -6,7 +6,7 @@ LL | | //~^ WARN private trait `m::PrivTr` in public interface LL | | //~| WARN this was previously accepted LL | | //~| WARN private type `m::Priv` in public interface ... | -LL | | //~^ ERROR private type `m::Priv` in public interface +LL | | fn infer_exist() -> Self::Exist; LL | | } | |_____^ | @@ -22,7 +22,7 @@ LL | | //~^ WARN private trait `m::PrivTr` in public interface LL | | //~| WARN this was previously accepted LL | | //~| WARN private type `m::Priv` in public interface ... | -LL | | //~^ ERROR private type `m::Priv` in public interface +LL | | fn infer_exist() -> Self::Exist; LL | | } | |_____^ | @@ -39,7 +39,7 @@ LL | type Alias4 = Priv; | ^^^^^^^^^^^^^^^^^^^ can't leak private type error[E0446]: private type `m::Priv` in public interface - --> $DIR/private-in-public-assoc-ty.rs:28:9 + --> $DIR/private-in-public-assoc-ty.rs:31:9 | LL | struct Priv; | - `m::Priv` declared as private @@ -47,6 +47,16 @@ LL | struct Priv; LL | type Alias1 = Priv; | ^^^^^^^^^^^^^^^^^^^ can't leak private type -error: aborting due to 2 previous errors +error[E0445]: private trait `m::PrivTr` in public interface + --> $DIR/private-in-public-assoc-ty.rs:34:9 + | +LL | trait PrivTr {} + | - `m::PrivTr` declared as private +... +LL | existential type Exist: PrivTr; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0446`. +Some errors occurred: E0445, E0446. +For more information about an error, try `rustc --explain E0445`. diff --git a/src/test/ui/privacy/private-in-public-existential.rs b/src/test/ui/privacy/private-in-public-existential.rs index 95658f45df6f5..61c6130e47019 100644 --- a/src/test/ui/privacy/private-in-public-existential.rs +++ b/src/test/ui/privacy/private-in-public-existential.rs @@ -12,4 +12,14 @@ fn check() -> Pub { Priv } +pub trait Trait { + type Pub: Default; + fn method() -> Self::Pub; +} + +impl Trait for u8 { + existential type Pub: Default; + fn method() -> Self::Pub { Priv } +} + fn main() {} diff --git a/src/test/ui/resolve/resolve-hint-macro.stderr b/src/test/ui/resolve/resolve-hint-macro.stderr index 4f6d0f695df44..ebe3c36f21eb1 100644 --- a/src/test/ui/resolve/resolve-hint-macro.stderr +++ b/src/test/ui/resolve/resolve-hint-macro.stderr @@ -2,7 +2,7 @@ error[E0423]: expected function, found macro `assert` --> $DIR/resolve-hint-macro.rs:2:5 | LL | assert(true); - | ^^^^^^ did you mean `assert!(...)`? + | ^^^^^^ help: use `!` to invoke the macro: `assert!` error: aborting due to previous error diff --git a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr index 8a9426bfee862..b7b158ce7efa6 100644 --- a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr +++ b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr @@ -4,15 +4,15 @@ error[E0423]: expected value, found module `a` LL | a.I | ^-- | | - | did you mean `a::I`? + | help: use the path separator to refer to an item: `a::I` error[E0423]: expected value, found module `a` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:22:5 | LL | a.g() - | ^---- + | ^-- | | - | did you mean `a::g(...)`? + | help: use the path separator to refer to an item: `a::g` error[E0423]: expected value, found module `a` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:27:5 @@ -20,16 +20,21 @@ error[E0423]: expected value, found module `a` LL | a.b.J | ^-- | | - | did you mean `a::b`? + | help: use the path separator to refer to an item: `a::b` error[E0423]: expected value, found module `a::b` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:32:5 | LL | a::b.J - | ^^^--- - | | | - | | help: a constant with a similar name exists: `I` - | did you mean `a::b::J`? + | ^^^^ +help: a constant with a similar name exists + | +LL | a::I.J + | ^ +help: use the path separator to refer to an item + | +LL | a::b::J + | error[E0423]: expected value, found module `a` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:37:5 @@ -37,7 +42,7 @@ error[E0423]: expected value, found module `a` LL | a.b.f(); | ^-- | | - | did you mean `a::b`? + | help: use the path separator to refer to an item: `a::b` error[E0423]: expected value, found module `a::b` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:40:12 @@ -51,10 +56,15 @@ error[E0423]: expected value, found module `a::b` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:45:5 | LL | a::b.f() - | ^^^----- - | | | - | | help: a constant with a similar name exists: `I` - | did you mean `a::b::f(...)`? + | ^^^^ +help: a constant with a similar name exists + | +LL | a::I.f() + | ^ +help: use the path separator to refer to an item + | +LL | a::b::f() + | ^^^^^^^ error[E0423]: expected value, found module `a::b` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:50:5 diff --git a/src/test/ui/suggestions/suggest-move-lifetimes.stderr b/src/test/ui/suggestions/suggest-move-lifetimes.stderr index 72a2cbe6bf6de..b36e927b5c0c6 100644 --- a/src/test/ui/suggestions/suggest-move-lifetimes.stderr +++ b/src/test/ui/suggestions/suggest-move-lifetimes.stderr @@ -16,7 +16,7 @@ LL | struct B { //~ ERROR lifetime parameters must be declared help: move the lifetime parameter prior to the first type parameter | LL | struct B<'a, T, U> { //~ ERROR lifetime parameters must be declared - | ^^^ -- + | ^^^ -- error: lifetime parameters must be declared prior to type parameters --> $DIR/suggest-move-lifetimes.rs:10:16 @@ -36,7 +36,7 @@ LL | struct D { //~ ERROR lifetime parameters must be decla help: move the lifetime parameter prior to the first type parameter | LL | struct D<'a, 'b, 'c, T, U, V> { //~ ERROR lifetime parameters must be declared - | ^^^ ^^^ ^^^ --- + | ^^^ ^^^ ^^^ -- -- error: aborting due to 4 previous errors diff --git a/src/test/ui/thread-local-mutation.nll.stderr b/src/test/ui/thread-local-mutation.nll.stderr new file mode 100644 index 0000000000000..0a3664b0d9d40 --- /dev/null +++ b/src/test/ui/thread-local-mutation.nll.stderr @@ -0,0 +1,9 @@ +error[E0594]: cannot assign to immutable static item `S` + --> $DIR/thread-local-mutation.rs:11:5 + | +LL | S = "after"; //~ ERROR cannot assign to immutable + | ^^^^^^^^^^^ cannot assign + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/src/test/ui/thread-local-mutation.rs b/src/test/ui/thread-local-mutation.rs new file mode 100644 index 0000000000000..e738225ce2a48 --- /dev/null +++ b/src/test/ui/thread-local-mutation.rs @@ -0,0 +1,18 @@ +// Regression test for #54901: immutable thread locals could be mutated. See: +// https://github.com/rust-lang/rust/issues/29594#issuecomment-328177697 +// https://github.com/rust-lang/rust/issues/54901 + +#![feature(thread_local)] + +#[thread_local] +static S: &str = "before"; + +fn set_s() { + S = "after"; //~ ERROR cannot assign to immutable +} + +fn main() { + println!("{}", S); + set_s(); + println!("{}", S); +} diff --git a/src/test/ui/thread-local-mutation.stderr b/src/test/ui/thread-local-mutation.stderr new file mode 100644 index 0000000000000..bf298523e1b73 --- /dev/null +++ b/src/test/ui/thread-local-mutation.stderr @@ -0,0 +1,9 @@ +error[E0594]: cannot assign to immutable thread-local static item + --> $DIR/thread-local-mutation.rs:11:5 + | +LL | S = "after"; //~ ERROR cannot assign to immutable + | ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/src/test/ui/try-block/try-block-bad-type.stderr b/src/test/ui/try-block/try-block-bad-type.stderr index 202885e383ece..c2f9e9b52bee6 100644 --- a/src/test/ui/try-block/try-block-bad-type.stderr +++ b/src/test/ui/try-block/try-block-bad-type.stderr @@ -5,11 +5,11 @@ LL | Err("")?; //~ ERROR the trait bound `i32: std::convert::From<&str>` | ^^^^^^^^ the trait `std::convert::From<&str>` is not implemented for `i32` | = help: the following implementations were found: - > + > > > - > > + and 2 others = note: required by `std::convert::From::from` error[E0271]: type mismatch resolving ` as std::ops::Try>::Ok == &str` diff --git a/src/test/ui/try-block/try-block-in-edition2015.stderr b/src/test/ui/try-block/try-block-in-edition2015.stderr index 63650086bcaa9..a7b81060d3dc6 100644 --- a/src/test/ui/try-block/try-block-in-edition2015.stderr +++ b/src/test/ui/try-block/try-block-in-edition2015.stderr @@ -15,7 +15,7 @@ error[E0574]: expected struct, variant or union type, found macro `try` --> $DIR/try-block-in-edition2015.rs:4:33 | LL | let try_result: Option<_> = try { - | ^^^ did you mean `try!(...)`? + | ^^^ help: use `!` to invoke the macro: `try!` error: aborting due to 2 previous errors diff --git a/src/test/ui/type-alias-enum-variants-priority-2.rs b/src/test/ui/type-alias-enum-variants-priority-2.rs new file mode 100644 index 0000000000000..295f8acf62f85 --- /dev/null +++ b/src/test/ui/type-alias-enum-variants-priority-2.rs @@ -0,0 +1,13 @@ +#![feature(type_alias_enum_variants)] + +enum E { + V(u8) +} + +impl E { + fn V() {} +} + +fn main() { + ::V(); //~ ERROR this function takes 1 parameter but 0 parameters were supplied +} diff --git a/src/test/ui/type-alias-enum-variants-priority-2.stderr b/src/test/ui/type-alias-enum-variants-priority-2.stderr new file mode 100644 index 0000000000000..c6ec96ebb7d3b --- /dev/null +++ b/src/test/ui/type-alias-enum-variants-priority-2.stderr @@ -0,0 +1,12 @@ +error[E0061]: this function takes 1 parameter but 0 parameters were supplied + --> $DIR/type-alias-enum-variants-priority-2.rs:12:5 + | +LL | V(u8) + | ----- defined here +... +LL | ::V(); //~ ERROR this function takes 1 parameter but 0 parameters were supplied + | ^^^^^^^^ expected 1 parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0061`. diff --git a/src/test/ui/type-alias-enum-variants-priority-3.rs b/src/test/ui/type-alias-enum-variants-priority-3.rs new file mode 100644 index 0000000000000..33f96553b57f0 --- /dev/null +++ b/src/test/ui/type-alias-enum-variants-priority-3.rs @@ -0,0 +1,10 @@ +#![feature(type_alias_enum_variants)] + +enum E { + V +} + +fn check() -> ::V {} +//~^ ERROR expected type, found variant `V` + +fn main() {} diff --git a/src/test/ui/type-alias-enum-variants-priority-3.stderr b/src/test/ui/type-alias-enum-variants-priority-3.stderr new file mode 100644 index 0000000000000..b3451542a2570 --- /dev/null +++ b/src/test/ui/type-alias-enum-variants-priority-3.stderr @@ -0,0 +1,8 @@ +error: expected type, found variant `V` + --> $DIR/type-alias-enum-variants-priority-3.rs:7:15 + | +LL | fn check() -> ::V {} + | ^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/type-alias-enum-variants-priority.rs b/src/test/ui/type-alias-enum-variants-priority.rs new file mode 100644 index 0000000000000..db1da2b12e256 --- /dev/null +++ b/src/test/ui/type-alias-enum-variants-priority.rs @@ -0,0 +1,20 @@ +#![feature(type_alias_enum_variants)] +#![deny(ambiguous_associated_items)] + +enum E { + V +} + +trait Tr { + type V; + fn f() -> Self::V; +} + +impl Tr for E { + type V = u8; + fn f() -> Self::V { 0 } + //~^ ERROR ambiguous associated item + //~| WARN this was previously accepted +} + +fn main() {} diff --git a/src/test/ui/type-alias-enum-variants-priority.stderr b/src/test/ui/type-alias-enum-variants-priority.stderr new file mode 100644 index 0000000000000..dcf7dc77ed5ea --- /dev/null +++ b/src/test/ui/type-alias-enum-variants-priority.stderr @@ -0,0 +1,26 @@ +error: ambiguous associated item + --> $DIR/type-alias-enum-variants-priority.rs:15:15 + | +LL | fn f() -> Self::V { 0 } + | ^^^^^^^ help: use fully-qualified syntax: `::V` + | +note: lint level defined here + --> $DIR/type-alias-enum-variants-priority.rs:2:9 + | +LL | #![deny(ambiguous_associated_items)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #57644 +note: `V` could refer to variant defined here + --> $DIR/type-alias-enum-variants-priority.rs:5:5 + | +LL | V + | ^ +note: `V` could also refer to associated type defined here + --> $DIR/type-alias-enum-variants-priority.rs:9:5 + | +LL | type V; + | ^^^^^^^ + +error: aborting due to previous error + diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 8c1baa55bcdca..4ca285b9b1db1 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -95,6 +95,7 @@ static TARGETS: &'static [&'static str] = &[ "wasm32-unknown-unknown", "x86_64-apple-darwin", "x86_64-apple-ios", + "x86_64-fortanix-unknown-sgx", "x86_64-fuchsia", "x86_64-linux-android", "x86_64-pc-windows-gnu",