diff --git a/.mailmap b/.mailmap index 0733086284947..120d1f1457e65 100644 --- a/.mailmap +++ b/.mailmap @@ -29,6 +29,7 @@ Ariel Ben-Yehuda Ariel Ben-Yehuda Ariel Ben-Yehuda arielb1 Austin Seipp Aydin Kim aydin.kim +Bastian Kauschke Barosl Lee Barosl LEE Ben Alpert Ben Sago Ben S diff --git a/src/liballoc/borrow.rs b/src/liballoc/borrow.rs index 74c80a08b12ab..ee1799fad8e15 100644 --- a/src/liballoc/borrow.rs +++ b/src/liballoc/borrow.rs @@ -135,7 +135,7 @@ impl ToOwned for T /// Another example showing how to keep `Cow` in a struct: /// /// ``` -/// use std::borrow::{Cow, ToOwned}; +/// use std::borrow::Cow; /// /// struct Items<'a, X: 'a> where [X]: ToOwned> { /// values: Cow<'a, [X]>, diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 8383d305518ab..3b888244341f9 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -1186,7 +1186,6 @@ impl<'b, T: ?Sized> Ref<'b, T> { /// # Examples /// /// ``` - /// #![feature(refcell_map_split)] /// use std::cell::{Ref, RefCell}; /// /// let cell = RefCell::new([1, 2, 3, 4]); @@ -1195,7 +1194,7 @@ impl<'b, T: ?Sized> Ref<'b, T> { /// assert_eq!(*begin, [1, 2]); /// assert_eq!(*end, [3, 4]); /// ``` - #[unstable(feature = "refcell_map_split", issue = "51476")] + #[stable(feature = "refcell_map_split", since = "1.35.0")] #[inline] pub fn map_split(orig: Ref<'b, T>, f: F) -> (Ref<'b, U>, Ref<'b, V>) where F: FnOnce(&T) -> (&U, &V) @@ -1268,7 +1267,6 @@ impl<'b, T: ?Sized> RefMut<'b, T> { /// # Examples /// /// ``` - /// #![feature(refcell_map_split)] /// use std::cell::{RefCell, RefMut}; /// /// let cell = RefCell::new([1, 2, 3, 4]); @@ -1279,7 +1277,7 @@ impl<'b, T: ?Sized> RefMut<'b, T> { /// begin.copy_from_slice(&[4, 3]); /// end.copy_from_slice(&[2, 1]); /// ``` - #[unstable(feature = "refcell_map_split", issue = "51476")] + #[stable(feature = "refcell_map_split", since = "1.35.0")] #[inline] pub fn map_split( orig: RefMut<'b, T>, f: F @@ -1423,7 +1421,6 @@ impl fmt::Display for RefMut<'_, T> { /// /// ``` /// use std::cell::UnsafeCell; -/// use std::marker::Sync; /// /// # #[allow(dead_code)] /// struct NotThreadSafe { diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index b052f59b0f5c2..d77936c7ddd91 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -559,6 +559,65 @@ macro_rules! unimplemented { ($($arg:tt)+) => (panic!("not yet implemented: {}", format_args!($($arg)*))); } +/// A standardized placeholder for marking unfinished code. +/// +/// This can be useful if you are prototyping and are just looking to have your +/// code typecheck. `todo!` works exactly like `unimplemented!`, there only +/// difference between the two macros is the name. +/// +/// # Panics +/// +/// This will always [panic!](macro.panic.html) +/// +/// # Examples +/// +/// Here's an example of some in-progress code. We have a trait `Foo`: +/// +/// ``` +/// trait Foo { +/// fn bar(&self); +/// fn baz(&self); +/// } +/// ``` +/// +/// We want to implement `Foo` on one of our types, but we also want to work on +/// just `bar()` first. In order for our code to compile, we need to implement +/// `baz()`, so we can use `todo!`: +/// +/// ``` +/// #![feature(todo_macro)] +/// +/// # trait Foo { +/// # fn bar(&self); +/// # fn baz(&self); +/// # } +/// struct MyStruct; +/// +/// impl Foo for MyStruct { +/// fn bar(&self) { +/// // implementation goes here +/// } +/// +/// fn baz(&self) { +/// // let's not worry about implementing baz() for now +/// todo!(); +/// } +/// } +/// +/// fn main() { +/// let s = MyStruct; +/// s.bar(); +/// +/// // we aren't even using baz() yet, so this is fine. +/// } +/// ``` +#[macro_export] +#[unstable(feature = "todo_macro", issue = "59277")] +macro_rules! todo { + () => (panic!("not yet implemented")); + ($($arg:tt)+) => (panic!("not yet implemented: {}", format_args!($($arg)*))); +} + /// A macro to create an array of [`MaybeUninit`] /// /// This macro constructs an uninitialized array of the type `[MaybeUninit; N]`. diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index cf55b6c379d04..57bd3ed12b28e 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -109,7 +109,7 @@ //! assert_eq!(still_unmoved.slice, NonNull::from(&still_unmoved.data)); //! //! // Since our type doesn't implement Unpin, this will fail to compile: -//! // let new_unmoved = Unmovable::new("world".to_string()); +//! // let mut new_unmoved = Unmovable::new("world".to_string()); //! // std::mem::swap(&mut *still_unmoved, &mut *new_unmoved); //! ``` //! diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index a50310e195f0d..08dda4bcc3d24 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -16,7 +16,6 @@ #![feature(pattern)] #![feature(range_is_empty)] #![feature(raw)] -#![feature(refcell_map_split)] #![feature(refcell_replace_swap)] #![feature(slice_patterns)] #![feature(sort_internals)] diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index ad0ed39185c1c..f118abea2adea 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -482,6 +482,7 @@ pub enum BuiltinLintDiagnostics { UnknownCrateTypes(Span, String, String), UnusedImports(String, Vec<(Span, String)>), NestedImplTrait { outer_impl_trait_span: Span, inner_impl_trait_span: Span }, + RedundantImport(Vec<(Span, bool)>, ast::Ident), } impl BuiltinLintDiagnostics { @@ -578,6 +579,15 @@ impl BuiltinLintDiagnostics { db.span_label(outer_impl_trait_span, "outer `impl Trait`"); db.span_label(inner_impl_trait_span, "nested `impl Trait` here"); } + BuiltinLintDiagnostics::RedundantImport(spans, ident) => { + for (span, is_imported) in spans { + let introduced = if is_imported { "imported" } else { "defined" }; + db.span_label( + span, + format!("the item `{}` is already {} here", ident, introduced) + ); + } + } } } } diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs index c16f861dedb50..7259ef0cc6cf6 100644 --- a/src/librustc/ty/query/on_disk_cache.rs +++ b/src/librustc/ty/query/on_disk_cache.rs @@ -778,7 +778,6 @@ impl<'enc, 'a, 'tcx, E> CacheEncoder<'enc, 'a, 'tcx, E> value: &V) -> Result<(), E::Error> { - use crate::ty::codec::TyEncoder; let start_pos = self.position(); tag.encode(self)?; diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index 23e3a8425d370..c0adee8284292 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -377,7 +377,6 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { // Returns a Value of the "eh_unwind_resume" lang item if one is defined, // otherwise declares it as an external function. fn eh_unwind_resume(&self) -> &'ll Value { - use crate::attributes; let unwresume = &self.eh_unwind_resume; if let Some(llfn) = unwresume.get() { return llfn; diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index b8131671320e1..0ef664dac02d8 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -750,7 +750,6 @@ fn cast_int_to_float<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( // All inputs greater or equal to (f32::MAX + 0.5 ULP) are rounded to infinity, // and for everything else LLVM's uitofp works just fine. use rustc_apfloat::ieee::Single; - use rustc_apfloat::Float; const MAX_F32_PLUS_HALF_ULP: u128 = ((1 << (Single::PRECISION + 1)) - 1) << (Single::MAX_EXP - Single::PRECISION as i16); let max = bx.cx().const_uint_big(int_ty, MAX_F32_PLUS_HALF_ULP); diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 6b4b437930d26..ebbc5a3d3a340 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -155,7 +155,7 @@ impl CodeSuggestion { /// Returns the assembled code suggestions and whether they should be shown with an underline. pub fn splice_lines(&self, cm: &SourceMapperDyn) -> Vec<(String, Vec)> { - use syntax_pos::{CharPos, Loc, Pos}; + use syntax_pos::{CharPos, Pos}; fn push_trailing(buf: &mut String, line_opt: Option<&Cow<'_, str>>, diff --git a/src/librustc_interface/profile/mod.rs b/src/librustc_interface/profile/mod.rs index eb13a5668f927..b6e30e87f0515 100644 --- a/src/librustc_interface/profile/mod.rs +++ b/src/librustc_interface/profile/mod.rs @@ -61,7 +61,6 @@ fn total_duration(traces: &[trace::Rec]) -> Duration { fn profile_queries_thread(r: Receiver) { use self::trace::*; use std::fs::File; - use std::time::{Instant}; let mut profq_msgs: Vec = vec![]; let mut frame: StackFrame = StackFrame { parse_st: ParseState::Clear, traces: vec![] }; diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 8614be8d407b1..17e24e596aed7 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -427,7 +427,6 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { let mut kind = match (lo, hi) { (PatternKind::Constant { value: lo }, PatternKind::Constant { value: hi }) => { - use std::cmp::Ordering; let cmp = compare_const_vals( self.tcx, lo, diff --git a/src/librustc_mir/interpret/operator.rs b/src/librustc_mir/interpret/operator.rs index 944e393d296fc..b6227569f3b00 100644 --- a/src/librustc_mir/interpret/operator.rs +++ b/src/librustc_mir/interpret/operator.rs @@ -331,8 +331,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> val: ImmTy<'tcx, M::PointerTag>, ) -> EvalResult<'tcx, Scalar> { use rustc::mir::UnOp::*; - use rustc_apfloat::ieee::{Single, Double}; - use rustc_apfloat::Float; let layout = val.layout; let val = val.to_scalar()?; diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index ac149be4b2a89..622594a038096 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1733,7 +1733,6 @@ impl<'a> Resolver<'a> { /// just that an error occurred. pub fn resolve_str_path_error(&mut self, span: Span, path_str: &str, is_value: bool) -> Result { - use std::iter; let mut errored = false; let path = if path_str.starts_with("::") { diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 9daffd522bf2c..529c3f51b6458 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -7,6 +7,7 @@ use crate::{NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyErro use crate::{Resolver, Segment}; use crate::{names_to_string, module_to_string}; use crate::{resolve_error, ResolutionError, Suggestion}; +use crate::ModuleKind; use crate::macros::ParentScope; use errors::Applicability; @@ -14,7 +15,11 @@ use errors::Applicability; use rustc_data_structures::ptr_key::PtrKey; use rustc::ty; use rustc::lint::builtin::BuiltinLintDiagnostics; -use rustc::lint::builtin::{DUPLICATE_MACRO_EXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE}; +use rustc::lint::builtin::{ + DUPLICATE_MACRO_EXPORTS, + PUB_USE_OF_PRIVATE_EXTERN_CRATE, + UNUSED_IMPORTS, +}; use rustc::hir::def_id::{CrateNum, DefId}; use rustc::hir::def::*; use rustc::session::DiagnosticMessageId; @@ -1230,10 +1235,97 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { import[ns] = Some(PathResolution::new(def)); }); + self.check_for_redundant_imports( + ident, + directive, + source_bindings, + target_bindings, + target, + ); + debug!("(resolving single import) successfully resolved import"); None } + fn check_for_redundant_imports( + &mut self, + ident: Ident, + directive: &'b ImportDirective<'b>, + source_bindings: &PerNS, Determinacy>>>, + target_bindings: &PerNS>>>, + target: Ident, + ) { + // Skip if the import was produced by a macro. + if directive.parent_scope.expansion != Mark::root() { + return; + } + + // Skip if we are inside a named module (in contrast to an anonymous + // module defined by a block). + if let ModuleKind::Def(_, _) = directive.parent_scope.module.kind { + return; + } + + let mut is_redundant = PerNS { + value_ns: None, + type_ns: None, + macro_ns: None, + }; + + let mut redundant_span = PerNS { + value_ns: None, + type_ns: None, + macro_ns: None, + }; + + self.per_ns(|this, ns| if let Some(binding) = source_bindings[ns].get().ok() { + if binding.def() == Def::Err { + return; + } + + let orig_blacklisted_binding = mem::replace( + &mut this.blacklisted_binding, + target_bindings[ns].get() + ); + + match this.early_resolve_ident_in_lexical_scope( + target, + ScopeSet::Import(ns), + &directive.parent_scope, + false, + false, + directive.span, + ) { + Ok(other_binding) => { + is_redundant[ns] = Some( + binding.def() == other_binding.def() + && !other_binding.is_ambiguity() + ); + redundant_span[ns] = + Some((other_binding.span, other_binding.is_import())); + } + Err(_) => is_redundant[ns] = Some(false) + } + + this.blacklisted_binding = orig_blacklisted_binding; + }); + + if !is_redundant.is_empty() && + is_redundant.present_items().all(|is_redundant| is_redundant) + { + self.session.buffer_lint_with_diagnostic( + UNUSED_IMPORTS, + directive.id, + directive.span, + &format!("the item `{}` is imported redundantly", ident), + BuiltinLintDiagnostics::RedundantImport( + redundant_span.present_items().collect(), + ident, + ), + ); + } + } + fn resolve_glob_import(&mut self, directive: &'b ImportDirective<'b>) { let module = match directive.imported_module.get().unwrap() { ModuleOrUniformRoot::Module(module) => module, diff --git a/src/librustc_traits/lowering/environment.rs b/src/librustc_traits/lowering/environment.rs index c908c6993e19e..a6062fac61d61 100644 --- a/src/librustc_traits/lowering/environment.rs +++ b/src/librustc_traits/lowering/environment.rs @@ -190,7 +190,7 @@ crate fn environment<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId ) -> Environment<'tcx> { - use super::{Lower, IntoFromEnvGoal}; + use super::IntoFromEnvGoal; use rustc::hir::{Node, TraitItemKind, ImplItemKind, ItemKind, ForeignItemKind}; debug!("environment(def_id = {:?})", def_id); diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 0675feade53ef..45f54e52673cf 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -420,9 +420,6 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>( def_id: DefId, return_ty: Option>, ) { - use ty::subst::Subst; - use rustc::ty::TypeFoldable; - let predicates = fcx.tcx.predicates_of(def_id); let generics = tcx.generics_of(def_id); @@ -1010,8 +1007,6 @@ fn check_false_global_bounds<'a, 'gcx, 'tcx>( span: Span, id: hir::HirId) { - use rustc::ty::TypeFoldable; - let empty_env = ty::ParamEnv::empty(); let def_id = fcx.tcx.hir().local_def_id_from_hir_id(id); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index c51c8027de64e..4819256a54550 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -508,6 +508,18 @@ impl Item { .as_ref() .or_else(|| self.stability.as_ref().and_then(|s| s.deprecation.as_ref())) } + pub fn is_default(&self) -> bool { + match self.inner { + ItemEnum::MethodItem(ref meth) => { + if let Some(defaultness) = meth.defaultness { + defaultness.has_value() && !defaultness.is_final() + } else { + false + } + } + _ => false, + } + } } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] @@ -1700,9 +1712,11 @@ pub struct Method { pub generics: Generics, pub decl: FnDecl, pub header: hir::FnHeader, + pub defaultness: Option, } -impl<'a> Clean for (&'a hir::MethodSig, &'a hir::Generics, hir::BodyId) { +impl<'a> Clean for (&'a hir::MethodSig, &'a hir::Generics, hir::BodyId, + Option) { fn clean(&self, cx: &DocContext<'_>) -> Method { let (generics, decl) = enter_impl_trait(cx, || { (self.1.clean(cx), (&*self.0.decl, self.2).clean(cx)) @@ -1711,6 +1725,7 @@ impl<'a> Clean for (&'a hir::MethodSig, &'a hir::Generics, hir::BodyId) decl, generics, header: self.0.header, + defaultness: self.3, } } } @@ -2016,7 +2031,7 @@ impl Clean for hir::TraitItem { default.map(|e| print_const_expr(cx, e))) } hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => { - MethodItem((sig, &self.generics, body).clean(cx)) + MethodItem((sig, &self.generics, body, None).clean(cx)) } hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref names)) => { let (generics, decl) = enter_impl_trait(cx, || { @@ -2054,7 +2069,7 @@ impl Clean for hir::ImplItem { Some(print_const_expr(cx, expr))) } hir::ImplItemKind::Method(ref sig, body) => { - MethodItem((sig, &self.generics, body).clean(cx)) + MethodItem((sig, &self.generics, body, Some(self.defaultness)).clean(cx)) } hir::ImplItemKind::Type(ref ty) => TypedefItem(Typedef { type_: ty.clean(cx), @@ -2137,7 +2152,8 @@ impl<'tcx> Clean for ty::AssociatedItem { abi: sig.abi(), constness, asyncness: hir::IsAsync::NotAsync, - } + }, + defaultness: Some(self.defaultness), }) } else { TyMethodItem(TyMethod { diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index d204a179ca62c..48baf27bae20a 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -45,6 +45,7 @@ pub struct GenericBounds<'a>(pub &'a [clean::GenericBound]); /// Wrapper struct for emitting a comma-separated list of items pub struct CommaSep<'a, T>(pub &'a [T]); pub struct AbiSpace(pub Abi); +pub struct DefaultSpace(pub bool); /// Wrapper struct for properly emitting a function or method declaration. pub struct Function<'a> { @@ -1057,3 +1058,13 @@ impl fmt::Display for AbiSpace { } } } + +impl fmt::Display for DefaultSpace { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if self.0 { + write!(f, "default ") + } else { + Ok(()) + } + } +} diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index b3a816d17f56c..54074845f10e4 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -61,7 +61,7 @@ use crate::doctree; use crate::fold::DocFolder; use crate::html::escape::Escape; use crate::html::format::{AsyncSpace, ConstnessSpace}; -use crate::html::format::{GenericBounds, WhereClause, href, AbiSpace}; +use crate::html::format::{GenericBounds, WhereClause, href, AbiSpace, DefaultSpace}; use crate::html::format::{VisSpace, Function, UnsafetySpace, MutableSpace}; use crate::html::format::fmt_impl_for_trait_page; use crate::html::item_type::ItemType; @@ -1061,8 +1061,6 @@ themePicker.onblur = handleThemeButtonsBlur; } if cx.shared.include_sources { - use std::path::Component; - let mut hierarchy = Hierarchy::new(OsString::new()); for source in cx.shared.local_sources.iter() .filter_map(|p| p.0.strip_prefix(&cx.shared.src_root) @@ -3429,11 +3427,12 @@ fn render_assoc_item(w: &mut fmt::Formatter<'_>, } }; let mut header_len = format!( - "{}{}{}{}{:#}fn {}{:#}", + "{}{}{}{}{}{:#}fn {}{:#}", VisSpace(&meth.visibility), ConstnessSpace(header.constness), UnsafetySpace(header.unsafety), AsyncSpace(header.asyncness), + DefaultSpace(meth.is_default()), AbiSpace(header.abi), name, *g @@ -3445,12 +3444,13 @@ fn render_assoc_item(w: &mut fmt::Formatter<'_>, (0, true) }; render_attributes(w, meth)?; - write!(w, "{}{}{}{}{}fn {name}\ + write!(w, "{}{}{}{}{}{}fn {name}\ {generics}{decl}{where_clause}", VisSpace(&meth.visibility), ConstnessSpace(header.constness), UnsafetySpace(header.unsafety), AsyncSpace(header.asyncness), + DefaultSpace(meth.is_default()), AbiSpace(header.abi), href = href, name = name, diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index f1d4d8470b2a5..0bbc7c5c4b223 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -371,8 +371,7 @@ pub fn make_test(s: &str, // Uses libsyntax to parse the doctest and find if there's a main fn and the extern // crate already is included. let (already_has_main, already_has_extern_crate, found_macro) = crate::syntax::with_globals(|| { - use crate::syntax::{ast, parse::{self, ParseSess}, source_map::FilePathMapping}; - use crate::syntax_pos::FileName; + use crate::syntax::{parse::{self, ParseSess}, source_map::FilePathMapping}; use errors::emitter::EmitterWriter; use errors::Handler; diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index a2b12d00a78c2..2fabe30fa9366 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -32,11 +32,13 @@ impl f32 { /// # Examples /// /// ``` - /// let f = 3.99_f32; + /// let f = 3.7_f32; /// let g = 3.0_f32; + /// let h = -3.7_f32; /// /// assert_eq!(f.floor(), 3.0); /// assert_eq!(g.floor(), 3.0); + /// assert_eq!(h.floor(), -4.0); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -104,11 +106,13 @@ impl f32 { /// # Examples /// /// ``` - /// let f = 3.3_f32; - /// let g = -3.7_f32; + /// let f = 3.7_f32; + /// let g = 3.0_f32; + /// let h = -3.7_f32; /// /// assert_eq!(f.trunc(), 3.0); - /// assert_eq!(g.trunc(), -3.0); + /// assert_eq!(g.trunc(), 3.0); + /// assert_eq!(h.trunc(), -3.0); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index be5cd92d4167b..a471117f6d6fd 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -32,11 +32,13 @@ impl f64 { /// # Examples /// /// ``` - /// let f = 3.99_f64; + /// let f = 3.7_f64; /// let g = 3.0_f64; + /// let h = -3.7_f64; /// /// assert_eq!(f.floor(), 3.0); /// assert_eq!(g.floor(), 3.0); + /// assert_eq!(h.floor(), -4.0); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] @@ -84,11 +86,13 @@ impl f64 { /// # Examples /// /// ``` - /// let f = 3.3_f64; - /// let g = -3.7_f64; + /// let f = 3.7_f64; + /// let g = 3.0_f64; + /// let h = -3.7_f64; /// /// assert_eq!(f.trunc(), 3.0); - /// assert_eq!(g.trunc(), -3.0); + /// assert_eq!(g.trunc(), 3.0); + /// assert_eq!(h.trunc(), -3.0); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index a14c10d0b61e9..4668e3ec7eabd 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -193,6 +193,13 @@ impl BufReader { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn into_inner(self) -> R { self.inner } + + /// Invalidates all data in the internal buffer. + #[inline] + fn discard_buffer(&mut self) { + self.pos = 0; + self.cap = 0; + } } impl BufReader { @@ -227,6 +234,7 @@ impl Read for BufReader { // (larger than our internal buffer), bypass our internal buffer // entirely. if self.pos == self.cap && buf.len() >= self.buf.len() { + self.discard_buffer(); return self.inner.read(buf); } let nread = { @@ -240,6 +248,7 @@ impl Read for BufReader { fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> io::Result { let total_len = bufs.iter().map(|b| b.len()).sum::(); if self.pos == self.cap && total_len >= self.buf.len() { + self.discard_buffer(); return self.inner.read_vectored(bufs); } let nread = { @@ -325,14 +334,14 @@ impl Seek for BufReader { } else { // seek backwards by our remainder, and then by the offset self.inner.seek(SeekFrom::Current(-remainder))?; - self.pos = self.cap; // empty the buffer + self.discard_buffer(); result = self.inner.seek(SeekFrom::Current(n))?; } } else { // Seeking with Start/End doesn't care about our buffer length. result = self.inner.seek(pos)?; } - self.pos = self.cap; // empty the buffer + self.discard_buffer(); Ok(result) } } @@ -1068,6 +1077,40 @@ mod tests { assert_eq!(reader.fill_buf().ok(), Some(&[2, 3][..])); } + #[test] + fn test_buffered_reader_invalidated_after_read() { + let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4]; + let mut reader = BufReader::with_capacity(3, io::Cursor::new(inner)); + + assert_eq!(reader.fill_buf().ok(), Some(&[5, 6, 7][..])); + reader.consume(3); + + let mut buffer = [0, 0, 0, 0, 0]; + assert_eq!(reader.read(&mut buffer).ok(), Some(5)); + assert_eq!(buffer, [0, 1, 2, 3, 4]); + + assert!(reader.seek_relative(-2).is_ok()); + let mut buffer = [0, 0]; + assert_eq!(reader.read(&mut buffer).ok(), Some(2)); + assert_eq!(buffer, [3, 4]); + } + + #[test] + fn test_buffered_reader_invalidated_after_seek() { + let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4]; + let mut reader = BufReader::with_capacity(3, io::Cursor::new(inner)); + + assert_eq!(reader.fill_buf().ok(), Some(&[5, 6, 7][..])); + reader.consume(3); + + assert!(reader.seek(SeekFrom::Current(5)).is_ok()); + + assert!(reader.seek_relative(-2).is_ok()); + let mut buffer = [0, 0]; + assert_eq!(reader.read(&mut buffer).ok(), Some(2)); + assert_eq!(buffer, [3, 4]); + } + #[test] fn test_buffered_reader_seek_underflow() { // gimmick reader that yields its position modulo 256 for each byte diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index fc8ac9a0b3e00..296c4c887274e 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -301,6 +301,7 @@ #![feature(stmt_expr_attributes)] #![feature(str_internals)] #![feature(thread_local)] +#![feature(todo_macro)] #![feature(toowned_clone_into)] #![feature(try_reserve)] #![feature(unboxed_closures)] @@ -323,7 +324,7 @@ use prelude::v1::*; #[stable(feature = "rust1", since = "1.0.0")] pub use core::{assert_eq, assert_ne, debug_assert, debug_assert_eq, debug_assert_ne}; #[stable(feature = "rust1", since = "1.0.0")] -pub use core::{unreachable, unimplemented, write, writeln, r#try}; +pub use core::{unreachable, unimplemented, write, writeln, r#try, todo}; #[allow(unused_imports)] // macros from `alloc` are not used on all platforms #[macro_use] diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 9d0eb2e6b1cef..d5dc5f7c4f0df 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -305,10 +305,16 @@ macro_rules! eprintln { /// let _ = dbg!(a); // <-- `a` is moved again; error! /// ``` /// +/// You can also use `dbg!()` without a value to just print the +/// file and line whenever it's reached. +/// /// [stderr]: https://en.wikipedia.org/wiki/Standard_streams#Standard_error_(stderr) #[macro_export] #[stable(feature = "dbg_macro", since = "1.32.0")] macro_rules! dbg { + () => { + eprintln!("[{}:{}]", file!(), line!()); + }; ($val:expr) => { // Use of `match` here is intentional because it affects the lifetimes // of temporaries - https://stackoverflow.com/a/48732525/1063961 diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs index edc9d665444a0..b42a812304269 100644 --- a/src/libstd/net/udp.rs +++ b/src/libstd/net/udp.rs @@ -180,6 +180,37 @@ impl UdpSocket { } } + /// Returns the socket address of the remote peer this socket was connected to. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(udp_peer_addr)] + /// use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, UdpSocket}; + /// + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); + /// socket.connect("192.168.0.1:41203").expect("couldn't connect to address"); + /// assert_eq!(socket.peer_addr().unwrap(), + /// SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(192, 168, 0, 1), 41203))); + /// ``` + /// + /// If the socket isn't connected, it will return a [`NotConnected`] error. + /// + /// [`NotConnected`]: ../../std/io/enum.ErrorKind.html#variant.NotConnected + /// + /// ```no_run + /// #![feature(udp_peer_addr)] + /// use std::net::UdpSocket; + /// + /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); + /// assert_eq!(socket.peer_addr().unwrap_err().kind(), + /// ::std::io::ErrorKind::NotConnected); + /// ``` + #[unstable(feature = "udp_peer_addr", issue = "59127")] + pub fn peer_addr(&self) -> io::Result { + self.0.peer_addr() + } + /// Returns the socket address that this socket was created from. /// /// # Examples @@ -865,13 +896,23 @@ mod tests { } #[test] - fn socket_name_ip4() { + fn socket_name() { each_ip(&mut |addr, _| { let server = t!(UdpSocket::bind(&addr)); assert_eq!(addr, t!(server.local_addr())); }) } + #[test] + fn socket_peer() { + each_ip(&mut |addr1, addr2| { + let server = t!(UdpSocket::bind(&addr1)); + assert_eq!(server.peer_addr().unwrap_err().kind(), ErrorKind::NotConnected); + t!(server.connect(&addr2)); + assert_eq!(addr2, t!(server.peer_addr())); + }) + } + #[test] fn udp_clone_smoke() { each_ip(&mut |addr1, addr2| { diff --git a/src/libstd/sys/cloudabi/shims/net.rs b/src/libstd/sys/cloudabi/shims/net.rs index 6d2a4962ab444..4364a1365443a 100644 --- a/src/libstd/sys/cloudabi/shims/net.rs +++ b/src/libstd/sys/cloudabi/shims/net.rs @@ -159,6 +159,10 @@ impl UdpSocket { unsupported() } + pub fn peer_addr(&self) -> io::Result { + match self.0 {} + } + pub fn socket_addr(&self) -> io::Result { match self.0 {} } diff --git a/src/libstd/sys/redox/net/udp.rs b/src/libstd/sys/redox/net/udp.rs index b1a60b1457083..274123dce4b58 100644 --- a/src/libstd/sys/redox/net/udp.rs +++ b/src/libstd/sys/redox/net/udp.rs @@ -72,6 +72,11 @@ impl UdpSocket { Ok(None) } + pub fn peer_addr(&self) -> Result { + let path = self.0.path()?; + Ok(path_to_peer_addr(path.to_str().unwrap_or(""))) + } + pub fn socket_addr(&self) -> Result { let path = self.0.path()?; Ok(path_to_local_addr(path.to_str().unwrap_or(""))) diff --git a/src/libstd/sys/sgx/net.rs b/src/libstd/sys/sgx/net.rs index e167e917957f3..81f33c16294c3 100644 --- a/src/libstd/sys/sgx/net.rs +++ b/src/libstd/sys/sgx/net.rs @@ -249,6 +249,10 @@ impl UdpSocket { unsupported() } + pub fn peer_addr(&self) -> io::Result { + match self.0 {} + } + pub fn socket_addr(&self) -> io::Result { match self.0 {} } diff --git a/src/libstd/sys/unix/l4re.rs b/src/libstd/sys/unix/l4re.rs index b9e725371a36e..b3dd1cf6aaac7 100644 --- a/src/libstd/sys/unix/l4re.rs +++ b/src/libstd/sys/unix/l4re.rs @@ -292,6 +292,10 @@ pub mod net { pub fn into_socket(self) -> Socket { self.inner } + pub fn peer_addr(&self) -> io::Result { + unimpl!(); + } + pub fn socket_addr(&self) -> io::Result { unimpl!(); } @@ -463,4 +467,3 @@ pub mod net { } } } - diff --git a/src/libstd/sys/wasm/net.rs b/src/libstd/sys/wasm/net.rs index a2ea2dfbbc032..c85dd000afe6f 100644 --- a/src/libstd/sys/wasm/net.rs +++ b/src/libstd/sys/wasm/net.rs @@ -156,6 +156,10 @@ impl UdpSocket { unsupported() } + pub fn peer_addr(&self) -> io::Result { + match self.0 {} + } + pub fn socket_addr(&self) -> io::Result { match self.0 {} } diff --git a/src/libstd/sys_common/net.rs b/src/libstd/sys_common/net.rs index b9505aaa69ba5..b77bcee4b9d04 100644 --- a/src/libstd/sys_common/net.rs +++ b/src/libstd/sys_common/net.rs @@ -472,6 +472,12 @@ impl UdpSocket { pub fn into_socket(self) -> Socket { self.inner } + pub fn peer_addr(&self) -> io::Result { + sockname(|buf, len| unsafe { + c::getpeername(*self.inner.as_inner(), buf, len) + }) + } + pub fn socket_addr(&self) -> io::Result { sockname(|buf, len| unsafe { c::getsockname(*self.inner.as_inner(), buf, len) diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index 4ce308d015c00..80a7bde606afa 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -178,9 +178,11 @@ impl TokenStream { while let Some((pos, ts)) = iter.next() { if let Some((_, next)) = iter.peek() { let sp = match (&ts, &next) { - ((TokenTree::Token(_, token::Token::Comma), NonJoint), _) | - (_, (TokenTree::Token(_, token::Token::Comma), NonJoint)) => continue, - ((TokenTree::Token(sp, _), NonJoint), _) => *sp, + (_, (TokenTree::Token(_, token::Token::Comma), _)) => continue, + ((TokenTree::Token(sp, token_left), NonJoint), + (TokenTree::Token(_, token_right), _)) + if (token_left.is_ident() || token_left.is_lit()) && + (token_right.is_ident() || token_right.is_lit()) => *sp, ((TokenTree::Delimited(sp, ..), NonJoint), _) => sp.entire(), _ => continue, }; diff --git a/src/test/run-pass/binding/match-arm-statics.rs b/src/test/run-pass/binding/match-arm-statics.rs index 359c39211588c..5f7e357eeb2a9 100644 --- a/src/test/run-pass/binding/match-arm-statics.rs +++ b/src/test/run-pass/binding/match-arm-statics.rs @@ -45,8 +45,6 @@ pub mod glfw { } fn issue_6533() { - use glfw; - fn action_to_str(state: glfw::InputState) -> &'static str { use glfw::{RELEASE, PRESS, REPEAT}; match state { diff --git a/src/test/run-pass/ifmt.rs b/src/test/run-pass/ifmt.rs index 56222fa46f7c9..8c17b01e2bd89 100644 --- a/src/test/run-pass/ifmt.rs +++ b/src/test/run-pass/ifmt.rs @@ -238,7 +238,6 @@ pub fn main() { // Basic test to make sure that we can invoke the `write!` macro with an // fmt::Write instance. fn test_write() { - use std::fmt::Write; let mut buf = String::new(); write!(&mut buf, "{}", 3); { @@ -267,7 +266,6 @@ fn test_print() { // Just make sure that the macros are defined, there's not really a lot that we // can do with them just yet (to test the output) fn test_format_args() { - use std::fmt::Write; let mut buf = String::new(); { let w = &mut buf; diff --git a/src/test/run-pass/invalid_const_promotion.rs b/src/test/run-pass/invalid_const_promotion.rs index 1524373895d9b..2775aac015615 100644 --- a/src/test/run-pass/invalid_const_promotion.rs +++ b/src/test/run-pass/invalid_const_promotion.rs @@ -25,7 +25,6 @@ fn foo() { #[cfg(unix)] fn check_status(status: std::process::ExitStatus) { - use libc; use std::os::unix::process::ExitStatusExt; assert!(status.signal() == Some(libc::SIGILL) diff --git a/src/test/run-pass/issues/issue-38556.rs b/src/test/run-pass/issues/issue-38556.rs index 0cc247f5b9ca5..63fd9db08ff2f 100644 --- a/src/test/run-pass/issues/issue-38556.rs +++ b/src/test/run-pass/issues/issue-38556.rs @@ -9,6 +9,5 @@ macro_rules! reexport { reexport!(); fn main() { - use Bar; fn f(_: Bar) {} } diff --git a/src/test/run-pass/issues/issue-39367.rs b/src/test/run-pass/issues/issue-39367.rs index bd92224bce161..484cd782a09df 100644 --- a/src/test/run-pass/issues/issue-39367.rs +++ b/src/test/run-pass/issues/issue-39367.rs @@ -15,7 +15,6 @@ fn arena() -> &'static ArenaSet> { fn require_sync(_: &T) { } unsafe fn __stability() -> &'static ArenaSet> { use std::mem::transmute; - use std::boxed::Box; static mut DATA: *const ArenaSet> = 0 as *const ArenaSet>; static mut ONCE: Once = ONCE_INIT; diff --git a/src/test/run-pass/out-of-stack.rs b/src/test/run-pass/out-of-stack.rs index 72d6d6806229e..9f868d6e5c3e4 100644 --- a/src/test/run-pass/out-of-stack.rs +++ b/src/test/run-pass/out-of-stack.rs @@ -36,7 +36,6 @@ fn loud_recurse() { #[cfg(unix)] fn check_status(status: std::process::ExitStatus) { - use libc; use std::os::unix::process::ExitStatusExt; assert!(!status.success()); diff --git a/src/test/run-pass/rfcs/rfc-2126-extern-absolute-paths/basic.rs b/src/test/run-pass/rfcs/rfc-2126-extern-absolute-paths/basic.rs index 15449a6b83e2e..566b3581046d9 100644 --- a/src/test/run-pass/rfcs/rfc-2126-extern-absolute-paths/basic.rs +++ b/src/test/run-pass/rfcs/rfc-2126-extern-absolute-paths/basic.rs @@ -4,6 +4,8 @@ // compile-flags:--extern xcrate // edition:2018 +#![allow(unused_imports)] + use xcrate::Z; fn f() { diff --git a/src/test/run-pass/traits/traits-multidispatch-infer-convert-target.rs b/src/test/run-pass/traits/traits-multidispatch-infer-convert-target.rs index ca47d9736f63c..626e1ae71bc2f 100644 --- a/src/test/run-pass/traits/traits-multidispatch-infer-convert-target.rs +++ b/src/test/run-pass/traits/traits-multidispatch-infer-convert-target.rs @@ -28,7 +28,6 @@ where T : Convert } fn main() { - use std::default::Default; // T = i16, U = u32 test(22_i16, Default::default(), 2, 4); diff --git a/src/test/rustdoc/default_trait_method.rs b/src/test/rustdoc/default_trait_method.rs new file mode 100644 index 0000000000000..dfbd8f2210fa4 --- /dev/null +++ b/src/test/rustdoc/default_trait_method.rs @@ -0,0 +1,15 @@ +#![feature(specialization)] + +pub trait Item { + fn foo(); + fn bar(); +} + +// @has default_trait_method/trait.Item.html +// @has - '//*[@id="method.foo"]' 'default fn foo()' +// @has - '//*[@id="method.bar"]' 'fn bar()' +// @!has - '//*[@id="method.bar"]' 'default fn bar()' +impl Item for T { + default fn foo() {} + fn bar() {} +} diff --git a/src/test/ui/lint/lint-unused-imports.rs b/src/test/ui/lint/lint-unused-imports.rs index 9c5b206203c1d..4754d8880763a 100644 --- a/src/test/ui/lint/lint-unused-imports.rs +++ b/src/test/ui/lint/lint-unused-imports.rs @@ -66,6 +66,7 @@ mod bar { fn g() { use self::g; //~ ERROR unused import: `self::g` + //~^ ERROR the item `g` is imported redundantly fn f() { self::g(); } @@ -75,6 +76,7 @@ fn g() { #[allow(unused_variables)] fn h() { use test2::foo; //~ ERROR unused import: `test2::foo` + //~^ ERROR the item `foo` is imported redundantly let foo = 0; } diff --git a/src/test/ui/lint/lint-unused-imports.stderr b/src/test/ui/lint/lint-unused-imports.stderr index f9a54f477f998..96d71a228a5f2 100644 --- a/src/test/ui/lint/lint-unused-imports.stderr +++ b/src/test/ui/lint/lint-unused-imports.stderr @@ -34,14 +34,36 @@ error: unused import: `foo::Square` LL | use foo::Square; | ^^^^^^^^^^^ +error: the item `g` is imported redundantly + --> $DIR/lint-unused-imports.rs:68:9 + | +LL | / fn g() { +LL | | use self::g; + | | ^^^^^^^ +LL | | +LL | | fn f() { +LL | | self::g(); +LL | | } +LL | | } + | |_- the item `g` is already defined here + error: unused import: `self::g` --> $DIR/lint-unused-imports.rs:68:9 | LL | use self::g; | ^^^^^^^ +error: the item `foo` is imported redundantly + --> $DIR/lint-unused-imports.rs:78:9 + | +LL | use test2::{foo, bar}; + | --- the item `foo` is already imported here +... +LL | use test2::foo; + | ^^^^^^^^^^ + error: unused import: `test2::foo` - --> $DIR/lint-unused-imports.rs:77:9 + --> $DIR/lint-unused-imports.rs:78:9 | LL | use test2::foo; | ^^^^^^^^^^ @@ -52,5 +74,5 @@ error: unused import: `test::B2` LL | use test::B2; | ^^^^^^^^ -error: aborting due to 8 previous errors +error: aborting due to 10 previous errors diff --git a/src/test/ui/lint/use-redundant.rs b/src/test/ui/lint/use-redundant.rs new file mode 100644 index 0000000000000..328f8232bafa8 --- /dev/null +++ b/src/test/ui/lint/use-redundant.rs @@ -0,0 +1,27 @@ +// compile-pass +#![warn(unused_imports)] + +use crate::foo::Bar; //~ WARNING first import + +mod foo { + pub type Bar = i32; +} + +fn baz() -> Bar { + 3 +} + +mod m1 { pub struct S {} } +mod m2 { pub struct S {} } + +use m1::*; +use m2::*; + +fn main() { + use crate::foo::Bar; //~ WARNING redundant import + let _a: Bar = 3; + baz(); + + use m1::S; //~ WARNING redundant import + let _s = S {}; +} diff --git a/src/test/ui/lint/use-redundant.stderr b/src/test/ui/lint/use-redundant.stderr new file mode 100644 index 0000000000000..fbd9f81f18f8a --- /dev/null +++ b/src/test/ui/lint/use-redundant.stderr @@ -0,0 +1,27 @@ +warning: unused import: `m1::*` + --> $DIR/use-redundant.rs:17:5 + | +LL | use m1::*; + | ^^^^^ + | +note: lint level defined here + --> $DIR/use-redundant.rs:2:9 + | +LL | #![warn(unused_imports)] + | ^^^^^^^^^^^^^^ + +warning: unused import: `m2::*` + --> $DIR/use-redundant.rs:18:5 + | +LL | use m2::*; + | ^^^^^ + +warning: the item `Bar` is imported redundantly + --> $DIR/use-redundant.rs:21:9 + | +LL | use crate::foo::Bar; + | --------------- the item `Bar` is already imported here +... +LL | use crate::foo::Bar; + | ^^^^^^^^^^^^^^^ + diff --git a/src/test/ui/macros/missing-comma.rs b/src/test/ui/macros/missing-comma.rs index 1e146875bcc76..2b411aba8a2ee 100644 --- a/src/test/ui/macros/missing-comma.rs +++ b/src/test/ui/macros/missing-comma.rs @@ -6,6 +6,11 @@ macro_rules! foo { ($a:ident, $b:ident, $c:ident, $d:ident, $e:ident) => (); } +macro_rules! bar { + ($lvl:expr, $($arg:tt)+) => {} +} + + fn main() { println!("{}" a); //~^ ERROR expected token: `,` @@ -17,4 +22,6 @@ fn main() { //~^ ERROR no rules expected the token `d` foo!(a, b, c d e); //~^ ERROR no rules expected the token `d` + bar!(Level::Error, ); + //~^ ERROR unexpected end of macro invocation } diff --git a/src/test/ui/macros/missing-comma.stderr b/src/test/ui/macros/missing-comma.stderr index 5881e0b7b68c6..424fefd00f873 100644 --- a/src/test/ui/macros/missing-comma.stderr +++ b/src/test/ui/macros/missing-comma.stderr @@ -1,11 +1,11 @@ error: expected token: `,` - --> $DIR/missing-comma.rs:10:19 + --> $DIR/missing-comma.rs:15:19 | LL | println!("{}" a); | ^ error: no rules expected the token `b` - --> $DIR/missing-comma.rs:12:12 + --> $DIR/missing-comma.rs:17:12 | LL | macro_rules! foo { | ---------------- when calling this macro @@ -16,7 +16,7 @@ LL | foo!(a b); | help: missing comma here error: no rules expected the token `e` - --> $DIR/missing-comma.rs:14:21 + --> $DIR/missing-comma.rs:19:21 | LL | macro_rules! foo { | ---------------- when calling this macro @@ -27,7 +27,7 @@ LL | foo!(a, b, c, d e); | help: missing comma here error: no rules expected the token `d` - --> $DIR/missing-comma.rs:16:18 + --> $DIR/missing-comma.rs:21:18 | LL | macro_rules! foo { | ---------------- when calling this macro @@ -38,7 +38,7 @@ LL | foo!(a, b, c d, e); | help: missing comma here error: no rules expected the token `d` - --> $DIR/missing-comma.rs:18:18 + --> $DIR/missing-comma.rs:23:18 | LL | macro_rules! foo { | ---------------- when calling this macro @@ -46,5 +46,14 @@ LL | macro_rules! foo { LL | foo!(a, b, c d e); | ^ no rules expected this token in macro call -error: aborting due to 5 previous errors +error: unexpected end of macro invocation + --> $DIR/missing-comma.rs:25:23 + | +LL | macro_rules! bar { + | ---------------- when calling this macro +... +LL | bar!(Level::Error, ); + | ^ missing tokens in macro arguments + +error: aborting due to 6 previous errors diff --git a/src/test/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.rs b/src/test/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.rs new file mode 100644 index 0000000000000..3d042d442d531 --- /dev/null +++ b/src/test/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.rs @@ -0,0 +1,70 @@ +// This test is ensuring that type ascriptions on let bindings +// constrain both: +// +// 1. the input expression on the right-hand side (after any potential +// coercion, and allowing for covariance), *and* +// +// 2. the bindings (if any) nested within the pattern on the left-hand +// side (and here, the type-constraint is *invariant*). + +#![feature(nll)] + +#![allow(dead_code, unused_mut)] +type PairUncoupled<'a, 'b, T> = (&'a T, &'b T); +type PairCoupledRegions<'a, T> = (&'a T, &'a T); +type PairCoupledTypes = (T, T); + +fn uncoupled_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 { + let ((mut y, mut _z),): (PairUncoupled,) = ((s, &_x),); // ok + // Above compiling does *not* imply below would compile. + // ::std::mem::swap(&mut y, &mut _z); + y +} + +fn swap_regions((mut y, mut _z): PairCoupledRegions) { + ::std::mem::swap(&mut y, &mut _z); +} + +fn coupled_regions_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 { + let ((y, _z),): (PairCoupledRegions,) = ((s, &_x),); + // If above line compiled, so should line below ... + + // swap_regions((y, _z)); + + // ... but the ascribed type also invalidates this use of `y` + y //~ ERROR lifetime may not live long enough +} + +fn swap_types((mut y, mut _z): PairCoupledTypes<&u32>) { + ::std::mem::swap(&mut y, &mut _z); +} + +fn coupled_types_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 { + let ((y, _z),): (PairCoupledTypes<&u32>,) = ((s, &_x),); + // If above line compiled, so should line below ... + + // swap_types((y, _z)); + + // ... but the ascribed type also invalidates this use of `y` + y //~ ERROR lifetime may not live long enough +} + +fn swap_wilds((mut y, mut _z): PairCoupledTypes<&u32>) { + ::std::mem::swap(&mut y, &mut _z); +} + +fn coupled_wilds_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 { + let ((y, _z),): (PairCoupledTypes<_>,) = ((s, &_x),); + // If above line compiled, so should line below + // swap_wilds((y, _z)); + + // ... but the ascribed type also invalidates this use of `y` + y //~ ERROR lifetime may not live long enough +} + +fn main() { + uncoupled_lhs(&3, &4); + coupled_regions_lhs(&3, &4); + coupled_types_lhs(&3, &4); + coupled_wilds_lhs(&3, &4); +} diff --git a/src/test/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.stderr b/src/test/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.stderr new file mode 100644 index 0000000000000..5929707e41e10 --- /dev/null +++ b/src/test/ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.stderr @@ -0,0 +1,29 @@ +error: lifetime may not live long enough + --> $DIR/issue-55748-pat-types-constrain-bindings.rs:35:5 + | +LL | fn coupled_regions_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 { + | -- lifetime `'a` defined here +... +LL | y + | ^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/issue-55748-pat-types-constrain-bindings.rs:49:5 + | +LL | fn coupled_types_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 { + | -- lifetime `'a` defined here +... +LL | y + | ^ returning this value requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/issue-55748-pat-types-constrain-bindings.rs:62:5 + | +LL | fn coupled_wilds_lhs<'a>(_x: &'a u32, s: &'static u32) -> &'static u32 { + | -- lifetime `'a` defined here +... +LL | y + | ^ returning this value requires that `'a` must outlive `'static` + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs index 3d24f49ad7509..67f7f80a9e2da 100644 --- a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs +++ b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs @@ -33,6 +33,9 @@ fn test() { // We can move `b` because it's Copy. drop(b); + // Without parameters works as expected. + let _: () = dbg!(); + // Test that we can borrow and that successive applications is still identity. let a = NoCopy(1337); let b: &NoCopy = dbg!(dbg!(&a)); @@ -69,17 +72,19 @@ fn validate_stderr(stderr: Vec) { " y: 24", "}", - ":38] &a = NoCopy(", + ":37]", + + ":41] &a = NoCopy(", " 1337", ")", - ":38] dbg!(& a) = NoCopy(", + ":41] dbg!(& a) = NoCopy(", " 1337", ")", - ":43] f(&42) = 42", + ":46] f(&42) = 42", "before", - ":48] { foo += 1; eprintln!(\"before\"); 7331 } = 7331", + ":51] { foo += 1; eprintln!(\"before\"); 7331 } = 7331", ]); } diff --git a/src/test/ui/rust-2018/future-proofing-locals.rs b/src/test/ui/rust-2018/future-proofing-locals.rs index 1e53c2d1daca4..2c388cf3713b0 100644 --- a/src/test/ui/rust-2018/future-proofing-locals.rs +++ b/src/test/ui/rust-2018/future-proofing-locals.rs @@ -1,6 +1,7 @@ // edition:2018 #![allow(non_camel_case_types)] +#![allow(unused_imports)] mod T { pub struct U; diff --git a/src/test/ui/rust-2018/future-proofing-locals.stderr b/src/test/ui/rust-2018/future-proofing-locals.stderr index 4d666d22afed1..7021489a6ddcf 100644 --- a/src/test/ui/rust-2018/future-proofing-locals.stderr +++ b/src/test/ui/rust-2018/future-proofing-locals.stderr @@ -1,53 +1,53 @@ error: imports cannot refer to type parameters - --> $DIR/future-proofing-locals.rs:13:9 + --> $DIR/future-proofing-locals.rs:14:9 | LL | use T as _; | ^ error: imports cannot refer to type parameters - --> $DIR/future-proofing-locals.rs:14:9 + --> $DIR/future-proofing-locals.rs:15:9 | LL | use T::U; | ^ error: imports cannot refer to type parameters - --> $DIR/future-proofing-locals.rs:15:9 + --> $DIR/future-proofing-locals.rs:16:9 | LL | use T::*; | ^ error: imports cannot refer to type parameters - --> $DIR/future-proofing-locals.rs:19:9 + --> $DIR/future-proofing-locals.rs:20:9 | LL | use T; | ^ error: imports cannot refer to local variables - --> $DIR/future-proofing-locals.rs:25:9 + --> $DIR/future-proofing-locals.rs:26:9 | LL | use x as _; | ^ error: imports cannot refer to local variables - --> $DIR/future-proofing-locals.rs:31:9 + --> $DIR/future-proofing-locals.rs:32:9 | LL | use x; | ^ error: imports cannot refer to local variables - --> $DIR/future-proofing-locals.rs:37:17 + --> $DIR/future-proofing-locals.rs:38:17 | LL | use x; | ^ error: imports cannot refer to type parameters - --> $DIR/future-proofing-locals.rs:45:10 + --> $DIR/future-proofing-locals.rs:46:10 | LL | use {T as _, x}; | ^ error: imports cannot refer to local variables - --> $DIR/future-proofing-locals.rs:45:18 + --> $DIR/future-proofing-locals.rs:46:18 | LL | use {T as _, x}; | ^