From 36bcbc352d4b48f0f3aea35fd9ca74e856f797c9 Mon Sep 17 00:00:00 2001 From: Marcel Hellwig Date: Mon, 25 Feb 2019 07:09:16 +0100 Subject: [PATCH 01/19] Add FromStr impl for NonZero types --- src/libcore/num/mod.rs | 106 +++++++++++++++++++++++++++++++++++ src/libcore/tests/nonzero.rs | 17 ++++++ 2 files changed, 123 insertions(+) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 5b7d5f45d9246..1479b891fa2b6 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -112,6 +112,112 @@ nonzero_integers! { #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroIsize(isize); } +/// An error which can be returned when parsing a non-zero integer. +/// +/// # Potential causes +/// +/// Among other causes, `ParseNonZeroIntError` can be thrown because of leading or trailing +/// whitespace in the string e.g., when it is obtained from the standard input. +/// Using the [`str.trim()`] method ensures that no whitespace remains before parsing. +/// +/// [`str.trim()`]: ../../std/primitive.str.html#method.trim +#[unstable(feature = "nonzero_parse", issue = "0")] +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ParseNonZeroIntError { + kind: NonZeroIntErrorKind, +} + +/// Enum to store the various types of errors that can cause parsing a non-zero integer to fail. +#[unstable(feature = "nonzero_parse", issue = "0")] +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum NonZeroIntErrorKind { + /// Value being parsed is empty. + /// + /// Among other causes, this variant will be constructed when parsing an empty string. + Empty, + /// Contains an invalid digit. + /// + /// Among other causes, this variant will be constructed when parsing a string that + /// contains a letter. + InvalidDigit, + /// Integer is too large to store in target integer type. + Overflow, + /// Integer is too small to store in target integer type. + Underflow, + /// Integer contains the value `0` which is forbidden for a non-zero integer + Zero, +} + +#[unstable(feature = "nonzero_parse", issue = "0")] +impl From for ParseNonZeroIntError { + fn from(p: ParseIntError) -> Self { + use self::IntErrorKind as IK; + use self::NonZeroIntErrorKind as NK; + ParseNonZeroIntError { + kind: match p.kind { + IK::Empty => NK::Empty, + IK::InvalidDigit => NK::InvalidDigit, + IK::Overflow => NK::Overflow, + IK::Underflow => NK::Underflow, + }, + } + } +} + +impl ParseNonZeroIntError { + /// Outputs the detailed cause of parsing an integer failing. + #[unstable(feature = "int_error_matching", + reason = "it can be useful to match errors when making error messages \ + for integer parsing", + issue = "22639")] + pub fn kind(&self) -> &NonZeroIntErrorKind { + &self.kind + } + + #[unstable(feature = "int_error_internals", + reason = "available through Error trait and this method should \ + not be exposed publicly", + issue = "0")] + #[doc(hidden)] + pub fn __description(&self) -> &str { + match self.kind { + NonZeroIntErrorKind::Empty => "cannot parse integer from empty string", + NonZeroIntErrorKind::InvalidDigit => "invalid digit found in string", + NonZeroIntErrorKind::Overflow => "number too large to fit in target type", + NonZeroIntErrorKind::Underflow => "number too small to fit in target type", + NonZeroIntErrorKind::Zero => "number is 0", + } + } + +} + +#[unstable(feature = "nonzero_parse", issue = "0")] +impl fmt::Display for ParseNonZeroIntError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.__description().fmt(f) + } +} + + +macro_rules! from_str_radix_nzint_impl { + ($($t:ty)*) => {$( + #[unstable(feature = "nonzero_parse", issue = "0")] + impl FromStr for $t { + type Err = ParseNonZeroIntError; + fn from_str(src: &str) -> Result { + Self::new(from_str_radix(src, 10)?) + .ok_or(ParseNonZeroIntError { + kind: NonZeroIntErrorKind::Zero + }) + } + } + )*} +} + +from_str_radix_nzint_impl! { NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 NonZeroU128 NonZeroUsize + NonZeroI8 NonZeroI16 NonZeroI32 NonZeroI64 NonZeroI128 NonZeroIsize } + /// Provides intentionally-wrapped arithmetic on `T`. /// /// Operations like `+` on `u32` values is intended to never overflow, diff --git a/src/libcore/tests/nonzero.rs b/src/libcore/tests/nonzero.rs index 4532568ee0c16..6e2d4588edc71 100644 --- a/src/libcore/tests/nonzero.rs +++ b/src/libcore/tests/nonzero.rs @@ -126,3 +126,20 @@ fn test_from_signed_nonzero() { let num: i32 = nz.into(); assert_eq!(num, 1i32); } + +#[test] +fn test_from_str() { + assert_eq!(FromStr::from_str("123"), Ok(NonZeroU8::new(123).unwrap())); + assert_eq!( + FromStr::from_str("0"), + Err(ParseNonZeroIntError { + kind: NonZeroIntErrorKind::Zero + }) + ); + assert_eq!( + FromStr::from_str("-1", + Err(ParseNonZeroIntError { + kind: NonZeroIntErrorKind::Underflow + }) + ); +} From ce30d4e1b947f8580636909c4c6f5aaeb254ea4c Mon Sep 17 00:00:00 2001 From: Marcel Hellwig Date: Wed, 27 Feb 2019 18:37:35 +0100 Subject: [PATCH 02/19] replaced nonzeroparseerror with regular interror --- src/libcore/num/mod.rs | 102 ++++------------------------------- src/libcore/tests/nonzero.rs | 20 ++++--- 2 files changed, 23 insertions(+), 99 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 1479b891fa2b6..77b709a050d57 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -112,103 +112,15 @@ nonzero_integers! { #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroIsize(isize); } -/// An error which can be returned when parsing a non-zero integer. -/// -/// # Potential causes -/// -/// Among other causes, `ParseNonZeroIntError` can be thrown because of leading or trailing -/// whitespace in the string e.g., when it is obtained from the standard input. -/// Using the [`str.trim()`] method ensures that no whitespace remains before parsing. -/// -/// [`str.trim()`]: ../../std/primitive.str.html#method.trim -#[unstable(feature = "nonzero_parse", issue = "0")] -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct ParseNonZeroIntError { - kind: NonZeroIntErrorKind, -} - -/// Enum to store the various types of errors that can cause parsing a non-zero integer to fail. -#[unstable(feature = "nonzero_parse", issue = "0")] -#[derive(Debug, Clone, PartialEq, Eq)] -#[non_exhaustive] -pub enum NonZeroIntErrorKind { - /// Value being parsed is empty. - /// - /// Among other causes, this variant will be constructed when parsing an empty string. - Empty, - /// Contains an invalid digit. - /// - /// Among other causes, this variant will be constructed when parsing a string that - /// contains a letter. - InvalidDigit, - /// Integer is too large to store in target integer type. - Overflow, - /// Integer is too small to store in target integer type. - Underflow, - /// Integer contains the value `0` which is forbidden for a non-zero integer - Zero, -} - -#[unstable(feature = "nonzero_parse", issue = "0")] -impl From for ParseNonZeroIntError { - fn from(p: ParseIntError) -> Self { - use self::IntErrorKind as IK; - use self::NonZeroIntErrorKind as NK; - ParseNonZeroIntError { - kind: match p.kind { - IK::Empty => NK::Empty, - IK::InvalidDigit => NK::InvalidDigit, - IK::Overflow => NK::Overflow, - IK::Underflow => NK::Underflow, - }, - } - } -} - -impl ParseNonZeroIntError { - /// Outputs the detailed cause of parsing an integer failing. - #[unstable(feature = "int_error_matching", - reason = "it can be useful to match errors when making error messages \ - for integer parsing", - issue = "22639")] - pub fn kind(&self) -> &NonZeroIntErrorKind { - &self.kind - } - - #[unstable(feature = "int_error_internals", - reason = "available through Error trait and this method should \ - not be exposed publicly", - issue = "0")] - #[doc(hidden)] - pub fn __description(&self) -> &str { - match self.kind { - NonZeroIntErrorKind::Empty => "cannot parse integer from empty string", - NonZeroIntErrorKind::InvalidDigit => "invalid digit found in string", - NonZeroIntErrorKind::Overflow => "number too large to fit in target type", - NonZeroIntErrorKind::Underflow => "number too small to fit in target type", - NonZeroIntErrorKind::Zero => "number is 0", - } - } - -} - -#[unstable(feature = "nonzero_parse", issue = "0")] -impl fmt::Display for ParseNonZeroIntError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.__description().fmt(f) - } -} - - macro_rules! from_str_radix_nzint_impl { ($($t:ty)*) => {$( - #[unstable(feature = "nonzero_parse", issue = "0")] + #[stable(feature = "nonzero_parse", since = "1.35.0")] impl FromStr for $t { - type Err = ParseNonZeroIntError; + type Err = ParseIntError; fn from_str(src: &str) -> Result { Self::new(from_str_radix(src, 10)?) - .ok_or(ParseNonZeroIntError { - kind: NonZeroIntErrorKind::Zero + .ok_or(ParseIntError { + kind: IntErrorKind::Zero }) } } @@ -4968,6 +4880,11 @@ pub enum IntErrorKind { Overflow, /// Integer is too small to store in target integer type. Underflow, + /// Value was Zero + /// + /// This variant will be emitted when the parsing string has a value of zero, which + /// would be illegal for non-zero types. + Zero, } impl ParseIntError { @@ -4990,6 +4907,7 @@ impl ParseIntError { IntErrorKind::InvalidDigit => "invalid digit found in string", IntErrorKind::Overflow => "number too large to fit in target type", IntErrorKind::Underflow => "number too small to fit in target type", + IntErrorKind::Zero => "number would be zero for non-zero type", } } } diff --git a/src/libcore/tests/nonzero.rs b/src/libcore/tests/nonzero.rs index 6e2d4588edc71..764b0c249f9ca 100644 --- a/src/libcore/tests/nonzero.rs +++ b/src/libcore/tests/nonzero.rs @@ -129,17 +129,23 @@ fn test_from_signed_nonzero() { #[test] fn test_from_str() { - assert_eq!(FromStr::from_str("123"), Ok(NonZeroU8::new(123).unwrap())); + assert_eq!("123".parse::(), Ok(NonZeroU8::new(123).unwrap())); assert_eq!( - FromStr::from_str("0"), - Err(ParseNonZeroIntError { - kind: NonZeroIntErrorKind::Zero + "0".parse::(), + Err(ParseIntError { + kind: IntErrorKind::Zero }) ); assert_eq!( - FromStr::from_str("-1", - Err(ParseNonZeroIntError { - kind: NonZeroIntErrorKind::Underflow + "-1".parse::(), + Err(ParseIntError { + kind: IntErrorKind::Underflow + }) + ); + assert_eq!( + "129".parse::(), + Err(ParseIntError { + kind: IntErrorKind::Overflow }) ); } From 912ad6831ef0913afb7b0b5b6edc62bf002ebea8 Mon Sep 17 00:00:00 2001 From: Marcel Hellwig Date: Thu, 28 Feb 2019 07:45:33 +0100 Subject: [PATCH 03/19] fixed nonzero tests --- src/libcore/tests/nonzero.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/libcore/tests/nonzero.rs b/src/libcore/tests/nonzero.rs index 764b0c249f9ca..8e2d4177d08c7 100644 --- a/src/libcore/tests/nonzero.rs +++ b/src/libcore/tests/nonzero.rs @@ -1,6 +1,5 @@ -use core::num::{NonZeroU32, NonZeroI32}; -use core::option::Option; -use core::option::Option::{Some, None}; +use core::num::{IntErrorKind, NonZeroU8, NonZeroU32, NonZeroI32, ParseIntError}; +use core::option::Option::{self, Some, None}; use std::mem::size_of; #[test] @@ -143,7 +142,7 @@ fn test_from_str() { }) ); assert_eq!( - "129".parse::(), + "257".parse::(), Err(ParseIntError { kind: IntErrorKind::Overflow }) From ad240ea70c2ba4b4a03286320a7909e485507d75 Mon Sep 17 00:00:00 2001 From: Marcel Hellwig Date: Thu, 28 Feb 2019 14:47:32 +0100 Subject: [PATCH 04/19] add feature flag to test --- src/libcore/tests/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 4cd734bad90a4..6db0d88e35554 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -34,6 +34,7 @@ #![feature(slice_internals)] #![feature(slice_partition_dedup)] #![feature(copy_within)] +#![feature(int_error_matching)] extern crate core; extern crate test; From 7330525e8fa8e873bc7feeb476fa161d20786a43 Mon Sep 17 00:00:00 2001 From: Marcel Hellwig Date: Thu, 28 Feb 2019 20:48:08 +0100 Subject: [PATCH 05/19] fixed tests again --- src/libcore/tests/nonzero.rs | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/libcore/tests/nonzero.rs b/src/libcore/tests/nonzero.rs index 8e2d4177d08c7..77e484601bc22 100644 --- a/src/libcore/tests/nonzero.rs +++ b/src/libcore/tests/nonzero.rs @@ -1,5 +1,5 @@ -use core::num::{IntErrorKind, NonZeroU8, NonZeroU32, NonZeroI32, ParseIntError}; -use core::option::Option::{self, Some, None}; +use core::num::{IntErrorKind, NonZeroI32, NonZeroI8, NonZeroU32, NonZeroU8}; +use core::option::Option::{self, None, Some}; use std::mem::size_of; #[test] @@ -130,21 +130,19 @@ fn test_from_signed_nonzero() { fn test_from_str() { assert_eq!("123".parse::(), Ok(NonZeroU8::new(123).unwrap())); assert_eq!( - "0".parse::(), - Err(ParseIntError { - kind: IntErrorKind::Zero - }) + "0".parse::().err().map(|e| e.kind().clone()), + Some(IntErrorKind::Zero) ); assert_eq!( - "-1".parse::(), - Err(ParseIntError { - kind: IntErrorKind::Underflow - }) + "-1".parse::().err().map(|e| e.kind().clone()), + Some(IntErrorKind::InvalidDigit) ); assert_eq!( - "257".parse::(), - Err(ParseIntError { - kind: IntErrorKind::Overflow - }) + "-129".parse::().err().map(|e| e.kind().clone()), + Some(IntErrorKind::Underflow) + ); + assert_eq!( + "257".parse::().err().map(|e| e.kind().clone()), + Some(IntErrorKind::Overflow) ); } From f4742f46fe540e289888eec0bac077ff606f63c5 Mon Sep 17 00:00:00 2001 From: Tomas Koutsky Date: Fri, 15 Mar 2019 17:42:34 +0100 Subject: [PATCH 06/19] Add def getting methods to librustc/ty/context --- src/librustc/middle/dead.rs | 4 ++-- src/librustc/middle/expr_use_visitor.rs | 3 +-- src/librustc/middle/reachable.rs | 2 +- src/librustc/ty/context.rs | 9 +++++++++ src/librustc_lint/unused.rs | 2 +- src/librustc_mir/hair/cx/expr.rs | 6 ++---- src/librustc_passes/rvalue_promotion.rs | 3 +-- src/librustc_privacy/lib.rs | 6 +++--- src/librustc_save_analysis/lib.rs | 4 ++-- src/librustc_typeck/check/mod.rs | 4 ++-- 10 files changed, 24 insertions(+), 19 deletions(-) diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 94de999c25da8..c199b8273263c 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -92,8 +92,8 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { } fn lookup_and_handle_method(&mut self, id: hir::HirId) { - if let Some(def) = self.tables.type_dependent_defs().get(id) { - self.check_def_id(def.def_id()); + if let Some(def_id) = self.tables.type_dependent_def_id(id) { + self.check_def_id(def_id); } else { bug!("no type-dependent def for method"); } diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 8ada67efaafdd..db640b581d353 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -559,8 +559,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { } ty::Error => { } _ => { - if let Some(def) = self.mc.tables.type_dependent_defs().get(call.hir_id) { - let def_id = def.def_id(); + if let Some(def_id) = self.mc.tables.type_dependent_def_id(call.hir_id) { let call_scope = region::Scope { id: call.hir_id.local_id, data: region::ScopeData::Node diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 72f6d22b696f7..9a71020d65d03 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -97,7 +97,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReachableContext<'a, 'tcx> { Some(self.tables.qpath_def(qpath, expr.hir_id)) } hir::ExprKind::MethodCall(..) => { - self.tables.type_dependent_defs().get(expr.hir_id).cloned() + self.tables.type_dependent_def(expr.hir_id) } _ => None }; diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index ecf1d8a980a8d..2fc95641693ef 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -482,6 +482,15 @@ impl<'tcx> TypeckTables<'tcx> { } } + pub fn type_dependent_def(&self, id: HirId) -> Option { + validate_hir_id_for_typeck_tables(self.local_id_root, id, false); + self.type_dependent_defs.get(&id.local_id).cloned() + } + + pub fn type_dependent_def_id(&self, id: HirId) -> Option { + self.type_dependent_def(id).map(|def| def.def_id()) + } + pub fn type_dependent_defs_mut(&mut self) -> LocalTableInContextMut<'_, Def> { LocalTableInContextMut { local_id_root: self.local_id_root, diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 86b8b276eafe5..2612efd83164c 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -112,7 +112,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { } }, hir::ExprKind::MethodCall(..) => { - cx.tables.type_dependent_defs().get(expr.hir_id).cloned() + cx.tables.type_dependent_def(expr.hir_id) }, _ => None }; diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 7749b3a5ca49e..8ca75831235f7 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -835,13 +835,11 @@ fn method_callee<'a, 'gcx, 'tcx>( let (def_id, substs, user_ty) = match overloaded_callee { Some((def_id, substs)) => (def_id, substs, None), None => { - let type_dependent_defs = cx.tables().type_dependent_defs(); - let def = type_dependent_defs - .get(expr.hir_id) + let def = cx.tables().type_dependent_def(expr.hir_id) .unwrap_or_else(|| { span_bug!(expr.span, "no type-dependent def for method callee") }); - let user_ty = user_substs_applied_to_def(cx, expr.hir_id, def); + let user_ty = user_substs_applied_to_def(cx, expr.hir_id, &def); debug!("method_callee: user_ty={:?}", user_ty); (def.def_id(), cx.tables().node_substs(expr.hir_id), user_ty) } diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index 6de98675a3dc8..fcd51062cd97a 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -406,8 +406,7 @@ fn check_expr_kind<'a, 'tcx>( for index in hirvec.iter() { method_call_result &= v.check_expr(index); } - if let Some(def) = v.tables.type_dependent_defs().get(e.hir_id) { - let def_id = def.def_id(); + if let Some(def_id) = v.tables.type_dependent_def_id(e.hir_id) { match v.tcx.associated_item(def_id).container { ty::ImplContainer(_) => method_call_result & v.handle_const_fn_call(def_id), ty::TraitContainer(_) => NotPromotable, diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 52514a3ca97d6..98ee871489db8 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -1041,8 +1041,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { hir::ExprKind::MethodCall(_, span, _) => { // Method calls have to be checked specially. self.span = span; - if let Some(def) = self.tables.type_dependent_defs().get(expr.hir_id) { - if self.visit(self.tcx.type_of(def.def_id())) { + if let Some(def_id) = self.tables.type_dependent_def_id(expr.hir_id) { + if self.visit(self.tcx.type_of(def_id)) { return; } } else { @@ -1071,7 +1071,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { _ => None, } hir::QPath::TypeRelative(..) => { - self.tables.type_dependent_defs().get(id).cloned() + self.tables.type_dependent_def(id) } }; if let Some(def) = def { diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index d80f3e5ce759c..f6a43e888d206 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -565,8 +565,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } ast::ExprKind::MethodCall(ref seg, ..) => { let expr_hir_id = self.tcx.hir().definitions().node_to_hir_id(expr.id); - let method_id = match self.tables.type_dependent_defs().get(expr_hir_id) { - Some(id) => id.def_id(), + let method_id = match self.tables.type_dependent_def_id(expr_hir_id) { + Some(id) => id, None => { debug!("Could not resolve method id for {:?}", expr); return None; diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 28c79ce0c74e8..ceb33439c3ec7 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4757,10 +4757,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { (self.to_ty(qself), qself, segment) } }; - if let Some(cached_def) = self.tables.borrow().type_dependent_defs().get(hir_id) { + if let Some(cached_def) = self.tables.borrow().type_dependent_def(hir_id) { // Return directly on cache hit. This is useful to avoid doubly reporting // errors with default match binding modes. See #44614. - return (*cached_def, Some(ty), slice::from_ref(&**item_segment)) + return (cached_def, Some(ty), slice::from_ref(&**item_segment)) } let item_name = item_segment.ident; let def = match self.resolve_ufcs(span, item_name, ty, hir_id) { From 664838582b6d973620930a2ba75f369f44debecd Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 19 Mar 2019 13:01:14 -0700 Subject: [PATCH 07/19] rustc: Update linker flavor inference from filename This commit fixes what is believed to be a preexisting bug in the linker flavor inference and additionally adds a new features. Previously if the linker didn't end in `exe` the entire file name was compared to infer the linker's flavor. This commit fixes the code to instead unconditionally inspect `file_stem()` which is the relevant part we're looking at to figure out what the linker flavor is. Additionally this commit now also adds recognition of `clang` and clang wrappers that end in `-clang` (which look like gcc wrappers). This should allow clang-specific wrappers to get correctly inferred to the `Gcc` linker flavor rather than the default linker flavor configured for a target. --- src/librustc_codegen_ssa/back/link.rs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 7f1aebace8fc6..a0e2dcd646df8 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -152,17 +152,20 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) { LinkerFlavor::PtxLinker => "rust-ptx-linker", }), flavor)), (Some(linker), None) => { - let stem = if linker.extension().and_then(|ext| ext.to_str()) == Some("exe") { - linker.file_stem().and_then(|stem| stem.to_str()) - } else { - linker.to_str() - }.unwrap_or_else(|| { - sess.fatal("couldn't extract file stem from specified linker"); - }).to_owned(); + let stem = linker + .file_stem() + .and_then(|stem| stem.to_str()) + .unwrap_or_else(|| { + sess.fatal("couldn't extract file stem from specified linker") + }); let flavor = if stem == "emcc" { LinkerFlavor::Em - } else if stem == "gcc" || stem.ends_with("-gcc") { + } else if stem == "gcc" + || stem.ends_with("-gcc") + || stem == "clang" + || stem.ends_with("-clang") + { LinkerFlavor::Gcc } else if stem == "ld" || stem == "ld.lld" || stem.ends_with("-ld") { LinkerFlavor::Ld From 0e945411f2f54fdb3404b382844b9818ecc10b89 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 19 Mar 2019 13:06:37 -0700 Subject: [PATCH 08/19] rustc: Allow using `clang` for wasm32 targets This commit adds support code for using `clang` directly to link the wasm32-unknown-unknown target. Currently the target is only really configured to link with LLD directly, but this ensures that `clang` can be configured as well. While not immediately useful in the near term it's likely that more wasm32 targets will pop up over time with Clang's new native support for WebAssembly in the 8.0.0 release. Getting support into rustc early should make it easier to experiment with these targets and try out various changes here and there. --- src/librustc_codegen_ssa/back/linker.rs | 77 +++-------- src/librustc_target/spec/mod.rs | 1 + src/librustc_target/spec/wasm32_base.rs | 123 ++++++++++++++++++ .../spec/wasm32_unknown_unknown.rs | 80 +++++------- 4 files changed, 174 insertions(+), 107 deletions(-) create mode 100644 src/librustc_target/spec/wasm32_base.rs diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs index e6470dbb61ce1..0bdac1a51a162 100644 --- a/src/librustc_codegen_ssa/back/linker.rs +++ b/src/librustc_codegen_ssa/back/linker.rs @@ -160,7 +160,16 @@ impl<'a> GccLinker<'a> { } fn takes_hints(&self) -> bool { - !self.sess.target.target.options.is_like_osx + // Really this function only returns true if the underlying linker + // configured for a compiler is binutils `ld.bfd` and `ld.gold`. We + // don't really have a foolproof way to detect that, so rule out some + // platforms where currently this is guaranteed to *not* be the case: + // + // * On OSX they have their own linker, not binutils' + // * For WebAssembly the only functional linker is LLD, which doesn't + // support hint flags + !self.sess.target.target.options.is_like_osx && + self.sess.target.target.arch != "wasm32" } // Some platforms take hints about whether a library is static or dynamic. @@ -375,6 +384,13 @@ impl<'a> Linker for GccLinker<'a> { return } + // Symbol visibility takes care of this for the WebAssembly. + // Additionally the only known linker, LLD, doesn't support the script + // arguments just yet + if self.sess.target.target.arch == "wasm32" { + return; + } + let mut arg = OsString::new(); let path = tmpdir.join("list"); @@ -441,13 +457,13 @@ impl<'a> Linker for GccLinker<'a> { } fn group_start(&mut self) { - if !self.sess.target.target.options.is_like_osx { + if self.takes_hints() { self.linker_arg("--start-group"); } } fn group_end(&mut self) { - if !self.sess.target.target.options.is_like_osx { + if self.takes_hints() { self.linker_arg("--end-group"); } } @@ -874,59 +890,7 @@ pub struct WasmLd<'a> { } impl<'a> WasmLd<'a> { - fn new(mut cmd: Command, sess: &'a Session, info: &'a LinkerInfo) -> WasmLd<'a> { - // There have been reports in the wild (rustwasm/wasm-bindgen#119) of - // using threads causing weird hangs and bugs. Disable it entirely as - // this isn't yet the bottleneck of compilation at all anyway. - cmd.arg("--no-threads"); - - // By default LLD only gives us one page of stack (64k) which is a - // little small. Default to a larger stack closer to other PC platforms - // (1MB) and users can always inject their own link-args to override this. - cmd.arg("-z").arg("stack-size=1048576"); - - // By default LLD's memory layout is: - // - // 1. First, a blank page - // 2. Next, all static data - // 3. Finally, the main stack (which grows down) - // - // This has the unfortunate consequence that on stack overflows you - // corrupt static data and can cause some exceedingly weird bugs. To - // help detect this a little sooner we instead request that the stack is - // placed before static data. - // - // This means that we'll generate slightly larger binaries as references - // to static data will take more bytes in the ULEB128 encoding, but - // stack overflow will be guaranteed to trap as it underflows instead of - // corrupting static data. - cmd.arg("--stack-first"); - - // FIXME we probably shouldn't pass this but instead pass an explicit - // whitelist of symbols we'll allow to be undefined. Unfortunately - // though we can't handle symbols like `log10` that LLVM injects at a - // super late date without actually parsing object files. For now let's - // stick to this and hopefully fix it before stabilization happens. - cmd.arg("--allow-undefined"); - - // For now we just never have an entry symbol - cmd.arg("--no-entry"); - - // Rust code should never have warnings, and warnings are often - // indicative of bugs, let's prevent them. - cmd.arg("--fatal-warnings"); - - // The symbol visibility story is a bit in flux right now with LLD. - // It's... not entirely clear to me what's going on, but this looks to - // make everything work when `export_symbols` isn't otherwise called for - // things like executables. - cmd.arg("--export-dynamic"); - - // LLD only implements C++-like demangling, which doesn't match our own - // mangling scheme. Tell LLD to not demangle anything and leave it up to - // us to demangle these symbols later. - cmd.arg("--no-demangle"); - + fn new(cmd: Command, sess: &'a Session, info: &'a LinkerInfo) -> WasmLd<'a> { WasmLd { cmd, sess, info } } } @@ -1022,6 +986,7 @@ impl<'a> Linker for WasmLd<'a> { } fn build_dylib(&mut self, _out_filename: &Path) { + self.cmd.arg("--no-entry"); } fn export_symbols(&mut self, _tmpdir: &Path, crate_type: CrateType) { diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index fdb1db645c3c4..401b81ee98723 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -66,6 +66,7 @@ mod l4re_base; mod fuchsia_base; mod redox_base; mod riscv_base; +mod wasm32_base; #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash, RustcEncodable, RustcDecodable)] diff --git a/src/librustc_target/spec/wasm32_base.rs b/src/librustc_target/spec/wasm32_base.rs new file mode 100644 index 0000000000000..c7e75b4fa0903 --- /dev/null +++ b/src/librustc_target/spec/wasm32_base.rs @@ -0,0 +1,123 @@ +use std::collections::BTreeMap; +use super::{LldFlavor, TargetOptions, PanicStrategy, LinkerFlavor}; + +pub fn options() -> TargetOptions { + let mut lld_args = Vec::new(); + let mut clang_args = Vec::new(); + let mut arg = |arg: &str| { + lld_args.push(arg.to_string()); + clang_args.push(format!("-Wl,{}", arg)); + }; + + // There have been reports in the wild (rustwasm/wasm-bindgen#119) of + // using threads causing weird hangs and bugs. Disable it entirely as + // this isn't yet the bottleneck of compilation at all anyway. + // + // FIXME: we should file an upstream issue with LLD about this + arg("--no-threads"); + + // By default LLD only gives us one page of stack (64k) which is a + // little small. Default to a larger stack closer to other PC platforms + // (1MB) and users can always inject their own link-args to override this. + arg("-z"); + arg("stack-size=1048576"); + + // By default LLD's memory layout is: + // + // 1. First, a blank page + // 2. Next, all static data + // 3. Finally, the main stack (which grows down) + // + // This has the unfortunate consequence that on stack overflows you + // corrupt static data and can cause some exceedingly weird bugs. To + // help detect this a little sooner we instead request that the stack is + // placed before static data. + // + // This means that we'll generate slightly larger binaries as references + // to static data will take more bytes in the ULEB128 encoding, but + // stack overflow will be guaranteed to trap as it underflows instead of + // corrupting static data. + arg("--stack-first"); + + // FIXME we probably shouldn't pass this but instead pass an explicit + // whitelist of symbols we'll allow to be undefined. We don't currently have + // a mechanism of knowing, however, which symbols are intended to be + // imported from the environment and which are intended to be imported from + // other objects linked elsewhere. This is a coarse approximation but is + // sure to hide some bugs and frustrate someone at some point, so we should + // ideally work towards a world where we can explicitly list symbols that + // are supposed to be imported and have all other symbols generate errors if + // they remain undefined. + arg("--allow-undefined"); + + // Rust code should never have warnings, and warnings are often + // indicative of bugs, let's prevent them. + arg("--fatal-warnings"); + + // LLD only implements C++-like demangling, which doesn't match our own + // mangling scheme. Tell LLD to not demangle anything and leave it up to + // us to demangle these symbols later. Currently rustc does not perform + // further demangling, but tools like twiggy and wasm-bindgen are intended + // to do so. + arg("--no-demangle"); + + // The symbol visibility story is a bit in flux right now with LLD. + // It's... not entirely clear to me what's going on, but this looks to + // make everything work when `export_symbols` isn't otherwise called for + // things like executables. + // + // This is really only here to get things working. If it can be removed and + // basic tests still work, then sounds like it should be removed! + arg("--export-dynamic"); + + let mut pre_link_args = BTreeMap::new(); + pre_link_args.insert(LinkerFlavor::Lld(LldFlavor::Wasm), lld_args); + pre_link_args.insert(LinkerFlavor::Gcc, clang_args); + + TargetOptions { + // we allow dynamic linking, but only cdylibs. Basically we allow a + // final library artifact that exports some symbols (a wasm module) but + // we don't allow intermediate `dylib` crate types + dynamic_linking: true, + only_cdylib: true, + + // This means we'll just embed a `start` function in the wasm module + executables: true, + + // relatively self-explanatory! + exe_suffix: ".wasm".to_string(), + dll_prefix: String::new(), + dll_suffix: ".wasm".to_string(), + linker_is_gnu: false, + + max_atomic_width: Some(64), + + // Unwinding doesn't work right now, so the whole target unconditionally + // defaults to panic=abort. Note that this is guaranteed to change in + // the future once unwinding is implemented. Don't rely on this as we're + // basically guaranteed to change it once WebAssembly supports + // exceptions. + panic_strategy: PanicStrategy::Abort, + + // Wasm doesn't have atomics yet, so tell LLVM that we're in a single + // threaded model which will legalize atomics to normal operations. + singlethread: true, + + // no dynamic linking, no need for default visibility! + default_hidden_visibility: true, + + // we use the LLD shipped with the Rust toolchain by default + linker: Some("rust-lld".to_owned()), + lld_flavor: LldFlavor::Wasm, + + // No need for indirection here, simd types can always be passed by + // value as the whole module either has simd or not, which is different + // from x86 (for example) where programs can have functions that don't + // enable simd features. + simd_types_indirect: false, + + pre_link_args, + + .. Default::default() + } +} diff --git a/src/librustc_target/spec/wasm32_unknown_unknown.rs b/src/librustc_target/spec/wasm32_unknown_unknown.rs index ee2160c472080..909527d2b6120 100644 --- a/src/librustc_target/spec/wasm32_unknown_unknown.rs +++ b/src/librustc_target/spec/wasm32_unknown_unknown.rs @@ -1,70 +1,48 @@ -// The wasm32-unknown-unknown target is currently an experimental version of a -// wasm-based target which does *not* use the Emscripten toolchain. Instead -// this toolchain is based purely on LLVM's own toolchain, using LLVM's native -// WebAssembly backend as well as LLD for a native linker. -// -// There's some trickery below on crate types supported and various defaults -// (aka panic=abort by default), but otherwise this is in general a relatively -// standard target. - -use super::{LldFlavor, LinkerFlavor, Target, TargetOptions, PanicStrategy}; +//! A "bare wasm" target representing a WebAssembly output that makes zero +//! assumptions about its environment. +//! +//! The `wasm32-unknown-unknown` target is intended to encapsulate use cases +//! that do not rely on any imported functionality. The binaries generated are +//! entirely self-contained by default when using the standard library. Although +//! the standard library is available, most of it returns an error immediately +//! (e.g. trying to create a TCP stream or something like that). +//! +//! This target is more or less managed by the Rust and WebAssembly Working +//! Group nowadays at https://github.com/rustwasm. + +use super::{LldFlavor, LinkerFlavor, Target}; +use super::wasm32_base; pub fn target() -> Result { - let opts = TargetOptions { - // we allow dynamic linking, but only cdylibs. Basically we allow a - // final library artifact that exports some symbols (a wasm module) but - // we don't allow intermediate `dylib` crate types - dynamic_linking: true, - only_cdylib: true, - - // This means we'll just embed a `start` function in the wasm module - executables: true, - - // relatively self-explanatory! - exe_suffix: ".wasm".to_string(), - dll_prefix: String::new(), - dll_suffix: ".wasm".to_string(), - linker_is_gnu: false, - - max_atomic_width: Some(64), - - // Unwinding doesn't work right now, so the whole target unconditionally - // defaults to panic=abort. Note that this is guaranteed to change in - // the future once unwinding is implemented. Don't rely on this. - panic_strategy: PanicStrategy::Abort, - - // Wasm doesn't have atomics yet, so tell LLVM that we're in a single - // threaded model which will legalize atomics to normal operations. - singlethread: true, + let mut options = wasm32_base::options(); + let clang_args = options.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap(); - // no dynamic linking, no need for default visibility! - default_hidden_visibility: true, + // Make sure clang uses LLD as its linker and is configured appropriately + // otherwise + clang_args.push("--target=wasm32-unknown-unknown".to_string()); - // we use the LLD shipped with the Rust toolchain by default - linker: Some("rust-lld".to_owned()), - lld_flavor: LldFlavor::Wasm, + // Disable attempting to link crt1.o since it typically isn't present and + // isn't needed currently. + clang_args.push("-nostdlib".to_string()); - // No need for indirection here, simd types can always be passed by - // value as the whole module either has simd or not, which is different - // from x86 (for example) where programs can have functions that don't - // enable simd features. - simd_types_indirect: false, + // For now this target just never has an entry symbol no matter the output + // type, so unconditionally pass this. + clang_args.push("-Wl,--no-entry".to_string()); + options.pre_link_args.get_mut(&LinkerFlavor::Lld(LldFlavor::Wasm)) + .unwrap() + .push("--no-entry".to_string()); - .. Default::default() - }; Ok(Target { llvm_target: "wasm32-unknown-unknown".to_string(), target_endian: "little".to_string(), target_pointer_width: "32".to_string(), target_c_int_width: "32".to_string(), - // This is basically guaranteed to change in the future, don't rely on - // this. Use `not(target_os = "emscripten")` for now. target_os: "unknown".to_string(), target_env: String::new(), target_vendor: "unknown".to_string(), data_layout: "e-m:e-p:32:32-i64:64-n32:64-S128".to_string(), arch: "wasm32".to_string(), linker_flavor: LinkerFlavor::Lld(LldFlavor::Wasm), - options: opts, + options, }) } From 8ea435caf8ad8d762d628979043e15907a36fac7 Mon Sep 17 00:00:00 2001 From: Dan Robertson Date: Fri, 22 Mar 2019 16:09:16 +0000 Subject: [PATCH 09/19] ffi: rename VaList::copy to VaList::with_copy Rename `VaList::copy` to `VaList::with_copy`. --- src/libcore/ffi.rs | 2 +- .../c-link-to-rust-va-list-fn/checkrust.rs | 2 +- src/test/ui/c-variadic/variadic-ffi-4.rs | 2 +- src/test/ui/c-variadic/variadic-ffi-4.stderr | 22 +++++++++---------- src/test/ui/c-variadic/variadic-ffi-5.rs | 2 +- src/test/ui/c-variadic/variadic-ffi-5.stderr | 12 +++++----- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/libcore/ffi.rs b/src/libcore/ffi.rs index 5cc9c25c21e0f..7ae3ced4bcedb 100644 --- a/src/libcore/ffi.rs +++ b/src/libcore/ffi.rs @@ -189,7 +189,7 @@ impl<'a> VaList<'a> { reason = "the `c_variadic` feature has not been properly tested on \ all supported platforms", issue = "44930")] - pub unsafe fn copy(&self, f: F) -> R + pub unsafe fn with_copy(&self, f: F) -> R where F: for<'copy> FnOnce(VaList<'copy>) -> R { #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")), diff --git a/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/checkrust.rs b/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/checkrust.rs index 96a238afaec05..163d50c4e4b4a 100644 --- a/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/checkrust.rs +++ b/src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/checkrust.rs @@ -62,7 +62,7 @@ pub unsafe extern "C" fn check_list_copy_0(mut ap: VaList) -> usize { continue_if!(ap.arg::() == 16); continue_if!(ap.arg::() == 'A' as c_char); continue_if!(compare_c_str(ap.arg::<*const c_char>(), "Skip Me!")); - ap.copy(|mut ap| { + ap.with_copy(|mut ap| { if compare_c_str(ap.arg::<*const c_char>(), "Correct") { 0 } else { diff --git a/src/test/ui/c-variadic/variadic-ffi-4.rs b/src/test/ui/c-variadic/variadic-ffi-4.rs index 9101be5645646..1c77479d02f40 100644 --- a/src/test/ui/c-variadic/variadic-ffi-4.rs +++ b/src/test/ui/c-variadic/variadic-ffi-4.rs @@ -13,7 +13,7 @@ pub unsafe extern "C" fn no_escape1(_: usize, ap: ...) -> VaList<'static> { } pub unsafe extern "C" fn no_escape2(_: usize, ap: ...) { - let _ = ap.copy(|ap| { ap }); //~ ERROR: cannot infer an appropriate lifetime + let _ = ap.with_copy(|ap| { ap }); //~ ERROR: cannot infer an appropriate lifetime } pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaList, mut ap1: ...) { diff --git a/src/test/ui/c-variadic/variadic-ffi-4.stderr b/src/test/ui/c-variadic/variadic-ffi-4.stderr index a3e3f81b73d80..311e2173702c8 100644 --- a/src/test/ui/c-variadic/variadic-ffi-4.stderr +++ b/src/test/ui/c-variadic/variadic-ffi-4.stderr @@ -15,29 +15,29 @@ LL | ap | ^^ lifetime `'static` required error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements - --> $DIR/variadic-ffi-4.rs:16:28 + --> $DIR/variadic-ffi-4.rs:16:33 | -LL | let _ = ap.copy(|ap| { ap }); - | ^^ +LL | let _ = ap.with_copy(|ap| { ap }); + | ^^ | -note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 16:21... - --> $DIR/variadic-ffi-4.rs:16:21 +note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 16:26... + --> $DIR/variadic-ffi-4.rs:16:26 | -LL | let _ = ap.copy(|ap| { ap }); - | ^^^^^^^^^^^ +LL | let _ = ap.with_copy(|ap| { ap }); + | ^^^^^^^^^^^ = note: ...so that the expression is assignable: expected core::ffi::VaList<'_> found core::ffi::VaList<'_> note: but, the lifetime must be valid for the method call at 16:13... --> $DIR/variadic-ffi-4.rs:16:13 | -LL | let _ = ap.copy(|ap| { ap }); - | ^^^^^^^^^^^^^^^^^^^^ +LL | let _ = ap.with_copy(|ap| { ap }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...so type `core::ffi::VaList<'_>` of expression is valid during the expression --> $DIR/variadic-ffi-4.rs:16:13 | -LL | let _ = ap.copy(|ap| { ap }); - | ^^^^^^^^^^^^^^^^^^^^ +LL | let _ = ap.with_copy(|ap| { ap }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0308]: mismatched types --> $DIR/variadic-ffi-4.rs:20:12 diff --git a/src/test/ui/c-variadic/variadic-ffi-5.rs b/src/test/ui/c-variadic/variadic-ffi-5.rs index d96482ff4d17a..fcc80d9b0cca0 100644 --- a/src/test/ui/c-variadic/variadic-ffi-5.rs +++ b/src/test/ui/c-variadic/variadic-ffi-5.rs @@ -16,7 +16,7 @@ pub unsafe extern "C" fn no_escape1(_: usize, ap: ...) -> VaList<'static> { } pub unsafe extern "C" fn no_escape2(_: usize, ap: ...) { - let _ = ap.copy(|ap| { ap }); //~ ERROR: lifetime may not live long enough + let _ = ap.with_copy(|ap| { ap }); //~ ERROR: lifetime may not live long enough } pub unsafe extern "C" fn no_escape3(_: usize, ap0: &mut VaList, mut ap1: ...) { diff --git a/src/test/ui/c-variadic/variadic-ffi-5.stderr b/src/test/ui/c-variadic/variadic-ffi-5.stderr index 2ad1964b6fc7b..8f1dfe8ba9b63 100644 --- a/src/test/ui/c-variadic/variadic-ffi-5.stderr +++ b/src/test/ui/c-variadic/variadic-ffi-5.stderr @@ -15,13 +15,13 @@ LL | ap | ^^ lifetime `'static` required error: lifetime may not live long enough - --> $DIR/variadic-ffi-5.rs:19:28 + --> $DIR/variadic-ffi-5.rs:19:33 | -LL | let _ = ap.copy(|ap| { ap }); - | --- ^^ returning this value requires that `'1` must outlive `'2` - | | | - | | return type of closure is core::ffi::VaList<'2> - | has type `core::ffi::VaList<'1>` +LL | let _ = ap.with_copy(|ap| { ap }); + | --- ^^ returning this value requires that `'1` must outlive `'2` + | | | + | | return type of closure is core::ffi::VaList<'2> + | has type `core::ffi::VaList<'1>` error: lifetime may not live long enough --> $DIR/variadic-ffi-5.rs:23:5 From 3eb4eae96d2e400c2a99146491367bffa34ba29e Mon Sep 17 00:00:00 2001 From: Peter Hall Date: Fri, 22 Mar 2019 11:51:37 +0000 Subject: [PATCH 10/19] Fixes #59361 --- src/librustc/session/config.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 0ae7c10cf5630..eb629dc44c156 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1706,6 +1706,12 @@ pub fn rustc_short_optgroups() -> Vec { "Specify the name of the crate being built", "NAME", ), + opt::opt_s( + "", + "edition", + "Specify which edition of the compiler to use when compiling code.", + EDITION_NAME_LIST, + ), opt::multi_s( "", "emit", @@ -1808,12 +1814,6 @@ pub fn rustc_optgroups() -> Vec { `expanded,identified` (fully parenthesized, AST nodes with IDs).", "TYPE", ), - opt::opt_s( - "", - "edition", - "Specify which edition of the compiler to use when compiling code.", - EDITION_NAME_LIST, - ), opt::multi_s( "", "remap-path-prefix", From 02b8533ac8c1cc4521b1da91e52c1327f656c44a Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 24 Mar 2019 14:06:47 +0100 Subject: [PATCH 11/19] Add a way to track Rustfix UI test coverage This came out of the first Rustfix WG meeting. One of the goals is to enable Rustfix tests for all UI tests that trigger lints with `MachineApplicable` suggestions. In order to do that we first want to create a tracking issue that lists all files with missing `// run-rustfix` headers. This PR adds a `--rustfix-coverage` flag to `./x.py` and compiletest to list the files with the missing headers in `/tmp/rustfix_missing_coverage.txt`. From that file we can create the tracking issue and at some point also enforce the `// run-rustfix` flag on UI tests with `MachineApplicable` lints. --- src/bootstrap/flags.rs | 15 +++++++++++++++ src/bootstrap/test.rs | 4 ++++ src/tools/compiletest/src/common.rs | 5 +++++ src/tools/compiletest/src/main.rs | 19 +++++++++++++++++++ src/tools/compiletest/src/runtest.rs | 24 +++++++++++++++++++++++- 5 files changed, 66 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 0f9a4271ac062..23719378c840a 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -56,6 +56,7 @@ pub enum Subcommand { rustc_args: Vec, fail_fast: bool, doc_tests: DocTests, + rustfix_coverage: bool, }, Bench { paths: Vec, @@ -188,6 +189,12 @@ To learn more about a subcommand, run `./x.py -h`" "mode describing what file the actual ui output will be compared to", "COMPARE MODE", ); + opts.optflag( + "", + "rustfix-coverage", + "enable this to generate a Rustfix coverage file, which is saved in \ + `/tmp/rustfix_missing_coverage.txt`", + ); } "bench" => { opts.optmulti("", "test-args", "extra arguments", "ARGS"); @@ -363,6 +370,7 @@ Arguments: test_args: matches.opt_strs("test-args"), rustc_args: matches.opt_strs("rustc-args"), fail_fast: !matches.opt_present("no-fail-fast"), + rustfix_coverage: matches.opt_present("rustfix-coverage"), doc_tests: if matches.opt_present("doc") { DocTests::Only } else if matches.opt_present("no-doc") { @@ -467,6 +475,13 @@ impl Subcommand { } } + pub fn rustfix_coverage(&self) -> bool { + match *self { + Subcommand::Test { rustfix_coverage, .. } => rustfix_coverage, + _ => false, + } + } + pub fn compare_mode(&self) -> Option<&str> { match *self { Subcommand::Test { diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index bbe1872d3958d..41c73f307b6d0 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1284,6 +1284,10 @@ impl Step for Compiletest { cmd.arg("--android-cross-path").arg(""); } + if builder.config.cmd.rustfix_coverage() { + cmd.arg("--rustfix-coverage"); + } + builder.ci_env.force_coloring_in_ci(&mut cmd); let _folder = builder.fold_output(|| format!("test_{}", suite)); diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 80b8a8b728bb2..fe0c4f14940ad 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -245,6 +245,11 @@ pub struct Config { /// mode describing what file the actual ui output will be compared to pub compare_mode: Option, + /// If true, this will generate a coverage file with UI test files that run `MachineApplicable` + /// lints but are missing `run-rustfix` annotations. The generated coverage file is created in + /// `/tmp/rustfix_missing_coverage.txt` + pub rustfix_coverage: bool, + // Configuration for various run-make tests frobbing things like C compilers // or querying about various LLVM component information. pub cc: String, diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 86cdadade108f..1045ea1bf0c96 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -233,6 +233,12 @@ pub fn parse_config(args: Vec) -> Config { "mode describing what file the actual ui output will be compared to", "COMPARE MODE", ) + .optflag( + "", + "rustfix-coverage", + "enable this to generate a Rustfix coverage file, which is saved in \ + `/tmp/rustfix_missing_coverage.txt`", + ) .optflag("h", "help", "show this message"); let (argv0, args_) = args.split_first().unwrap(); @@ -336,6 +342,7 @@ pub fn parse_config(args: Vec) -> Config { color, remote_test_client: matches.opt_str("remote-test-client").map(PathBuf::from), compare_mode: matches.opt_str("compare-mode").map(CompareMode::parse), + rustfix_coverage: matches.opt_present("rustfix-coverage"), cc: matches.opt_str("cc").unwrap(), cxx: matches.opt_str("cxx").unwrap(), @@ -475,6 +482,18 @@ pub fn run_tests(config: &Config) { let _ = fs::remove_dir_all("tmp/partitioning-tests"); } + // If we want to collect rustfix coverage information, + // we first make sure that the coverage file does not exist. + // It will be created later on. + if config.rustfix_coverage { + let coverage_file_path = Path::new("/tmp/rustfix_missing_coverage.txt"); + if coverage_file_path.exists() { + if let Err(e) = fs::remove_file(coverage_file_path) { + panic!("Could not delete {} due to {}", coverage_file_path.display(), e) + } + } + } + let opts = test_opts(config); let tests = make_tests(config); // sadly osx needs some file descriptor limits raised for running tests in diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 3e3499edf60f0..0ca656bb13328 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -19,7 +19,7 @@ use std::collections::{HashMap, HashSet, VecDeque}; use std::env; use std::ffi::{OsStr, OsString}; use std::fmt; -use std::fs::{self, create_dir_all, File}; +use std::fs::{self, create_dir_all, File, OpenOptions}; use std::hash::{Hash, Hasher}; use std::io::prelude::*; use std::io::{self, BufReader}; @@ -2818,6 +2818,28 @@ impl<'test> TestCx<'test> { if self.config.compare_mode.is_some() { // don't test rustfix with nll right now + } else if self.config.rustfix_coverage { + // Find out which tests have `MachineApplicable` suggestions but are missing + // `run-rustfix` or `run-rustfix-only-machine-applicable` headers + let suggestions = get_suggestions_from_json( + &proc_res.stderr, + &HashSet::new(), + Filter::MachineApplicableOnly + ).unwrap(); + if suggestions.len() > 0 + && !self.props.run_rustfix + && !self.props.rustfix_only_machine_applicable { + let coverage_file_path = Path::new("/tmp/rustfix_missing_coverage.txt"); + let mut file = OpenOptions::new() + .create(true) + .append(true) + .open(coverage_file_path) + .expect("could not create or open file"); + + if let Err(_) = writeln!(file, "{}", self.testpaths.file.display()) { + panic!("couldn't write to {}", coverage_file_path.display()); + } + } } else if self.props.run_rustfix { // Apply suggestions from rustc to the code itself let unfixed_code = self From 695dfe7dff89b986d1a5eb551633189338a0af6e Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Wed, 13 Mar 2019 00:47:36 -0400 Subject: [PATCH 12/19] compiletest: make path normalization smarter --- .../deny-intra-link-resolution-failure.stderr | 2 +- .../rustdoc-ui/intra-doc-alias-ice.stderr | 2 +- .../intra-link-span-ice-55723.stderr | 2 +- .../intra-links-warning-crlf.stderr | 8 +- .../rustdoc-ui/intra-links-warning.stderr | 44 ++++---- src/test/rustdoc-ui/invalid-syntax.stderr | 22 ++-- src/test/rustdoc-ui/lint-group.stderr | 2 +- src/test/ui/cast_char.stderr | 4 +- src/test/ui/error-codes/E0648.stderr | 2 +- src/test/ui/fmt/format-string-error-2.stderr | 50 ++++----- src/test/ui/fmt/format-string-error.stderr | 6 +- src/test/ui/issues/issue-13727.stderr | 2 +- src/test/ui/macros/format-foreign.stderr | 8 +- .../ui/macros/macro-backtrace-println.stderr | 2 +- .../parser/ascii-only-character-escape.stderr | 12 +- src/test/ui/parser/bad-char-literals.stderr | 6 +- src/test/ui/parser/byte-literals.stderr | 10 +- .../ui/parser/byte-string-literals.stderr | 8 +- .../parser/issue-23620-invalid-escapes.stderr | 46 ++++---- src/test/ui/parser/issue-43692.stderr | 2 +- .../ui/parser/lex-bad-char-literals-1.stderr | 12 +- .../ui/parser/lex-bad-char-literals-5.stderr | 8 +- src/test/ui/parser/lex-bad-token.stderr | 2 +- ...-bare-cr-string-literal-doc-comment.stderr | 8 +- src/test/ui/parser/lex-stray-backslash.stderr | 4 +- .../ui/parser/new-unicode-escapes-1.stderr | 2 +- .../ui/parser/new-unicode-escapes-2.stderr | 2 +- .../ui/parser/new-unicode-escapes-3.stderr | 4 +- .../ui/parser/new-unicode-escapes-4.stderr | 2 +- .../ui/parser/raw-byte-string-literals.stderr | 2 +- .../trailing-carriage-return-in-string.stderr | 4 +- src/test/ui/parser/unicode-chars.stderr | 2 +- src/test/ui/parser/unicode-quote-chars.stderr | 2 +- .../wrong-escape-of-curly-braces.stderr | 4 +- src/tools/compiletest/src/runtest.rs | 103 +++++++++++++++++- 35 files changed, 247 insertions(+), 154 deletions(-) diff --git a/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr b/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr index e0e45d55a9e73..1a120dcb18654 100644 --- a/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr +++ b/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr @@ -9,7 +9,7 @@ note: lint level defined here | LL | #![deny(intra_doc_link_resolution_failure)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` error: aborting due to previous error diff --git a/src/test/rustdoc-ui/intra-doc-alias-ice.stderr b/src/test/rustdoc-ui/intra-doc-alias-ice.stderr index d273ec019752c..cebb14cba7c11 100644 --- a/src/test/rustdoc-ui/intra-doc-alias-ice.stderr +++ b/src/test/rustdoc-ui/intra-doc-alias-ice.stderr @@ -9,7 +9,7 @@ note: lint level defined here | LL | #![deny(intra_doc_link_resolution_failure)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` error: aborting due to previous error diff --git a/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr b/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr index 93c05a0c4dd29..7ee9ca4792395 100644 --- a/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr +++ b/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr @@ -9,7 +9,7 @@ note: lint level defined here | LL | #![deny(intra_doc_link_resolution_failure)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` error: aborting due to previous error diff --git a/src/test/rustdoc-ui/intra-links-warning-crlf.stderr b/src/test/rustdoc-ui/intra-links-warning-crlf.stderr index 62537f2ce2dc9..8ccc04a4c0bcd 100644 --- a/src/test/rustdoc-ui/intra-links-warning-crlf.stderr +++ b/src/test/rustdoc-ui/intra-links-warning-crlf.stderr @@ -5,7 +5,7 @@ LL | /// [error] | ^^^^^ cannot be resolved, ignoring | = note: #[warn(intra_doc_link_resolution_failure)] on by default - = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` warning: `[error1]` cannot be resolved, ignoring it... --> $DIR/intra-links-warning-crlf.rs:12:11 @@ -13,7 +13,7 @@ warning: `[error1]` cannot be resolved, ignoring it... LL | /// docs [error1] | ^^^^^^ cannot be resolved, ignoring | - = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` warning: `[error2]` cannot be resolved, ignoring it... --> $DIR/intra-links-warning-crlf.rs:14:11 @@ -21,7 +21,7 @@ warning: `[error2]` cannot be resolved, ignoring it... LL | /// docs [error2] | ^^^^^^ cannot be resolved, ignoring | - = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` warning: `[error]` cannot be resolved, ignoring it... --> $DIR/intra-links-warning-crlf.rs:21:20 @@ -29,5 +29,5 @@ warning: `[error]` cannot be resolved, ignoring it... LL | * It also has an [error]. | ^^^^^ cannot be resolved, ignoring | - = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` diff --git a/src/test/rustdoc-ui/intra-links-warning.stderr b/src/test/rustdoc-ui/intra-links-warning.stderr index 60fc131dbda17..1eec3c57b68de 100644 --- a/src/test/rustdoc-ui/intra-links-warning.stderr +++ b/src/test/rustdoc-ui/intra-links-warning.stderr @@ -5,7 +5,7 @@ LL | //! Test with [Foo::baz], [Bar::foo], ... | ^^^^^^^^ cannot be resolved, ignoring | = note: #[warn(intra_doc_link_resolution_failure)] on by default - = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` warning: `[Bar::foo]` cannot be resolved, ignoring it... --> $DIR/intra-links-warning.rs:3:35 @@ -13,7 +13,7 @@ warning: `[Bar::foo]` cannot be resolved, ignoring it... LL | //! Test with [Foo::baz], [Bar::foo], ... | ^^^^^^^^ cannot be resolved, ignoring | - = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` warning: `[Uniooon::X]` cannot be resolved, ignoring it... --> $DIR/intra-links-warning.rs:4:13 @@ -21,7 +21,7 @@ warning: `[Uniooon::X]` cannot be resolved, ignoring it... LL | //! , [Uniooon::X] and [Qux::Z]. | ^^^^^^^^^^ cannot be resolved, ignoring | - = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` warning: `[Qux::Z]` cannot be resolved, ignoring it... --> $DIR/intra-links-warning.rs:4:30 @@ -29,7 +29,7 @@ warning: `[Qux::Z]` cannot be resolved, ignoring it... LL | //! , [Uniooon::X] and [Qux::Z]. | ^^^^^^ cannot be resolved, ignoring | - = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` warning: `[Uniooon::X]` cannot be resolved, ignoring it... --> $DIR/intra-links-warning.rs:6:14 @@ -37,7 +37,7 @@ warning: `[Uniooon::X]` cannot be resolved, ignoring it... LL | //! , [Uniooon::X] and [Qux::Z]. | ^^^^^^^^^^ cannot be resolved, ignoring | - = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` warning: `[Qux::Z]` cannot be resolved, ignoring it... --> $DIR/intra-links-warning.rs:6:31 @@ -45,7 +45,7 @@ warning: `[Qux::Z]` cannot be resolved, ignoring it... LL | //! , [Uniooon::X] and [Qux::Z]. | ^^^^^^ cannot be resolved, ignoring | - = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` warning: `[Qux:Y]` cannot be resolved, ignoring it... --> $DIR/intra-links-warning.rs:8:13 @@ -53,7 +53,7 @@ warning: `[Qux:Y]` cannot be resolved, ignoring it... LL | /// [Qux:Y] | ^^^^^ cannot be resolved, ignoring | - = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` warning: `[error]` cannot be resolved, ignoring it... --> $DIR/intra-links-warning.rs:51:30 @@ -61,7 +61,7 @@ warning: `[error]` cannot be resolved, ignoring it... LL | * time to introduce a link [error]*/ | ^^^^^ cannot be resolved, ignoring | - = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` warning: `[error]` cannot be resolved, ignoring it... --> $DIR/intra-links-warning.rs:57:30 @@ -69,7 +69,7 @@ warning: `[error]` cannot be resolved, ignoring it... LL | * time to introduce a link [error] | ^^^^^ cannot be resolved, ignoring | - = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` warning: `[error]` cannot be resolved, ignoring it... --> $DIR/intra-links-warning.rs:61:1 @@ -81,19 +81,19 @@ LL | #[doc = "single line [error]"] single line [error] ^^^^^ - = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` warning: `[error]` cannot be resolved, ignoring it... --> $DIR/intra-links-warning.rs:64:1 | -LL | #[doc = "single line with /"escaping/" [error]"] +LL | #[doc = "single line with \"escaping\" [error]"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the link appears in this line: single line with "escaping" [error] ^^^^^ - = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` warning: `[error]` cannot be resolved, ignoring it... --> $DIR/intra-links-warning.rs:67:1 @@ -107,7 +107,7 @@ LL | | /// [error] [error] ^^^^^ - = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` warning: `[error1]` cannot be resolved, ignoring it... --> $DIR/intra-links-warning.rs:73:11 @@ -115,7 +115,7 @@ warning: `[error1]` cannot be resolved, ignoring it... LL | /// docs [error1] | ^^^^^^ cannot be resolved, ignoring | - = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` warning: `[error2]` cannot be resolved, ignoring it... --> $DIR/intra-links-warning.rs:75:11 @@ -123,7 +123,7 @@ warning: `[error2]` cannot be resolved, ignoring it... LL | /// docs [error2] | ^^^^^^ cannot be resolved, ignoring | - = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` warning: `[BarA]` cannot be resolved, ignoring it... --> $DIR/intra-links-warning.rs:14:10 @@ -131,7 +131,7 @@ warning: `[BarA]` cannot be resolved, ignoring it... LL | /// bar [BarA] bar | ^^^^ cannot be resolved, ignoring | - = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` warning: `[BarB]` cannot be resolved, ignoring it... --> $DIR/intra-links-warning.rs:20:9 @@ -139,7 +139,7 @@ warning: `[BarB]` cannot be resolved, ignoring it... LL | * bar [BarB] bar | ^^^^ cannot be resolved, ignoring | - = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` warning: `[BarC]` cannot be resolved, ignoring it... --> $DIR/intra-links-warning.rs:27:6 @@ -147,19 +147,19 @@ warning: `[BarC]` cannot be resolved, ignoring it... LL | bar [BarC] bar | ^^^^ cannot be resolved, ignoring | - = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` warning: `[BarD]` cannot be resolved, ignoring it... --> $DIR/intra-links-warning.rs:38:1 | -LL | #[doc = "Foo/nbar [BarD] bar/nbaz"] +LL | #[doc = "Foo\nbar [BarD] bar\nbaz"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the link appears in this line: bar [BarD] bar ^^^^ - = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` warning: `[BarF]` cannot be resolved, ignoring it... --> $DIR/intra-links-warning.rs:43:9 @@ -167,12 +167,12 @@ warning: `[BarF]` cannot be resolved, ignoring it... LL | #[doc = $f] | ^^^^^^^^^^^ ... -LL | f!("Foo/nbar [BarF] bar/nbaz"); +LL | f!("Foo\nbar [BarF] bar\nbaz"); | ------------------------------- in this macro invocation | = note: the link appears in this line: bar [BarF] bar ^^^^ - = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` diff --git a/src/test/rustdoc-ui/invalid-syntax.stderr b/src/test/rustdoc-ui/invalid-syntax.stderr index 10800380a05d3..b4ed747b44c81 100644 --- a/src/test/rustdoc-ui/invalid-syntax.stderr +++ b/src/test/rustdoc-ui/invalid-syntax.stderr @@ -3,11 +3,11 @@ warning: could not parse code block as Rust code | LL | /// ``` | _____^ -LL | | /// /__________pkt->size___________/ /_result->size_/ /__pkt->size__/ +LL | | /// \__________pkt->size___________/ \_result->size_/ \__pkt->size__/ LL | | /// ``` | |_______^ | - = note: error from rustc: unknown start of token: / + = note: error from rustc: unknown start of token: \ help: mark blocks that do not contain Rust code as text | LL | /// ```text @@ -35,11 +35,11 @@ warning: could not parse code block as Rust code | LL | /// ``` | _____^ -LL | | /// /_ +LL | | /// \_ LL | | /// ``` | |_______^ | - = note: error from rustc: unknown start of token: / + = note: error from rustc: unknown start of token: \ help: mark blocks that do not contain Rust code as text | LL | /// ```text @@ -50,21 +50,21 @@ warning: could not parse code block as Rust code | LL | /// ```rust | _____^ -LL | | /// /_ +LL | | /// \_ LL | | /// ``` | |_______^ | - = note: error from rustc: unknown start of token: / + = note: error from rustc: unknown start of token: \ warning: could not parse code block as Rust code --> $DIR/invalid-syntax.rs:41:9 | LL | /// code with bad syntax | _________^ -LL | | /// /_ +LL | | /// \_ | |__________^ | - = note: error from rustc: unknown start of token: / + = note: error from rustc: unknown start of token: \ warning: could not parse code block as Rust code --> $DIR/invalid-syntax.rs:55:9 @@ -79,17 +79,17 @@ warning: could not parse code block as Rust code | LL | /// ```edition2018 | _____^ -LL | | /// /_ +LL | | /// \_ LL | | /// ``` | |_______^ | - = note: error from rustc: unknown start of token: / + = note: error from rustc: unknown start of token: \ warning: doc comment contains an invalid Rust code block --> $DIR/invalid-syntax.rs:63:1 | LL | / #[doc = "```"] -LL | | /// /_ +LL | | /// \_ LL | | #[doc = "```"] | |______________^ | diff --git a/src/test/rustdoc-ui/lint-group.stderr b/src/test/rustdoc-ui/lint-group.stderr index 76a9133147eac..24db3453ec509 100644 --- a/src/test/rustdoc-ui/lint-group.stderr +++ b/src/test/rustdoc-ui/lint-group.stderr @@ -27,7 +27,7 @@ note: lint level defined here LL | #![deny(rustdoc)] | ^^^^^^^ = note: #[deny(intra_doc_link_resolution_failure)] implied by #[deny(rustdoc)] - = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]` error: Missing code example in this documentation --> $DIR/lint-group.rs:16:1 diff --git a/src/test/ui/cast_char.stderr b/src/test/ui/cast_char.stderr index 570ca7cba8635..f0c9b8988903b 100644 --- a/src/test/ui/cast_char.stderr +++ b/src/test/ui/cast_char.stderr @@ -2,7 +2,7 @@ error: only u8 can be cast into char --> $DIR/cast_char.rs:4:23 | LL | const XYZ: char = 0x1F888 as char; - | ^^^^^^^^^^^^^^^ help: use a char literal instead: `'/u{1F888}'` + | ^^^^^^^^^^^^^^^ help: use a char literal instead: `'\u{1F888}'` | note: lint level defined here --> $DIR/cast_char.rs:1:9 @@ -14,7 +14,7 @@ error: only u8 can be cast into char --> $DIR/cast_char.rs:6:22 | LL | const XY: char = 129160 as char; - | ^^^^^^^^^^^^^^ help: use a char literal instead: `'/u{1F888}'` + | ^^^^^^^^^^^^^^ help: use a char literal instead: `'\u{1F888}'` error: aborting due to 2 previous errors diff --git a/src/test/ui/error-codes/E0648.stderr b/src/test/ui/error-codes/E0648.stderr index f682b4f41e521..1a65825c7b6c6 100644 --- a/src/test/ui/error-codes/E0648.stderr +++ b/src/test/ui/error-codes/E0648.stderr @@ -1,7 +1,7 @@ error[E0648]: `export_name` may not contain null characters --> $DIR/E0648.rs:1:1 | -LL | #[export_name="/0foo"] +LL | #[export_name="\0foo"] | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/fmt/format-string-error-2.stderr b/src/test/ui/fmt/format-string-error-2.stderr index baab8529940c5..66d35a1b854d3 100644 --- a/src/test/ui/fmt/format-string-error-2.stderr +++ b/src/test/ui/fmt/format-string-error-2.stderr @@ -1,10 +1,10 @@ error: incorrect unicode escape sequence --> $DIR/format-string-error-2.rs:77:20 | -LL | println!("/x7B}/u8 {", 1); +LL | println!("\x7B}\u8 {", 1); | ^^- | | - | help: format of unicode escape sequences uses braces: `/u{8}` + | help: format of unicode escape sequences uses braces: `\u{8}` error: invalid format string: expected `'}'`, found `'a'` --> $DIR/format-string-error-2.rs:5:5 @@ -19,7 +19,7 @@ LL | a"); error: invalid format string: expected `'}'`, found `'b'` --> $DIR/format-string-error-2.rs:9:5 | -LL | format!("{ / +LL | format!("{ \ | - because of this opening brace LL | LL | b"); @@ -27,20 +27,20 @@ LL | b"); | = note: if you intended to print `{`, you can escape it using `{{` -error: invalid format string: expected `'}'`, found `'/'` +error: invalid format string: expected `'}'`, found `'\'` --> $DIR/format-string-error-2.rs:11:18 | -LL | format!(r#"{ / +LL | format!(r#"{ \ | - ^ expected `}` in format string | | | because of this opening brace | = note: if you intended to print `{`, you can escape it using `{{` -error: invalid format string: expected `'}'`, found `'/'` +error: invalid format string: expected `'}'`, found `'\'` --> $DIR/format-string-error-2.rs:15:18 | -LL | format!(r#"{ /n +LL | format!(r#"{ \n | - ^ expected `}` in format string | | | because of this opening brace @@ -50,9 +50,9 @@ LL | format!(r#"{ /n error: invalid format string: expected `'}'`, found `'e'` --> $DIR/format-string-error-2.rs:21:5 | -LL | format!("{ /n +LL | format!("{ \n | - because of this opening brace -LL | /n +LL | \n LL | e"); | ^ expected `}` in format string | @@ -81,9 +81,9 @@ LL | a error: invalid format string: expected `'}'`, found `'b'` --> $DIR/format-string-error-2.rs:35:5 | -LL | { / +LL | { \ | - because of this opening brace -LL | / +LL | \ LL | b"); | ^ expected `}` in format string | @@ -92,28 +92,28 @@ LL | b"); error: invalid format string: expected `'}'`, found `'b'` --> $DIR/format-string-error-2.rs:40:5 | -LL | { / +LL | { \ | - because of this opening brace -LL | / -LL | b / +LL | \ +LL | b \ | ^ expected `}` in format string | = note: if you intended to print `{`, you can escape it using `{{` -error: invalid format string: expected `'}'`, found `'/'` +error: invalid format string: expected `'}'`, found `'\'` --> $DIR/format-string-error-2.rs:45:8 | -LL | raw { / +LL | raw { \ | - ^ expected `}` in format string | | | because of this opening brace | = note: if you intended to print `{`, you can escape it using `{{` -error: invalid format string: expected `'}'`, found `'/'` +error: invalid format string: expected `'}'`, found `'\'` --> $DIR/format-string-error-2.rs:50:8 | -LL | raw { /n +LL | raw { \n | - ^ expected `}` in format string | | | because of this opening brace @@ -123,9 +123,9 @@ LL | raw { /n error: invalid format string: expected `'}'`, found `'e'` --> $DIR/format-string-error-2.rs:57:5 | -LL | { /n +LL | { \n | - because of this opening brace -LL | /n +LL | \n LL | e"); | ^ expected `}` in format string | @@ -144,13 +144,13 @@ LL | asdf} error: 1 positional argument in format string, but no arguments were given --> $DIR/format-string-error-2.rs:70:17 | -LL | println!("/t{}"); +LL | println!("\t{}"); | ^^ error: invalid format string: expected `'}'` but string was terminated --> $DIR/format-string-error-2.rs:74:27 | -LL | println!("/x7B}/u{8} {", 1); +LL | println!("\x7B}\u{8} {", 1); | -^ expected `'}'` in format string | | | because of this opening brace @@ -160,7 +160,7 @@ LL | println!("/x7B}/u{8} {", 1); error: argument never used --> $DIR/format-string-error-2.rs:77:28 | -LL | println!("/x7B}/u8 {", 1); +LL | println!("\x7B}\u8 {", 1); | ------------ ^ argument never used | | | formatting specifier missing @@ -168,7 +168,7 @@ LL | println!("/x7B}/u8 {", 1); error: invalid format string: unmatched `}` found --> $DIR/format-string-error-2.rs:82:21 | -LL | println!(r#"/x7B}/u{8} {"#, 1); +LL | println!(r#"\x7B}\u{8} {"#, 1); | ^ unmatched `}` in format string | = note: if you intended to print `}`, you can escape it using `}}` @@ -176,7 +176,7 @@ LL | println!(r#"/x7B}/u{8} {"#, 1); error: invalid format string: unmatched `}` found --> $DIR/format-string-error-2.rs:85:21 | -LL | println!(r#"/x7B}/u8 {"#, 1); +LL | println!(r#"\x7B}\u8 {"#, 1); | ^ unmatched `}` in format string | = note: if you intended to print `}`, you can escape it using `}}` diff --git a/src/test/ui/fmt/format-string-error.stderr b/src/test/ui/fmt/format-string-error.stderr index 86ab163591e0d..3dc122a7399dd 100644 --- a/src/test/ui/fmt/format-string-error.stderr +++ b/src/test/ui/fmt/format-string-error.stderr @@ -50,10 +50,10 @@ LL | let _ = format!("}"); | = note: if you intended to print `}`, you can escape it using `}}` -error: invalid format string: expected `'}'`, found `'/'` +error: invalid format string: expected `'}'`, found `'\'` --> $DIR/format-string-error.rs:17:23 | -LL | let _ = format!("{/}"); +LL | let _ = format!("{\}"); | -^ expected `}` in format string | | | because of this opening brace @@ -63,7 +63,7 @@ LL | let _ = format!("{/}"); error: invalid format string: expected `'}'` but string was terminated --> $DIR/format-string-error.rs:19:35 | -LL | let _ = format!("/n/n/n{/n/n/n"); +LL | let _ = format!("\n\n\n{\n\n\n"); | - ^ expected `'}'` in format string | | | because of this opening brace diff --git a/src/test/ui/issues/issue-13727.stderr b/src/test/ui/issues/issue-13727.stderr index 0c2ce9f8b488e..4d1066516249b 100644 --- a/src/test/ui/issues/issue-13727.stderr +++ b/src/test/ui/issues/issue-13727.stderr @@ -1,7 +1,7 @@ error: unreachable pattern --> $DIR/issue-13727.rs:7:5 | -LL | 512 => print!("0b1111/n"), +LL | 512 => print!("0b1111\n"), | ^^^ | note: lint level defined here diff --git a/src/test/ui/macros/format-foreign.stderr b/src/test/ui/macros/format-foreign.stderr index 87cadada3c782..e2f2f14dce319 100644 --- a/src/test/ui/macros/format-foreign.stderr +++ b/src/test/ui/macros/format-foreign.stderr @@ -1,7 +1,7 @@ error: multiple unused formatting arguments --> $DIR/format-foreign.rs:2:30 | -LL | println!("%.*3$s %s!/n", "Hello,", "World", 4); +LL | println!("%.*3$s %s!\n", "Hello,", "World", 4); | -------------- ^^^^^^^^ ^^^^^^^ ^ argument never used | | | | | | | argument never used @@ -11,7 +11,7 @@ LL | println!("%.*3$s %s!/n", "Hello,", "World", 4); = note: printf formatting not supported; see the documentation for `std::fmt` help: format specifiers use curly braces | -LL | println!("{:.2$} {}!/n", "Hello,", "World", 4); +LL | println!("{:.2$} {}!\n", "Hello,", "World", 4); | ^^^^^^ ^^ error: argument never used @@ -29,7 +29,7 @@ error: multiple unused formatting arguments | LL | println!(r###"%.*3$s | ______________- -LL | | %s!/n +LL | | %s!\n LL | | "###, "Hello,", "World", 4); | | - ^^^^^^^^ ^^^^^^^ ^ argument never used | | | | | @@ -41,7 +41,7 @@ LL | | "###, "Hello,", "World", 4); help: format specifiers use curly braces | LL | println!(r###"{:.2$} -LL | {}!/n +LL | {}!\n | error: argument never used diff --git a/src/test/ui/macros/macro-backtrace-println.stderr b/src/test/ui/macros/macro-backtrace-println.stderr index 573184b63b1ed..209ff09aea41b 100644 --- a/src/test/ui/macros/macro-backtrace-println.stderr +++ b/src/test/ui/macros/macro-backtrace-println.stderr @@ -1,7 +1,7 @@ error: 1 positional argument in format string, but no arguments were given --> $DIR/macro-backtrace-println.rs:14:30 | -LL | ($fmt:expr) => (myprint!(concat!($fmt, "/n"))); +LL | ($fmt:expr) => (myprint!(concat!($fmt, "\n"))); | ^^^^^^^^^^^^^^^^^^^ ... LL | myprintln!("{}"); diff --git a/src/test/ui/parser/ascii-only-character-escape.stderr b/src/test/ui/parser/ascii-only-character-escape.stderr index 7524c4eccd98a..8a981e8d62e2b 100644 --- a/src/test/ui/parser/ascii-only-character-escape.stderr +++ b/src/test/ui/parser/ascii-only-character-escape.stderr @@ -1,19 +1,19 @@ -error: this form of character escape may only be used with characters in the range [/x00-/x7f] +error: this form of character escape may only be used with characters in the range [\x00-\x7f] --> $DIR/ascii-only-character-escape.rs:4:16 | -LL | let x = "/x80"; +LL | let x = "\x80"; | ^^ -error: this form of character escape may only be used with characters in the range [/x00-/x7f] +error: this form of character escape may only be used with characters in the range [\x00-\x7f] --> $DIR/ascii-only-character-escape.rs:5:16 | -LL | let y = "/xff"; +LL | let y = "\xff"; | ^^ -error: this form of character escape may only be used with characters in the range [/x00-/x7f] +error: this form of character escape may only be used with characters in the range [\x00-\x7f] --> $DIR/ascii-only-character-escape.rs:6:16 | -LL | let z = "/xe2"; +LL | let z = "\xe2"; | ^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/parser/bad-char-literals.stderr b/src/test/ui/parser/bad-char-literals.stderr index eb048b08c71b0..8e96ea22771b8 100644 --- a/src/test/ui/parser/bad-char-literals.stderr +++ b/src/test/ui/parser/bad-char-literals.stderr @@ -4,7 +4,7 @@ error: character constant must be escaped: ' LL | '''; | ^ -error: character constant must be escaped: /n +error: character constant must be escaped: \n --> $DIR/bad-char-literals.rs:11:6 | LL | ' @@ -12,13 +12,13 @@ LL | ' LL | | '; | |_ -error: character constant must be escaped: /r +error: character constant must be escaped: \r --> $DIR/bad-char-literals.rs:16:6 | LL | ' '; | ^ -error: character constant must be escaped: /t +error: character constant must be escaped: \t --> $DIR/bad-char-literals.rs:19:6 | LL | ' '; diff --git a/src/test/ui/parser/byte-literals.stderr b/src/test/ui/parser/byte-literals.stderr index 4edeccfe47556..28385f34f2ab2 100644 --- a/src/test/ui/parser/byte-literals.stderr +++ b/src/test/ui/parser/byte-literals.stderr @@ -1,22 +1,22 @@ error: unknown byte escape: f --> $DIR/byte-literals.rs:6:21 | -LL | static FOO: u8 = b'/f'; +LL | static FOO: u8 = b'\f'; | ^ unknown byte escape error: unknown byte escape: f --> $DIR/byte-literals.rs:9:8 | -LL | b'/f'; +LL | b'\f'; | ^ unknown byte escape error: invalid character in numeric character escape: Z --> $DIR/byte-literals.rs:10:10 | -LL | b'/x0Z'; +LL | b'\x0Z'; | ^ -error: byte constant must be escaped: /t +error: byte constant must be escaped: \t --> $DIR/byte-literals.rs:11:7 | LL | b' '; @@ -28,7 +28,7 @@ error: byte constant must be escaped: ' LL | b'''; | ^ -error: byte constant must be ASCII. Use a /xHH escape for a non-ASCII byte +error: byte constant must be ASCII. Use a \xHH escape for a non-ASCII byte --> $DIR/byte-literals.rs:13:7 | LL | b'é'; diff --git a/src/test/ui/parser/byte-string-literals.stderr b/src/test/ui/parser/byte-string-literals.stderr index 45c1a94b519a3..6701cfd8e66c2 100644 --- a/src/test/ui/parser/byte-string-literals.stderr +++ b/src/test/ui/parser/byte-string-literals.stderr @@ -1,22 +1,22 @@ error: unknown byte escape: f --> $DIR/byte-string-literals.rs:6:32 | -LL | static FOO: &'static [u8] = b"/f"; +LL | static FOO: &'static [u8] = b"\f"; | ^ unknown byte escape error: unknown byte escape: f --> $DIR/byte-string-literals.rs:9:8 | -LL | b"/f"; +LL | b"\f"; | ^ unknown byte escape error: invalid character in numeric character escape: Z --> $DIR/byte-string-literals.rs:10:10 | -LL | b"/x0Z"; +LL | b"\x0Z"; | ^ -error: byte constant must be ASCII. Use a /xHH escape for a non-ASCII byte +error: byte constant must be ASCII. Use a \xHH escape for a non-ASCII byte --> $DIR/byte-string-literals.rs:11:7 | LL | b"é"; diff --git a/src/test/ui/parser/issue-23620-invalid-escapes.stderr b/src/test/ui/parser/issue-23620-invalid-escapes.stderr index 669a6d26905d1..295ba3b73e861 100644 --- a/src/test/ui/parser/issue-23620-invalid-escapes.stderr +++ b/src/test/ui/parser/issue-23620-invalid-escapes.stderr @@ -1,118 +1,118 @@ error: unicode escape sequences cannot be used as a byte or in a byte string --> $DIR/issue-23620-invalid-escapes.rs:4:15 | -LL | let _ = b"/u{a66e}"; +LL | let _ = b"\u{a66e}"; | ^^^^^^^^ error: unicode escape sequences cannot be used as a byte or in a byte string --> $DIR/issue-23620-invalid-escapes.rs:7:15 | -LL | let _ = b'/u{a66e}'; +LL | let _ = b'\u{a66e}'; | ^^^^^^^^ error: incorrect unicode escape sequence --> $DIR/issue-23620-invalid-escapes.rs:10:15 | -LL | let _ = b'/u'; +LL | let _ = b'\u'; | ^^ incorrect unicode escape sequence | - = help: format of unicode escape sequences is `/u{...}` + = help: format of unicode escape sequences is `\u{...}` error: unicode escape sequences cannot be used as a byte or in a byte string --> $DIR/issue-23620-invalid-escapes.rs:10:15 | -LL | let _ = b'/u'; +LL | let _ = b'\u'; | ^^ error: numeric character escape is too short --> $DIR/issue-23620-invalid-escapes.rs:14:17 | -LL | let _ = b'/x5'; +LL | let _ = b'\x5'; | ^ error: invalid character in numeric character escape: x --> $DIR/issue-23620-invalid-escapes.rs:17:17 | -LL | let _ = b'/xxy'; +LL | let _ = b'\xxy'; | ^ error: invalid character in numeric character escape: y --> $DIR/issue-23620-invalid-escapes.rs:17:18 | -LL | let _ = b'/xxy'; +LL | let _ = b'\xxy'; | ^ error: numeric character escape is too short --> $DIR/issue-23620-invalid-escapes.rs:21:16 | -LL | let _ = '/x5'; +LL | let _ = '\x5'; | ^ error: invalid character in numeric character escape: x --> $DIR/issue-23620-invalid-escapes.rs:24:16 | -LL | let _ = '/xxy'; +LL | let _ = '\xxy'; | ^ error: invalid character in numeric character escape: y --> $DIR/issue-23620-invalid-escapes.rs:24:17 | -LL | let _ = '/xxy'; +LL | let _ = '\xxy'; | ^ error: unicode escape sequences cannot be used as a byte or in a byte string --> $DIR/issue-23620-invalid-escapes.rs:28:15 | -LL | let _ = b"/u{a4a4} /xf /u"; +LL | let _ = b"\u{a4a4} \xf \u"; | ^^^^^^^^ error: invalid character in numeric character escape: --> $DIR/issue-23620-invalid-escapes.rs:28:27 | -LL | let _ = b"/u{a4a4} /xf /u"; +LL | let _ = b"\u{a4a4} \xf \u"; | ^ error: incorrect unicode escape sequence --> $DIR/issue-23620-invalid-escapes.rs:28:28 | -LL | let _ = b"/u{a4a4} /xf /u"; +LL | let _ = b"\u{a4a4} \xf \u"; | ^^ incorrect unicode escape sequence | - = help: format of unicode escape sequences is `/u{...}` + = help: format of unicode escape sequences is `\u{...}` error: unicode escape sequences cannot be used as a byte or in a byte string --> $DIR/issue-23620-invalid-escapes.rs:28:28 | -LL | let _ = b"/u{a4a4} /xf /u"; +LL | let _ = b"\u{a4a4} \xf \u"; | ^^ error: invalid character in numeric character escape: --> $DIR/issue-23620-invalid-escapes.rs:34:17 | -LL | let _ = "/xf /u"; +LL | let _ = "\xf \u"; | ^ -error: this form of character escape may only be used with characters in the range [/x00-/x7f] +error: this form of character escape may only be used with characters in the range [\x00-\x7f] --> $DIR/issue-23620-invalid-escapes.rs:34:16 | -LL | let _ = "/xf /u"; +LL | let _ = "\xf \u"; | ^^ error: incorrect unicode escape sequence --> $DIR/issue-23620-invalid-escapes.rs:34:18 | -LL | let _ = "/xf /u"; +LL | let _ = "\xf \u"; | ^^ incorrect unicode escape sequence | - = help: format of unicode escape sequences is `/u{...}` + = help: format of unicode escape sequences is `\u{...}` error: incorrect unicode escape sequence --> $DIR/issue-23620-invalid-escapes.rs:39:14 | -LL | let _ = "/u8f"; +LL | let _ = "\u8f"; | ^^-- | | - | help: format of unicode escape sequences uses braces: `/u{8f}` + | help: format of unicode escape sequences uses braces: `\u{8f}` error: aborting due to 18 previous errors diff --git a/src/test/ui/parser/issue-43692.stderr b/src/test/ui/parser/issue-43692.stderr index 9408182f9527b..69a54af3d82ed 100644 --- a/src/test/ui/parser/issue-43692.stderr +++ b/src/test/ui/parser/issue-43692.stderr @@ -1,7 +1,7 @@ error: invalid start of unicode escape --> $DIR/issue-43692.rs:2:9 | -LL | '/u{_10FFFF}'; +LL | '\u{_10FFFF}'; | ^ error: aborting due to previous error diff --git a/src/test/ui/parser/lex-bad-char-literals-1.stderr b/src/test/ui/parser/lex-bad-char-literals-1.stderr index e6b71108086df..414ad81512ae5 100644 --- a/src/test/ui/parser/lex-bad-char-literals-1.stderr +++ b/src/test/ui/parser/lex-bad-char-literals-1.stderr @@ -1,25 +1,25 @@ error: numeric character escape is too short --> $DIR/lex-bad-char-literals-1.rs:3:8 | -LL | '/x1' +LL | '\x1' | ^ error: numeric character escape is too short --> $DIR/lex-bad-char-literals-1.rs:7:8 | -LL | "/x1" +LL | "\x1" | ^ -error: unknown character escape: /u{25cf} +error: unknown character escape: \u{25cf} --> $DIR/lex-bad-char-literals-1.rs:11:7 | -LL | '/●' +LL | '\●' | ^ unknown character escape -error: unknown character escape: /u{25cf} +error: unknown character escape: \u{25cf} --> $DIR/lex-bad-char-literals-1.rs:15:7 | -LL | "/●" +LL | "\●" | ^ unknown character escape error: aborting due to 4 previous errors diff --git a/src/test/ui/parser/lex-bad-char-literals-5.stderr b/src/test/ui/parser/lex-bad-char-literals-5.stderr index ef02973310153..97c6338820d73 100644 --- a/src/test/ui/parser/lex-bad-char-literals-5.stderr +++ b/src/test/ui/parser/lex-bad-char-literals-5.stderr @@ -1,21 +1,21 @@ error: character literal may only contain one codepoint --> $DIR/lex-bad-char-literals-5.rs:1:18 | -LL | static c: char = '/x10/x10'; +LL | static c: char = '\x10\x10'; | ^^^^^^^^^^ help: if you meant to write a `str` literal, use double quotes | -LL | static c: char = "/x10/x10"; +LL | static c: char = "\x10\x10"; | ^^^^^^^^^^ error: character literal may only contain one codepoint --> $DIR/lex-bad-char-literals-5.rs:5:20 | -LL | let ch: &str = '/x10/x10'; +LL | let ch: &str = '\x10\x10'; | ^^^^^^^^^^ help: if you meant to write a `str` literal, use double quotes | -LL | let ch: &str = "/x10/x10"; +LL | let ch: &str = "\x10\x10"; | ^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/parser/lex-bad-token.stderr b/src/test/ui/parser/lex-bad-token.stderr index c0c2e542058bb..43c43721b19f2 100644 --- a/src/test/ui/parser/lex-bad-token.stderr +++ b/src/test/ui/parser/lex-bad-token.stderr @@ -1,4 +1,4 @@ -error: unknown start of token: /u{25cf} +error: unknown start of token: \u{25cf} --> $DIR/lex-bad-token.rs:1:1 | LL | ● diff --git a/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.stderr b/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.stderr index b4d538bf61312..7d944569ca9c4 100644 --- a/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.stderr +++ b/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.stderr @@ -22,22 +22,22 @@ error: bare CR not allowed in block doc-comment LL | /*! block doc comment with bare CR: ' ' */ | ^ -error: bare CR not allowed in string, use /r instead +error: bare CR not allowed in string, use \r instead --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:21:18 | LL | let _s = "foo bar"; | ^ -error: bare CR not allowed in raw string, use /r instead +error: bare CR not allowed in raw string, use \r instead --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:24:14 | LL | let _s = r"bar foo"; | ^^^^^ -error: unknown character escape: /r +error: unknown character escape: \r --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:27:19 | -LL | let _s = "foo/ bar"; +LL | let _s = "foo\ bar"; | ^ unknown character escape | = help: this is an isolated carriage return; consider checking your editor and version control settings diff --git a/src/test/ui/parser/lex-stray-backslash.stderr b/src/test/ui/parser/lex-stray-backslash.stderr index 7ce061b8be079..06dc0f2b537ba 100644 --- a/src/test/ui/parser/lex-stray-backslash.stderr +++ b/src/test/ui/parser/lex-stray-backslash.stderr @@ -1,7 +1,7 @@ -error: unknown start of token: / +error: unknown start of token: \ --> $DIR/lex-stray-backslash.rs:1:1 | -LL | / +LL | \ | ^ error: aborting due to previous error diff --git a/src/test/ui/parser/new-unicode-escapes-1.stderr b/src/test/ui/parser/new-unicode-escapes-1.stderr index 5a191735307a9..a8da50951ddf3 100644 --- a/src/test/ui/parser/new-unicode-escapes-1.stderr +++ b/src/test/ui/parser/new-unicode-escapes-1.stderr @@ -1,7 +1,7 @@ error: unterminated unicode escape (needed a `}`) --> $DIR/new-unicode-escapes-1.rs:2:21 | -LL | let s = "/u{2603"; +LL | let s = "\u{2603"; | ^ error: aborting due to previous error diff --git a/src/test/ui/parser/new-unicode-escapes-2.stderr b/src/test/ui/parser/new-unicode-escapes-2.stderr index 0fb8befa45b0c..ede49cdf7e1d1 100644 --- a/src/test/ui/parser/new-unicode-escapes-2.stderr +++ b/src/test/ui/parser/new-unicode-escapes-2.stderr @@ -1,7 +1,7 @@ error: overlong unicode escape (must have at most 6 hex digits) --> $DIR/new-unicode-escapes-2.rs:2:17 | -LL | let s = "/u{260311111111}"; +LL | let s = "\u{260311111111}"; | ^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/new-unicode-escapes-3.stderr b/src/test/ui/parser/new-unicode-escapes-3.stderr index 427426788f6f8..59cfb988f2897 100644 --- a/src/test/ui/parser/new-unicode-escapes-3.stderr +++ b/src/test/ui/parser/new-unicode-escapes-3.stderr @@ -1,7 +1,7 @@ error: invalid unicode character escape --> $DIR/new-unicode-escapes-3.rs:2:14 | -LL | let s1 = "/u{d805}"; +LL | let s1 = "\u{d805}"; | ^^^^^^^^^^ | = help: unicode escape must not be a surrogate @@ -9,7 +9,7 @@ LL | let s1 = "/u{d805}"; error: invalid unicode character escape --> $DIR/new-unicode-escapes-3.rs:3:14 | -LL | let s2 = "/u{ffffff}"; +LL | let s2 = "\u{ffffff}"; | ^^^^^^^^^^^^ | = help: unicode escape must be at most 10FFFF diff --git a/src/test/ui/parser/new-unicode-escapes-4.stderr b/src/test/ui/parser/new-unicode-escapes-4.stderr index c8dbe027184de..ca96b00aa7bc5 100644 --- a/src/test/ui/parser/new-unicode-escapes-4.stderr +++ b/src/test/ui/parser/new-unicode-escapes-4.stderr @@ -1,7 +1,7 @@ error: invalid character in unicode escape: l --> $DIR/new-unicode-escapes-4.rs:4:17 | -LL | let s = "/u{lol}"; +LL | let s = "\u{lol}"; | ^ error: aborting due to previous error diff --git a/src/test/ui/parser/raw-byte-string-literals.stderr b/src/test/ui/parser/raw-byte-string-literals.stderr index 5670ed6590a18..a7f1af0a3474c 100644 --- a/src/test/ui/parser/raw-byte-string-literals.stderr +++ b/src/test/ui/parser/raw-byte-string-literals.stderr @@ -1,4 +1,4 @@ -error: raw byte string must be ASCII: /u{e9} +error: raw byte string must be ASCII: \u{e9} --> $DIR/raw-byte-string-literals.rs:5:8 | LL | br"é"; diff --git a/src/test/ui/parser/trailing-carriage-return-in-string.stderr b/src/test/ui/parser/trailing-carriage-return-in-string.stderr index f70f8ac8d7751..3687b9dd282d1 100644 --- a/src/test/ui/parser/trailing-carriage-return-in-string.stderr +++ b/src/test/ui/parser/trailing-carriage-return-in-string.stderr @@ -1,7 +1,7 @@ -error: unknown character escape: /r +error: unknown character escape: \r --> $DIR/trailing-carriage-return-in-string.rs:10:25 | -LL | let bad = "This is / a test"; +LL | let bad = "This is \ a test"; | ^ unknown character escape | = help: this is an isolated carriage return; consider checking your editor and version control settings diff --git a/src/test/ui/parser/unicode-chars.stderr b/src/test/ui/parser/unicode-chars.stderr index 3a360d8f4681f..76bf6627a4bc4 100644 --- a/src/test/ui/parser/unicode-chars.stderr +++ b/src/test/ui/parser/unicode-chars.stderr @@ -1,4 +1,4 @@ -error: unknown start of token: /u{37e} +error: unknown start of token: \u{37e} --> $DIR/unicode-chars.rs:2:14 | LL | let y = 0; diff --git a/src/test/ui/parser/unicode-quote-chars.stderr b/src/test/ui/parser/unicode-quote-chars.stderr index 315e20cf854cd..4a09ed75605e4 100644 --- a/src/test/ui/parser/unicode-quote-chars.stderr +++ b/src/test/ui/parser/unicode-quote-chars.stderr @@ -1,4 +1,4 @@ -error: unknown start of token: /u{201c} +error: unknown start of token: \u{201c} --> $DIR/unicode-quote-chars.rs:4:14 | LL | println!(“hello world”); diff --git a/src/test/ui/parser/wrong-escape-of-curly-braces.stderr b/src/test/ui/parser/wrong-escape-of-curly-braces.stderr index 346eba04c6500..1406b795ba8c3 100644 --- a/src/test/ui/parser/wrong-escape-of-curly-braces.stderr +++ b/src/test/ui/parser/wrong-escape-of-curly-braces.stderr @@ -1,7 +1,7 @@ error: unknown character escape: { --> $DIR/wrong-escape-of-curly-braces.rs:3:17 | -LL | let bad = "/{it is wrong/}"; +LL | let bad = "\{it is wrong\}"; | ^ unknown character escape | = help: if used in a formatting string, curly braces are escaped with `{{` and `}}` @@ -9,7 +9,7 @@ LL | let bad = "/{it is wrong/}"; error: unknown character escape: } --> $DIR/wrong-escape-of-curly-braces.rs:3:30 | -LL | let bad = "/{it is wrong/}"; +LL | let bad = "\{it is wrong\}"; | ^ unknown character escape | = help: if used in a formatting string, curly braces are escaped with `{{` and `}}` diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 3e3499edf60f0..22395e3c5bb06 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -10,7 +10,7 @@ use crate::errors::{self, Error, ErrorKind}; use filetime::FileTime; use crate::header::TestProps; use crate::json; -use regex::Regex; +use regex::{Captures, Regex}; use rustfix::{apply_suggestions, get_suggestions_from_json, Filter}; use crate::util::{logv, PathBufExt}; @@ -3147,10 +3147,8 @@ impl<'test> TestCx<'test> { normalized = Regex::new("SRC_DIR(.+):\\d+:\\d+").unwrap() .replace_all(&normalized, "SRC_DIR$1:LL:COL").into_owned(); - normalized = normalized.replace("\\\\", "\\") // denormalize for paths on windows - .replace("\\", "/") // normalize for paths on windows - .replace("\r\n", "\n") // normalize for linebreaks on windows - .replace("\t", "\\t"); // makes tabs visible + normalized = Self::normalize_platform_differences(&normalized); + normalized = normalized.replace("\t", "\\t"); // makes tabs visible // Remove test annotations like `//~ ERROR text` from the output, // since they duplicate actual errors and make the output hard to read. @@ -3164,6 +3162,36 @@ impl<'test> TestCx<'test> { normalized } + /// Normalize output differences across platforms. Generally changes Windows output to be more + /// Unix-like. + /// + /// Replaces backslashes in paths with forward slashes, and replaces CRLF line endings + /// with LF. + fn normalize_platform_differences(output: &str) -> String { + lazy_static! { + /// Used to find Windows paths. + /// + /// It's not possible to detect paths in the error messages generally, but this is a + /// decent enough heuristic. + static ref PATH_BACKSLASH_RE: Regex = Regex::new(r#"(?x) + (?: + # Match paths that don't include spaces. + (?:\\[\pL\pN\.\-_']+)+\.\pL+ + | + # If the path starts with a well-known root, then allow spaces. + \$(?:DIR|SRC_DIR|TEST_BUILD_DIR|BUILD_DIR|LIB_DIR)(?:\\[\pL\pN\.\-_' ]+)+ + )"# + ).unwrap(); + } + + let output = output.replace(r"\\", r"\"); + + PATH_BACKSLASH_RE.replace_all(&output, |caps: &Captures<'_>| { + println!("{}", &caps[0]); + caps[0].replace(r"\", "/") + }).replace("\r\n", "\n") + } + fn expected_output_path(&self, kind: &str) -> PathBuf { let mut path = expected_output_path( &self.testpaths, @@ -3495,3 +3523,68 @@ fn read2_abbreviated(mut child: Child) -> io::Result { stderr: stderr.into_bytes(), }) } + +#[cfg(test)] +mod tests { + use super::TestCx; + + #[test] + fn normalize_platform_differences() { + assert_eq!( + TestCx::normalize_platform_differences(r"$DIR\foo.rs"), + "$DIR/foo.rs" + ); + assert_eq!( + TestCx::normalize_platform_differences(r"$BUILD_DIR\..\parser.rs"), + "$BUILD_DIR/../parser.rs" + ); + assert_eq!( + TestCx::normalize_platform_differences(r"$DIR\bar.rs hello\nworld"), + r"$DIR/bar.rs hello\nworld" + ); + assert_eq!( + TestCx::normalize_platform_differences(r"either bar\baz.rs or bar\baz\mod.rs"), + r"either bar/baz.rs or bar/baz/mod.rs", + ); + assert_eq!( + TestCx::normalize_platform_differences(r"`.\some\path.rs`"), + r"`./some/path.rs`", + ); + assert_eq!( + TestCx::normalize_platform_differences(r"`some\path.rs`"), + r"`some/path.rs`", + ); + assert_eq!( + TestCx::normalize_platform_differences(r"$DIR\path-with-dashes.rs"), + r"$DIR/path-with-dashes.rs" + ); + assert_eq!( + TestCx::normalize_platform_differences(r"$DIR\path_with_underscores.rs"), + r"$DIR/path_with_underscores.rs", + ); + assert_eq!( + TestCx::normalize_platform_differences(r"$DIR\foo.rs:12:11"), "$DIR/foo.rs:12:11", + ); + assert_eq!( + TestCx::normalize_platform_differences(r"$DIR\path with spaces 'n' quotes"), + "$DIR/path with spaces 'n' quotes", + ); + assert_eq!( + TestCx::normalize_platform_differences(r"$DIR\file_with\no_extension"), + "$DIR/file_with/no_extension", + ); + + assert_eq!(TestCx::normalize_platform_differences(r"\n"), r"\n"); + assert_eq!(TestCx::normalize_platform_differences(r"{ \n"), r"{ \n"); + assert_eq!(TestCx::normalize_platform_differences(r"`\]`"), r"`\]`"); + assert_eq!(TestCx::normalize_platform_differences(r#""\{""#), r#""\{""#); + assert_eq!( + TestCx::normalize_platform_differences(r#"write!(&mut v, "Hello\n")"#), + r#"write!(&mut v, "Hello\n")"# + ); + assert_eq!( + TestCx::normalize_platform_differences(r#"println!("test\ntest")"#), + r#"println!("test\ntest")"#, + ); + } +} From d485ebfc211533900464927d57d6500e29e519f3 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 25 Mar 2019 06:57:32 +0100 Subject: [PATCH 13/19] Fix two bootstrap tests --- src/bootstrap/builder.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index f93f3e72f83e7..7851ea3e363a4 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -1856,6 +1856,7 @@ mod __test { doc_tests: DocTests::No, bless: false, compare_mode: None, + rustfix_coverage: false, }; let build = Build::new(config); @@ -1897,6 +1898,7 @@ mod __test { doc_tests: DocTests::No, bless: false, compare_mode: None, + rustfix_coverage: false, }; let build = Build::new(config); From 98d7c5463b4f8099d7e1e50087deaa195589294f Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 25 Mar 2019 06:58:30 +0100 Subject: [PATCH 14/19] s/lints/diagnostics Not all suggestions come from lints --- src/tools/compiletest/src/common.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index fe0c4f14940ad..7a15d753e2df1 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -246,8 +246,8 @@ pub struct Config { pub compare_mode: Option, /// If true, this will generate a coverage file with UI test files that run `MachineApplicable` - /// lints but are missing `run-rustfix` annotations. The generated coverage file is created in - /// `/tmp/rustfix_missing_coverage.txt` + /// diagnostics but are missing `run-rustfix` annotations. The generated coverage file is + /// created in `/tmp/rustfix_missing_coverage.txt` pub rustfix_coverage: bool, // Configuration for various run-make tests frobbing things like C compilers From d808bd46515e4de5d21a62b2c1557ac9d2751846 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 25 Mar 2019 22:48:35 +0100 Subject: [PATCH 15/19] Save coverage file in build_base path, not /tmp --- src/bootstrap/flags.rs | 2 +- src/tools/compiletest/src/common.rs | 2 +- src/tools/compiletest/src/main.rs | 7 ++++--- src/tools/compiletest/src/runtest.rs | 7 +++++-- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 23719378c840a..a1f89d6c86f1d 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -193,7 +193,7 @@ To learn more about a subcommand, run `./x.py -h`" "", "rustfix-coverage", "enable this to generate a Rustfix coverage file, which is saved in \ - `/tmp/rustfix_missing_coverage.txt`", + `//rustfix_missing_coverage.txt`", ); } "bench" => { diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 7a15d753e2df1..9d4effb4f5860 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -247,7 +247,7 @@ pub struct Config { /// If true, this will generate a coverage file with UI test files that run `MachineApplicable` /// diagnostics but are missing `run-rustfix` annotations. The generated coverage file is - /// created in `/tmp/rustfix_missing_coverage.txt` + /// created in `//rustfix_missing_coverage.txt` pub rustfix_coverage: bool, // Configuration for various run-make tests frobbing things like C compilers diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 1045ea1bf0c96..b9ddf04fad987 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -237,7 +237,7 @@ pub fn parse_config(args: Vec) -> Config { "", "rustfix-coverage", "enable this to generate a Rustfix coverage file, which is saved in \ - `/tmp/rustfix_missing_coverage.txt`", + `.//rustfix_missing_coverage.txt`", ) .optflag("h", "help", "show this message"); @@ -486,9 +486,10 @@ pub fn run_tests(config: &Config) { // we first make sure that the coverage file does not exist. // It will be created later on. if config.rustfix_coverage { - let coverage_file_path = Path::new("/tmp/rustfix_missing_coverage.txt"); + let mut coverage_file_path = config.build_base.clone(); + coverage_file_path.push("rustfix_missing_coverage.txt"); if coverage_file_path.exists() { - if let Err(e) = fs::remove_file(coverage_file_path) { + if let Err(e) = fs::remove_file(&coverage_file_path) { panic!("Could not delete {} due to {}", coverage_file_path.display(), e) } } diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 0ca656bb13328..c18b6db9a010f 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2829,11 +2829,14 @@ impl<'test> TestCx<'test> { if suggestions.len() > 0 && !self.props.run_rustfix && !self.props.rustfix_only_machine_applicable { - let coverage_file_path = Path::new("/tmp/rustfix_missing_coverage.txt"); + let mut coverage_file_path = self.config.build_base.clone(); + coverage_file_path.push("rustfix_missing_coverage.txt"); + debug!("coverage_file_path: {}", coverage_file_path.display()); + let mut file = OpenOptions::new() .create(true) .append(true) - .open(coverage_file_path) + .open(coverage_file_path.as_path()) .expect("could not create or open file"); if let Err(_) = writeln!(file, "{}", self.testpaths.file.display()) { From 4bad56e54c1a870377b04b0b7f17e3051f246248 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 25 Mar 2019 19:11:41 -0700 Subject: [PATCH 16/19] When moving out of a for loop head, suggest borrowing it in nll mode --- .../borrow_check/error_reporting.rs | 47 +++++++++++++++---- .../borrow_check/nll/explain_borrow/mod.rs | 18 ++++--- src/test/ui/augmented-assignments.nll.stderr | 17 ++----- ...-bound-on-closure-outlives-call.nll.stderr | 9 ++-- ...owck-call-is-borrow-issue-12224.nll.stderr | 1 - .../borrow-for-loop-head.nll.stderr | 9 ++-- 6 files changed, 63 insertions(+), 38 deletions(-) diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 14289381aef45..88ff231202085 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -19,6 +19,7 @@ use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, DiagnosticBuilder}; use syntax_pos::Span; +use syntax::source_map::CompilerDesugaringKind; use super::borrow_set::BorrowData; use super::{Context, MirBorrowckCtxt}; @@ -154,6 +155,18 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { span, format!("value moved{} here, in previous iteration of loop", move_msg), ); + if Some(CompilerDesugaringKind::ForLoop) == span.compiler_desugaring_kind() { + if let Ok(snippet) = self.infcx.tcx.sess.source_map() + .span_to_snippet(span) + { + err.span_suggestion( + move_span, + "consider borrowing this to avoid moving it into the for loop", + format!("&{}", snippet), + Applicability::MaybeIncorrect, + ); + } + } is_loop_move = true; } else if move_site.traversed_back_edge { err.span_label( @@ -291,8 +304,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { format!("move occurs due to use{}", move_spans.describe()) ); - self.explain_why_borrow_contains_point(context, borrow, None) - .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, ""); + self.explain_why_borrow_contains_point( + context, + borrow, + None, + ).add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "", Some(borrow_span)); err.buffer(&mut self.errors_buffer); } @@ -329,7 +345,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { }); self.explain_why_borrow_contains_point(context, borrow, None) - .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, ""); + .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "", None); err.buffer(&mut self.errors_buffer); } @@ -542,8 +558,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { )); } - explanation - .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, first_borrow_desc); + explanation.add_explanation_to_diagnostic( + self.infcx.tcx, + self.mir, + &mut err, + first_borrow_desc, + None, + ); err.buffer(&mut self.errors_buffer); } @@ -866,7 +887,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { if let BorrowExplanation::MustBeValidFor { .. } = explanation { } else { - explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, ""); + explanation.add_explanation_to_diagnostic( + self.infcx.tcx, + self.mir, + &mut err, + "", + None, + ); } } else { err.span_label(borrow_span, "borrowed value does not live long enough"); @@ -886,7 +913,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { format!("value captured here{}", within), ); - explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, ""); + explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "", None); } err @@ -946,7 +973,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { _ => {} } - explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, ""); + explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "", None); err.buffer(&mut self.errors_buffer); } @@ -1027,7 +1054,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } _ => {} } - explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, ""); + explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "", None); let within = if borrow_spans.for_generator() { " by generator" @@ -1367,7 +1394,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ); self.explain_why_borrow_contains_point(context, loan, None) - .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, ""); + .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "", None); err.buffer(&mut self.errors_buffer); } diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs index dfa5af444d37e..67b77605f3c92 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -56,17 +56,23 @@ impl BorrowExplanation { mir: &Mir<'tcx>, err: &mut DiagnosticBuilder<'_>, borrow_desc: &str, + borrow_span: Option, ) { match *self { BorrowExplanation::UsedLater(later_use_kind, var_or_use_span) => { let message = match later_use_kind { - LaterUseKind::TraitCapture => "borrow later captured here by trait object", - LaterUseKind::ClosureCapture => "borrow later captured here by closure", - LaterUseKind::Call => "borrow later used by call", - LaterUseKind::FakeLetRead => "borrow later stored here", - LaterUseKind::Other => "borrow later used here", + LaterUseKind::TraitCapture => "captured here by trait object", + LaterUseKind::ClosureCapture => "captured here by closure", + LaterUseKind::Call => "used by call", + LaterUseKind::FakeLetRead => "stored here", + LaterUseKind::Other => "used here", }; - err.span_label(var_or_use_span, format!("{}{}", borrow_desc, message)); + if !borrow_span.map(|sp| sp.overlaps(var_or_use_span)).unwrap_or(false) { + err.span_label( + var_or_use_span, + format!("{}borrow later {}", borrow_desc, message), + ); + } } BorrowExplanation::UsedLaterInLoop(later_use_kind, var_or_use_span) => { let message = match later_use_kind { diff --git a/src/test/ui/augmented-assignments.nll.stderr b/src/test/ui/augmented-assignments.nll.stderr index 08f06e90162b4..e205e2a87810f 100644 --- a/src/test/ui/augmented-assignments.nll.stderr +++ b/src/test/ui/augmented-assignments.nll.stderr @@ -1,18 +1,11 @@ error[E0505]: cannot move out of `x` because it is borrowed --> $DIR/augmented-assignments.rs:16:5 | -LL | x - | - - | | - | _____borrow of `x` occurs here - | | -LL | | -LL | | += -LL | | x; - | | ^ - | | | - | |_____move out of `x` occurs here - | borrow later used here +LL | x + | - borrow of `x` occurs here +... +LL | x; + | ^ move out of `x` occurs here error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable --> $DIR/augmented-assignments.rs:21:5 diff --git a/src/test/ui/regions/region-bound-on-closure-outlives-call.nll.stderr b/src/test/ui/regions/region-bound-on-closure-outlives-call.nll.stderr index bce310bafaa92..d455902ee8c07 100644 --- a/src/test/ui/regions/region-bound-on-closure-outlives-call.nll.stderr +++ b/src/test/ui/regions/region-bound-on-closure-outlives-call.nll.stderr @@ -14,11 +14,10 @@ error[E0505]: cannot move out of `f` because it is borrowed --> $DIR/region-bound-on-closure-outlives-call.rs:3:25 | LL | (|x| f(x))(call_rec(f)) - | ---------- ^ move out of `f` occurs here - | || | - | || borrow occurs due to use in closure - | |borrow of `f` occurs here - | borrow later used by call + | --- - ^ move out of `f` occurs here + | | | + | | borrow occurs due to use in closure + | borrow of `f` occurs here error: aborting due to previous error diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr index 80dc3ef2f80f2..1a5ab7a7d56a0 100644 --- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr +++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr @@ -42,7 +42,6 @@ LL | f(Box::new(|a| { | - ^^^ move out of `f` occurs here | | | borrow of `f` occurs here - | borrow later used by call LL | foo(f); | - move occurs due to use in closure diff --git a/src/test/ui/suggestions/borrow-for-loop-head.nll.stderr b/src/test/ui/suggestions/borrow-for-loop-head.nll.stderr index 6450f7f52a47b..96dbdec7074a9 100644 --- a/src/test/ui/suggestions/borrow-for-loop-head.nll.stderr +++ b/src/test/ui/suggestions/borrow-for-loop-head.nll.stderr @@ -2,10 +2,7 @@ error[E0505]: cannot move out of `a` because it is borrowed --> $DIR/borrow-for-loop-head.rs:4:18 | LL | for i in &a { - | -- - | | - | borrow of `a` occurs here - | borrow later used here + | -- borrow of `a` occurs here LL | for j in a { | ^ move out of `a` occurs here @@ -17,6 +14,10 @@ LL | let a = vec![1, 2, 3]; LL | for i in &a { LL | for j in a { | ^ value moved here, in previous iteration of loop +help: consider borrowing this to avoid moving it into the for loop + | +LL | for j in &a { + | ^^ error: aborting due to 2 previous errors From 0b7b454820eff3109604c274d095948660a834dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sun, 10 Mar 2019 10:11:15 +0100 Subject: [PATCH 17/19] Combine input and eval_always query types --- src/librustc/dep_graph/dep_node.rs | 76 ++++++++++++------------------ src/librustc/dep_graph/graph.rs | 41 ++++------------ src/librustc/hir/map/mod.rs | 2 +- src/librustc/ty/query/plumbing.rs | 10 ++-- 4 files changed, 45 insertions(+), 84 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 4babadb67bce6..330862d7907d1 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -85,11 +85,6 @@ macro_rules! is_anon_attr { ($attr:ident) => (false); } -macro_rules! is_input_attr { - (input) => (true); - ($attr:ident) => (false); -} - macro_rules! is_eval_always_attr { (eval_always) => (true); ($attr:ident) => (false); @@ -99,10 +94,6 @@ macro_rules! contains_anon_attr { ($($attr:ident),*) => ({$(is_anon_attr!($attr) | )* false}); } -macro_rules! contains_input_attr { - ($($attr:ident),*) => ({$(is_input_attr!($attr) | )* false}); -} - macro_rules! contains_eval_always_attr { ($($attr:ident),*) => ({$(is_eval_always_attr!($attr) | )* false}); } @@ -151,7 +142,7 @@ macro_rules! define_dep_nodes { } } - // FIXME: Make `is_anon`, `is_input`, `is_eval_always` and `has_params` properties + // FIXME: Make `is_anon`, `is_eval_always` and `has_params` properties // of queries #[inline(always)] pub fn is_anon(&self) -> bool { @@ -162,15 +153,6 @@ macro_rules! define_dep_nodes { } } - #[inline(always)] - pub fn is_input(&self) -> bool { - match *self { - $( - DepKind :: $variant => { contains_input_attr!($($attr),*) } - )* - } - } - #[inline(always)] pub fn is_eval_always(&self) -> bool { match *self { @@ -438,17 +420,17 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx> // suitable wrapper, you can use `tcx.dep_graph.ignore()` to gain // access to the krate, but you must remember to add suitable // edges yourself for the individual items that you read. - [input] Krate, + [eval_always] Krate, // Represents the body of a function or method. The def-id is that of the // function/method. - [input] HirBody(DefId), + [eval_always] HirBody(DefId), // Represents the HIR node with the given node-id - [input] Hir(DefId), + [eval_always] Hir(DefId), // Represents metadata from an extern crate. - [input] CrateMetadata(CrateNum), + [eval_always] CrateMetadata(CrateNum), // Represents different phases in the compiler. [] RegionScopeTree(DefId), @@ -533,7 +515,7 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx> // The set of impls for a given trait. [] TraitImpls(DefId), - [input] AllLocalTraitImpls, + [eval_always] AllLocalTraitImpls, [anon] TraitSelect, @@ -545,7 +527,7 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx> // to make type debuginfo to be source location independent. Declaring // DefSpan an input makes sure that changes to these are always detected // regardless of HIR hashing. - [input] DefSpan(DefId), + [eval_always] DefSpan(DefId), [] LookupStability(DefId), [] LookupDeprecationEntry(DefId), [] ConstIsRvaluePromotableToStatic(DefId), @@ -563,10 +545,10 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx> [] IsCompilerBuiltins(CrateNum), [] HasGlobalAllocator(CrateNum), [] HasPanicHandler(CrateNum), - [input] ExternCrate(DefId), + [eval_always] ExternCrate(DefId), [] Specializes { impl1: DefId, impl2: DefId }, - [input] InScopeTraits(DefIndex), - [input] ModuleExports(DefId), + [eval_always] InScopeTraits(DefIndex), + [eval_always] ModuleExports(DefId), [] IsSanitizerRuntime(CrateNum), [] IsProfilerRuntime(CrateNum), [] GetPanicStrategy(CrateNum), @@ -579,10 +561,10 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx> [] EntryFn(CrateNum), [] PluginRegistrarFn(CrateNum), [] ProcMacroDeclsStatic(CrateNum), - [input] CrateDisambiguator(CrateNum), - [input] CrateHash(CrateNum), - [input] OriginalCrateName(CrateNum), - [input] ExtraFileName(CrateNum), + [eval_always] CrateDisambiguator(CrateNum), + [eval_always] CrateHash(CrateNum), + [eval_always] OriginalCrateName(CrateNum), + [eval_always] ExtraFileName(CrateNum), [] ImplementationsOfTrait { krate: CrateNum, trait_id: DefId }, [] AllTraitImplementations(CrateNum), @@ -591,7 +573,7 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx> [] IsDllimportForeignItem(DefId), [] IsStaticallyIncludedForeignItem(DefId), [] NativeLibraryKind(DefId), - [input] LinkArgs, + [eval_always] LinkArgs, [] ResolveLifetimes(CrateNum), [] NamedRegion(DefIndex), @@ -599,8 +581,8 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx> [] ObjectLifetimeDefaults(DefIndex), [] Visibility(DefId), - [input] DepKind(CrateNum), - [input] CrateName(CrateNum), + [eval_always] DepKind(CrateNum), + [eval_always] CrateName(CrateNum), [] ItemChildren(DefId), [] ExternModStmtCnum(DefId), [eval_always] GetLibFeatures, @@ -609,24 +591,24 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx> [] DefinedLangItems(CrateNum), [] MissingLangItems(CrateNum), [] VisibleParentMap, - [input] MissingExternCrateItem(CrateNum), - [input] UsedCrateSource(CrateNum), - [input] PostorderCnums, - - [input] Freevars(DefId), - [input] MaybeUnusedTraitImport(DefId), - [input] MaybeUnusedExternCrates, - [input] NamesImportedByGlobUse(DefId), + [eval_always] MissingExternCrateItem(CrateNum), + [eval_always] UsedCrateSource(CrateNum), + [eval_always] PostorderCnums, + + [eval_always] Freevars(DefId), + [eval_always] MaybeUnusedTraitImport(DefId), + [eval_always] MaybeUnusedExternCrates, + [eval_always] NamesImportedByGlobUse(DefId), [eval_always] StabilityIndex, [eval_always] AllTraits, - [input] AllCrateNums, + [eval_always] AllCrateNums, [] ExportedSymbols(CrateNum), [eval_always] CollectAndPartitionMonoItems, [] IsCodegenedItem(DefId), [] CodegenUnit(InternedString), [] BackendOptimizationLevel(CrateNum), [] CompileCodegenUnit(InternedString), - [input] OutputFilenames, + [eval_always] OutputFilenames, [] NormalizeProjectionTy(CanonicalProjectionGoal<'tcx>), [] NormalizeTyAfterErasingRegions(ParamEnvAnd<'tcx, Ty<'tcx>>), [] ImpliedOutlivesBounds(CanonicalTyGoal<'tcx>), @@ -645,11 +627,11 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx> [] SubstituteNormalizeAndTestPredicates { key: (DefId, SubstsRef<'tcx>) }, [] MethodAutoderefSteps(CanonicalTyGoal<'tcx>), - [input] TargetFeaturesWhitelist, + [eval_always] TargetFeaturesWhitelist, [] InstanceDefSizeEstimate { instance_def: InstanceDef<'tcx> }, - [input] Features, + [eval_always] Features, [] ForeignModules(CrateNum), diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 8a2f79e6793c0..db81a9d826f8c 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -388,10 +388,7 @@ impl DepGraph { |_| None, |data, key, fingerprint, _| { let mut current = data.borrow_mut(); - let krate_idx = current.node_to_node_index[ - &DepNode::new_no_params(DepKind::Krate) - ]; - current.alloc_node(key, smallvec![krate_idx], fingerprint) + current.alloc_node(key, smallvec![], fingerprint) }, hash_result) } @@ -576,7 +573,7 @@ impl DepGraph { tcx: TyCtxt<'_, '_, '_>, dep_node: &DepNode ) -> Option<(SerializedDepNodeIndex, DepNodeIndex)> { - debug_assert!(!dep_node.kind.is_input()); + debug_assert!(!dep_node.kind.is_eval_always()); // Return None if the dep graph is disabled let data = self.data.as_ref()?; @@ -620,8 +617,8 @@ impl DepGraph { debug_assert!(data.colors.get(prev_dep_node_index).is_none()); } - // We never try to mark inputs as green - debug_assert!(!dep_node.kind.is_input()); + // We never try to mark eval_always nodes as green + debug_assert!(!dep_node.kind.is_eval_always()); debug_assert_eq!(data.previous.index_to_node(prev_dep_node_index), *dep_node); @@ -658,8 +655,8 @@ impl DepGraph { let dep_dep_node = &data.previous.index_to_node(dep_dep_node_index); // We don't know the state of this dependency. If it isn't - // an input node, let's try to mark it green recursively. - if !dep_dep_node.kind.is_input() { + // an eval_always node, let's try to mark it green recursively. + if !dep_dep_node.kind.is_eval_always() { debug!("try_mark_previous_green({:?}) --- state of dependency {:?} \ is unknown, trying to mark it green", dep_node, dep_dep_node); @@ -694,7 +691,7 @@ impl DepGraph { } } _ => { - // For other kinds of inputs it's OK to be + // For other kinds of nodes it's OK to be // forced. } } @@ -1017,33 +1014,11 @@ impl CurrentDepGraph { task_deps: TaskDeps, fingerprint: Fingerprint ) -> DepNodeIndex { - // If this is an input node, we expect that it either has no - // dependencies, or that it just depends on DepKind::CrateMetadata - // or DepKind::Krate. This happens for some "thin wrapper queries" - // like `crate_disambiguator` which sometimes have zero deps (for - // when called for LOCAL_CRATE) or they depend on a CrateMetadata - // node. - if cfg!(debug_assertions) { - if node.kind.is_input() && task_deps.reads.len() > 0 && - // FIXME(mw): Special case for DefSpan until Spans are handled - // better in general. - node.kind != DepKind::DefSpan && - task_deps.reads.iter().any(|&i| { - !(self.data[i].node.kind == DepKind::CrateMetadata || - self.data[i].node.kind == DepKind::Krate) - }) - { - bug!("Input node {:?} with unexpected reads: {:?}", - node, - task_deps.reads.iter().map(|&i| self.data[i].node).collect::>()) - } - } - self.alloc_node(node, task_deps.reads, fingerprint) } fn complete_anon_task(&mut self, kind: DepKind, task_deps: TaskDeps) -> DepNodeIndex { - debug_assert!(!kind.is_input()); + debug_assert!(!kind.is_eval_always()); let mut fingerprint = self.anon_id_seed; let mut hasher = StableHasher::new(); diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index d810a9310c55f..ba5ed12a0c084 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -153,7 +153,7 @@ impl Forest { &self.krate } - /// This is internally in the depedency tracking system. + /// This is used internally in the dependency tracking system. /// Use the `krate` method to ensure your dependency on the /// crate is tracked. pub fn untracked_krate<'hir>(&'hir self) -> &'hir Crate { diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index adac19d3410b2..0a9bcac760301 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -414,7 +414,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { return result; } - if !dep_node.kind.is_input() { + if !dep_node.kind.is_eval_always() { // The diagnostics for this query will be // promoted to the current session during // try_mark_green(), so we can ignore them here. @@ -601,9 +601,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub(super) fn ensure_query>(self, key: Q::Key) -> () { let dep_node = Q::to_dep_node(self, &key); - // Ensuring an "input" or anonymous query makes no sense + if dep_node.kind.is_eval_always() { + let _ = self.get_query::(DUMMY_SP, key); + return; + } + + // Ensuring an anonymous query makes no sense assert!(!dep_node.kind.is_anon()); - assert!(!dep_node.kind.is_input()); if self.dep_graph.try_mark_green_and_read(self, &dep_node).is_none() { // A None return from `try_mark_green_and_read` means that this is either // a new dep node or that the dep node has already been marked red. From 629e3a3f12a5823d4a10c079c11a6473a37d7d4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Thu, 14 Mar 2019 03:10:47 +0100 Subject: [PATCH 18/19] Make crate_variances a regular query --- src/librustc/dep_graph/dep_node.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 330862d7907d1..ce027af8d6ab1 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -462,7 +462,7 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx> [] CollectModItemTypes(DefId), [] Reachability, - [eval_always] CrateVariances, + [] CrateVariances, // Nodes representing bits of computed IR in the tcx. Each shared // table in the tcx (or elsewhere) maps to one of these From 8f3e862797ecf83e89245d3f28532ab285c780ef Mon Sep 17 00:00:00 2001 From: Marcel Hellwig Date: Thu, 28 Mar 2019 09:31:18 +0100 Subject: [PATCH 19/19] fixed shift overflow Fix according to oli-obk (https://github.com/rust-lang/rust/pull/58717#issuecomment-477494457) --- src/librustc_codegen_llvm/debuginfo/metadata.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index da9ff54b0626c..17e6703d03dbe 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -22,6 +22,7 @@ use rustc::hir::CodegenFnAttrFlags; use rustc::hir::def::CtorKind; use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE}; use rustc::ich::NodeIdHashingMode; +use rustc::mir::interpret::truncate; use rustc_data_structures::fingerprint::Fingerprint; use rustc::ty::Instance; use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt}; @@ -1366,7 +1367,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { let value = (i.as_u32() as u128) .wrapping_sub(niche_variants.start().as_u32() as u128) .wrapping_add(niche_start); - let value = value & ((1u128 << niche.value.size(cx).bits()) - 1); + let value = truncate(value, niche.value.size(cx)); Some(value as u64) };