diff --git a/Cargo.lock b/Cargo.lock index 0f770f3eadbea..8b157d2b3f4bc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3506,6 +3506,7 @@ dependencies = [ "rustc_mir", "rustc_plugin", "rustc_plugin_impl", + "rustc_resolve", "rustc_save_analysis", "rustc_target", "serialize", diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index 131fb52e2d22b..726d187d2e981 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -1274,6 +1274,10 @@ pub(crate) mod builtin { } /// Inline assembly. + /// + /// Read the [unstable book] for the usage. + /// + /// [unstable book]: ../unstable-book/library-features/asm.html #[unstable(feature = "asm", issue = "29722", reason = "inline assembly is not stable enough for use and is subject to change")] #[rustc_builtin_macro] diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index d22420e76dcd4..24b19028ac117 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -35,7 +35,7 @@ impl InnerOffset { /// A piece is a portion of the format string which represents the next part /// to emit. These are emitted as a stream by the `Parser` class. -#[derive(Copy, Clone, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq)] pub enum Piece<'a> { /// A literal string which should directly be emitted String(&'a str), @@ -45,7 +45,7 @@ pub enum Piece<'a> { } /// Representation of an argument specification. -#[derive(Copy, Clone, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq)] pub struct Argument<'a> { /// Where to find this argument pub position: Position, @@ -54,7 +54,7 @@ pub struct Argument<'a> { } /// Specification for the formatting of an argument in the format string. -#[derive(Copy, Clone, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq)] pub struct FormatSpec<'a> { /// Optionally specified character to fill alignment with. pub fill: Option, @@ -74,10 +74,12 @@ pub struct FormatSpec<'a> { /// this argument, this can be empty or any number of characters, although /// it is required to be one word. pub ty: &'a str, + /// The span of the descriptor string (for diagnostics). + pub ty_span: Option, } /// Enum describing where an argument for a format can be located. -#[derive(Copy, Clone, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq)] pub enum Position { /// The argument is implied to be located at an index ArgumentImplicitlyIs(usize), @@ -97,7 +99,7 @@ impl Position { } /// Enum of alignments which are supported. -#[derive(Copy, Clone, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq)] pub enum Alignment { /// The value will be aligned to the left. AlignLeft, @@ -111,7 +113,7 @@ pub enum Alignment { /// Various flags which can be applied to format strings. The meaning of these /// flags is defined by the formatters themselves. -#[derive(Copy, Clone, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq)] pub enum Flag { /// A `+` will be used to denote positive numbers. FlagSignPlus, @@ -131,7 +133,7 @@ pub enum Flag { /// A count is used for the precision and width parameters of an integer, and /// can reference either an argument or a literal integer. -#[derive(Copy, Clone, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq)] pub enum Count { /// The count is specified explicitly. CountIs(usize), @@ -475,6 +477,7 @@ impl<'a> Parser<'a> { width: CountImplied, width_span: None, ty: &self.input[..0], + ty_span: None, }; if !self.consume(':') { return spec; @@ -548,6 +551,7 @@ impl<'a> Parser<'a> { spec.precision_span = sp; } } + let ty_span_start = self.cur.peek().map(|(pos, _)| *pos); // Optional radix followed by the actual format specifier if self.consume('x') { if self.consume('?') { @@ -567,6 +571,12 @@ impl<'a> Parser<'a> { spec.ty = "?"; } else { spec.ty = self.word(); + let ty_span_end = self.cur.peek().map(|(pos, _)| *pos); + if !spec.ty.is_empty() { + spec.ty_span = ty_span_start + .and_then(|s| ty_span_end.map(|e| (s, e))) + .map(|(start, end)| self.to_span_index(start).to(self.to_span_index(end))); + } } spec } diff --git a/src/libfmt_macros/tests.rs b/src/libfmt_macros/tests.rs index e2ddb8810e90a..81359033eda29 100644 --- a/src/libfmt_macros/tests.rs +++ b/src/libfmt_macros/tests.rs @@ -2,7 +2,7 @@ use super::*; fn same(fmt: &'static str, p: &[Piece<'static>]) { let parser = Parser::new(fmt, None, vec![], false); - assert!(parser.collect::>>() == p); + assert_eq!(parser.collect::>>(), p); } fn fmtdflt() -> FormatSpec<'static> { @@ -15,6 +15,7 @@ fn fmtdflt() -> FormatSpec<'static> { precision_span: None, width_span: None, ty: "", + ty_span: None, }; } @@ -82,7 +83,7 @@ fn format_position_nothing_else() { #[test] fn format_type() { same( - "{3:a}", + "{3:x}", &[NextArgument(Argument { position: ArgumentIs(3), format: FormatSpec { @@ -93,7 +94,8 @@ fn format_type() { width: CountImplied, precision_span: None, width_span: None, - ty: "a", + ty: "x", + ty_span: None, }, })]); } @@ -112,6 +114,7 @@ fn format_align_fill() { precision_span: None, width_span: None, ty: "", + ty_span: None, }, })]); same( @@ -127,6 +130,7 @@ fn format_align_fill() { precision_span: None, width_span: None, ty: "", + ty_span: None, }, })]); same( @@ -142,6 +146,7 @@ fn format_align_fill() { precision_span: None, width_span: None, ty: "abcd", + ty_span: Some(InnerSpan::new(6, 10)), }, })]); } @@ -150,7 +155,7 @@ fn format_counts() { use syntax_pos::{GLOBALS, Globals, edition}; GLOBALS.set(&Globals::new(edition::DEFAULT_EDITION), || { same( - "{:10s}", + "{:10x}", &[NextArgument(Argument { position: ArgumentImplicitlyIs(0), format: FormatSpec { @@ -161,11 +166,12 @@ fn format_counts() { width: CountIs(10), precision_span: None, width_span: None, - ty: "s", + ty: "x", + ty_span: None, }, })]); same( - "{:10$.10s}", + "{:10$.10x}", &[NextArgument(Argument { position: ArgumentImplicitlyIs(0), format: FormatSpec { @@ -176,11 +182,12 @@ fn format_counts() { width: CountIsParam(10), precision_span: None, width_span: Some(InnerSpan::new(3, 6)), - ty: "s", + ty: "x", + ty_span: None, }, })]); same( - "{:.*s}", + "{:.*x}", &[NextArgument(Argument { position: ArgumentImplicitlyIs(1), format: FormatSpec { @@ -191,11 +198,12 @@ fn format_counts() { width: CountImplied, precision_span: Some(InnerSpan::new(3, 5)), width_span: None, - ty: "s", + ty: "x", + ty_span: None, }, })]); same( - "{:.10$s}", + "{:.10$x}", &[NextArgument(Argument { position: ArgumentImplicitlyIs(0), format: FormatSpec { @@ -206,11 +214,12 @@ fn format_counts() { width: CountImplied, precision_span: Some(InnerSpan::new(3, 7)), width_span: None, - ty: "s", + ty: "x", + ty_span: None, }, })]); same( - "{:a$.b$s}", + "{:a$.b$?}", &[NextArgument(Argument { position: ArgumentImplicitlyIs(0), format: FormatSpec { @@ -221,7 +230,8 @@ fn format_counts() { width: CountIsName(Symbol::intern("a")), precision_span: None, width_span: None, - ty: "s", + ty: "?", + ty_span: None, }, })]); }); @@ -241,6 +251,7 @@ fn format_flags() { precision_span: None, width_span: None, ty: "", + ty_span: None, }, })]); same( @@ -256,13 +267,14 @@ fn format_flags() { precision_span: None, width_span: None, ty: "", + ty_span: None, }, })]); } #[test] fn format_mixture() { same( - "abcd {3:a} efg", + "abcd {3:x} efg", &[ String("abcd "), NextArgument(Argument { @@ -275,7 +287,8 @@ fn format_mixture() { width: CountImplied, precision_span: None, width_span: None, - ty: "a", + ty: "x", + ty_span: None, }, }), String(" efg"), diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 278f45371b151..effc13c8301ef 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -183,6 +183,8 @@ pub trait Resolver { ) -> (ast::Path, Res); fn lint_buffer(&mut self) -> &mut lint::LintBuffer; + + fn next_node_id(&mut self) -> NodeId; } type NtToTokenstream = fn(&Nonterminal, &ParseSess, Span) -> TokenStream; @@ -672,7 +674,8 @@ impl<'a> LoweringContext<'a> { } fn next_id(&mut self) -> hir::HirId { - self.lower_node_id(self.sess.next_node_id()) + let node_id = self.resolver.next_node_id(); + self.lower_node_id(node_id) } fn lower_res(&mut self, res: Res) -> Res { @@ -781,7 +784,7 @@ impl<'a> LoweringContext<'a> { hir_name: ParamName, parent_index: DefIndex, ) -> hir::GenericParam { - let node_id = self.sess.next_node_id(); + let node_id = self.resolver.next_node_id(); // Get the name we'll use to make the def-path. Note // that collisions are ok here and this shouldn't @@ -1106,7 +1109,7 @@ impl<'a> LoweringContext<'a> { // Desugar `AssocTy: Bounds` into `AssocTy = impl Bounds`. We do this by // constructing the HIR for `impl bounds...` and then lowering that. - let impl_trait_node_id = self.sess.next_node_id(); + let impl_trait_node_id = self.resolver.next_node_id(); let parent_def_index = self.current_hir_id_owner.last().unwrap().0; self.resolver.definitions().create_def_with_parent( parent_def_index, @@ -1117,9 +1120,10 @@ impl<'a> LoweringContext<'a> { ); self.with_dyn_type_scope(false, |this| { + let node_id = this.resolver.next_node_id(); let ty = this.lower_ty( &Ty { - id: this.sess.next_node_id(), + id: node_id, kind: TyKind::ImplTrait(impl_trait_node_id, bounds.clone()), span: constraint.span, }, @@ -1586,7 +1590,7 @@ impl<'a> LoweringContext<'a> { name, })); - let def_node_id = self.context.sess.next_node_id(); + let def_node_id = self.context.resolver.next_node_id(); let hir_id = self.context.lower_node_id_with_owner(def_node_id, self.opaque_ty_id); self.context.resolver.definitions().create_def_with_parent( @@ -2120,6 +2124,16 @@ impl<'a> LoweringContext<'a> { impl_trait_return_allow: bool, make_ret_async: Option, ) -> P { + debug!("lower_fn_decl(\ + fn_decl: {:?}, \ + in_band_ty_params: {:?}, \ + impl_trait_return_allow: {}, \ + make_ret_async: {:?})", + decl, + in_band_ty_params, + impl_trait_return_allow, + make_ret_async, + ); let lt_mode = if make_ret_async.is_some() { // In `async fn`, argument-position elided lifetimes // must be transformed into fresh generic parameters so that @@ -2412,7 +2426,7 @@ impl<'a> LoweringContext<'a> { hir::FunctionRetTy::Return(P(hir::Ty { kind: opaque_ty_ref, - span, + span: opaque_ty_span, hir_id: self.next_id(), })) } @@ -2522,7 +2536,7 @@ impl<'a> LoweringContext<'a> { hir::Lifetime { hir_id: self.lower_node_id(id), span, - name: name, + name, } } @@ -3234,7 +3248,7 @@ impl<'a> LoweringContext<'a> { Some(id) => (id, "`'_` cannot be used here", "`'_` is a reserved lifetime name"), None => ( - self.sess.next_node_id(), + self.resolver.next_node_id(), "`&` without an explicit lifetime name cannot be used here", "explicit lifetime name needed here", ), @@ -3271,7 +3285,7 @@ impl<'a> LoweringContext<'a> { span, "expected 'implicit elided lifetime not allowed' error", ); - let id = self.sess.next_node_id(); + let id = self.resolver.next_node_id(); self.new_named_lifetime(id, span, hir::LifetimeName::Error) } // `PassThrough` is the normal case. diff --git a/src/librustc/hir/lowering/expr.rs b/src/librustc/hir/lowering/expr.rs index 73db762a64bda..42ce74aedef95 100644 --- a/src/librustc/hir/lowering/expr.rs +++ b/src/librustc/hir/lowering/expr.rs @@ -595,7 +595,7 @@ impl LoweringContext<'_> { }; // `::std::task::Poll::Ready(result) => break result` - let loop_node_id = self.sess.next_node_id(); + let loop_node_id = self.resolver.next_node_id(); let loop_hir_id = self.lower_node_id(loop_node_id); let ready_arm = { let x_ident = Ident::with_dummy_span(sym::result); diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index 7aa1aa8bb514a..4e20f476d85cd 100644 --- a/src/librustc/hir/lowering/item.rs +++ b/src/librustc/hir/lowering/item.rs @@ -522,7 +522,7 @@ impl LoweringContext<'_> { let ident = *ident; let mut path = path.clone(); for seg in &mut path.segments { - seg.id = self.sess.next_node_id(); + seg.id = self.resolver.next_node_id(); } let span = path.span; @@ -599,7 +599,7 @@ impl LoweringContext<'_> { // Give the segments new node-ids since they are being cloned. for seg in &mut prefix.segments { - seg.id = self.sess.next_node_id(); + seg.id = self.resolver.next_node_id(); } // Each `use` import is an item and thus are owners of the diff --git a/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs b/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs index 979815fa7f184..3d98dd8de8b47 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs @@ -43,7 +43,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { /// /// It will later be extended to trait objects. pub(super) fn try_report_anon_anon_conflict(&self) -> Option { - let (span, sub, sup) = self.get_regions(); + let (span, sub, sup) = self.regions(); // Determine whether the sub and sup consist of both anonymous (elided) regions. let anon_reg_sup = self.tcx().is_suitable_region(sup)?; diff --git a/src/librustc/infer/error_reporting/nice_region_error/mod.rs b/src/librustc/infer/error_reporting/nice_region_error/mod.rs index cd003aa8dab70..09cfbf850a57d 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/mod.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/mod.rs @@ -77,7 +77,7 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> { .or_else(|| self.try_report_impl_not_conforming_to_trait()) } - pub fn get_regions(&self) -> (Span, ty::Region<'tcx>, ty::Region<'tcx>) { + pub fn regions(&self) -> (Span, ty::Region<'tcx>, ty::Region<'tcx>) { match (&self.error, self.regions) { (Some(ConcreteFailure(origin, sub, sup)), None) => (origin.span(), sub, sup), (Some(SubSupConflict(_, _, origin, sub, _, sup)), None) => (origin.span(), sub, sup), diff --git a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs index a9a2c15d7d99b..43b0e43a5fd89 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs @@ -9,7 +9,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { /// When given a `ConcreteFailure` for a function with parameters containing a named region and /// an anonymous region, emit an descriptive diagnostic error. pub(super) fn try_report_named_anon_conflict(&self) -> Option> { - let (span, sub, sup) = self.get_regions(); + let (span, sub, sup) = self.regions(); debug!( "try_report_named_anon_conflict(sub={:?}, sup={:?}, error={:?})", diff --git a/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs index 9d405d4ea40c9..01ba748c4e1f9 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -20,8 +20,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { ) = error.clone() { let anon_reg_sup = self.tcx().is_suitable_region(sup_r)?; + let return_ty = self.tcx().return_type_impl_trait(anon_reg_sup.def_id); if sub_r == &RegionKind::ReStatic && - self.tcx().return_type_impl_trait(anon_reg_sup.def_id).is_some() + return_ty.is_some() { let sp = var_origin.span(); let return_sp = sub_origin.span(); @@ -52,17 +53,23 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { }) => name.to_string(), _ => "'_".to_owned(), }; - if let Ok(snippet) = self.tcx().sess.source_map().span_to_snippet(return_sp) { - err.span_suggestion( - return_sp, - &format!( - "you can add a constraint to the return type to make it last \ + let fn_return_span = return_ty.unwrap().1; + if let Ok(snippet) = + self.tcx().sess.source_map().span_to_snippet(fn_return_span) { + // only apply this suggestion onto functions with + // explicit non-desugar'able return. + if fn_return_span.desugaring_kind().is_none() { + err.span_suggestion( + fn_return_span, + &format!( + "you can add a constraint to the return type to make it last \ less than `'static` and match {}", - lifetime, - ), - format!("{} + {}", snippet, lifetime_name), - Applicability::Unspecified, - ); + lifetime, + ), + format!("{} + {}", snippet, lifetime_name), + Applicability::Unspecified, + ); + } } err.emit(); return Some(ErrorReported); diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index eb5654e80a82c..4a14960aa69bd 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1,10 +1,13 @@ //! Contains infrastructure for configuring the compiler, including parsing //! command-line options. +// ignore-tidy-filelength + use crate::lint; use crate::middle::cstore; use crate::session::{early_error, early_warn, Session}; use crate::session::search_paths::SearchPath; +use crate::hir::map as hir_map; use rustc_data_structures::fx::FxHashSet; @@ -440,6 +443,8 @@ top_level_options!( // `true` if we're emitting JSON blobs about each artifact produced // by the compiler. json_artifact_notifications: bool [TRACKED], + + pretty: Option<(PpMode, Option)> [UNTRACKED], } ); @@ -621,6 +626,7 @@ impl Default for Options { remap_path_prefix: Vec::new(), edition: DEFAULT_EDITION, json_artifact_notifications: false, + pretty: None, } } } @@ -2516,6 +2522,8 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { let remap_path_prefix = parse_remap_path_prefix(matches, error_format); + let pretty = parse_pretty(matches, &debugging_opts, error_format); + Options { crate_types, optimize: opt_level, @@ -2546,6 +2554,73 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { remap_path_prefix, edition, json_artifact_notifications, + pretty, + } +} + +fn parse_pretty( + matches: &getopts::Matches, + debugging_opts: &DebuggingOptions, + efmt: ErrorOutputType, +) -> Option<(PpMode, Option)> { + let pretty = if debugging_opts.unstable_options { + matches.opt_default("pretty", "normal").map(|a| { + // stable pretty-print variants only + parse_pretty_inner(efmt, &a, false) + }) + } else { + None + }; + + return if pretty.is_none() { + debugging_opts.unpretty.as_ref().map(|a| { + // extended with unstable pretty-print variants + parse_pretty_inner(efmt, &a, true) + }) + } else { + pretty + }; + + fn parse_pretty_inner( + efmt: ErrorOutputType, + name: &str, + extended: bool, + ) -> (PpMode, Option) { + use PpMode::*; + use PpSourceMode::*; + let mut split = name.splitn(2, '='); + let first = split.next().unwrap(); + let opt_second = split.next(); + let first = match (first, extended) { + ("normal", _) => PpmSource(PpmNormal), + ("identified", _) => PpmSource(PpmIdentified), + ("everybody_loops", true) => PpmSource(PpmEveryBodyLoops), + ("expanded", _) => PpmSource(PpmExpanded), + ("expanded,identified", _) => PpmSource(PpmExpandedIdentified), + ("expanded,hygiene", _) => PpmSource(PpmExpandedHygiene), + ("hir", true) => PpmHir(PpmNormal), + ("hir,identified", true) => PpmHir(PpmIdentified), + ("hir,typed", true) => PpmHir(PpmTyped), + ("hir-tree", true) => PpmHirTree(PpmNormal), + ("mir", true) => PpmMir, + ("mir-cfg", true) => PpmMirCFG, + _ => { + if extended { + early_error(efmt, &format!("argument to `unpretty` must be one of `normal`, \ + `expanded`, `identified`, `expanded,identified`, \ + `expanded,hygiene`, `everybody_loops`, \ + `hir`, `hir,identified`, `hir,typed`, `hir-tree`, \ + `mir` or `mir-cfg`; got {}", + name)); + } else { + early_error(efmt, &format!("argument to `pretty` must be one of `normal`, \ + `expanded`, `identified`, or `expanded,identified`; got {}", + name)); + } + } + }; + let opt_second = opt_second.and_then(|s| s.parse::().ok()); + (first, opt_second) } } @@ -2656,6 +2731,151 @@ impl fmt::Display for CrateType { } } +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum PpSourceMode { + PpmNormal, + PpmEveryBodyLoops, + PpmExpanded, + PpmIdentified, + PpmExpandedIdentified, + PpmExpandedHygiene, + PpmTyped, +} + +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum PpMode { + PpmSource(PpSourceMode), + PpmHir(PpSourceMode), + PpmHirTree(PpSourceMode), + PpmMir, + PpmMirCFG, +} + +impl PpMode { + pub fn needs_ast_map(&self, opt_uii: &Option) -> bool { + use PpMode::*; + use PpSourceMode::*; + match *self { + PpmSource(PpmNormal) | + PpmSource(PpmEveryBodyLoops) | + PpmSource(PpmIdentified) => opt_uii.is_some(), + + PpmSource(PpmExpanded) | + PpmSource(PpmExpandedIdentified) | + PpmSource(PpmExpandedHygiene) | + PpmHir(_) | + PpmHirTree(_) | + PpmMir | + PpmMirCFG => true, + PpmSource(PpmTyped) => panic!("invalid state"), + } + } + + pub fn needs_analysis(&self) -> bool { + use PpMode::*; + match *self { + PpmMir | PpmMirCFG => true, + _ => false, + } + } +} + +#[derive(Clone, Debug)] +pub enum UserIdentifiedItem { + ItemViaNode(ast::NodeId), + ItemViaPath(Vec), +} + +impl FromStr for UserIdentifiedItem { + type Err = (); + fn from_str(s: &str) -> Result { + use UserIdentifiedItem::*; + Ok(s.parse() + .map(ast::NodeId::from_u32) + .map(ItemViaNode) + .unwrap_or_else(|_| ItemViaPath(s.split("::").map(|s| s.to_string()).collect()))) + } +} + +pub enum NodesMatchingUII<'a> { + NodesMatchingDirect(std::option::IntoIter), + NodesMatchingSuffix(Box + 'a>), +} + +impl<'a> Iterator for NodesMatchingUII<'a> { + type Item = ast::NodeId; + + fn next(&mut self) -> Option { + use NodesMatchingUII::*; + match self { + &mut NodesMatchingDirect(ref mut iter) => iter.next(), + &mut NodesMatchingSuffix(ref mut iter) => iter.next(), + } + } + + fn size_hint(&self) -> (usize, Option) { + use NodesMatchingUII::*; + match self { + &NodesMatchingDirect(ref iter) => iter.size_hint(), + &NodesMatchingSuffix(ref iter) => iter.size_hint(), + } + } +} + +impl UserIdentifiedItem { + pub fn reconstructed_input(&self) -> String { + use UserIdentifiedItem::*; + match *self { + ItemViaNode(node_id) => node_id.to_string(), + ItemViaPath(ref parts) => parts.join("::"), + } + } + + pub fn all_matching_node_ids<'a, 'hir>(&'a self, + map: &'a hir_map::Map<'hir>) + -> NodesMatchingUII<'a> { + use UserIdentifiedItem::*; + use NodesMatchingUII::*; + match *self { + ItemViaNode(node_id) => NodesMatchingDirect(Some(node_id).into_iter()), + ItemViaPath(ref parts) => { + NodesMatchingSuffix(Box::new(map.nodes_matching_suffix(&parts))) + } + } + } + + pub fn to_one_node_id(self, + user_option: &str, + sess: &Session, + map: &hir_map::Map<'_>) + -> ast::NodeId { + let fail_because = |is_wrong_because| -> ast::NodeId { + let message = format!("{} needs NodeId (int) or unique path suffix (b::c::d); got \ + {}, which {}", + user_option, + self.reconstructed_input(), + is_wrong_because); + sess.fatal(&message) + }; + + let mut saw_node = ast::DUMMY_NODE_ID; + let mut seen = 0; + for node in self.all_matching_node_ids(map) { + saw_node = node; + seen += 1; + if seen > 1 { + fail_because("does not resolve uniquely"); + } + } + if seen == 0 { + fail_because("does not resolve to any item"); + } + + assert!(seen == 1); + return saw_node; + } +} + /// Command-line arguments passed to the compiler have to be incorporated with /// the dependency tracking system for incremental compilation. This module /// provides some utilities to make this more convenient. diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 403b32df20e10..bab7ab89ce751 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -21,7 +21,6 @@ use errors::{DiagnosticBuilder, DiagnosticId, Applicability}; use errors::emitter::{Emitter, EmitterWriter}; use errors::emitter::HumanReadableErrorType; use errors::annotate_snippet_emitter_writer::{AnnotateSnippetEmitterWriter}; -use syntax::ast::{self, NodeId}; use syntax::edition::Edition; use syntax::expand::allocator::AllocatorKind; use syntax::feature_gate::{self, AttributeType}; @@ -38,7 +37,7 @@ use rustc_data_structures::jobserver; use ::jobserver::Client; use std; -use std::cell::{self, Cell, RefCell}; +use std::cell::{self, RefCell}; use std::env; use std::fmt; use std::io::Write; @@ -127,8 +126,6 @@ pub struct Session { /// Data about code being compiled, gathered during compilation. pub code_stats: Lock, - next_node_id: OneThread>, - /// If `-zfuel=crate=n` is specified, `Some(crate)`. optimization_fuel_crate: Option, @@ -355,21 +352,6 @@ impl Session { self.diagnostic().span_note_without_error(sp, msg) } - pub fn reserve_node_ids(&self, count: usize) -> ast::NodeId { - let id = self.next_node_id.get(); - - match id.as_usize().checked_add(count) { - Some(next) => { - self.next_node_id.set(ast::NodeId::from_usize(next)); - } - None => bug!("input too large; ran out of node-IDs!"), - } - - id - } - pub fn next_node_id(&self) -> NodeId { - self.reserve_node_ids(1) - } pub fn diagnostic(&self) -> &errors::Handler { &self.parse_sess.span_diagnostic } @@ -1187,7 +1169,6 @@ fn build_session_( recursion_limit: Once::new(), type_length_limit: Once::new(), const_eval_stack_frame_limit: 100, - next_node_id: OneThread::new(Cell::new(NodeId::from_u32(1))), allocator_kind: Once::new(), injected_panic_runtime: Once::new(), imported_macro_spans: OneThread::new(RefCell::new(FxHashMap::default())), diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 54c0103422173..23c4ec062ea3f 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -2287,11 +2287,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ); } } - ObligationCauseCode::AssocTypeBound(impl_span, orig) => { - err.span_label(orig, "associated type defined here"); - if let Some(sp) = impl_span { + ObligationCauseCode::AssocTypeBound(ref data) => { + err.span_label(data.original, "associated type defined here"); + if let Some(sp) = data.impl_span { err.span_label(sp, "in this `impl` item"); } + for sp in &data.bounds { + err.span_label(*sp, "restricted in this bound"); + } } } } diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index b8275299562ce..a29d8c66d811d 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -276,7 +276,14 @@ pub enum ObligationCauseCode<'tcx> { /// #[feature(trivial_bounds)] is not enabled TrivialBound, - AssocTypeBound(/*impl*/ Option, /*original*/ Span), + AssocTypeBound(Box), +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct AssocTypeBoundData { + pub impl_span: Option, + pub original: Span, + pub bounds: Vec, } // `ObligationCauseCode` is used a lot. Make sure it doesn't unintentionally get bigger. diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 109e884f8bd16..59f2bb3754803 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -549,7 +549,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> { super::MethodReceiver => Some(super::MethodReceiver), super::BlockTailExpression(id) => Some(super::BlockTailExpression(id)), super::TrivialBound => Some(super::TrivialBound), - super::AssocTypeBound(impl_sp, sp) => Some(super::AssocTypeBound(impl_sp, sp)), + super::AssocTypeBound(ref data) => Some(super::AssocTypeBound(data.clone())), } } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 0906d9ebd8e7f..3985d47abe1dc 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1552,14 +1552,14 @@ impl<'tcx> TyCtxt<'tcx> { return Some(FreeRegionInfo { def_id: suitable_region_binding_scope, boundregion: bound_region, - is_impl_item: is_impl_item, + is_impl_item, }); } pub fn return_type_impl_trait( &self, scope_def_id: DefId, - ) -> Option> { + ) -> Option<(Ty<'tcx>, Span)> { // HACK: `type_of_def_id()` will fail on these (#55796), so return `None`. let hir_id = self.hir().as_local_hir_id(scope_def_id).unwrap(); match self.hir().get(hir_id) { @@ -1580,7 +1580,8 @@ impl<'tcx> TyCtxt<'tcx> { let sig = ret_ty.fn_sig(*self); let output = self.erase_late_bound_regions(&sig.output()); if output.is_impl_trait() { - Some(output) + let fn_decl = self.hir().fn_decl_by_hir_id(hir_id).unwrap(); + Some((output, fn_decl.output.span())) } else { None } diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index 4ea01bf96476a..f9e7a8030a6fc 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -2,9 +2,10 @@ use crate::hir; use crate::hir::def_id::DefId; use crate::infer::InferCtxt; use crate::ty::subst::SubstsRef; -use crate::traits; +use crate::traits::{self, AssocTypeBoundData}; use crate::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable}; use std::iter::once; +use syntax::symbol::{kw, Ident}; use syntax_pos::Span; use crate::middle::lang_items; use crate::mir::interpret::ConstValue; @@ -176,6 +177,23 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { pred: &ty::Predicate<'_>, trait_assoc_items: ty::AssocItemsIterator<'_>, | { + let trait_item = tcx.hir().as_local_hir_id(trait_ref.def_id).and_then(|trait_id| { + tcx.hir().find(trait_id) + }); + let (trait_name, trait_generics) = match trait_item { + Some(hir::Node::Item(hir::Item { + ident, + kind: hir::ItemKind::Trait(.., generics, _, _), + .. + })) | + Some(hir::Node::Item(hir::Item { + ident, + kind: hir::ItemKind::TraitAlias(generics, _), + .. + })) => (Some(ident), Some(generics)), + _ => (None, None), + }; + let item_span = item.map(|i| tcx.sess.source_map().def_span(i.span)); match pred { ty::Predicate::Projection(proj) => { @@ -226,10 +244,11 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { item.ident == trait_assoc_item.ident }).next() { cause.span = impl_item.span; - cause.code = traits::AssocTypeBound( - item_span, - trait_assoc_item.ident.span, - ); + cause.code = traits::AssocTypeBound(Box::new(AssocTypeBoundData { + impl_span: item_span, + original: trait_assoc_item.ident.span, + bounds: vec![], + })); } } } @@ -251,14 +270,13 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { // LL | type Assoc = bool; // | ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool` // - // FIXME: if the obligation comes from the where clause in the `trait`, we - // should point at it: + // If the obligation comes from the where clause in the `trait`, we point at it: // // error[E0277]: the trait bound `bool: Bar` is not satisfied // --> $DIR/point-at-type-on-obligation-failure-2.rs:8:5 // | // | trait Foo where >::Assoc: Bar { - // | -------------------------- obligation set here + // | -------------------------- restricted in this bound // LL | type Assoc; // | ----- associated type defined here // ... @@ -278,11 +296,17 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { .next() .map(|impl_item| (impl_item, trait_assoc_item))) { + let bounds = trait_generics.map(|generics| get_generic_bound_spans( + &generics, + trait_name, + trait_assoc_item.ident, + )).unwrap_or_else(Vec::new); cause.span = impl_item.span; - cause.code = traits::AssocTypeBound( - item_span, - trait_assoc_item.ident.span, - ); + cause.code = traits::AssocTypeBound(Box::new(AssocTypeBoundData { + impl_span: item_span, + original: trait_assoc_item.ident.span, + bounds, + })); } } } @@ -666,3 +690,56 @@ pub fn object_region_bounds<'tcx>( tcx.required_region_bounds(open_ty, predicates) } + +/// Find the span of a generic bound affecting an associated type. +fn get_generic_bound_spans( + generics: &hir::Generics, + trait_name: Option<&Ident>, + assoc_item_name: Ident, +) -> Vec { + let mut bounds = vec![]; + for clause in generics.where_clause.predicates.iter() { + if let hir::WherePredicate::BoundPredicate(pred) = clause { + match &pred.bounded_ty.kind { + hir::TyKind::Path(hir::QPath::Resolved(Some(ty), path)) => { + let mut s = path.segments.iter(); + if let (a, Some(b), None) = (s.next(), s.next(), s.next()) { + if a.map(|s| &s.ident) == trait_name + && b.ident == assoc_item_name + && is_self_path(&ty.kind) + { + // `::Bar` + bounds.push(pred.span); + } + } + } + hir::TyKind::Path(hir::QPath::TypeRelative(ty, segment)) => { + if segment.ident == assoc_item_name { + if is_self_path(&ty.kind) { + // `Self::Bar` + bounds.push(pred.span); + } + } + } + _ => {} + } + } + } + bounds +} + +fn is_self_path(kind: &hir::TyKind) -> bool { + match kind { + hir::TyKind::Path(hir::QPath::Resolved(None, path)) => { + let mut s = path.segments.iter(); + if let (Some(segment), None) = (s.next(), s.next()) { + if segment.ident.name == kw::SelfUpper { + // `type(Self)` + return true; + } + } + } + _ => {} + } + false +} diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index a9e4e6db1c75f..0a803187d49a8 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -27,5 +27,6 @@ rustc_save_analysis = { path = "../librustc_save_analysis" } rustc_codegen_utils = { path = "../librustc_codegen_utils" } rustc_interface = { path = "../librustc_interface" } rustc_serialize = { path = "../libserialize", package = "serialize" } +rustc_resolve = { path = "../librustc_resolve" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_driver/args.rs b/src/librustc_driver/args.rs index 0906d358badd4..339a10f914044 100644 --- a/src/librustc_driver/args.rs +++ b/src/librustc_driver/args.rs @@ -3,22 +3,12 @@ use std::fmt; use std::fs; use std::io; use std::str; -use std::sync::atomic::{AtomicBool, Ordering}; - -static USED_ARGSFILE_FEATURE: AtomicBool = AtomicBool::new(false); - -pub fn used_unstable_argsfile() -> bool { - USED_ARGSFILE_FEATURE.load(Ordering::Relaxed) -} pub fn arg_expand(arg: String) -> Result, Error> { if arg.starts_with("@") { let path = &arg[1..]; let file = match fs::read_to_string(path) { - Ok(file) => { - USED_ARGSFILE_FEATURE.store(true, Ordering::Relaxed); - file - } + Ok(file) => file, Err(ref err) if err.kind() == io::ErrorKind::InvalidData => { return Err(Error::Utf8Error(Some(path.to_string()))); } diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 611b891d99abf..7973a804f1a46 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -25,8 +25,6 @@ extern crate lazy_static; pub extern crate rustc_plugin_impl as plugin; -use pretty::{PpMode, UserIdentifiedItem}; - //use rustc_resolve as resolve; use rustc_save_analysis as save; use rustc_save_analysis::DumpHandler; @@ -285,33 +283,29 @@ pub fn run_compiler( return sess.compile_status(); } - let pretty_info = parse_pretty(sess, &matches); - compiler.parse()?; - if let Some((ppm, opt_uii)) = pretty_info { + if let Some((ppm, opt_uii)) = &sess.opts.pretty { if ppm.needs_ast_map(&opt_uii) { - pretty::visit_crate(sess, &mut compiler.parse()?.peek_mut(), ppm); compiler.global_ctxt()?.peek_mut().enter(|tcx| { let expanded_crate = compiler.expansion()?.take().0; pretty::print_after_hir_lowering( tcx, compiler.input(), &expanded_crate, - ppm, + *ppm, opt_uii.clone(), compiler.output_file().as_ref().map(|p| &**p), ); Ok(()) })?; } else { - let mut krate = compiler.parse()?.take(); - pretty::visit_crate(sess, &mut krate, ppm); + let krate = compiler.parse()?.take(); pretty::print_after_parsing( sess, &compiler.input(), &krate, - ppm, + *ppm, compiler.output_file().as_ref().map(|p| &**p), ); } @@ -470,28 +464,6 @@ fn make_input(free_matches: &[String]) -> Option<(Input, Option, Option } } -fn parse_pretty(sess: &Session, - matches: &getopts::Matches) - -> Option<(PpMode, Option)> { - let pretty = if sess.opts.debugging_opts.unstable_options { - matches.opt_default("pretty", "normal").map(|a| { - // stable pretty-print variants only - pretty::parse_pretty(sess, &a, false) - }) - } else { - None - }; - - if pretty.is_none() { - sess.opts.debugging_opts.unpretty.as_ref().map(|a| { - // extended with unstable pretty-print variants - pretty::parse_pretty(sess, &a, true) - }) - } else { - pretty - } -} - // Whether to stop or continue compilation. #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum Compilation { @@ -1044,12 +1016,6 @@ pub fn handle_options(args: &[String]) -> Option { // (unstable option being used on stable) nightly_options::check_nightly_options(&matches, &config::rustc_optgroups()); - // Late check to see if @file was used without unstable options enabled - if crate::args::used_unstable_argsfile() && !nightly_options::is_unstable_enabled(&matches) { - early_error(ErrorOutputType::default(), - "@path is unstable - use -Z unstable-options to enable its use"); - } - if matches.opt_present("h") || matches.opt_present("help") { // Only show unstable options in --help if we accept unstable options. usage(matches.opt_present("verbose"), nightly_options::is_unstable_enabled(&matches)); diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 0de5b700b4faa..23253dc4dadec 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -5,117 +5,27 @@ use rustc::hir::map as hir_map; use rustc::hir::print as pprust_hir; use rustc::hir::def_id::LOCAL_CRATE; use rustc::session::Session; -use rustc::session::config::Input; +use rustc::session::config::{PpMode, PpSourceMode, UserIdentifiedItem, Input}; use rustc::ty::{self, TyCtxt}; use rustc::util::common::ErrorReported; -use rustc_interface::util::ReplaceBodyWithLoop; use rustc_mir::util::{write_mir_pretty, write_mir_graphviz}; use syntax::ast; -use syntax::mut_visit::MutVisitor; use syntax::print::{pprust}; use syntax_pos::FileName; use std::cell::Cell; use std::fs::File; use std::io::Write; -use std::option; use std::path::Path; -use std::str::FromStr; pub use self::UserIdentifiedItem::*; pub use self::PpSourceMode::*; pub use self::PpMode::*; -use self::NodesMatchingUII::*; use crate::abort_on_err; use crate::source_name; -#[derive(Copy, Clone, PartialEq, Debug)] -pub enum PpSourceMode { - PpmNormal, - PpmEveryBodyLoops, - PpmExpanded, - PpmIdentified, - PpmExpandedIdentified, - PpmExpandedHygiene, - PpmTyped, -} - -#[derive(Copy, Clone, PartialEq, Debug)] -pub enum PpMode { - PpmSource(PpSourceMode), - PpmHir(PpSourceMode), - PpmHirTree(PpSourceMode), - PpmMir, - PpmMirCFG, -} - -impl PpMode { - pub fn needs_ast_map(&self, opt_uii: &Option) -> bool { - match *self { - PpmSource(PpmNormal) | - PpmSource(PpmEveryBodyLoops) | - PpmSource(PpmIdentified) => opt_uii.is_some(), - - PpmSource(PpmExpanded) | - PpmSource(PpmExpandedIdentified) | - PpmSource(PpmExpandedHygiene) | - PpmHir(_) | - PpmHirTree(_) | - PpmMir | - PpmMirCFG => true, - PpmSource(PpmTyped) => panic!("invalid state"), - } - } - - pub fn needs_analysis(&self) -> bool { - match *self { - PpmMir | PpmMirCFG => true, - _ => false, - } - } -} - -pub fn parse_pretty(sess: &Session, - name: &str, - extended: bool) - -> (PpMode, Option) { - let mut split = name.splitn(2, '='); - let first = split.next().unwrap(); - let opt_second = split.next(); - let first = match (first, extended) { - ("normal", _) => PpmSource(PpmNormal), - ("identified", _) => PpmSource(PpmIdentified), - ("everybody_loops", true) => PpmSource(PpmEveryBodyLoops), - ("expanded", _) => PpmSource(PpmExpanded), - ("expanded,identified", _) => PpmSource(PpmExpandedIdentified), - ("expanded,hygiene", _) => PpmSource(PpmExpandedHygiene), - ("hir", true) => PpmHir(PpmNormal), - ("hir,identified", true) => PpmHir(PpmIdentified), - ("hir,typed", true) => PpmHir(PpmTyped), - ("hir-tree", true) => PpmHirTree(PpmNormal), - ("mir", true) => PpmMir, - ("mir-cfg", true) => PpmMirCFG, - _ => { - if extended { - sess.fatal(&format!("argument to `unpretty` must be one of `normal`, \ - `expanded`, `identified`, `expanded,identified`, \ - `expanded,hygiene`, `everybody_loops`, \ - `hir`, `hir,identified`, `hir,typed`, `hir-tree`, \ - `mir` or `mir-cfg`; got {}", - name)); - } else { - sess.fatal(&format!("argument to `pretty` must be one of `normal`, `expanded`, \ - `identified`, or `expanded,identified`; got {}", - name)); - } - } - }; - let opt_second = opt_second.and_then(|s| s.parse::().ok()); - (first, opt_second) -} - // This slightly awkward construction is to allow for each PpMode to @@ -131,76 +41,74 @@ pub fn parse_pretty(sess: &Session, // (The `use_once_payload` is working around the current lack of once // functions in the compiler.) -impl PpSourceMode { - /// Constructs a `PrinterSupport` object and passes it to `f`. - fn call_with_pp_support<'tcx, A, F>( - &self, - sess: &'tcx Session, - tcx: Option>, - f: F, - ) -> A - where - F: FnOnce(&dyn PrinterSupport) -> A, - { - match *self { - PpmNormal | PpmEveryBodyLoops | PpmExpanded => { - let annotation = NoAnn { - sess, - tcx, - }; - f(&annotation) - } +/// Constructs a `PrinterSupport` object and passes it to `f`. +fn call_with_pp_support<'tcx, A, F>( + ppmode: &PpSourceMode, + sess: &'tcx Session, + tcx: Option>, + f: F, +) -> A +where + F: FnOnce(&dyn PrinterSupport) -> A, +{ + match *ppmode { + PpmNormal | PpmEveryBodyLoops | PpmExpanded => { + let annotation = NoAnn { + sess, + tcx, + }; + f(&annotation) + } - PpmIdentified | PpmExpandedIdentified => { - let annotation = IdentifiedAnnotation { - sess, - tcx, - }; - f(&annotation) - } - PpmExpandedHygiene => { - let annotation = HygieneAnnotation { - sess, - }; - f(&annotation) - } - _ => panic!("Should use call_with_pp_support_hir"), + PpmIdentified | PpmExpandedIdentified => { + let annotation = IdentifiedAnnotation { + sess, + tcx, + }; + f(&annotation) + } + PpmExpandedHygiene => { + let annotation = HygieneAnnotation { + sess, + }; + f(&annotation) + } + _ => panic!("Should use call_with_pp_support_hir"), + } +} +fn call_with_pp_support_hir(ppmode: &PpSourceMode, tcx: TyCtxt<'_>, f: F) -> A +where + F: FnOnce(&dyn HirPrinterSupport<'_>, &hir::Crate) -> A, +{ + match *ppmode { + PpmNormal => { + let annotation = NoAnn { + sess: tcx.sess, + tcx: Some(tcx), + }; + f(&annotation, tcx.hir().forest.krate()) } - } - fn call_with_pp_support_hir(&self, tcx: TyCtxt<'_>, f: F) -> A - where - F: FnOnce(&dyn HirPrinterSupport<'_>, &hir::Crate) -> A, - { - match *self { - PpmNormal => { - let annotation = NoAnn { - sess: tcx.sess, - tcx: Some(tcx), - }; - f(&annotation, tcx.hir().forest.krate()) - } - PpmIdentified => { - let annotation = IdentifiedAnnotation { - sess: tcx.sess, - tcx: Some(tcx), - }; + PpmIdentified => { + let annotation = IdentifiedAnnotation { + sess: tcx.sess, + tcx: Some(tcx), + }; + f(&annotation, tcx.hir().forest.krate()) + } + PpmTyped => { + abort_on_err(tcx.analysis(LOCAL_CRATE), tcx.sess); + + let empty_tables = ty::TypeckTables::empty(None); + let annotation = TypedAnnotation { + tcx, + tables: Cell::new(&empty_tables) + }; + tcx.dep_graph.with_ignore(|| { f(&annotation, tcx.hir().forest.krate()) - } - PpmTyped => { - abort_on_err(tcx.analysis(LOCAL_CRATE), tcx.sess); - - let empty_tables = ty::TypeckTables::empty(None); - let annotation = TypedAnnotation { - tcx, - tables: Cell::new(&empty_tables) - }; - tcx.dep_graph.with_ignore(|| { - f(&annotation, tcx.hir().forest.krate()) - }) - } - _ => panic!("Should use call_with_pp_support"), + }) } + _ => panic!("Should use call_with_pp_support"), } } @@ -482,102 +390,6 @@ impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> { } } -#[derive(Clone, Debug)] -pub enum UserIdentifiedItem { - ItemViaNode(ast::NodeId), - ItemViaPath(Vec), -} - -impl FromStr for UserIdentifiedItem { - type Err = (); - fn from_str(s: &str) -> Result { - Ok(s.parse() - .map(ast::NodeId::from_u32) - .map(ItemViaNode) - .unwrap_or_else(|_| ItemViaPath(s.split("::").map(|s| s.to_string()).collect()))) - } -} - -enum NodesMatchingUII<'a> { - NodesMatchingDirect(option::IntoIter), - NodesMatchingSuffix(Box + 'a>), -} - -impl<'a> Iterator for NodesMatchingUII<'a> { - type Item = ast::NodeId; - - fn next(&mut self) -> Option { - match self { - &mut NodesMatchingDirect(ref mut iter) => iter.next(), - &mut NodesMatchingSuffix(ref mut iter) => iter.next(), - } - } - - fn size_hint(&self) -> (usize, Option) { - match self { - &NodesMatchingDirect(ref iter) => iter.size_hint(), - &NodesMatchingSuffix(ref iter) => iter.size_hint(), - } - } -} - -impl UserIdentifiedItem { - fn reconstructed_input(&self) -> String { - match *self { - ItemViaNode(node_id) => node_id.to_string(), - ItemViaPath(ref parts) => parts.join("::"), - } - } - - fn all_matching_node_ids<'a, 'hir>(&'a self, - map: &'a hir_map::Map<'hir>) - -> NodesMatchingUII<'a> { - match *self { - ItemViaNode(node_id) => NodesMatchingDirect(Some(node_id).into_iter()), - ItemViaPath(ref parts) => { - NodesMatchingSuffix(Box::new(map.nodes_matching_suffix(&parts))) - } - } - } - - fn to_one_node_id(self, - user_option: &str, - sess: &Session, - map: &hir_map::Map<'_>) - -> ast::NodeId { - let fail_because = |is_wrong_because| -> ast::NodeId { - let message = format!("{} needs NodeId (int) or unique path suffix (b::c::d); got \ - {}, which {}", - user_option, - self.reconstructed_input(), - is_wrong_because); - sess.fatal(&message) - }; - - let mut saw_node = ast::DUMMY_NODE_ID; - let mut seen = 0; - for node in self.all_matching_node_ids(map) { - saw_node = node; - seen += 1; - if seen > 1 { - fail_because("does not resolve uniquely"); - } - } - if seen == 0 { - fail_because("does not resolve to any item"); - } - - assert!(seen == 1); - return saw_node; - } -} - -pub fn visit_crate(sess: &Session, krate: &mut ast::Crate, ppm: PpMode) { - if let PpmSource(PpmEveryBodyLoops) = ppm { - ReplaceBodyWithLoop::new(sess).visit_crate(krate); - } -} - fn get_source(input: &Input, sess: &Session) -> (String, FileName) { let src_name = source_name(input); let src = String::clone(&sess.source_map() @@ -613,7 +425,7 @@ pub fn print_after_parsing(sess: &Session, if let PpmSource(s) = ppm { // Silently ignores an identified node. let out = &mut out; - s.call_with_pp_support(sess, None, move |annotation| { + call_with_pp_support(&s, sess, None, move |annotation| { debug!("pretty printing source code {:?}", s); let sess = annotation.sess(); *out = pprust::print_crate(sess.source_map(), @@ -658,7 +470,7 @@ pub fn print_after_hir_lowering<'tcx>( // Silently ignores an identified node. let out = &mut out; let src = src.clone(); - s.call_with_pp_support(tcx.sess, Some(tcx), move |annotation| { + call_with_pp_support(&s, tcx.sess, Some(tcx), move |annotation| { debug!("pretty printing source code {:?}", s); let sess = annotation.sess(); *out = pprust::print_crate(sess.source_map(), @@ -674,7 +486,7 @@ pub fn print_after_hir_lowering<'tcx>( (PpmHir(s), None) => { let out = &mut out; let src = src.clone(); - s.call_with_pp_support_hir(tcx, move |annotation, krate| { + call_with_pp_support_hir(&s, tcx, move |annotation, krate| { debug!("pretty printing source code {:?}", s); let sess = annotation.sess(); *out = pprust_hir::print_crate(sess.source_map(), @@ -688,7 +500,7 @@ pub fn print_after_hir_lowering<'tcx>( (PpmHirTree(s), None) => { let out = &mut out; - s.call_with_pp_support_hir(tcx, move |_annotation, krate| { + call_with_pp_support_hir(&s, tcx, move |_annotation, krate| { debug!("pretty printing source code {:?}", s); *out = format!("{:#?}", krate); }); @@ -697,7 +509,7 @@ pub fn print_after_hir_lowering<'tcx>( (PpmHir(s), Some(uii)) => { let out = &mut out; let src = src.clone(); - s.call_with_pp_support_hir(tcx, move |annotation, _| { + call_with_pp_support_hir(&s, tcx, move |annotation, _| { debug!("pretty printing source code {:?}", s); let sess = annotation.sess(); let hir_map = annotation.hir_map().expect("-Z unpretty missing HIR map"); @@ -722,7 +534,7 @@ pub fn print_after_hir_lowering<'tcx>( (PpmHirTree(s), Some(uii)) => { let out = &mut out; - s.call_with_pp_support_hir(tcx, move |_annotation, _krate| { + call_with_pp_support_hir(&s, tcx, move |_annotation, _krate| { debug!("pretty printing source code {:?}", s); for node_id in uii.all_matching_node_ids(tcx.hir()) { let hir_id = tcx.hir().node_to_hir_id(node_id); diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index ce34caee6fab3..04a0b0e761961 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -16,6 +16,7 @@ use rustc::traits; use rustc::util::common::{time, ErrorReported}; use rustc::session::Session; use rustc::session::config::{self, CrateType, Input, OutputFilenames, OutputType}; +use rustc::session::config::{PpMode, PpSourceMode}; use rustc::session::search_paths::PathKind; use rustc_codegen_ssa::back::link::emit_metadata; use rustc_codegen_utils::codegen_backend::CodegenBackend; @@ -394,8 +395,12 @@ fn configure_and_expand_inner<'a>( // If we're actually rustdoc then there's no need to actually compile // anything, so switch everything to just looping - if sess.opts.actually_rustdoc { - util::ReplaceBodyWithLoop::new(sess).visit_crate(&mut krate); + let mut should_loop = sess.opts.actually_rustdoc; + if let Some((PpMode::PpmSource(PpSourceMode::PpmEveryBodyLoops), _)) = sess.opts.pretty { + should_loop |= true; + } + if should_loop { + util::ReplaceBodyWithLoop::new(&mut resolver).visit_crate(&mut krate); } let has_proc_macro_decls = time(sess, "AST validation", || { diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index a74ea4bca39eb..24c441f7289ed 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -18,7 +18,7 @@ use rustc_mir; use rustc_passes; use rustc_plugin; use rustc_privacy; -use rustc_resolve; +use rustc_resolve::{self, Resolver}; use rustc_typeck; use std::env; use std::env::consts::{DLL_PREFIX, DLL_SUFFIX}; @@ -715,18 +715,18 @@ pub fn build_output_filenames( // ambitious form of the closed RFC #1637. See also [#34511]. // // [#34511]: https://github.com/rust-lang/rust/issues/34511#issuecomment-322340401 -pub struct ReplaceBodyWithLoop<'a> { +pub struct ReplaceBodyWithLoop<'a, 'b> { within_static_or_const: bool, nested_blocks: Option>, - sess: &'a Session, + resolver: &'a mut Resolver<'b>, } -impl<'a> ReplaceBodyWithLoop<'a> { - pub fn new(sess: &'a Session) -> ReplaceBodyWithLoop<'a> { +impl<'a, 'b> ReplaceBodyWithLoop<'a, 'b> { + pub fn new(resolver: &'a mut Resolver<'b>) -> ReplaceBodyWithLoop<'a, 'b> { ReplaceBodyWithLoop { within_static_or_const: false, nested_blocks: None, - sess + resolver, } } @@ -792,7 +792,7 @@ impl<'a> ReplaceBodyWithLoop<'a> { } } -impl<'a> MutVisitor for ReplaceBodyWithLoop<'a> { +impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> { fn visit_item_kind(&mut self, i: &mut ast::ItemKind) { let is_const = match i { ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => true, @@ -827,40 +827,40 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a> { fn visit_block(&mut self, b: &mut P) { fn stmt_to_block(rules: ast::BlockCheckMode, s: Option, - sess: &Session) -> ast::Block { + resolver: &mut Resolver<'_>) -> ast::Block { ast::Block { stmts: s.into_iter().collect(), rules, - id: sess.next_node_id(), + id: resolver.next_node_id(), span: syntax_pos::DUMMY_SP, } } - fn block_to_stmt(b: ast::Block, sess: &Session) -> ast::Stmt { + fn block_to_stmt(b: ast::Block, resolver: &mut Resolver<'_>) -> ast::Stmt { let expr = P(ast::Expr { - id: sess.next_node_id(), + id: resolver.next_node_id(), kind: ast::ExprKind::Block(P(b), None), span: syntax_pos::DUMMY_SP, attrs: ThinVec::new(), }); ast::Stmt { - id: sess.next_node_id(), + id: resolver.next_node_id(), kind: ast::StmtKind::Expr(expr), span: syntax_pos::DUMMY_SP, } } - let empty_block = stmt_to_block(BlockCheckMode::Default, None, self.sess); + let empty_block = stmt_to_block(BlockCheckMode::Default, None, self.resolver); let loop_expr = P(ast::Expr { kind: ast::ExprKind::Loop(P(empty_block), None), - id: self.sess.next_node_id(), + id: self.resolver.next_node_id(), span: syntax_pos::DUMMY_SP, attrs: ThinVec::new(), }); let loop_stmt = ast::Stmt { - id: self.sess.next_node_id(), + id: self.resolver.next_node_id(), span: syntax_pos::DUMMY_SP, kind: ast::StmtKind::Expr(loop_expr), }; @@ -878,7 +878,7 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a> { // we put a Some in there earlier with that replace(), so this is valid let new_blocks = self.nested_blocks.take().unwrap(); self.nested_blocks = old_blocks; - stmts.extend(new_blocks.into_iter().map(|b| block_to_stmt(b, &self.sess))); + stmts.extend(new_blocks.into_iter().map(|b| block_to_stmt(b, self.resolver))); } let mut new_block = ast::Block { @@ -892,7 +892,7 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a> { old_blocks.push(new_block); } - stmt_to_block(b.rules, Some(loop_stmt), self.sess) + stmt_to_block(b.rules, Some(loop_stmt), &mut self.resolver) } else { //push `loop {}` onto the end of our fresh block and yield that new_block.stmts.push(loop_stmt); diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs index 7362ae9c638b1..3a202c66a665b 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs @@ -698,10 +698,10 @@ impl<'tcx> RegionInferenceContext<'tcx> { if let (Some(f), Some(ty::RegionKind::ReStatic)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) { - if let Some(ty::TyS { + if let Some((ty::TyS { kind: ty::Opaque(did, substs), .. - }) = infcx + }, _)) = infcx .tcx .is_suitable_region(f) .map(|r| r.def_id) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 4239518b879e3..1ce356d48913d 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -449,7 +449,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { name: kw::PathRoot, span: source.ident.span, }, - id: Some(self.r.session.next_node_id()), + id: Some(self.r.next_node_id()), }); source.ident.name = crate_name; } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 5c996bffb9ad9..e94b544582e80 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -961,6 +961,8 @@ pub struct Resolver<'a> { variant_vis: DefIdMap, lint_buffer: lint::LintBuffer, + + next_node_id: NodeId, } /// Nothing really interesting here; it just provides memory for the rest of the crate. @@ -1078,6 +1080,10 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> { fn lint_buffer(&mut self) -> &mut lint::LintBuffer { &mut self.lint_buffer } + + fn next_node_id(&mut self) -> NodeId { + self.next_node_id() + } } impl<'a> Resolver<'a> { @@ -1226,9 +1232,18 @@ impl<'a> Resolver<'a> { .collect(), variant_vis: Default::default(), lint_buffer: lint::LintBuffer::default(), + next_node_id: NodeId::from_u32(1), } } + pub fn next_node_id(&mut self) -> NodeId { + let next = self.next_node_id.as_usize() + .checked_add(1) + .expect("input too large; ran out of NodeIds"); + self.next_node_id = ast::NodeId::from_usize(next); + self.next_node_id + } + pub fn lint_buffer(&mut self) -> &mut lint::LintBuffer { &mut self.lint_buffer } @@ -2827,9 +2842,9 @@ impl<'a> Resolver<'a> { } } - fn new_ast_path_segment(&self, ident: Ident) -> ast::PathSegment { + fn new_ast_path_segment(&mut self, ident: Ident) -> ast::PathSegment { let mut seg = ast::PathSegment::from_ident(ident); - seg.id = self.session.next_node_id(); + seg.id = self.next_node_id(); seg } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 3d5a7f26eda55..cc811d3b59a41 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -95,7 +95,7 @@ fn fast_print_path(path: &ast::Path) -> Symbol { impl<'a> base::Resolver for Resolver<'a> { fn next_node_id(&mut self) -> NodeId { - self.session.next_node_id() + self.next_node_id() } fn resolve_dollar_crates(&mut self) { diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index e25ba7b178371..25daca9237fd6 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -21,7 +21,7 @@ use std::collections::hash_map::Entry; #[derive(PartialEq)] enum ArgumentType { - Placeholder(String), + Placeholder(&'static str), Count, } @@ -244,7 +244,57 @@ impl<'a, 'b> Context<'a, 'b> { parse::ArgumentNamed(s) => Named(s), }; - let ty = Placeholder(arg.format.ty.to_string()); + let ty = Placeholder(match &arg.format.ty[..] { + "" => "Display", + "?" => "Debug", + "e" => "LowerExp", + "E" => "UpperExp", + "o" => "Octal", + "p" => "Pointer", + "b" => "Binary", + "x" => "LowerHex", + "X" => "UpperHex", + _ => { + let fmtsp = self.fmtsp; + let sp = arg.format.ty_span.map(|sp| fmtsp.from_inner(sp)); + let mut err = self.ecx.struct_span_err( + sp.unwrap_or(fmtsp), + &format!("unknown format trait `{}`", arg.format.ty), + ); + err.note("the only appropriate formatting traits are:\n\ + - ``, which uses the `Display` trait\n\ + - `?`, which uses the `Debug` trait\n\ + - `e`, which uses the `LowerExp` trait\n\ + - `E`, which uses the `UpperExp` trait\n\ + - `o`, which uses the `Octal` trait\n\ + - `p`, which uses the `Pointer` trait\n\ + - `b`, which uses the `Binary` trait\n\ + - `x`, which uses the `LowerHex` trait\n\ + - `X`, which uses the `UpperHex` trait"); + if let Some(sp) = sp { + for (fmt, name) in &[ + ("", "Display"), + ("?", "Debug"), + ("e", "LowerExp"), + ("E", "UpperExp"), + ("o", "Octal"), + ("p", "Pointer"), + ("b", "Binary"), + ("x", "LowerHex"), + ("X", "UpperHex"), + ] { + err.tool_only_span_suggestion( + sp, + &format!("use the `{}` trait", name), + fmt.to_string(), + Applicability::MaybeIncorrect, + ); + } + } + err.emit(); + "" + } + }); self.verify_arg_type(pos, ty); self.curpiece += 1; } @@ -590,6 +640,7 @@ impl<'a, 'b> Context<'a, 'b> { width: parse::CountImplied, width_span: None, ty: arg.format.ty, + ty_span: arg.format.ty_span, }, }; @@ -761,37 +812,8 @@ impl<'a, 'b> Context<'a, 'b> { sp = ecx.with_def_site_ctxt(sp); let arg = ecx.expr_ident(sp, arg); let trait_ = match *ty { - Placeholder(ref tyname) => { - match &tyname[..] { - "" => "Display", - "?" => "Debug", - "e" => "LowerExp", - "E" => "UpperExp", - "o" => "Octal", - "p" => "Pointer", - "b" => "Binary", - "x" => "LowerHex", - "X" => "UpperHex", - _ => { - let mut err = ecx.struct_span_err( - sp, - &format!("unknown format trait `{}`", *tyname), - ); - err.note("the only appropriate formatting traits are:\n\ - - ``, which uses the `Display` trait\n\ - - `?`, which uses the `Debug` trait\n\ - - `e`, which uses the `LowerExp` trait\n\ - - `E`, which uses the `UpperExp` trait\n\ - - `o`, which uses the `Octal` trait\n\ - - `p`, which uses the `Pointer` trait\n\ - - `b`, which uses the `Binary` trait\n\ - - `x`, which uses the `LowerHex` trait\n\ - - `X`, which uses the `UpperHex` trait"); - err.emit(); - return DummyResult::raw_expr(sp, true); - } - } - } + Placeholder(trait_) if trait_ == "" => return DummyResult::raw_expr(sp, true), + Placeholder(trait_) => trait_, Count => { let path = ecx.std_path(&[sym::fmt, sym::ArgumentV1, sym::from_usize]); return ecx.expr_call_global(macsp, path, vec![arg]); diff --git a/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs b/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs index 9360d96f05e17..67b7c78071c37 100644 --- a/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs +++ b/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs @@ -8,4 +8,20 @@ impl Foo for () { type Assoc = bool; //~ ERROR the trait bound `bool: Bar` is not satisfied } +trait Baz where Self::Assoc: Bar { + type Assoc; +} + +impl Baz for () { + type Assoc = bool; //~ ERROR the trait bound `bool: Bar` is not satisfied +} + +trait Bat where ::Assoc: Bar { + type Assoc; +} + +impl Bat for () { + type Assoc = bool; //~ ERROR the trait bound `bool: Bar` is not satisfied +} + fn main() {} diff --git a/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.stderr b/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.stderr index f1a2e343a7ec3..072e9dad062e0 100644 --- a/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.stderr +++ b/src/test/ui/associated-types/point-at-type-on-obligation-failure-2.stderr @@ -9,6 +9,32 @@ LL | impl Foo for () { LL | type Assoc = bool; | ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool` -error: aborting due to previous error +error[E0277]: the trait bound `bool: Bar` is not satisfied + --> $DIR/point-at-type-on-obligation-failure-2.rs:16:5 + | +LL | trait Baz where Self::Assoc: Bar { + | ---------------- restricted in this bound +LL | type Assoc; + | ----- associated type defined here +... +LL | impl Baz for () { + | --------------- in this `impl` item +LL | type Assoc = bool; + | ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool` + +error[E0277]: the trait bound `bool: Bar` is not satisfied + --> $DIR/point-at-type-on-obligation-failure-2.rs:24:5 + | +LL | trait Bat where ::Assoc: Bar { + | ------------------------- restricted in this bound +LL | type Assoc; + | ----- associated type defined here +... +LL | impl Bat for () { + | --------------- in this `impl` item +LL | type Assoc = bool; + | ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool` + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/async-await/issues/issue-62097.rs b/src/test/ui/async-await/issues/issue-62097.rs new file mode 100644 index 0000000000000..ea482d3667e2b --- /dev/null +++ b/src/test/ui/async-await/issues/issue-62097.rs @@ -0,0 +1,19 @@ +// edition:2018 +async fn foo(fun: F) +where + F: FnOnce() + 'static +{ + fun() +} + +struct Struct; + +impl Struct { + pub async fn run_dummy_fn(&self) { //~ ERROR cannot infer + foo(|| self.bar()).await; + } + + pub fn bar(&self) {} +} + +fn main() {} diff --git a/src/test/ui/async-await/issues/issue-62097.stderr b/src/test/ui/async-await/issues/issue-62097.stderr new file mode 100644 index 0000000000000..94afccc06a9e7 --- /dev/null +++ b/src/test/ui/async-await/issues/issue-62097.stderr @@ -0,0 +1,16 @@ +error: cannot infer an appropriate lifetime + --> $DIR/issue-62097.rs:12:31 + | +LL | pub async fn run_dummy_fn(&self) { + | ^^^^^ ...but this borrow... +LL | foo(|| self.bar()).await; + | --- this return type evaluates to the `'static` lifetime... + | +note: ...can't outlive the lifetime `'_` as defined on the method body at 12:31 + --> $DIR/issue-62097.rs:12:31 + | +LL | pub async fn run_dummy_fn(&self) { + | ^ + +error: aborting due to previous error + diff --git a/src/test/ui/async-await/issues/issue-63388-2.stderr b/src/test/ui/async-await/issues/issue-63388-2.stderr index efec160588fc4..7e45d588c6c6c 100644 --- a/src/test/ui/async-await/issues/issue-63388-2.stderr +++ b/src/test/ui/async-await/issues/issue-63388-2.stderr @@ -20,10 +20,6 @@ note: ...can't outlive the lifetime `'_` as defined on the method body at 11:14 | LL | foo: &dyn Foo, bar: &'a dyn Foo | ^ -help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime `'_` as defined on the method body at 11:14 - | -LL | foo + '_ - | error: aborting due to 2 previous errors diff --git a/src/test/ui/if/ifmt-bad-arg.stderr b/src/test/ui/if/ifmt-bad-arg.stderr index 11dcc3a6d232e..d65ffd8506034 100644 --- a/src/test/ui/if/ifmt-bad-arg.stderr +++ b/src/test/ui/if/ifmt-bad-arg.stderr @@ -257,10 +257,10 @@ LL | println!("{} {:07$} {}", 1, 3.2, 4); = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html error: unknown format trait `foo` - --> $DIR/ifmt-bad-arg.rs:86:24 + --> $DIR/ifmt-bad-arg.rs:86:17 | LL | println!("{:foo}", 1); - | ^ + | ^^^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait diff --git a/src/test/ui/if/ifmt-unknown-trait.stderr b/src/test/ui/if/ifmt-unknown-trait.stderr index 7853b5ca0c9a6..459432bf4e426 100644 --- a/src/test/ui/if/ifmt-unknown-trait.stderr +++ b/src/test/ui/if/ifmt-unknown-trait.stderr @@ -1,8 +1,8 @@ error: unknown format trait `notimplemented` - --> $DIR/ifmt-unknown-trait.rs:2:34 + --> $DIR/ifmt-unknown-trait.rs:2:16 | LL | format!("{:notimplemented}", "3"); - | ^^^ + | ^^^^^^^^^^^^^^ | = note: the only appropriate formatting traits are: - ``, which uses the `Display` trait diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr index bce1900ca602c..91075ffbdb605 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -11,10 +11,6 @@ note: ...can't outlive the lifetime `'_` as defined on the method body at 8:26 | LL | async fn f(self: Pin<&Self>) -> impl Clone { self } | ^ -help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime `'_` as defined on the method body at 8:26 - | -LL | async fn f(self: Pin<&Self>) -> impl Clone + '_ { self } - | ^^^^^^^^^^^^^^^ error: aborting due to previous error