From 14d288fe125813b130a6571bbf2ae49c5f247174 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 23 Apr 2022 11:05:31 +0100 Subject: [PATCH 01/25] socket `set_mark` addition. to be able to set a marker/id on the socket for network filtering (iptables/ipfw here) purpose. --- library/std/src/os/unix/net/stream.rs | 6 ++++++ library/std/src/sys/unix/net.rs | 10 ++++++++++ 2 files changed, 16 insertions(+) diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs index 1d6083e66e172..7eb06be3e0907 100644 --- a/library/std/src/os/unix/net/stream.rs +++ b/library/std/src/os/unix/net/stream.rs @@ -424,6 +424,12 @@ impl UnixStream { self.0.passcred() } + #[cfg(any(doc, target_os = "linux", target_os = "freebsd",))] + #[unstable(feature = "unix_set_mark", issue = "none")] + pub fn set_mark(&self, mark: u32) -> io::Result<()> { + self.0.set_mark(mark) + } + /// Returns the value of the `SO_ERROR` option. /// /// # Examples diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs index a1bbc2d87b640..60ee52528c59a 100644 --- a/library/std/src/sys/unix/net.rs +++ b/library/std/src/sys/unix/net.rs @@ -427,6 +427,16 @@ impl Socket { self.0.set_nonblocking(nonblocking) } + #[cfg(target_os = "linux")] + pub fn set_mark(&self, mark: u32) -> io::Result<()> { + setsockopt(self, libc::SOL_SOCKET, libc::SO_MARK, mark as libc::c_int) + } + + #[cfg(target_os = "freebsd")] + pub fn set_mark(&self, mark: u32) -> io::Result<()> { + setsockopt(self, libc::SOL_SOCKET, libc::SO_USER_COOKIE, mark) + } + pub fn take_error(&self) -> io::Result> { let raw: c_int = getsockopt(self, libc::SOL_SOCKET, libc::SO_ERROR)?; if raw == 0 { Ok(None) } else { Ok(Some(io::Error::from_raw_os_error(raw as i32))) } From 48ef00e36f58c1debaec8d5612297b8819f7a690 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Wed, 27 Apr 2022 06:01:05 +0100 Subject: [PATCH 02/25] doc additions --- library/std/src/os/unix/net/datagram.rs | 19 +++++++++++++++++++ library/std/src/os/unix/net/stream.rs | 15 ++++++++++++++- library/std/src/sys/unix/net.rs | 5 +++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs index 8008acfd1c96f..7f5d760481b86 100644 --- a/library/std/src/os/unix/net/datagram.rs +++ b/library/std/src/os/unix/net/datagram.rs @@ -838,6 +838,25 @@ impl UnixDatagram { self.0.passcred() } + /// Set the id of the socket for network filtering purpose + /// and is only a setter. + /// + /// ```no_run + /// #![feature(unix_set_mark)] + /// use std::os::unix::net::UnixDatagram; + /// + /// fn main() -> std::io::Result<()> { + /// let sock = UnixDatagram::unbound()?; + /// sock.set_mark(32 as u32).expect("set_mark function failed"); + /// Ok(()) + /// } + /// ``` + #[cfg(any(doc, target_os = "linux", target_os = "freebsd", target_os = "openbsd",))] + #[unstable(feature = "unix_set_mark", issue = "none")] + pub fn set_mark(&self, mark: u32) -> io::Result<()> { + self.0.set_mark(mark) + } + /// Returns the value of the `SO_ERROR` option. /// /// # Examples diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs index 7eb06be3e0907..7ecb81340ac8d 100644 --- a/library/std/src/os/unix/net/stream.rs +++ b/library/std/src/os/unix/net/stream.rs @@ -424,7 +424,20 @@ impl UnixStream { self.0.passcred() } - #[cfg(any(doc, target_os = "linux", target_os = "freebsd",))] + /// Set the id of the socket for network filtering purpose + /// and is only a setter. + /// + /// ```no_run + /// #![feature(unix_set_mark)] + /// use std::os::unix::net::UnixStream; + /// + /// fn main() -> std::io::Result<()> { + /// let sock = UnixStream::connect("/tmp/sock")?; + /// sock.set_mark(32 as u32).expect("set_mark function failed"); + /// Ok(()) + /// } + /// ``` + #[cfg(any(doc, target_os = "linux", target_os = "freebsd", target_os = "openbsd",))] #[unstable(feature = "unix_set_mark", issue = "none")] pub fn set_mark(&self, mark: u32) -> io::Result<()> { self.0.set_mark(mark) diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs index 60ee52528c59a..30667edafbaef 100644 --- a/library/std/src/sys/unix/net.rs +++ b/library/std/src/sys/unix/net.rs @@ -437,6 +437,11 @@ impl Socket { setsockopt(self, libc::SOL_SOCKET, libc::SO_USER_COOKIE, mark) } + #[cfg(target_os = "openbsd")] + pub fn set_mark(&self, mark: u32) -> io::Result<()> { + setsockopt(self, libc::SOL_SOCKET, libc::SO_RTABLE, mark as libc::c_int) + } + pub fn take_error(&self) -> io::Result> { let raw: c_int = getsockopt(self, libc::SOL_SOCKET, libc::SO_ERROR)?; if raw == 0 { Ok(None) } else { Ok(Some(io::Error::from_raw_os_error(raw as i32))) } From 10f5a19a4deac4a7300ed6bfad11731d451713b0 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Wed, 6 Jul 2022 20:01:25 +0100 Subject: [PATCH 03/25] changes from feedback --- library/std/src/os/unix/net/datagram.rs | 5 ++--- library/std/src/os/unix/net/stream.rs | 5 ++--- library/std/src/sys/unix/net.rs | 20 ++++++++------------ 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs index 7f5d760481b86..02d0f24cd6526 100644 --- a/library/std/src/os/unix/net/datagram.rs +++ b/library/std/src/os/unix/net/datagram.rs @@ -839,7 +839,6 @@ impl UnixDatagram { } /// Set the id of the socket for network filtering purpose - /// and is only a setter. /// /// ```no_run /// #![feature(unix_set_mark)] @@ -847,12 +846,12 @@ impl UnixDatagram { /// /// fn main() -> std::io::Result<()> { /// let sock = UnixDatagram::unbound()?; - /// sock.set_mark(32 as u32).expect("set_mark function failed"); + /// sock.set_mark(32)?; /// Ok(()) /// } /// ``` #[cfg(any(doc, target_os = "linux", target_os = "freebsd", target_os = "openbsd",))] - #[unstable(feature = "unix_set_mark", issue = "none")] + #[unstable(feature = "unix_set_mark", issue = "96467")] pub fn set_mark(&self, mark: u32) -> io::Result<()> { self.0.set_mark(mark) } diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs index 7ecb81340ac8d..ece0f91dad029 100644 --- a/library/std/src/os/unix/net/stream.rs +++ b/library/std/src/os/unix/net/stream.rs @@ -425,7 +425,6 @@ impl UnixStream { } /// Set the id of the socket for network filtering purpose - /// and is only a setter. /// /// ```no_run /// #![feature(unix_set_mark)] @@ -433,12 +432,12 @@ impl UnixStream { /// /// fn main() -> std::io::Result<()> { /// let sock = UnixStream::connect("/tmp/sock")?; - /// sock.set_mark(32 as u32).expect("set_mark function failed"); + /// sock.set_mark(32)?; /// Ok(()) /// } /// ``` #[cfg(any(doc, target_os = "linux", target_os = "freebsd", target_os = "openbsd",))] - #[unstable(feature = "unix_set_mark", issue = "none")] + #[unstable(feature = "unix_set_mark", issue = "96467")] pub fn set_mark(&self, mark: u32) -> io::Result<()> { self.0.set_mark(mark) } diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs index 30667edafbaef..c942689eddf48 100644 --- a/library/std/src/sys/unix/net.rs +++ b/library/std/src/sys/unix/net.rs @@ -427,19 +427,15 @@ impl Socket { self.0.set_nonblocking(nonblocking) } - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "openbsd"))] pub fn set_mark(&self, mark: u32) -> io::Result<()> { - setsockopt(self, libc::SOL_SOCKET, libc::SO_MARK, mark as libc::c_int) - } - - #[cfg(target_os = "freebsd")] - pub fn set_mark(&self, mark: u32) -> io::Result<()> { - setsockopt(self, libc::SOL_SOCKET, libc::SO_USER_COOKIE, mark) - } - - #[cfg(target_os = "openbsd")] - pub fn set_mark(&self, mark: u32) -> io::Result<()> { - setsockopt(self, libc::SOL_SOCKET, libc::SO_RTABLE, mark as libc::c_int) + #[cfg(target_os = "linux")] + let option = libc::SO_MARK; + #[cfg(target_os = "freebsd")] + let option = libc::SO_USER_COOKIE; + #[cfg(target_os = "openbsd")] + let option = libc::SO_RTABLE; + setsockopt(self, libc::SOL_SOCKET, option, mark as libc::c_int) } pub fn take_error(&self) -> io::Result> { From f6efb0b74f286dc806b2fb46b3bd880606533c64 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Thu, 7 Jul 2022 13:45:05 +0100 Subject: [PATCH 04/25] Fix doc build on unsupported oses --- library/std/src/os/unix/net/datagram.rs | 9 ++++++++- library/std/src/os/unix/net/stream.rs | 9 ++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs index 02d0f24cd6526..f758f88d0a370 100644 --- a/library/std/src/os/unix/net/datagram.rs +++ b/library/std/src/os/unix/net/datagram.rs @@ -840,7 +840,14 @@ impl UnixDatagram { /// Set the id of the socket for network filtering purpose /// - /// ```no_run + #[cfg_attr( + any(target_os = "linux", target_os = "freebsd", target_os = "openbsd"), + doc = "```no_run" + )] + #[cfg_attr( + not(any(target_os = "linux", target_os = "freebsd", target_os = "openbsd")), + doc = "```ignore" + )] /// #![feature(unix_set_mark)] /// use std::os::unix::net::UnixDatagram; /// diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs index ece0f91dad029..240c5a77105d5 100644 --- a/library/std/src/os/unix/net/stream.rs +++ b/library/std/src/os/unix/net/stream.rs @@ -426,7 +426,14 @@ impl UnixStream { /// Set the id of the socket for network filtering purpose /// - /// ```no_run + #[cfg_attr( + any(target_os = "linux", target_os = "freebsd", target_os = "openbsd"), + doc = "```no_run" + )] + #[cfg_attr( + not(any(target_os = "linux", target_os = "freebsd", target_os = "openbsd")), + doc = "```ignore" + )] /// #![feature(unix_set_mark)] /// use std::os::unix::net::UnixStream; /// From 313d474b35fd6e60302324f75622d77765e1cbf8 Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Sun, 21 Aug 2022 20:56:00 +0300 Subject: [PATCH 05/25] Migrate OpaqueHiddenType, E0282, E0283, E0284, E0698 --- Cargo.lock | 1 + .../locales/en-US/infer.ftl | 65 ++++ compiler/rustc_error_messages/src/lib.rs | 1 + compiler/rustc_infer/Cargo.toml | 1 + compiler/rustc_infer/src/errors.rs | 187 +++++++++++ .../infer/error_reporting/need_type_info.rs | 312 ++++++++++-------- compiler/rustc_infer/src/lib.rs | 3 + 7 files changed, 440 insertions(+), 130 deletions(-) create mode 100644 compiler/rustc_error_messages/locales/en-US/infer.ftl create mode 100644 compiler/rustc_infer/src/errors.rs diff --git a/Cargo.lock b/Cargo.lock index ebacd32db4fc7..853a2976bc61d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3983,6 +3983,7 @@ dependencies = [ "rustc_macros", "rustc_middle", "rustc_serialize", + "rustc_session", "rustc_span", "rustc_target", "smallvec", diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl new file mode 100644 index 0000000000000..9250363551dbb --- /dev/null +++ b/compiler/rustc_error_messages/locales/en-US/infer.ftl @@ -0,0 +1,65 @@ +infer_opaque_hidden_type = + opaque type's hidden type cannot be another opaque type from the same scope + .label = one of the two opaque types used here has to be outside its defining scope + .opaque_type = opaque type whose hidden type is being assigned + .hidden_type = opaque type being used as hidden type + +infer_type_annotations_needed = {$source_kind -> + [closure] type annotations needed for the closure `{$source_name}` + [normal] type annotations needed for `{$source_name}` + *[other] type annotations needed +} + .label = type must be known at this point + +infer_label_bad = {$bad_kind -> + *[other] cannot infer type + [more_info] cannot infer {$prefix_kind -> + *[type] type for {$prefix} + [const_with_param] the value of const parameter + [const] the value of the constant + } `{$name}`{$has_parent -> + [true] {" "}declared on the {$parent_prefix} `{$parent_name}` + *[false] {""} + } +} + +infer_source_kind_subdiag_let = {$kind -> + [with_pattern] consider giving `{$name}` an explicit type + [closure] consider giving this closure parameter an explicit type + *[other] consider giving this pattern a type +}{$x_kind -> + [has_name] , where the {$prefix_kind -> + *[type] type for {$prefix} + [const_with_param] the value of const parameter + [const] the value of the constant + } `{$arg_name}` is specified + [underscore] , where the placeholders `_` are specified + *[empty] {""} +} + +infer_source_kind_subdiag_generic_label = + cannot infer {$is_type -> + [true] type + *[false] the value + } of the {$is_type -> + [true] type + *[false] const + } {$parent_exists -> + [true] parameter `{$param_name}` declared on the {$parent_prefix} `{$parent_name}` + *[false] parameter {$param_name} + } + +infer_source_kind_subdiag_generic_suggestion = + consider specifying the generic {$arg_count -> + [one] argument + *[other] arguments + } + +infer_source_kind_fully_qualified = + try using a fully qualified path to specify the expected types + +infer_source_kind_closure_return = + try giving this closure an explicit return type + +infer_need_type_info_in_generator = + type inside {$generator_kind} must be known in this context diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 3569c7f063064..a24ab3072925f 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -38,6 +38,7 @@ fluent_messages! { const_eval => "../locales/en-US/const_eval.ftl", expand => "../locales/en-US/expand.ftl", interface => "../locales/en-US/interface.ftl", + infer => "../locales/en-US/infer.ftl", lint => "../locales/en-US/lint.ftl", parser => "../locales/en-US/parser.ftl", passes => "../locales/en-US/passes.ftl", diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml index 02ac83a5e8b25..aced787d67116 100644 --- a/compiler/rustc_infer/Cargo.toml +++ b/compiler/rustc_infer/Cargo.toml @@ -15,6 +15,7 @@ rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } +rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } diff --git a/compiler/rustc_infer/src/errors.rs b/compiler/rustc_infer/src/errors.rs new file mode 100644 index 0000000000000..7bd418ddf5f4c --- /dev/null +++ b/compiler/rustc_infer/src/errors.rs @@ -0,0 +1,187 @@ +use rustc_errors::{fluent, AddSubdiagnostic}; +use rustc_hir::FnRetTy; +use rustc_macros::SessionDiagnostic; +use rustc_span::{BytePos, Span}; + +#[derive(SessionDiagnostic)] +#[diag(infer::opaque_hidden_type)] +pub struct OpaqueHiddenTypeDiag { + #[primary_span] + #[label] + pub span: Span, + #[note(infer::opaque_type)] + pub opaque_type: Span, + #[note(infer::hidden_type)] + pub hidden_type: Span, +} + +#[derive(SessionDiagnostic)] +#[diag(infer::type_annotations_needed, code = "E0282")] +pub struct AnnotationRequired<'a> { + #[primary_span] + pub span: Span, + pub source_kind: &'static str, + pub source_name: &'a str, + #[label] + pub failure_span: Option, + #[subdiagnostic] + pub bad_label: Option>, + #[subdiagnostic] + pub infer_subdiags: Vec>, + #[subdiagnostic] + pub multi_suggestions: Vec>, +} + +// Copy of `AnnotationRequired` for E0283 +#[derive(SessionDiagnostic)] +#[diag(infer::type_annotations_needed, code = "E0283")] +pub struct AmbigousImpl<'a> { + #[primary_span] + pub span: Span, + pub source_kind: &'static str, + pub source_name: &'a str, + #[label] + pub failure_span: Option, + #[subdiagnostic] + pub bad_label: Option>, + #[subdiagnostic] + pub infer_subdiags: Vec>, + #[subdiagnostic] + pub multi_suggestions: Vec>, +} + +// Copy of `AnnotationRequired` for E0284 +#[derive(SessionDiagnostic)] +#[diag(infer::type_annotations_needed, code = "E0284")] +pub struct AmbigousReturn<'a> { + #[primary_span] + pub span: Span, + pub source_kind: &'static str, + pub source_name: &'a str, + #[label] + pub failure_span: Option, + #[subdiagnostic] + pub bad_label: Option>, + #[subdiagnostic] + pub infer_subdiags: Vec>, + #[subdiagnostic] + pub multi_suggestions: Vec>, +} + +#[derive(SessionDiagnostic)] +#[diag(infer::need_type_info_in_generator, code = "E0698")] +pub struct NeedTypeInfoInGenerator<'a> { + #[primary_span] + pub span: Span, + pub generator_kind: String, + #[subdiagnostic] + pub bad_label: InferenceBadError<'a>, +} + +// Used when a better one isn't available +#[derive(SessionSubdiagnostic)] +#[label(infer::label_bad)] +pub struct InferenceBadError<'a> { + #[primary_span] + pub span: Span, + pub bad_kind: &'static str, + pub prefix_kind: &'static str, + pub has_parent: bool, + pub prefix: &'a str, + pub parent_prefix: &'a str, + pub parent_name: String, + pub name: String, +} + +#[derive(SessionSubdiagnostic)] +pub enum SourceKindSubdiag<'a> { + #[suggestion_verbose( + infer::source_kind_subdiag_let, + code = ": {type_name}", + applicability = "has-placeholders" + )] + LetLike { + #[primary_span] + span: Span, + name: String, + type_name: String, + kind: &'static str, + x_kind: &'static str, + prefix_kind: &'static str, + prefix: &'a str, + arg_name: String, + }, + #[label(infer::source_kind_subdiag_generic_label)] + GenericLabel { + #[primary_span] + span: Span, + is_type: bool, + param_name: String, + parent_exists: bool, + parent_prefix: String, + parent_name: String, + }, + #[suggestion_verbose( + infer::source_kind_subdiag_generic_suggestion, + code = "::<{args}>", + applicability = "has-placeholders" + )] + GenericSuggestion { + #[primary_span] + span: Span, + arg_count: usize, + args: String, + }, +} + +// Has to be implemented manually because multipart suggestions are not supported by the derive macro. +// Would be a part of `SourceKindSubdiag` otherwise. +pub enum SourceKindMultiSuggestion<'a> { + FullyQualified { + span: Span, + def_path: String, + adjustment: &'a str, + successor: (&'a str, BytePos), + }, + ClosureReturn { + ty_info: String, + data: &'a FnRetTy<'a>, + should_wrap_expr: Option, + }, +} + +impl AddSubdiagnostic for SourceKindMultiSuggestion<'_> { + fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) { + match self { + Self::FullyQualified { span, def_path, adjustment, successor } => { + let suggestion = vec![ + (span.shrink_to_lo(), format!("{def_path}({adjustment}")), + (span.shrink_to_hi().with_hi(successor.1), successor.0.to_string()), + ]; + diag.multipart_suggestion_verbose( + fluent::infer::source_kind_fully_qualified, + suggestion, + rustc_errors::Applicability::HasPlaceholders, + ); + } + Self::ClosureReturn { ty_info, data, should_wrap_expr } => { + let (arrow, post) = match data { + FnRetTy::DefaultReturn(_) => ("-> ", " "), + _ => ("", ""), + }; + let suggestion = match should_wrap_expr { + Some(end_span) => vec![ + (data.span(), format!("{}{}{}{{ ", arrow, ty_info, post)), + (end_span, " }".to_string()), + ], + None => vec![(data.span(), format!("{}{}{}", arrow, ty_info, post))], + }; + diag.multipart_suggestion_verbose( + fluent::infer::source_kind_closure_return, + suggestion, + rustc_errors::Applicability::HasPlaceholders, + ); + } + } + } +} diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 561d1354edd21..da0035d2519f1 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -1,6 +1,10 @@ +use crate::errors::{ + AmbigousImpl, AmbigousReturn, AnnotationRequired, InferenceBadError, NeedTypeInfoInGenerator, + SourceKindMultiSuggestion, SourceKindSubdiag, +}; use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::infer::InferCtxt; -use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed}; +use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::def::{CtorOf, DefKind, Namespace}; @@ -14,6 +18,7 @@ use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer}; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef}; use rustc_middle::ty::{self, DefIdTree, InferConst}; use rustc_middle::ty::{IsSuggestable, Ty, TyCtxt, TypeckResults}; +use rustc_session::SessionDiagnostic; use rustc_span::symbol::{kw, Ident}; use rustc_span::{BytePos, Span}; use std::borrow::Cow; @@ -66,32 +71,42 @@ pub enum UnderspecifiedArgKind { } impl InferenceDiagnosticsData { - /// Generate a label for a generic argument which can't be inferred. When not - /// much is known about the argument, `use_diag` may be used to describe the - /// labeled value. - fn cannot_infer_msg(&self) -> String { - if self.name == "_" && matches!(self.kind, UnderspecifiedArgKind::Type { .. }) { - return "cannot infer type".to_string(); - } - - let suffix = match &self.parent { - Some(parent) => parent.suffix_string(), - None => String::new(), - }; - - // For example: "cannot infer type for type parameter `T`" - format!("cannot infer {} `{}`{}", self.kind.prefix_string(), self.name, suffix) + fn can_add_more_info(&self) -> bool { + !(self.name == "_" && matches!(self.kind, UnderspecifiedArgKind::Type { .. })) } - fn where_x_is_specified(&self, in_type: Ty<'_>) -> String { + fn where_x_is_kind(&self, in_type: Ty<'_>) -> &'static str { if in_type.is_ty_infer() { - String::new() + "empty" } else if self.name == "_" { // FIXME: Consider specializing this message if there is a single `_` // in the type. - ", where the placeholders `_` are specified".to_string() + "underscore" } else { - format!(", where the {} `{}` is specified", self.kind.prefix_string(), self.name) + "has_name" + } + } + + /// Generate a label for a generic argument which can't be inferred. When not + /// much is known about the argument, `use_diag` may be used to describe the + /// labeled value. + fn make_bad_error(&self, span: Span) -> InferenceBadError<'_> { + let has_parent = self.parent.is_some(); + let bad_kind = if self.can_add_more_info() { "more_info" } else { "other" }; + let (parent_prefix, parent_name) = self + .parent + .as_ref() + .map(|parent| (parent.prefix, parent.name.clone())) + .unwrap_or_default(); + InferenceBadError { + span, + bad_kind, + prefix_kind: self.kind.prefix_kind(), + prefix: self.kind.try_get_prefix().unwrap_or_default(), + name: self.name.clone(), + has_parent, + parent_prefix, + parent_name, } } } @@ -113,18 +128,20 @@ impl InferenceDiagnosticsParentData { fn for_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> Option { Self::for_parent_def_id(tcx, tcx.parent(def_id)) } - - fn suffix_string(&self) -> String { - format!(" declared on the {} `{}`", self.prefix, self.name) - } } impl UnderspecifiedArgKind { - fn prefix_string(&self) -> Cow<'static, str> { + fn prefix_kind(&self) -> &'static str { + match self { + Self::Type { .. } => "type", + Self::Const { is_parameter: true } => "const_with_param", + Self::Const { is_parameter: false } => "const", + } + } + fn try_get_prefix(&self) -> Option<&str> { match self { - Self::Type { prefix } => format!("type for {}", prefix).into(), - Self::Const { is_parameter: true } => "the value of const parameter".into(), - Self::Const { is_parameter: false } => "the value of the constant".into(), + Self::Type { prefix } => Some(prefix.as_ref()), + Self::Const { .. } => None, } } } @@ -303,11 +320,44 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { arg_data: InferenceDiagnosticsData, error_code: TypeAnnotationNeeded, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - let error_code = error_code.into(); - let mut err = - self.tcx.sess.struct_span_err_with_code(span, "type annotations needed", error_code); - err.span_label(span, arg_data.cannot_infer_msg()); - err + let source_kind = "other"; + let source_name = ""; + let failure_span = None; + let infer_subdiags = Vec::new(); + let multi_suggestions = Vec::new(); + let bad_label = Some(arg_data.make_bad_error(span)); + match error_code { + TypeAnnotationNeeded::E0282 => AnnotationRequired { + span, + source_kind, + source_name, + failure_span, + infer_subdiags, + multi_suggestions, + bad_label, + } + .into_diagnostic(&self.tcx.sess.parse_sess), + TypeAnnotationNeeded::E0283 => AmbigousImpl { + span, + source_kind, + source_name, + failure_span, + infer_subdiags, + multi_suggestions, + bad_label, + } + .into_diagnostic(&self.tcx.sess.parse_sess), + TypeAnnotationNeeded::E0284 => AmbigousReturn { + span, + source_kind, + source_name, + failure_span, + infer_subdiags, + multi_suggestions, + bad_label, + } + .into_diagnostic(&self.tcx.sess.parse_sess), + } } pub fn emit_inference_failure_err( @@ -340,48 +390,39 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { return self.bad_inference_failure_err(failure_span, arg_data, error_code) }; - let error_code = error_code.into(); - let mut err = self.tcx.sess.struct_span_err_with_code( - span, - &format!("type annotations needed{}", kind.ty_msg(self)), - error_code, - ); - - if should_label_span && !failure_span.overlaps(span) { - err.span_label(failure_span, "type must be known at this point"); - } + let (source_kind, name) = kind.ty_localized_msg(self); + let failure_span = if should_label_span && !failure_span.overlaps(span) { + Some(failure_span) + } else { + None + }; + let mut infer_subdiags = Vec::new(); + let mut multi_suggestions = Vec::new(); match kind { InferSourceKind::LetBinding { insert_span, pattern_name, ty } => { - let suggestion_msg = if let Some(name) = pattern_name { - format!( - "consider giving `{}` an explicit type{}", - name, - arg_data.where_x_is_specified(ty) - ) - } else { - format!( - "consider giving this pattern a type{}", - arg_data.where_x_is_specified(ty) - ) - }; - err.span_suggestion_verbose( - insert_span, - &suggestion_msg, - format!(": {}", ty_to_string(self, ty)), - Applicability::HasPlaceholders, - ); + infer_subdiags.push(SourceKindSubdiag::LetLike { + span: insert_span, + name: pattern_name.map(|name| name.to_string()).unwrap_or_else(String::new), + x_kind: arg_data.where_x_is_kind(ty), + prefix_kind: arg_data.kind.prefix_kind(), + prefix: arg_data.kind.try_get_prefix().unwrap_or_default(), + arg_name: arg_data.name, + kind: if pattern_name.is_some() { "with_pattern" } else { "other" }, + type_name: ty_to_string(self, ty), + }); } InferSourceKind::ClosureArg { insert_span, ty } => { - err.span_suggestion_verbose( - insert_span, - &format!( - "consider giving this closure parameter an explicit type{}", - arg_data.where_x_is_specified(ty) - ), - format!(": {}", ty_to_string(self, ty)), - Applicability::HasPlaceholders, - ); + infer_subdiags.push(SourceKindSubdiag::LetLike { + span: insert_span, + name: String::new(), + x_kind: arg_data.where_x_is_kind(ty), + prefix_kind: arg_data.kind.prefix_kind(), + prefix: arg_data.kind.try_get_prefix().unwrap_or_default(), + arg_name: arg_data.name, + kind: "closure", + type_name: ty_to_string(self, ty), + }); } InferSourceKind::GenericArg { insert_span, @@ -393,19 +434,20 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let generics = self.tcx.generics_of(generics_def_id); let is_type = matches!(arg.unpack(), GenericArgKind::Type(_)); - let cannot_infer_msg = format!( - "cannot infer {} of the {} parameter `{}`{}", - if is_type { "type" } else { "the value" }, - if is_type { "type" } else { "const" }, - generics.params[argument_index].name, - // We use the `generics_def_id` here, as even when suggesting `None::`, - // the type parameter `T` was still declared on the enum, not on the - // variant. + let (parent_exists, parent_prefix, parent_name) = InferenceDiagnosticsParentData::for_parent_def_id(self.tcx, generics_def_id) - .map_or(String::new(), |parent| parent.suffix_string()), - ); + .map_or((false, String::new(), String::new()), |parent| { + (true, parent.prefix.to_string(), parent.name) + }); - err.span_label(span, cannot_infer_msg); + infer_subdiags.push(SourceKindSubdiag::GenericLabel { + span, + is_type, + param_name: generics.params[argument_index].name.to_string(), + parent_exists, + parent_prefix, + parent_name, + }); let args = fmt_printer(self, Namespace::TypeNS) .comma_sep(generic_args.iter().copied().map(|arg| { @@ -435,15 +477,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .unwrap() .into_buffer(); - err.span_suggestion_verbose( - insert_span, - &format!( - "consider specifying the generic argument{}", - pluralize!(generic_args.len()), - ), - format!("::<{}>", args), - Applicability::HasPlaceholders, - ); + infer_subdiags.push(SourceKindSubdiag::GenericSuggestion { + span: insert_span, + arg_count: generic_args.len(), + args, + }); } InferSourceKind::FullyQualifiedMethodCall { receiver, successor, substs, def_id } => { let printer = fmt_printer(self, Namespace::ValueNS); @@ -468,37 +506,54 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { _ => "", }; - let suggestion = vec![ - (receiver.span.shrink_to_lo(), format!("{def_path}({adjustment}")), - (receiver.span.shrink_to_hi().with_hi(successor.1), successor.0.to_string()), - ]; - err.multipart_suggestion_verbose( - "try using a fully qualified path to specify the expected types", - suggestion, - Applicability::HasPlaceholders, - ); + multi_suggestions.push(SourceKindMultiSuggestion::FullyQualified { + span: receiver.span, + def_path, + adjustment, + successor, + }); } InferSourceKind::ClosureReturn { ty, data, should_wrap_expr } => { - let ret = ty_to_string(self, ty); - let (arrow, post) = match data { - FnRetTy::DefaultReturn(_) => ("-> ", " "), - _ => ("", ""), - }; - let suggestion = match should_wrap_expr { - Some(end_span) => vec![ - (data.span(), format!("{}{}{}{{ ", arrow, ret, post)), - (end_span, " }".to_string()), - ], - None => vec![(data.span(), format!("{}{}{}", arrow, ret, post))], - }; - err.multipart_suggestion_verbose( - "try giving this closure an explicit return type", - suggestion, - Applicability::HasPlaceholders, - ); + let ty_info = ty_to_string(self, ty); + multi_suggestions.push(SourceKindMultiSuggestion::ClosureReturn { + ty_info, + data, + should_wrap_expr, + }); + } + } + match error_code { + TypeAnnotationNeeded::E0282 => AnnotationRequired { + span, + source_kind, + source_name: &name, + failure_span, + infer_subdiags, + multi_suggestions, + bad_label: None, } + .into_diagnostic(&self.tcx.sess.parse_sess), + TypeAnnotationNeeded::E0283 => AmbigousImpl { + span, + source_kind, + source_name: &name, + failure_span, + infer_subdiags, + multi_suggestions, + bad_label: None, + } + .into_diagnostic(&self.tcx.sess.parse_sess), + TypeAnnotationNeeded::E0284 => AmbigousReturn { + span, + source_kind, + source_name: &name, + failure_span, + infer_subdiags, + multi_suggestions, + bad_label: None, + } + .into_diagnostic(&self.tcx.sess.parse_sess), } - err } pub fn need_type_info_err_in_generator( @@ -510,15 +565,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let ty = self.resolve_vars_if_possible(ty); let data = self.extract_inference_diagnostics_data(ty.into(), None); - let mut err = struct_span_err!( - self.tcx.sess, + NeedTypeInfoInGenerator { + bad_label: data.make_bad_error(span), span, - E0698, - "type inside {} must be known in this context", - kind, - ); - err.span_label(span, data.cannot_infer_msg()); - err + generator_kind: kind.to_string(), + } + .into_diagnostic(&self.tcx.sess.parse_sess) } } @@ -579,22 +631,22 @@ impl<'tcx> InferSource<'tcx> { } impl<'tcx> InferSourceKind<'tcx> { - fn ty_msg(&self, infcx: &InferCtxt<'_, 'tcx>) -> String { + fn ty_localized_msg(&self, infcx: &InferCtxt<'_, 'tcx>) -> (&'static str, String) { match *self { InferSourceKind::LetBinding { ty, .. } | InferSourceKind::ClosureArg { ty, .. } | InferSourceKind::ClosureReturn { ty, .. } => { if ty.is_closure() { - format!(" for the closure `{}`", closure_as_fn_str(infcx, ty)) + ("closure", closure_as_fn_str(infcx, ty)) } else if !ty.is_ty_infer() { - format!(" for `{}`", ty_to_string(infcx, ty)) + ("normal", ty_to_string(infcx, ty)) } else { - String::new() + ("other", String::new()) } } // FIXME: We should be able to add some additional info here. InferSourceKind::GenericArg { .. } - | InferSourceKind::FullyQualifiedMethodCall { .. } => String::new(), + | InferSourceKind::FullyQualifiedMethodCall { .. } => ("other", String::new()), } } } diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index 1c515f5ee5722..2c1d339b578fe 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -23,6 +23,8 @@ #![feature(never_type)] #![feature(try_blocks)] #![recursion_limit = "512"] // For rustdoc +// #![deny(rustc::untranslatable_diagnostic)] +// #![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_macros; @@ -34,5 +36,6 @@ extern crate tracing; #[macro_use] extern crate rustc_middle; +mod errors; pub mod infer; pub mod traits; From 7e4f4337203b247bdbfbb0661e59ab1aa3bee3f1 Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Sun, 21 Aug 2022 22:39:46 +0300 Subject: [PATCH 06/25] Actually migrate OpaqueHiddenType --- .../rustc_infer/src/infer/opaque_types.rs | 22 +++++-------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index e579afbf38954..233a5004a3931 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -1,3 +1,4 @@ +use crate::errors::OpaqueHiddenTypeDiag; use crate::infer::{DefiningAnchor, InferCtxt, InferOk}; use crate::traits; use hir::def_id::{DefId, LocalDefId}; @@ -153,22 +154,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { if let Some(OpaqueTyOrigin::TyAlias) = did2.as_local().and_then(|did2| self.opaque_type_origin(did2, cause.span)) { - self.tcx - .sess - .struct_span_err( - cause.span, - "opaque type's hidden type cannot be another opaque type from the same scope", - ) - .span_label(cause.span, "one of the two opaque types used here has to be outside its defining scope") - .span_note( - self.tcx.def_span(def_id), - "opaque type whose hidden type is being assigned", - ) - .span_note( - self.tcx.def_span(did2), - "opaque type being used as hidden type", - ) - .emit(); + self.tcx.sess.emit_err(OpaqueHiddenTypeDiag { + span: cause.span, + hidden_type: self.tcx.def_span(did2), + opaque_type: self.tcx.def_span(def_id), + }); } } Some(self.register_hidden_type( From 3f6cb475f7aa1f4475fdb313316a7df644113376 Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Mon, 22 Aug 2022 00:17:46 +0300 Subject: [PATCH 07/25] Use GeneratorKind::descr() instead of it's Display impl Those are basically the same but the first one seems to fit better --- compiler/rustc_infer/src/errors.rs | 2 +- .../rustc_infer/src/infer/error_reporting/need_type_info.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_infer/src/errors.rs b/compiler/rustc_infer/src/errors.rs index 7bd418ddf5f4c..51993f37bb3a7 100644 --- a/compiler/rustc_infer/src/errors.rs +++ b/compiler/rustc_infer/src/errors.rs @@ -73,7 +73,7 @@ pub struct AmbigousReturn<'a> { pub struct NeedTypeInfoInGenerator<'a> { #[primary_span] pub span: Span, - pub generator_kind: String, + pub generator_kind: &'static str, #[subdiagnostic] pub bad_label: InferenceBadError<'a>, } diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index da0035d2519f1..daf64aeb053d3 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -568,7 +568,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { NeedTypeInfoInGenerator { bad_label: data.make_bad_error(span), span, - generator_kind: kind.to_string(), + generator_kind: kind.descr(), } .into_diagnostic(&self.tcx.sess.parse_sess) } From f50d1713fd4aab1ff9d160e9fa4b20cd2f71e68a Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Tue, 23 Aug 2022 13:48:14 +0300 Subject: [PATCH 08/25] Migrate note_region_origin function --- .../locales/en-US/infer.ftl | 43 ++++++++ compiler/rustc_infer/src/errors.rs | 64 ++++++++++- .../src/infer/error_reporting/mod.rs | 18 ++++ .../src/infer/error_reporting/note.rs | 101 +++++++++--------- 4 files changed, 173 insertions(+), 53 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl index 9250363551dbb..770eaa62b4118 100644 --- a/compiler/rustc_error_messages/locales/en-US/infer.ftl +++ b/compiler/rustc_error_messages/locales/en-US/infer.ftl @@ -61,5 +61,48 @@ infer_source_kind_fully_qualified = infer_source_kind_closure_return = try giving this closure an explicit return type +# generator_kind may need to be translated infer_need_type_info_in_generator = type inside {$generator_kind} must be known in this context + + +infer_subtype = ...so that the {$requirement -> + [method_compat] method type is compatible with trait + [type_compat] associated type is compatible with trait + [const_compat] const is compatible with trait + [expr_assignable] expression is assignable + [if_else_different] `if` and `else` have incompatible types + [no_else] `if` missing an `else` returns `()` + [fn_main_correct_type] `main` function has the correct type + [fn_start_correct_type] #[start]` function has the correct type + [intristic_correct_type] intrinsic has the correct type + [method_correct_type] method receiver has the correct type + *[other] types are compatible +} +infer_subtype_2 = ...so that {$requirement -> + [method_compat] method type is compatible with trait + [type_compat] associated type is compatible with trait + [const_compat] const is compatible with trait + [expr_assignable] expression is assignable + [if_else_different] `if` and `else` have incompatible types + [no_else] `if` missing an `else` returns `()` + [fn_main_correct_type] `main` function has the correct type + [fn_start_correct_type] #[start]` function has the correct type + [intristic_correct_type] intrinsic has the correct type + [method_correct_type] method receiver has the correct type + *[other] types are compatible +} + +infer_reborrow = ...so that reference does not outlive borrowed content +infer_reborrow_upvar = ...so that closure can access `{$name}` +infer_relate_object_bound = ...so that it can be closed over into an object +infer_data_borrowed = ...so that the type `{$name}` is not borrowed for too long +infer_reference_outlives_referent = ...so that the reference type `{$name}` does not outlive the data it points at +infer_relate_param_bound = ...so that the type `{$name}` will meet its required lifetime bounds{$continues -> +[true] ... +*[false] {""} +} +infer_relate_param_bound_2 = ...that is required by this bound +infer_relate_region_param_bound = ...so that the declared lifetime parameter bounds are satisfied +infer_compare_impl_item_obligation = ...so that the definition in impl matches the definition from the trait + diff --git a/compiler/rustc_infer/src/errors.rs b/compiler/rustc_infer/src/errors.rs index 51993f37bb3a7..1db8763e4996d 100644 --- a/compiler/rustc_infer/src/errors.rs +++ b/compiler/rustc_infer/src/errors.rs @@ -1,4 +1,4 @@ -use rustc_errors::{fluent, AddSubdiagnostic}; +use rustc_errors::{fluent, AddSubdiagnostic, DiagnosticMessage, DiagnosticStyledString}; use rustc_hir::FnRetTy; use rustc_macros::SessionDiagnostic; use rustc_span::{BytePos, Span}; @@ -185,3 +185,65 @@ impl AddSubdiagnostic for SourceKindMultiSuggestion<'_> { } } } + +pub enum RegionOriginNote<'a> { + Plain { + span: Span, + msg: DiagnosticMessage, + }, + WithName { + span: Span, + msg: DiagnosticMessage, + name: &'a str, + continues: bool, + }, + WithRequirement { + span: Span, + requirement: &'static str, + expected_found: Option<(DiagnosticStyledString, DiagnosticStyledString)>, + }, +} + +impl AddSubdiagnostic for RegionOriginNote<'_> { + fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) { + let mut label_or_note = |span, msg: DiagnosticMessage| { + let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count(); + let expanded_sub_count = diag.children.iter().filter(|d| !d.span.is_dummy()).count(); + let span_is_primary = diag.span.primary_spans().iter().all(|&sp| sp == span); + if span_is_primary && sub_count == 0 && expanded_sub_count == 0 { + diag.span_label(span, msg); + } else if span_is_primary && expanded_sub_count == 0 { + diag.note(msg); + } else { + diag.span_note(span, msg); + } + }; + match self { + RegionOriginNote::Plain { span, msg } => { + label_or_note(span, msg); + } + RegionOriginNote::WithName { span, msg, name, continues } => { + label_or_note(span, msg); + diag.set_arg("name", name); + diag.set_arg("continues", continues); + } + RegionOriginNote::WithRequirement { + span, + requirement, + expected_found: Some((expected, found)), + } => { + label_or_note(span, fluent::infer::subtype); + diag.set_arg("requirement", requirement); + + diag.note_expected_found(&"", expected, &"", found); + } + RegionOriginNote::WithRequirement { span, requirement, expected_found: None } => { + // FIXME: this really should be handled at some earlier stage. Our + // handling of region checking when type errors are present is + // *terrible*. + label_or_note(span, fluent::infer::subtype_2); + diag.set_arg("requirement", requirement); + } + }; + } +} diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 59ea1f3f9de45..13951326665d7 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2811,6 +2811,7 @@ pub enum FailureCode { pub trait ObligationCauseExt<'tcx> { fn as_failure_code(&self, terr: TypeError<'tcx>) -> FailureCode; fn as_requirement_str(&self) -> &'static str; + fn as_requirement_localised(&self) -> &'static str; } impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> { @@ -2879,6 +2880,23 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> { _ => "types are compatible", } } + + fn as_requirement_localised(&self) -> &'static str { + use crate::traits::ObligationCauseCode::*; + match self.code() { + CompareImplItemObligation { kind: ty::AssocKind::Fn, .. } => "method_compat", + CompareImplItemObligation { kind: ty::AssocKind::Type, .. } => "type_compat", + CompareImplItemObligation { kind: ty::AssocKind::Const, .. } => "const_compat", + ExprAssignable => "expr_assignable", + IfExpression { .. } => "if_else_different", + IfExpressionWithNoElse => "no_else", + MainFunctionType => "fn_main_correct_type", + StartFunctionType => "fn_start_correct_type", + IntrinsicType => "intristic_correct_type", + MethodReceiver => "method_correct_type", + _ => "other", + } + } } /// This is a bare signal of what kind of type we're dealing with. `ty::TyKind` tracks diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index 8c465b0876002..36efbd6824a77 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -1,13 +1,17 @@ +use crate::errors::RegionOriginNote; use crate::infer::error_reporting::{note_and_explain_region, ObligationCauseExt}; use crate::infer::{self, InferCtxt, SubregionOrigin}; -use rustc_errors::{struct_span_err, Diagnostic, DiagnosticBuilder, ErrorGuaranteed}; +use rustc_errors::{ + fluent, struct_span_err, AddSubdiagnostic, Diagnostic, DiagnosticBuilder, DiagnosticMessage, + ErrorGuaranteed, +}; use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::{self, Region}; impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub(super) fn note_region_origin(&self, err: &mut Diagnostic, origin: &SubregionOrigin<'tcx>) { - let mut label_or_note = |span, msg: &str| { + let mut label_or_note = |span, msg: DiagnosticMessage| { let sub_count = err.children.iter().filter(|d| d.span.is_dummy()).count(); let expanded_sub_count = err.children.iter().filter(|d| !d.span.is_dummy()).count(); let span_is_primary = err.span.primary_spans().iter().all(|&sp| sp == span); @@ -20,77 +24,70 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } }; match *origin { - infer::Subtype(ref trace) => { - if let Some((expected, found)) = self.values_str(trace.values) { - label_or_note( - trace.cause.span, - &format!("...so that the {}", trace.cause.as_requirement_str()), - ); - - err.note_expected_found(&"", expected, &"", found); - } else { - // FIXME: this really should be handled at some earlier stage. Our - // handling of region checking when type errors are present is - // *terrible*. - - label_or_note( - trace.cause.span, - &format!("...so that {}", trace.cause.as_requirement_str()), - ); - } + infer::Subtype(ref trace) => RegionOriginNote::WithRequirement { + span: trace.cause.span, + requirement: trace.cause.as_requirement_localised(), + expected_found: self.values_str(trace.values), } + .add_to_diagnostic(err), infer::Reborrow(span) => { - label_or_note(span, "...so that reference does not outlive borrowed content"); + label_or_note(span, fluent::infer::reborrow); + RegionOriginNote::Plain { span, msg: fluent::infer::reborrow } + .add_to_diagnostic(err) } infer::ReborrowUpvar(span, ref upvar_id) => { let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id); - label_or_note(span, &format!("...so that closure can access `{}`", var_name)); + RegionOriginNote::WithName { + span, + msg: fluent::infer::reborrow, + name: &var_name.to_string(), + continues: false, + } + .add_to_diagnostic(err); } infer::RelateObjectBound(span) => { - label_or_note(span, "...so that it can be closed over into an object"); + label_or_note(span, fluent::infer::relate_object_bound); + RegionOriginNote::Plain { span, msg: fluent::infer::relate_object_bound } + .add_to_diagnostic(err); } infer::DataBorrowed(ty, span) => { - label_or_note( + RegionOriginNote::WithName { span, - &format!( - "...so that the type `{}` is not borrowed for too long", - self.ty_to_string(ty) - ), - ); + msg: fluent::infer::data_borrowed, + name: &self.ty_to_string(ty), + continues: false, + } + .add_to_diagnostic(err); } infer::ReferenceOutlivesReferent(ty, span) => { - label_or_note( + RegionOriginNote::WithName { span, - &format!( - "...so that the reference type `{}` does not outlive the data it points at", - self.ty_to_string(ty) - ), - ); + msg: fluent::infer::reference_outlives_referent, + name: &self.ty_to_string(ty), + continues: false, + } + .add_to_diagnostic(err); } - infer::RelateParamBound(span, t, opt_span) => { - label_or_note( + infer::RelateParamBound(span, ty, opt_span) => { + RegionOriginNote::WithName { span, - &format!( - "...so that the type `{}` will meet its required lifetime bounds{}", - self.ty_to_string(t), - if opt_span.is_some() { "..." } else { "" }, - ), - ); + msg: fluent::infer::relate_param_bound, + name: &self.ty_to_string(ty), + continues: opt_span.is_some(), + } + .add_to_diagnostic(err); if let Some(span) = opt_span { - err.span_note(span, "...that is required by this bound"); + RegionOriginNote::Plain { span, msg: fluent::infer::relate_param_bound_2 } + .add_to_diagnostic(err); } } infer::RelateRegionParamBound(span) => { - label_or_note( - span, - "...so that the declared lifetime parameter bounds are satisfied", - ); + RegionOriginNote::Plain { span, msg: fluent::infer::relate_region_param_bound } + .add_to_diagnostic(err); } infer::CompareImplItemObligation { span, .. } => { - label_or_note( - span, - "...so that the definition in impl matches the definition from the trait", - ); + RegionOriginNote::Plain { span, msg: fluent::infer::compare_impl_item_obligation } + .add_to_diagnostic(err); } infer::CheckAssociatedTypeBounds { ref parent, .. } => { self.note_region_origin(err, &parent); From cb4cd7366415deb659641edcff695aa2e4ffb105 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 22 Aug 2022 21:25:03 -0400 Subject: [PATCH 09/25] extra sanity check against consts pointing to mutable memory --- .../src/interpret/validity.rs | 72 ++++++++++++------- .../const-points-to-static.32bit.stderr | 2 +- .../const-points-to-static.64bit.stderr | 2 +- .../const_refers_to_static2.32bit.stderr | 4 +- .../const_refers_to_static2.64bit.stderr | 4 +- ..._refers_to_static_cross_crate.32bit.stderr | 4 +- ..._refers_to_static_cross_crate.64bit.stderr | 4 +- 7 files changed, 55 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index f1b1855c3ec74..0e60f0c7ef131 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -8,6 +8,7 @@ use std::convert::TryFrom; use std::fmt::Write; use std::num::NonZeroUsize; +use rustc_ast::Mutability; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_middle::mir::interpret::InterpError; @@ -411,34 +412,51 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' // Proceed recursively even for ZST, no reason to skip them! // `!` is a ZST and we want to validate it. if let Ok((alloc_id, _offset, _prov)) = self.ecx.ptr_try_get_alloc_id(place.ptr) { - // Special handling for pointers to statics (irrespective of their type). + // Let's see what kind of memory this points to. let alloc_kind = self.ecx.tcx.try_get_global_alloc(alloc_id); - if let Some(GlobalAlloc::Static(did)) = alloc_kind { - assert!(!self.ecx.tcx.is_thread_local_static(did)); - assert!(self.ecx.tcx.is_static(did)); - if matches!( - self.ctfe_mode, - Some(CtfeValidationMode::Const { allow_static_ptrs: false, .. }) - ) { - // See const_eval::machine::MemoryExtra::can_access_statics for why - // this check is so important. - // This check is reachable when the const just referenced the static, - // but never read it (so we never entered `before_access_global`). - throw_validation_failure!(self.path, - { "a {} pointing to a static variable", kind } - ); + match alloc_kind { + Some(GlobalAlloc::Static(did)) => { + // Special handling for pointers to statics (irrespective of their type). + assert!(!self.ecx.tcx.is_thread_local_static(did)); + assert!(self.ecx.tcx.is_static(did)); + if matches!( + self.ctfe_mode, + Some(CtfeValidationMode::Const { allow_static_ptrs: false, .. }) + ) { + // See const_eval::machine::MemoryExtra::can_access_statics for why + // this check is so important. + // This check is reachable when the const just referenced the static, + // but never read it (so we never entered `before_access_global`). + throw_validation_failure!(self.path, + { "a {} pointing to a static variable in a constant", kind } + ); + } + // We skip recursively checking other statics. These statics must be sound by + // themselves, and the only way to get broken statics here is by using + // unsafe code. + // The reasons we don't check other statics is twofold. For one, in all + // sound cases, the static was already validated on its own, and second, we + // trigger cycle errors if we try to compute the value of the other static + // and that static refers back to us. + // We might miss const-invalid data, + // but things are still sound otherwise (in particular re: consts + // referring to statics). + return Ok(()); } - // We skip checking other statics. These statics must be sound by - // themselves, and the only way to get broken statics here is by using - // unsafe code. - // The reasons we don't check other statics is twofold. For one, in all - // sound cases, the static was already validated on its own, and second, we - // trigger cycle errors if we try to compute the value of the other static - // and that static refers back to us. - // We might miss const-invalid data, - // but things are still sound otherwise (in particular re: consts - // referring to statics). - return Ok(()); + Some(GlobalAlloc::Memory(alloc)) => { + if alloc.inner().mutability == Mutability::Mut + && matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { .. })) + { + // This should be unreachable, but if someone manages to copy a pointer + // out of a `static`, then that pointer might point to mutable memory, + // and we would catch that here. + throw_validation_failure!(self.path, + { "a {} pointing to mutable memory in a constant", kind } + ); + } + } + // Nothing to check for these. + None | Some(GlobalAlloc::Function(..) | GlobalAlloc::VTable(..)) => {} } } let path = &self.path; @@ -544,7 +562,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' } ty::Ref(_, ty, mutbl) => { if matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { .. })) - && *mutbl == hir::Mutability::Mut + && *mutbl == Mutability::Mut { // A mutable reference inside a const? That does not seem right (except if it is // a ZST). diff --git a/src/test/ui/consts/const-points-to-static.32bit.stderr b/src/test/ui/consts/const-points-to-static.32bit.stderr index 97825dd0eb517..c7a435a1ee3fc 100644 --- a/src/test/ui/consts/const-points-to-static.32bit.stderr +++ b/src/test/ui/consts/const-points-to-static.32bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const-points-to-static.rs:6:1 | LL | const TEST: &u8 = &MY_STATIC; - | ^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable + | ^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { diff --git a/src/test/ui/consts/const-points-to-static.64bit.stderr b/src/test/ui/consts/const-points-to-static.64bit.stderr index 0d4a5a8ce4f33..4d5b8eac541df 100644 --- a/src/test/ui/consts/const-points-to-static.64bit.stderr +++ b/src/test/ui/consts/const-points-to-static.64bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const-points-to-static.rs:6:1 | LL | const TEST: &u8 = &MY_STATIC; - | ^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable + | ^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static2.32bit.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static2.32bit.stderr index b3ad81e49bc16..14173ac9f69b4 100644 --- a/src/test/ui/consts/miri_unleashed/const_refers_to_static2.32bit.stderr +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static2.32bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const_refers_to_static2.rs:11:1 | LL | const REF_INTERIOR_MUT: &usize = { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -13,7 +13,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const_refers_to_static2.rs:18:1 | LL | const READ_IMMUT: &usize = { - | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable + | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static2.64bit.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static2.64bit.stderr index 24bd070928265..e7e51a41856e2 100644 --- a/src/test/ui/consts/miri_unleashed/const_refers_to_static2.64bit.stderr +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static2.64bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const_refers_to_static2.rs:11:1 | LL | const REF_INTERIOR_MUT: &usize = { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -13,7 +13,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const_refers_to_static2.rs:18:1 | LL | const READ_IMMUT: &usize = { - | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable + | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr index 20a96b57f29b9..3a22b06891629 100644 --- a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const_refers_to_static_cross_crate.rs:12:1 | LL | const SLICE_MUT: &[u8; 1] = { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable + | ^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -19,7 +19,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const_refers_to_static_cross_crate.rs:17:1 | LL | const U8_MUT: &u8 = { - | ^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable + | ^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr index dfa0f76baa186..39c874d6498b2 100644 --- a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const_refers_to_static_cross_crate.rs:12:1 | LL | const SLICE_MUT: &[u8; 1] = { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable + | ^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -19,7 +19,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const_refers_to_static_cross_crate.rs:17:1 | LL | const U8_MUT: &u8 = { - | ^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable + | ^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { From 74f99738244fc9ba2f6ad93b8c891d44d638b0f8 Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Tue, 23 Aug 2022 15:33:06 +0300 Subject: [PATCH 10/25] Fix formating in infer.ftl to make tidy happy --- .../rustc_error_messages/locales/en-US/infer.ftl | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl index 770eaa62b4118..6ae60d92e26ee 100644 --- a/compiler/rustc_error_messages/locales/en-US/infer.ftl +++ b/compiler/rustc_error_messages/locales/en-US/infer.ftl @@ -1,4 +1,4 @@ -infer_opaque_hidden_type = +infer_opaque_hidden_type = opaque type's hidden type cannot be another opaque type from the same scope .label = one of the two opaque types used here has to be outside its defining scope .opaque_type = opaque type whose hidden type is being assigned @@ -8,7 +8,7 @@ infer_type_annotations_needed = {$source_kind -> [closure] type annotations needed for the closure `{$source_name}` [normal] type annotations needed for `{$source_name}` *[other] type annotations needed -} +} .label = type must be known at this point infer_label_bad = {$bad_kind -> @@ -38,24 +38,24 @@ infer_source_kind_subdiag_let = {$kind -> } infer_source_kind_subdiag_generic_label = - cannot infer {$is_type -> + cannot infer {$is_type -> [true] type *[false] the value - } of the {$is_type -> + } of the {$is_type -> [true] type *[false] const } {$parent_exists -> [true] parameter `{$param_name}` declared on the {$parent_prefix} `{$parent_name}` - *[false] parameter {$param_name} + *[false] parameter {$param_name} } infer_source_kind_subdiag_generic_suggestion = - consider specifying the generic {$arg_count -> + consider specifying the generic {$arg_count -> [one] argument *[other] arguments } -infer_source_kind_fully_qualified = +infer_source_kind_fully_qualified = try using a fully qualified path to specify the expected types infer_source_kind_closure_return = @@ -105,4 +105,3 @@ infer_relate_param_bound = ...so that the type `{$name}` will meet its required infer_relate_param_bound_2 = ...that is required by this bound infer_relate_region_param_bound = ...so that the declared lifetime parameter bounds are satisfied infer_compare_impl_item_obligation = ...so that the definition in impl matches the definition from the trait - From 3fae3904b130272c782255066f79a13fa9fcdad6 Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Wed, 24 Aug 2022 15:46:29 +0300 Subject: [PATCH 11/25] Use `IntoDiagnosticArg` where it makes sense --- .../locales/en-US/infer.ftl | 7 +++- compiler/rustc_infer/src/errors.rs | 13 +++++-- .../src/infer/error_reporting/mod.rs | 16 +++++--- .../infer/error_reporting/need_type_info.rs | 37 ++++++++++++++----- .../src/infer/error_reporting/note.rs | 29 ++++----------- 5 files changed, 61 insertions(+), 41 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl index 6ae60d92e26ee..60086cd6e477f 100644 --- a/compiler/rustc_error_messages/locales/en-US/infer.ftl +++ b/compiler/rustc_error_messages/locales/en-US/infer.ftl @@ -63,7 +63,12 @@ infer_source_kind_closure_return = # generator_kind may need to be translated infer_need_type_info_in_generator = - type inside {$generator_kind} must be known in this context + type inside {$generator_kind -> + [async_block] `async` block + [async_closure] `async` closure + [async_fn] `async fn` body + *[generator] generator + } must be known in this context infer_subtype = ...so that the {$requirement -> diff --git a/compiler/rustc_infer/src/errors.rs b/compiler/rustc_infer/src/errors.rs index 1db8763e4996d..938f8aa77a5b4 100644 --- a/compiler/rustc_infer/src/errors.rs +++ b/compiler/rustc_infer/src/errors.rs @@ -3,6 +3,11 @@ use rustc_hir::FnRetTy; use rustc_macros::SessionDiagnostic; use rustc_span::{BytePos, Span}; +use crate::infer::error_reporting::{ + need_type_info::{GeneratorKindAsDiagArg, UnderspecifiedArgKind}, + ObligationCauseAsDiagArg, +}; + #[derive(SessionDiagnostic)] #[diag(infer::opaque_hidden_type)] pub struct OpaqueHiddenTypeDiag { @@ -73,7 +78,7 @@ pub struct AmbigousReturn<'a> { pub struct NeedTypeInfoInGenerator<'a> { #[primary_span] pub span: Span, - pub generator_kind: &'static str, + pub generator_kind: GeneratorKindAsDiagArg, #[subdiagnostic] pub bad_label: InferenceBadError<'a>, } @@ -85,7 +90,7 @@ pub struct InferenceBadError<'a> { #[primary_span] pub span: Span, pub bad_kind: &'static str, - pub prefix_kind: &'static str, + pub prefix_kind: UnderspecifiedArgKind, pub has_parent: bool, pub prefix: &'a str, pub parent_prefix: &'a str, @@ -107,7 +112,7 @@ pub enum SourceKindSubdiag<'a> { type_name: String, kind: &'static str, x_kind: &'static str, - prefix_kind: &'static str, + prefix_kind: UnderspecifiedArgKind, prefix: &'a str, arg_name: String, }, @@ -199,7 +204,7 @@ pub enum RegionOriginNote<'a> { }, WithRequirement { span: Span, - requirement: &'static str, + requirement: ObligationCauseAsDiagArg<'a>, expected_found: Option<(DiagnosticStyledString, DiagnosticStyledString)>, }, } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 13951326665d7..c7e258578e4de 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -58,7 +58,7 @@ use crate::traits::{ }; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed}; +use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed, IntoDiagnosticArg}; use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString, MultiSpan}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -78,7 +78,7 @@ use std::{cmp, fmt, iter}; mod note; -mod need_type_info; +pub(crate) mod need_type_info; pub use need_type_info::TypeAnnotationNeeded; pub mod nice_region_error; @@ -2811,7 +2811,6 @@ pub enum FailureCode { pub trait ObligationCauseExt<'tcx> { fn as_failure_code(&self, terr: TypeError<'tcx>) -> FailureCode; fn as_requirement_str(&self) -> &'static str; - fn as_requirement_localised(&self) -> &'static str; } impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> { @@ -2880,10 +2879,15 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> { _ => "types are compatible", } } +} + +/// Newtype to allow implementing IntoDiagnosticArg +pub struct ObligationCauseAsDiagArg<'tcx>(pub ObligationCause<'tcx>); - fn as_requirement_localised(&self) -> &'static str { +impl IntoDiagnosticArg for ObligationCauseAsDiagArg<'_> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { use crate::traits::ObligationCauseCode::*; - match self.code() { + let kind = match self.0.code() { CompareImplItemObligation { kind: ty::AssocKind::Fn, .. } => "method_compat", CompareImplItemObligation { kind: ty::AssocKind::Type, .. } => "type_compat", CompareImplItemObligation { kind: ty::AssocKind::Const, .. } => "const_compat", @@ -2896,6 +2900,8 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> { MethodReceiver => "method_correct_type", _ => "other", } + .into(); + rustc_errors::DiagnosticArgValue::Str(kind) } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index daf64aeb053d3..e990fe7ecb504 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -4,7 +4,7 @@ use crate::errors::{ }; use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::infer::InferCtxt; -use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed}; +use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, IntoDiagnosticArg}; use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::def::{CtorOf, DefKind, Namespace}; @@ -65,6 +65,7 @@ pub struct InferenceDiagnosticsParentData { name: String, } +#[derive(Clone)] pub enum UnderspecifiedArgKind { Type { prefix: Cow<'static, str> }, Const { is_parameter: bool }, @@ -101,7 +102,7 @@ impl InferenceDiagnosticsData { InferenceBadError { span, bad_kind, - prefix_kind: self.kind.prefix_kind(), + prefix_kind: self.kind.clone(), prefix: self.kind.try_get_prefix().unwrap_or_default(), name: self.name.clone(), has_parent, @@ -130,14 +131,18 @@ impl InferenceDiagnosticsParentData { } } -impl UnderspecifiedArgKind { - fn prefix_kind(&self) -> &'static str { - match self { +impl IntoDiagnosticArg for UnderspecifiedArgKind { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + let kind = match self { Self::Type { .. } => "type", Self::Const { is_parameter: true } => "const_with_param", Self::Const { is_parameter: false } => "const", - } + }; + rustc_errors::DiagnosticArgValue::Str(kind.into()) } +} + +impl UnderspecifiedArgKind { fn try_get_prefix(&self) -> Option<&str> { match self { Self::Type { prefix } => Some(prefix.as_ref()), @@ -405,7 +410,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { span: insert_span, name: pattern_name.map(|name| name.to_string()).unwrap_or_else(String::new), x_kind: arg_data.where_x_is_kind(ty), - prefix_kind: arg_data.kind.prefix_kind(), + prefix_kind: arg_data.kind.clone(), prefix: arg_data.kind.try_get_prefix().unwrap_or_default(), arg_name: arg_data.name, kind: if pattern_name.is_some() { "with_pattern" } else { "other" }, @@ -417,7 +422,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { span: insert_span, name: String::new(), x_kind: arg_data.where_x_is_kind(ty), - prefix_kind: arg_data.kind.prefix_kind(), + prefix_kind: arg_data.kind.clone(), prefix: arg_data.kind.try_get_prefix().unwrap_or_default(), arg_name: arg_data.name, kind: "closure", @@ -568,12 +573,26 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { NeedTypeInfoInGenerator { bad_label: data.make_bad_error(span), span, - generator_kind: kind.descr(), + generator_kind: GeneratorKindAsDiagArg(kind), } .into_diagnostic(&self.tcx.sess.parse_sess) } } +pub struct GeneratorKindAsDiagArg(pub hir::GeneratorKind); + +impl IntoDiagnosticArg for GeneratorKindAsDiagArg { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + let kind = match self.0 { + hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) => "async_block", + hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure) => "async_closure", + hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn) => "async_fn", + hir::GeneratorKind::Gen => "generator", + }; + rustc_errors::DiagnosticArgValue::Str(kind.into()) + } +} + #[derive(Debug)] struct InferSource<'tcx> { span: Span, diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index 36efbd6824a77..cffdf56bb6d48 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -1,40 +1,26 @@ use crate::errors::RegionOriginNote; -use crate::infer::error_reporting::{note_and_explain_region, ObligationCauseExt}; +use crate::infer::error_reporting::note_and_explain_region; use crate::infer::{self, InferCtxt, SubregionOrigin}; use rustc_errors::{ - fluent, struct_span_err, AddSubdiagnostic, Diagnostic, DiagnosticBuilder, DiagnosticMessage, - ErrorGuaranteed, + fluent, struct_span_err, AddSubdiagnostic, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, }; use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::{self, Region}; +use super::ObligationCauseAsDiagArg; + impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub(super) fn note_region_origin(&self, err: &mut Diagnostic, origin: &SubregionOrigin<'tcx>) { - let mut label_or_note = |span, msg: DiagnosticMessage| { - let sub_count = err.children.iter().filter(|d| d.span.is_dummy()).count(); - let expanded_sub_count = err.children.iter().filter(|d| !d.span.is_dummy()).count(); - let span_is_primary = err.span.primary_spans().iter().all(|&sp| sp == span); - if span_is_primary && sub_count == 0 && expanded_sub_count == 0 { - err.span_label(span, msg); - } else if span_is_primary && expanded_sub_count == 0 { - err.note(msg); - } else { - err.span_note(span, msg); - } - }; match *origin { infer::Subtype(ref trace) => RegionOriginNote::WithRequirement { span: trace.cause.span, - requirement: trace.cause.as_requirement_localised(), + requirement: ObligationCauseAsDiagArg(trace.cause.clone()), expected_found: self.values_str(trace.values), } .add_to_diagnostic(err), - infer::Reborrow(span) => { - label_or_note(span, fluent::infer::reborrow); - RegionOriginNote::Plain { span, msg: fluent::infer::reborrow } - .add_to_diagnostic(err) - } + infer::Reborrow(span) => RegionOriginNote::Plain { span, msg: fluent::infer::reborrow } + .add_to_diagnostic(err), infer::ReborrowUpvar(span, ref upvar_id) => { let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id); RegionOriginNote::WithName { @@ -46,7 +32,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .add_to_diagnostic(err); } infer::RelateObjectBound(span) => { - label_or_note(span, fluent::infer::relate_object_bound); RegionOriginNote::Plain { span, msg: fluent::infer::relate_object_bound } .add_to_diagnostic(err); } From e1765a9c56d8d9b235bc5b8fda2a0f1d4e92ff49 Mon Sep 17 00:00:00 2001 From: IQuant Date: Wed, 24 Aug 2022 17:09:07 +0300 Subject: [PATCH 12/25] Remove commented lines --- compiler/rustc_infer/src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index 2c1d339b578fe..eed2efd3ee0c0 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -23,8 +23,6 @@ #![feature(never_type)] #![feature(try_blocks)] #![recursion_limit = "512"] // For rustdoc -// #![deny(rustc::untranslatable_diagnostic)] -// #![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_macros; From b508b50617bd6a976f77d33962a6f0df52eee12d Mon Sep 17 00:00:00 2001 From: Luis Cardoso <61982523+LuisCardosoOliveira@users.noreply.github.com> Date: Wed, 24 Aug 2022 17:57:10 +0200 Subject: [PATCH 13/25] translations: rename warn_ to warning The macro warn_ was named like that because it the keyword warn is a built-in attribute and at the time this macro was created the word 'warning' was also taken. However it is no longer the case and we can rename warn_ to warning. --- .../src/diagnostics/diagnostic_builder.rs | 31 ++++++++++--------- .../src/diagnostics/subdiagnostic.rs | 4 +-- compiler/rustc_macros/src/lib.rs | 6 ++-- compiler/rustc_passes/src/errors.rs | 16 +++++----- .../session-diagnostic/diagnostic-derive.rs | 10 +++--- .../diagnostic-derive.stderr | 28 ++++++++--------- .../subdiagnostic-derive.rs | 7 ++--- 7 files changed, 52 insertions(+), 50 deletions(-) diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index 9df9fa4e9bf74..a4ccfcace1923 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -148,9 +148,9 @@ impl DiagnosticDeriveBuilder { // `#[help(..)]`/`#[note(..)]` when the user is specifying a alternative slug. Meta::List(MetaList { ref nested, .. }) => nested, // Subdiagnostics without spans can be applied to the type too, and these are just - // paths: `#[help]`, `#[note]` and `#[warn_]` + // paths: `#[help]`, `#[note]` and `#[warning]` Meta::Path(_) if !is_diag => { - let fn_name = if name == "warn_" { + let fn_name = if name == "warning" { Ident::new("warn", attr.span()) } else { Ident::new(name, attr.span()) @@ -163,12 +163,15 @@ impl DiagnosticDeriveBuilder { // Check the kind before doing any further processing so that there aren't misleading // "no kind specified" errors if there are failures later. match name { - "error" | "warning" | "lint" => throw_invalid_attr!(attr, &meta, |diag| { - diag.help("`error`, `warning` and `lint` have been replaced by `diag`") + "error" | "lint" => throw_invalid_attr!(attr, &meta, |diag| { + diag.help("`error` and `lint` have been replaced by `diag`") }), - "diag" | "help" | "note" | "warn_" => (), + "warn_" => throw_invalid_attr!(attr, &meta, |diag| { + diag.help("`warn_` have been replaced by `warning`") + }), + "diag" | "help" | "note" | "warning" => (), _ => throw_invalid_attr!(attr, &meta, |diag| { - diag.help("only `diag`, `help`, `note` and `warn_` are valid attributes") + diag.help("only `diag`, `help`, `note` and `warning` are valid attributes") }), } @@ -180,7 +183,7 @@ impl DiagnosticDeriveBuilder { if !is_diag && nested_iter.next().is_some() { throw_invalid_nested_attr!(attr, &nested_attr, |diag| { diag.help( - "`help`, `note` and `warn_` struct attributes can only have one argument", + "`help`, `note` and `warning` struct attributes can only have one argument", ) }); } @@ -348,12 +351,12 @@ impl DiagnosticDeriveBuilder { report_error_if_not_applied_to_span(attr, &info)?; Ok(self.add_spanned_subdiagnostic(binding, ident, parse_quote! { _subdiag::label })) } - "note" | "help" | "warn_" => { + "note" | "help" | "warning" => { let warn_ident = Ident::new("warn", Span::call_site()); let (ident, path) = match name { "note" => (ident, parse_quote! { _subdiag::note }), "help" => (ident, parse_quote! { _subdiag::help }), - "warn_" => (&warn_ident, parse_quote! { _subdiag::warn }), + "warning" => (&warn_ident, parse_quote! { _subdiag::warn }), _ => unreachable!(), }; if type_matches_path(&info.ty, &["rustc_span", "Span"]) { @@ -390,7 +393,7 @@ impl DiagnosticDeriveBuilder { "suggestion" | "suggestion_short" | "suggestion_hidden" | "suggestion_verbose" => { return self.generate_inner_field_code_suggestion(attr, info); } - "label" | "help" | "note" | "warn_" => (), + "label" | "help" | "note" | "warning" => (), _ => throw_invalid_attr!(attr, &meta, |diag| { diag.help( "only `label`, `help`, `note`, `warn` or `suggestion{,_short,_hidden,_verbose}` are \ @@ -422,14 +425,14 @@ impl DiagnosticDeriveBuilder { Ok(self.add_spanned_subdiagnostic(binding, ident, msg)) } "note" | "help" if type_is_unit(&info.ty) => Ok(self.add_subdiagnostic(ident, msg)), - // `warn_` must be special-cased because the attribute `warn` already has meaning and + // `warning` must be special-cased because the attribute `warn` already has meaning and // so isn't used, despite the diagnostic API being named `warn`. - "warn_" if type_matches_path(&info.ty, &["rustc_span", "Span"]) => Ok(self + "warning" if type_matches_path(&info.ty, &["rustc_span", "Span"]) => Ok(self .add_spanned_subdiagnostic(binding, &Ident::new("warn", Span::call_site()), msg)), - "warn_" if type_is_unit(&info.ty) => { + "warning" if type_is_unit(&info.ty) => { Ok(self.add_subdiagnostic(&Ident::new("warn", Span::call_site()), msg)) } - "note" | "help" | "warn_" => report_type_error(attr, "`Span` or `()`")?, + "note" | "help" | "warning" => report_type_error(attr, "`Span` or `()`")?, _ => unreachable!(), } } diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index edf4dbed9853e..666dbc23c287c 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -37,7 +37,7 @@ enum SubdiagnosticKind { Note, /// `#[help(...)]` Help, - /// `#[warn_(...)]` + /// `#[warning(...)]` Warn, /// `#[suggestion{,_short,_hidden,_verbose}]` Suggestion(SubdiagnosticSuggestionKind), @@ -51,7 +51,7 @@ impl FromStr for SubdiagnosticKind { "label" => Ok(SubdiagnosticKind::Label), "note" => Ok(SubdiagnosticKind::Note), "help" => Ok(SubdiagnosticKind::Help), - "warn_" => Ok(SubdiagnosticKind::Warn), + "warning" => Ok(SubdiagnosticKind::Warn), "suggestion" => Ok(SubdiagnosticKind::Suggestion(SubdiagnosticSuggestionKind::Normal)), "suggestion_short" => { Ok(SubdiagnosticKind::Suggestion(SubdiagnosticSuggestionKind::Short)) diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index 87d7ab6ed517b..8faac8ef36a53 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -132,7 +132,7 @@ decl_derive!( diag, help, note, - warn_, + warning, // field attributes skip_arg, primary_span, @@ -149,7 +149,7 @@ decl_derive!( diag, help, note, - warn_, + warning, // field attributes skip_arg, primary_span, @@ -166,7 +166,7 @@ decl_derive!( label, help, note, - warn_, + warning, suggestion, suggestion_short, suggestion_hidden, diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 383982013d9e7..901f56ad96d17 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -28,7 +28,7 @@ pub struct IgnoredInlineAttrFnProto; #[derive(LintDiagnostic)] #[diag(passes::inline_ignored_constants)] -#[warn_] +#[warning] #[note] pub struct IgnoredInlineAttrConstants; @@ -347,7 +347,7 @@ pub struct MustNotSuspend { #[derive(LintDiagnostic)] #[diag(passes::cold)] -#[warn_] +#[warning] pub struct Cold { #[label] pub span: Span, @@ -355,7 +355,7 @@ pub struct Cold { #[derive(LintDiagnostic)] #[diag(passes::link)] -#[warn_] +#[warning] pub struct Link { #[label] pub span: Option, @@ -363,7 +363,7 @@ pub struct Link { #[derive(LintDiagnostic)] #[diag(passes::link_name)] -#[warn_] +#[warning] pub struct LinkName<'a> { #[help] pub attr_span: Option, @@ -449,7 +449,7 @@ pub struct RustcDirtyClean { #[derive(LintDiagnostic)] #[diag(passes::link_section)] -#[warn_] +#[warning] pub struct LinkSection { #[label] pub span: Span, @@ -457,7 +457,7 @@ pub struct LinkSection { #[derive(LintDiagnostic)] #[diag(passes::no_mangle_foreign)] -#[warn_] +#[warning] #[note] pub struct NoMangleForeign { #[label] @@ -469,7 +469,7 @@ pub struct NoMangleForeign { #[derive(LintDiagnostic)] #[diag(passes::no_mangle)] -#[warn_] +#[warning] pub struct NoMangle { #[label] pub span: Span, @@ -617,7 +617,7 @@ pub struct UnusedDuplicate { pub this: Span, #[note] pub other: Span, - #[warn_] + #[warning] pub warning: Option<()>, } diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs index aaa8caa64f343..b1f557cb94de8 100644 --- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs +++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs @@ -549,7 +549,7 @@ struct ErrorWithMultiSpan { #[derive(SessionDiagnostic)] #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")] -#[warn_] +#[warning] struct ErrorWithWarn { val: String, } @@ -562,11 +562,11 @@ struct ErrorWithWarn { struct ErrorAttribute {} #[derive(SessionDiagnostic)] -#[warning(typeck::ambiguous_lifetime_bound, code = "E0123")] -//~^ ERROR `#[warning(...)]` is not a valid attribute +#[warn_(typeck::ambiguous_lifetime_bound, code = "E0123")] +//~^ ERROR `#[warn_(...)]` is not a valid attribute //~| ERROR diagnostic slug not specified -//~| ERROR cannot find attribute `warning` in this scope -struct WarningAttribute {} +//~| ERROR cannot find attribute `warn_` in this scope +struct WarnAttribute {} #[derive(SessionDiagnostic)] #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")] diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr index 866b1a1de999c..621c59f448951 100644 --- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr +++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr @@ -21,7 +21,7 @@ error: `#[nonsense(...)]` is not a valid attribute LL | #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: only `diag`, `help`, `note` and `warn_` are valid attributes + = help: only `diag`, `help`, `note` and `warning` are valid attributes error: diagnostic slug not specified --> $DIR/diagnostic-derive.rs:53:1 @@ -329,7 +329,7 @@ error: `#[error(...)]` is not a valid attribute LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: `error`, `warning` and `lint` have been replaced by `diag` + = help: `error` and `lint` have been replaced by `diag` error: diagnostic slug not specified --> $DIR/diagnostic-derive.rs:558:1 @@ -343,23 +343,23 @@ LL | | struct ErrorAttribute {} | = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]` -error: `#[warning(...)]` is not a valid attribute +error: `#[warn_(...)]` is not a valid attribute --> $DIR/diagnostic-derive.rs:565:1 | -LL | #[warning(typeck::ambiguous_lifetime_bound, code = "E0123")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[warn_(typeck::ambiguous_lifetime_bound, code = "E0123")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: `error`, `warning` and `lint` have been replaced by `diag` + = help: `warn_` have been replaced by `warning` error: diagnostic slug not specified --> $DIR/diagnostic-derive.rs:565:1 | -LL | / #[warning(typeck::ambiguous_lifetime_bound, code = "E0123")] +LL | / #[warn_(typeck::ambiguous_lifetime_bound, code = "E0123")] LL | | LL | | LL | | -LL | | struct WarningAttribute {} - | |__________________________^ +LL | | struct WarnAttribute {} + | |_______________________^ | = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]` @@ -369,7 +369,7 @@ error: `#[lint(...)]` is not a valid attribute LL | #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: `error`, `warning` and `lint` have been replaced by `diag` + = help: `error` and `lint` have been replaced by `diag` error: diagnostic slug not specified --> $DIR/diagnostic-derive.rs:572:1 @@ -389,7 +389,7 @@ error: `#[lint(...)]` is not a valid attribute LL | #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: `error`, `warning` and `lint` have been replaced by `diag` + = help: `error` and `lint` have been replaced by `diag` error: diagnostic slug not specified --> $DIR/diagnostic-derive.rs:579:1 @@ -421,11 +421,11 @@ error: cannot find attribute `error` in this scope LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^ -error: cannot find attribute `warning` in this scope +error: cannot find attribute `warn_` in this scope --> $DIR/diagnostic-derive.rs:565:3 | -LL | #[warning(typeck::ambiguous_lifetime_bound, code = "E0123")] - | ^^^^^^^ +LL | #[warn_(typeck::ambiguous_lifetime_bound, code = "E0123")] + | ^^^^^ help: a built-in attribute with a similar name exists: `warn` error: cannot find attribute `lint` in this scope --> $DIR/diagnostic-derive.rs:572:3 diff --git a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs index 16da25c402b57..ddfc0d3365df0 100644 --- a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs +++ b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs @@ -510,12 +510,11 @@ enum AX { } #[derive(SessionSubdiagnostic)] -#[warn_(parser::add_paren)] -struct AY { -} +#[warning(parser::add_paren)] +struct AY {} #[derive(SessionSubdiagnostic)] -#[warn_(parser::add_paren)] +#[warning(parser::add_paren)] struct AZ { #[primary_span] span: Span, From 4e976262a1598fa48cd08fa0e429f05299d1ae3e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 12 Aug 2022 02:00:37 +0000 Subject: [PATCH 14/25] Call them constants instead of types --- .../src/infer/error_reporting/mod.rs | 5 +++ .../generic-expr-default-concrete.stderr | 4 +-- ...neric-expr-default-mismatched-types.stderr | 4 +-- .../abstract-const-as-cast-3.stderr | 32 +++++++++---------- .../generic_const_exprs/different-fn.stderr | 4 +-- .../issue-62504.full.stderr | 4 +-- ...ue-72819-generic-in-const-eval.full.stderr | 8 ++--- .../generic_const_exprs/issue-83765.stderr | 8 ++--- .../generic_const_exprs/issue-85848.stderr | 4 +-- .../const-generics/issues/issue-73260.stderr | 8 ++--- .../const-generics/issues/issue-79674.stderr | 4 +-- .../types-mismatch-const-args.full.stderr | 4 +-- 12 files changed, 47 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 59ea1f3f9de45..16cffb45f0f06 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1588,9 +1588,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { Mismatch::Variable(infer::ExpectedFound { expected, found }), ) } + ValuePairs::Terms(infer::ExpectedFound { + expected: ty::Term::Const(_), + found: ty::Term::Const(_), + }) => (false, Mismatch::Fixed("constant")), ValuePairs::TraitRefs(_) | ValuePairs::PolyTraitRefs(_) => { (false, Mismatch::Fixed("trait")) } + ValuePairs::Regions(_) => (false, Mismatch::Fixed("lifetime")), _ => (false, Mismatch::Fixed("type")), }; let vals = match self.values_str(values) { diff --git a/src/test/ui/const-generics/defaults/generic-expr-default-concrete.stderr b/src/test/ui/const-generics/defaults/generic-expr-default-concrete.stderr index e8826ce4335e7..61b3551182c90 100644 --- a/src/test/ui/const-generics/defaults/generic-expr-default-concrete.stderr +++ b/src/test/ui/const-generics/defaults/generic-expr-default-concrete.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | Foo::<10, 12> | ^^^^^^^^^^^^^ expected `11`, found `12` | - = note: expected type `11` - found type `12` + = note: expected constant `11` + found constant `12` error: aborting due to previous error diff --git a/src/test/ui/const-generics/defaults/generic-expr-default-mismatched-types.stderr b/src/test/ui/const-generics/defaults/generic-expr-default-mismatched-types.stderr index d5a3071b77d15..e83f89a60333f 100644 --- a/src/test/ui/const-generics/defaults/generic-expr-default-mismatched-types.stderr +++ b/src/test/ui/const-generics/defaults/generic-expr-default-mismatched-types.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | Foo:: | ^^^^^^^^^^^^^^^^^^^ expected `{ N + 1 }`, found `{ N + 2 }` | - = note: expected type `{ N + 1 }` - found type `{ N + 2 }` + = note: expected constant `{ N + 1 }` + found constant `{ N + 2 }` error: aborting due to previous error diff --git a/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr b/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr index 615dc875f67a3..9e1297d5ee4bf 100644 --- a/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr @@ -22,8 +22,8 @@ error[E0308]: mismatched types LL | assert_impl::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as u128 }`, found `{ O as u128 }` | - = note: expected type `{ N as u128 }` - found type `{ O as u128 }` + = note: expected constant `{ N as u128 }` + found constant `{ O as u128 }` error: unconstrained generic constant --> $DIR/abstract-const-as-cast-3.rs:20:19 @@ -49,8 +49,8 @@ error[E0308]: mismatched types LL | assert_impl::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as _ }`, found `{ O as u128 }` | - = note: expected type `{ N as _ }` - found type `{ O as u128 }` + = note: expected constant `{ N as _ }` + found constant `{ O as u128 }` error[E0308]: mismatched types --> $DIR/abstract-const-as-cast-3.rs:23:5 @@ -58,8 +58,8 @@ error[E0308]: mismatched types LL | assert_impl::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `12`, found `13` | - = note: expected type `12` - found type `13` + = note: expected constant `12` + found constant `13` error[E0308]: mismatched types --> $DIR/abstract-const-as-cast-3.rs:25:5 @@ -67,8 +67,8 @@ error[E0308]: mismatched types LL | assert_impl::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `13`, found `14` | - = note: expected type `13` - found type `14` + = note: expected constant `13` + found constant `14` error: unconstrained generic constant --> $DIR/abstract-const-as-cast-3.rs:35:19 @@ -94,8 +94,8 @@ error[E0308]: mismatched types LL | assert_impl::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as u128 }`, found `{ O as u128 }` | - = note: expected type `{ N as u128 }` - found type `{ O as u128 }` + = note: expected constant `{ N as u128 }` + found constant `{ O as u128 }` error: unconstrained generic constant --> $DIR/abstract-const-as-cast-3.rs:38:19 @@ -121,8 +121,8 @@ error[E0308]: mismatched types LL | assert_impl::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as _ }`, found `{ O as u128 }` | - = note: expected type `{ N as _ }` - found type `{ O as u128 }` + = note: expected constant `{ N as _ }` + found constant `{ O as u128 }` error[E0308]: mismatched types --> $DIR/abstract-const-as-cast-3.rs:41:5 @@ -130,8 +130,8 @@ error[E0308]: mismatched types LL | assert_impl::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `12`, found `13` | - = note: expected type `12` - found type `13` + = note: expected constant `12` + found constant `13` error[E0308]: mismatched types --> $DIR/abstract-const-as-cast-3.rs:43:5 @@ -139,8 +139,8 @@ error[E0308]: mismatched types LL | assert_impl::>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `13`, found `14` | - = note: expected type `13` - found type `14` + = note: expected constant `13` + found constant `14` error: aborting due to 12 previous errors diff --git a/src/test/ui/const-generics/generic_const_exprs/different-fn.stderr b/src/test/ui/const-generics/generic_const_exprs/different-fn.stderr index 2aeb9b961ffde..83a2f3740b146 100644 --- a/src/test/ui/const-generics/generic_const_exprs/different-fn.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/different-fn.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | [0; size_of::>()] | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `size_of::()`, found `size_of::>()` | - = note: expected type `size_of::()` - found type `size_of::>()` + = note: expected constant `size_of::()` + found constant `size_of::>()` error: unconstrained generic constant --> $DIR/different-fn.rs:10:9 diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-62504.full.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-62504.full.stderr index f2ae361dc81d9..0742db398c9c4 100644 --- a/src/test/ui/const-generics/generic_const_exprs/issue-62504.full.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/issue-62504.full.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | ArrayHolder([0; Self::SIZE]) | ^^^^^^^^^^^^^^^ expected `X`, found `Self::SIZE` | - = note: expected type `X` - found type `Self::SIZE` + = note: expected constant `X` + found constant `Self::SIZE` error: unconstrained generic constant --> $DIR/issue-62504.rs:18:25 diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.full.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.full.stderr index d536f6fd1d557..38dfa65e4091f 100644 --- a/src/test/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.full.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.full.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | let x: Arr<{usize::MAX}> = Arr {}; | ^^^^^^^^^^^^^^^^^ expected `false`, found `true` | - = note: expected type `false` - found type `true` + = note: expected constant `false` + found constant `true` error[E0308]: mismatched types --> $DIR/issue-72819-generic-in-const-eval.rs:20:32 @@ -13,8 +13,8 @@ error[E0308]: mismatched types LL | let x: Arr<{usize::MAX}> = Arr {}; | ^^^ expected `false`, found `true` | - = note: expected type `false` - found type `true` + = note: expected constant `false` + found constant `true` error: aborting due to 2 previous errors diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-83765.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-83765.stderr index 0332e82fe0727..b693023f125a4 100644 --- a/src/test/ui/const-generics/generic_const_exprs/issue-83765.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/issue-83765.stderr @@ -4,8 +4,8 @@ error[E0308]: method not compatible with trait LL | fn size(&self) -> [usize; DIM] { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `DIM` | - = note: expected type `Self::DIM` - found type `DIM` + = note: expected constant `Self::DIM` + found constant `DIM` error: unconstrained generic constant --> $DIR/issue-83765.rs:32:24 @@ -26,8 +26,8 @@ error[E0308]: mismatched types LL | self.reference.size() | ^^^^^^^^^^^^^^^^^^^^^ expected `DIM`, found `Self::DIM` | - = note: expected type `DIM` - found type `Self::DIM` + = note: expected constant `DIM` + found constant `Self::DIM` error: aborting due to 3 previous errors diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-85848.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-85848.stderr index 808b305c680f3..09bcb0860b71b 100644 --- a/src/test/ui/const-generics/generic_const_exprs/issue-85848.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/issue-85848.stderr @@ -54,8 +54,8 @@ error[E0308]: mismatched types LL | writes_to_specific_path(&cap); | ^^^^^^^^^^^^^^^^^^^^^^^ expected `true`, found `{ contains::() }` | - = note: expected type `true` - found type `{ contains::() }` + = note: expected constant `true` + found constant `{ contains::() }` error: aborting due to 3 previous errors diff --git a/src/test/ui/const-generics/issues/issue-73260.stderr b/src/test/ui/const-generics/issues/issue-73260.stderr index f1fc50e6e5914..3d1f90271f9a3 100644 --- a/src/test/ui/const-generics/issues/issue-73260.stderr +++ b/src/test/ui/const-generics/issues/issue-73260.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | let x: Arr<{usize::MAX}> = Arr {}; | ^^^^^^^^^^^^^^^^^ expected `false`, found `true` | - = note: expected type `false` - found type `true` + = note: expected constant `false` + found constant `true` error[E0308]: mismatched types --> $DIR/issue-73260.rs:16:32 @@ -13,8 +13,8 @@ error[E0308]: mismatched types LL | let x: Arr<{usize::MAX}> = Arr {}; | ^^^ expected `false`, found `true` | - = note: expected type `false` - found type `true` + = note: expected constant `false` + found constant `true` error: aborting due to 2 previous errors diff --git a/src/test/ui/const-generics/issues/issue-79674.stderr b/src/test/ui/const-generics/issues/issue-79674.stderr index 8c029289cbb0d..344b2c5631064 100644 --- a/src/test/ui/const-generics/issues/issue-79674.stderr +++ b/src/test/ui/const-generics/issues/issue-79674.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | requires_distinct("str", 12); | ^^^^^^^^^^^^^^^^^ expected `true`, found `false` | - = note: expected type `true` - found type `false` + = note: expected constant `true` + found constant `false` error: aborting due to previous error diff --git a/src/test/ui/const-generics/types-mismatch-const-args.full.stderr b/src/test/ui/const-generics/types-mismatch-const-args.full.stderr index 486506239ddfd..b6a22df74369a 100644 --- a/src/test/ui/const-generics/types-mismatch-const-args.full.stderr +++ b/src/test/ui/const-generics/types-mismatch-const-args.full.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | let _: A<'a, u32, {2u32}, {3u32}> = A::<'a, u32, {2u32 + 2u32}, {3u32}> { data: PhantomData }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `2`, found `4` | - = note: expected type `2` - found type `4` + = note: expected constant `2` + found constant `4` error[E0308]: mismatched types --> $DIR/types-mismatch-const-args.rs:16:41 From 4ff587263e0a7f2081e2ad5fd3e88460a94adbb5 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 12 Aug 2022 03:13:45 +0000 Subject: [PATCH 15/25] Note binding obligation causes for const equate errors --- compiler/rustc_middle/src/traits/mod.rs | 7 ++++ .../src/traits/error_reporting/mod.rs | 19 +++++++-- .../abstract-const-as-cast-3.stderr | 40 +++++++++++++++++++ ...ue-72819-generic-in-const-eval.full.stderr | 14 +++++++ .../const-generics/issues/issue-73260.stderr | 16 ++++++++ .../const-generics/issues/issue-79674.stderr | 8 ++++ 6 files changed, 101 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 9b82320e556b3..ab7e5ba3a1067 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -469,6 +469,13 @@ impl<'tcx> ObligationCauseCode<'tcx> { _ => None, } } + + pub fn peel_match_impls(&self) -> &Self { + match self { + MatchImpl(cause, _) => cause.code(), + _ => self, + } + } } // `ObligationCauseCode` is used a lot. Make sure it doesn't unintentionally get bigger. diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 70fac83325a9c..1f031d33e0653 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1506,13 +1506,26 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { .emit(); } FulfillmentErrorCode::CodeConstEquateError(ref expected_found, ref err) => { - self.report_mismatched_consts( + let mut diag = self.report_mismatched_consts( &error.obligation.cause, expected_found.expected, expected_found.found, err.clone(), - ) - .emit(); + ); + let code = error.obligation.cause.code().peel_derives().peel_match_impls(); + if let ObligationCauseCode::BindingObligation(..) + | ObligationCauseCode::ItemObligation(..) = code + { + self.note_obligation_cause_code( + &mut diag, + &error.obligation.predicate, + error.obligation.param_env, + code, + &mut vec![], + &mut Default::default(), + ); + } + diag.emit(); } } } diff --git a/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr b/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr index 9e1297d5ee4bf..ada1050d35f35 100644 --- a/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr @@ -24,6 +24,11 @@ LL | assert_impl::>(); | = note: expected constant `{ N as u128 }` found constant `{ O as u128 }` +note: required by a bound in `use_trait_impl::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:14:23 + | +LL | fn assert_impl() {} + | ^^^^^ required by this bound in `use_trait_impl::assert_impl` error: unconstrained generic constant --> $DIR/abstract-const-as-cast-3.rs:20:19 @@ -51,6 +56,11 @@ LL | assert_impl::>(); | = note: expected constant `{ N as _ }` found constant `{ O as u128 }` +note: required by a bound in `use_trait_impl::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:14:23 + | +LL | fn assert_impl() {} + | ^^^^^ required by this bound in `use_trait_impl::assert_impl` error[E0308]: mismatched types --> $DIR/abstract-const-as-cast-3.rs:23:5 @@ -60,6 +70,11 @@ LL | assert_impl::>(); | = note: expected constant `12` found constant `13` +note: required by a bound in `use_trait_impl::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:14:23 + | +LL | fn assert_impl() {} + | ^^^^^ required by this bound in `use_trait_impl::assert_impl` error[E0308]: mismatched types --> $DIR/abstract-const-as-cast-3.rs:25:5 @@ -69,6 +84,11 @@ LL | assert_impl::>(); | = note: expected constant `13` found constant `14` +note: required by a bound in `use_trait_impl::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:14:23 + | +LL | fn assert_impl() {} + | ^^^^^ required by this bound in `use_trait_impl::assert_impl` error: unconstrained generic constant --> $DIR/abstract-const-as-cast-3.rs:35:19 @@ -96,6 +116,11 @@ LL | assert_impl::>(); | = note: expected constant `{ N as u128 }` found constant `{ O as u128 }` +note: required by a bound in `use_trait_impl_2::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:32:23 + | +LL | fn assert_impl() {} + | ^^^^^ required by this bound in `use_trait_impl_2::assert_impl` error: unconstrained generic constant --> $DIR/abstract-const-as-cast-3.rs:38:19 @@ -123,6 +148,11 @@ LL | assert_impl::>(); | = note: expected constant `{ N as _ }` found constant `{ O as u128 }` +note: required by a bound in `use_trait_impl_2::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:32:23 + | +LL | fn assert_impl() {} + | ^^^^^ required by this bound in `use_trait_impl_2::assert_impl` error[E0308]: mismatched types --> $DIR/abstract-const-as-cast-3.rs:41:5 @@ -132,6 +162,11 @@ LL | assert_impl::>(); | = note: expected constant `12` found constant `13` +note: required by a bound in `use_trait_impl_2::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:32:23 + | +LL | fn assert_impl() {} + | ^^^^^ required by this bound in `use_trait_impl_2::assert_impl` error[E0308]: mismatched types --> $DIR/abstract-const-as-cast-3.rs:43:5 @@ -141,6 +176,11 @@ LL | assert_impl::>(); | = note: expected constant `13` found constant `14` +note: required by a bound in `use_trait_impl_2::assert_impl` + --> $DIR/abstract-const-as-cast-3.rs:32:23 + | +LL | fn assert_impl() {} + | ^^^^^ required by this bound in `use_trait_impl_2::assert_impl` error: aborting due to 12 previous errors diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.full.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.full.stderr index 38dfa65e4091f..f2fddfbfbb52a 100644 --- a/src/test/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.full.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.full.stderr @@ -6,6 +6,13 @@ LL | let x: Arr<{usize::MAX}> = Arr {}; | = note: expected constant `false` found constant `true` +note: required by a bound in `Arr` + --> $DIR/issue-72819-generic-in-const-eval.rs:8:39 + | +LL | struct Arr + | --- required by a bound in this +LL | where Assert::<{N < usize::MAX / 2}>: IsTrue, + | ^^^^^^ required by this bound in `Arr` error[E0308]: mismatched types --> $DIR/issue-72819-generic-in-const-eval.rs:20:32 @@ -15,6 +22,13 @@ LL | let x: Arr<{usize::MAX}> = Arr {}; | = note: expected constant `false` found constant `true` +note: required by a bound in `Arr` + --> $DIR/issue-72819-generic-in-const-eval.rs:8:39 + | +LL | struct Arr + | --- required by a bound in this +LL | where Assert::<{N < usize::MAX / 2}>: IsTrue, + | ^^^^^^ required by this bound in `Arr` error: aborting due to 2 previous errors diff --git a/src/test/ui/const-generics/issues/issue-73260.stderr b/src/test/ui/const-generics/issues/issue-73260.stderr index 3d1f90271f9a3..7670032e5b758 100644 --- a/src/test/ui/const-generics/issues/issue-73260.stderr +++ b/src/test/ui/const-generics/issues/issue-73260.stderr @@ -6,6 +6,14 @@ LL | let x: Arr<{usize::MAX}> = Arr {}; | = note: expected constant `false` found constant `true` +note: required by a bound in `Arr` + --> $DIR/issue-73260.rs:6:37 + | +LL | struct Arr + | --- required by a bound in this +LL | where +LL | Assert::<{N < usize::MAX / 2}>: IsTrue, + | ^^^^^^ required by this bound in `Arr` error[E0308]: mismatched types --> $DIR/issue-73260.rs:16:32 @@ -15,6 +23,14 @@ LL | let x: Arr<{usize::MAX}> = Arr {}; | = note: expected constant `false` found constant `true` +note: required by a bound in `Arr` + --> $DIR/issue-73260.rs:6:37 + | +LL | struct Arr + | --- required by a bound in this +LL | where +LL | Assert::<{N < usize::MAX / 2}>: IsTrue, + | ^^^^^^ required by this bound in `Arr` error: aborting due to 2 previous errors diff --git a/src/test/ui/const-generics/issues/issue-79674.stderr b/src/test/ui/const-generics/issues/issue-79674.stderr index 344b2c5631064..02b48b55f8b38 100644 --- a/src/test/ui/const-generics/issues/issue-79674.stderr +++ b/src/test/ui/const-generics/issues/issue-79674.stderr @@ -6,6 +6,14 @@ LL | requires_distinct("str", 12); | = note: expected constant `true` found constant `false` +note: required by a bound in `requires_distinct` + --> $DIR/issue-79674.rs:23:37 + | +LL | fn requires_distinct(_a: A, _b: B) where + | ----------------- required by a bound in this +LL | A: MiniTypeId, B: MiniTypeId, +LL | Lift<{is_same_type::()}>: IsFalse {} + | ^^^^^^^ required by this bound in `requires_distinct` error: aborting due to previous error From d464d3a700138b48e13d62846a35165d661e2ea4 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 12 Aug 2022 03:41:57 +0000 Subject: [PATCH 16/25] Add test for #100414 --- .../generic_const_exprs/obligation-cause.rs | 24 +++++++++++++++++++ .../obligation-cause.stderr | 20 ++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 src/test/ui/const-generics/generic_const_exprs/obligation-cause.rs create mode 100644 src/test/ui/const-generics/generic_const_exprs/obligation-cause.stderr diff --git a/src/test/ui/const-generics/generic_const_exprs/obligation-cause.rs b/src/test/ui/const-generics/generic_const_exprs/obligation-cause.rs new file mode 100644 index 0000000000000..e7c8e4f667d05 --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/obligation-cause.rs @@ -0,0 +1,24 @@ +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +trait True {} + +struct Is; + +impl True for Is {} + +fn g() +//~^ NOTE required by a bound in this +where + Is<{ std::mem::size_of::() == 0 }>: True, + //~^ NOTE required by a bound in `g` + //~| NOTE required by this bound in `g` +{ +} + +fn main() { + g::(); + //~^ ERROR mismatched types + //~| NOTE expected `false`, found `true` + //~| NOTE expected constant `false` +} diff --git a/src/test/ui/const-generics/generic_const_exprs/obligation-cause.stderr b/src/test/ui/const-generics/generic_const_exprs/obligation-cause.stderr new file mode 100644 index 0000000000000..a253ec676f716 --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/obligation-cause.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/obligation-cause.rs:20:5 + | +LL | g::(); + | ^^^^^^^^^^ expected `false`, found `true` + | + = note: expected constant `false` + found constant `true` +note: required by a bound in `g` + --> $DIR/obligation-cause.rs:13:44 + | +LL | fn g() + | - required by a bound in this +... +LL | Is<{ std::mem::size_of::() == 0 }>: True, + | ^^^^ required by this bound in `g` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From 8189a4536be3730ecc161c77fc655b08be179b50 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 23 Aug 2022 05:38:18 +0000 Subject: [PATCH 17/25] Use ExprItemObligation and ExprBindingObligation too --- .../rustc_trait_selection/src/traits/error_reporting/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 1f031d33e0653..e4af7022239b8 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1514,7 +1514,9 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { ); let code = error.obligation.cause.code().peel_derives().peel_match_impls(); if let ObligationCauseCode::BindingObligation(..) - | ObligationCauseCode::ItemObligation(..) = code + | ObligationCauseCode::ItemObligation(..) + | ObligationCauseCode::ExprBindingObligation(..) + | ObligationCauseCode::ExprItemObligation(..) = code { self.note_obligation_cause_code( &mut diag, From 8bb4b5f44c8b7c811e2075022e5205f927287e0a Mon Sep 17 00:00:00 2001 From: marmeladema Date: Sat, 12 Mar 2022 19:32:41 +0100 Subject: [PATCH 18/25] Support parsing IP addresses from a byte string --- library/std/src/net/parser.rs | 138 ++++++++++++++++++++++++++++++---- 1 file changed, 125 insertions(+), 13 deletions(-) diff --git a/library/std/src/net/parser.rs b/library/std/src/net/parser.rs index 069b660998559..a38031c48c862 100644 --- a/library/std/src/net/parser.rs +++ b/library/std/src/net/parser.rs @@ -39,8 +39,8 @@ struct Parser<'a> { } impl<'a> Parser<'a> { - fn new(input: &'a str) -> Parser<'a> { - Parser { state: input.as_bytes() } + fn new(input: &'a [u8]) -> Parser<'a> { + Parser { state: input } } /// Run a parser, and restore the pre-parse state if it fails. @@ -273,32 +273,106 @@ impl<'a> Parser<'a> { } } +impl IpAddr { + /// Parse an IP address from a slice of bytes. + /// + /// ``` + /// #![feature(addr_parse_ascii)] + /// + /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + /// + /// let localhost_v4 = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)); + /// let localhost_v6 = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); + /// + /// assert_eq!(IpAddr::parse_ascii(b"127.0.0.1"), Ok(localhost_v4)); + /// assert_eq!(IpAddr::parse_ascii(b"::1"), Ok(localhost_v6)); + /// ``` + #[unstable(feature = "addr_parse_ascii", issue = "101035")] + pub fn parse_ascii(b: &[u8]) -> Result { + Parser::new(b).parse_with(|p| p.read_ip_addr(), AddrKind::Ip) + } +} + #[stable(feature = "ip_addr", since = "1.7.0")] impl FromStr for IpAddr { type Err = AddrParseError; fn from_str(s: &str) -> Result { - Parser::new(s).parse_with(|p| p.read_ip_addr(), AddrKind::Ip) + Self::parse_ascii(s.as_bytes()) } } -#[stable(feature = "rust1", since = "1.0.0")] -impl FromStr for Ipv4Addr { - type Err = AddrParseError; - fn from_str(s: &str) -> Result { +impl Ipv4Addr { + /// Parse an IPv4 address from a slice of bytes. + /// + /// ``` + /// #![feature(addr_parse_ascii)] + /// + /// use std::net::Ipv4Addr; + /// + /// let localhost = Ipv4Addr::new(127, 0, 0, 1); + /// + /// assert_eq!(Ipv4Addr::parse_ascii(b"127.0.0.1"), Ok(localhost)); + /// ``` + #[unstable(feature = "addr_parse_ascii", issue = "101035")] + pub fn parse_ascii(b: &[u8]) -> Result { // don't try to parse if too long - if s.len() > 15 { + if b.len() > 15 { Err(AddrParseError(AddrKind::Ipv4)) } else { - Parser::new(s).parse_with(|p| p.read_ipv4_addr(), AddrKind::Ipv4) + Parser::new(b).parse_with(|p| p.read_ipv4_addr(), AddrKind::Ipv4) } } } +#[stable(feature = "rust1", since = "1.0.0")] +impl FromStr for Ipv4Addr { + type Err = AddrParseError; + fn from_str(s: &str) -> Result { + Self::parse_ascii(s.as_bytes()) + } +} + +impl Ipv6Addr { + /// Parse an IPv6 address from a slice of bytes. + /// + /// ``` + /// #![feature(addr_parse_ascii)] + /// + /// use std::net::Ipv6Addr; + /// + /// let localhost = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1); + /// + /// assert_eq!(Ipv6Addr::parse_ascii(b"::1"), Ok(localhost)); + /// ``` + #[unstable(feature = "addr_parse_ascii", issue = "101035")] + pub fn parse_ascii(b: &[u8]) -> Result { + Parser::new(b).parse_with(|p| p.read_ipv6_addr(), AddrKind::Ipv6) + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl FromStr for Ipv6Addr { type Err = AddrParseError; fn from_str(s: &str) -> Result { - Parser::new(s).parse_with(|p| p.read_ipv6_addr(), AddrKind::Ipv6) + Self::parse_ascii(s.as_bytes()) + } +} + +impl SocketAddrV4 { + /// Parse an IPv4 socket address from a slice of bytes. + /// + /// ``` + /// #![feature(addr_parse_ascii)] + /// + /// use std::net::{Ipv4Addr, SocketAddrV4}; + /// + /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080); + /// + /// assert_eq!(SocketAddrV4::parse_ascii(b"127.0.0.1:8080"), Ok(socket)); + /// ``` + #[unstable(feature = "addr_parse_ascii", issue = "101035")] + pub fn parse_ascii(b: &[u8]) -> Result { + Parser::new(b).parse_with(|p| p.read_socket_addr_v4(), AddrKind::SocketV4) } } @@ -306,7 +380,25 @@ impl FromStr for Ipv6Addr { impl FromStr for SocketAddrV4 { type Err = AddrParseError; fn from_str(s: &str) -> Result { - Parser::new(s).parse_with(|p| p.read_socket_addr_v4(), AddrKind::SocketV4) + Self::parse_ascii(s.as_bytes()) + } +} + +impl SocketAddrV6 { + /// Parse an IPv6 socket address from a slice of bytes. + /// + /// ``` + /// #![feature(addr_parse_ascii)] + /// + /// use std::net::{Ipv6Addr, SocketAddrV6}; + /// + /// let socket = SocketAddrV6::new(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0, 0); + /// + /// assert_eq!(SocketAddrV6::parse_ascii(b"[2001:db8::1]:8080"), Ok(socket)); + /// ``` + #[unstable(feature = "addr_parse_ascii", issue = "101035")] + pub fn parse_ascii(b: &[u8]) -> Result { + Parser::new(b).parse_with(|p| p.read_socket_addr_v6(), AddrKind::SocketV6) } } @@ -314,7 +406,27 @@ impl FromStr for SocketAddrV4 { impl FromStr for SocketAddrV6 { type Err = AddrParseError; fn from_str(s: &str) -> Result { - Parser::new(s).parse_with(|p| p.read_socket_addr_v6(), AddrKind::SocketV6) + Self::parse_ascii(s.as_bytes()) + } +} + +impl SocketAddr { + /// Parse a socket address from a slice of bytes. + /// + /// ``` + /// #![feature(addr_parse_ascii)] + /// + /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; + /// + /// let socket_v4 = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); + /// let socket_v6 = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), 8080); + /// + /// assert_eq!(SocketAddr::parse_ascii(b"127.0.0.1:8080"), Ok(socket_v4)); + /// assert_eq!(SocketAddr::parse_ascii(b"[::1]:8080"), Ok(socket_v6)); + /// ``` + #[unstable(feature = "addr_parse_ascii", issue = "101035")] + pub fn parse_ascii(b: &[u8]) -> Result { + Parser::new(b).parse_with(|p| p.read_socket_addr(), AddrKind::Socket) } } @@ -322,7 +434,7 @@ impl FromStr for SocketAddrV6 { impl FromStr for SocketAddr { type Err = AddrParseError; fn from_str(s: &str) -> Result { - Parser::new(s).parse_with(|p| p.read_socket_addr(), AddrKind::Socket) + Self::parse_ascii(s.as_bytes()) } } From b48870b451dd9d3f3f827aa54d9becdfdd811ba3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Tue, 5 Jul 2022 00:00:00 +0000 Subject: [PATCH 19/25] Replace `Body::basic_blocks()` with field access --- .../rustc_borrowck/src/constraint_generation.rs | 2 +- compiler/rustc_borrowck/src/dataflow.rs | 2 +- .../src/diagnostics/explain_borrow.rs | 6 +++--- .../src/diagnostics/move_errors.rs | 2 +- compiler/rustc_borrowck/src/location.rs | 2 +- .../rustc_borrowck/src/region_infer/values.rs | 4 ++-- compiler/rustc_borrowck/src/type_check/mod.rs | 2 +- compiler/rustc_codegen_cranelift/src/analyze.rs | 2 +- compiler/rustc_codegen_cranelift/src/base.rs | 4 ++-- compiler/rustc_codegen_cranelift/src/constant.rs | 2 +- compiler/rustc_codegen_ssa/src/mir/analyze.rs | 6 +++--- compiler/rustc_codegen_ssa/src/mir/mod.rs | 8 ++++---- .../src/interpret/eval_context.rs | 2 +- .../src/interpret/intrinsics/caller_location.rs | 2 +- compiler/rustc_const_eval/src/interpret/step.rs | 2 +- .../src/transform/check_consts/check.rs | 2 +- .../src/transform/promote_consts.rs | 6 +++--- .../rustc_const_eval/src/transform/validate.rs | 8 ++++---- compiler/rustc_middle/src/mir/generic_graph.rs | 4 ++-- compiler/rustc_middle/src/mir/mod.rs | 7 +------ compiler/rustc_middle/src/mir/patch.rs | 10 +++++----- compiler/rustc_middle/src/mir/pretty.rs | 4 ++-- compiler/rustc_middle/src/mir/spanview.rs | 2 +- compiler/rustc_middle/src/mir/traversal.rs | 4 ++-- compiler/rustc_middle/src/mir/visit.rs | 2 +- compiler/rustc_mir_build/src/build/mod.rs | 2 +- .../rustc_mir_dataflow/src/framework/engine.rs | 9 ++++----- .../rustc_mir_dataflow/src/framework/graphviz.rs | 4 ++-- .../rustc_mir_dataflow/src/framework/tests.rs | 10 ++++------ .../rustc_mir_dataflow/src/move_paths/builder.rs | 2 +- .../rustc_mir_dataflow/src/move_paths/mod.rs | 2 +- compiler/rustc_mir_dataflow/src/rustc_peek.rs | 2 +- compiler/rustc_mir_dataflow/src/storage.rs | 2 +- .../src/abort_unwinding_calls.rs | 2 +- .../rustc_mir_transform/src/add_call_guards.rs | 2 +- .../src/add_moves_for_packed_drops.rs | 2 +- compiler/rustc_mir_transform/src/const_goto.rs | 4 ++-- compiler/rustc_mir_transform/src/const_prop.rs | 2 +- .../rustc_mir_transform/src/const_prop_lint.rs | 4 ++-- .../rustc_mir_transform/src/coverage/graph.rs | 4 ++-- compiler/rustc_mir_transform/src/coverage/mod.rs | 2 +- .../rustc_mir_transform/src/coverage/query.rs | 4 ++-- .../rustc_mir_transform/src/coverage/tests.rs | 6 +++--- .../src/deduplicate_blocks.rs | 5 ++--- compiler/rustc_mir_transform/src/dest_prop.rs | 6 +++--- .../src/early_otherwise_branch.rs | 6 +++--- .../rustc_mir_transform/src/elaborate_drops.rs | 12 ++++++------ .../rustc_mir_transform/src/ffi_unwind_calls.rs | 2 +- compiler/rustc_mir_transform/src/generator.rs | 14 +++++++------- compiler/rustc_mir_transform/src/inline.rs | 16 ++++++++-------- compiler/rustc_mir_transform/src/inline/cycle.rs | 2 +- .../src/multiple_return_terminators.rs | 2 +- .../src/normalize_array_len.rs | 4 ++-- compiler/rustc_mir_transform/src/nrvo.rs | 4 ++-- .../src/remove_noop_landing_pads.rs | 2 +- .../src/remove_uninit_drops.rs | 2 +- .../src/separate_const_switch.rs | 4 ++-- compiler/rustc_mir_transform/src/simplify.rs | 4 ++-- .../src/simplify_comparison_integral.rs | 2 +- compiler/rustc_mir_transform/src/simplify_try.rs | 4 ++-- .../src/uninhabited_enum_branching.rs | 6 +++--- .../rustc_monomorphize/src/partitioning/mod.rs | 2 +- compiler/rustc_ty_utils/src/ty.rs | 2 +- .../clippy/clippy_lints/src/redundant_clone.rs | 6 +++--- .../clippy_utils/src/qualify_min_const_fn.rs | 2 +- 65 files changed, 131 insertions(+), 140 deletions(-) diff --git a/compiler/rustc_borrowck/src/constraint_generation.rs b/compiler/rustc_borrowck/src/constraint_generation.rs index 5e9cec5c350c9..144fd15fc2407 100644 --- a/compiler/rustc_borrowck/src/constraint_generation.rs +++ b/compiler/rustc_borrowck/src/constraint_generation.rs @@ -31,7 +31,7 @@ pub(super) fn generate_constraints<'cx, 'tcx>( body, }; - for (bb, data) in body.basic_blocks().iter_enumerated() { + for (bb, data) in body.basic_blocks.iter_enumerated() { cg.visit_basic_block_data(bb, data); } } diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index 97d5a8d158e1e..816288eb50b29 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -143,7 +143,7 @@ struct OutOfScopePrecomputer<'a, 'tcx> { impl<'a, 'tcx> OutOfScopePrecomputer<'a, 'tcx> { fn new(body: &'a Body<'tcx>, regioncx: &'a RegionInferenceContext<'tcx>) -> Self { OutOfScopePrecomputer { - visited: BitSet::new_empty(body.basic_blocks().len()), + visited: BitSet::new_empty(body.basic_blocks.len()), visit_stack: vec![], body, regioncx, diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 68f9a7c5007c8..a6b8c6057e05e 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -459,7 +459,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { return outmost_back_edge; } - let block = &self.body.basic_blocks()[location.block]; + let block = &self.body.basic_blocks[location.block]; if location.statement_index < block.statements.len() { let successor = location.successor_within_block(); @@ -518,7 +518,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } if loop_head.dominates(from, &self.dominators) { - let block = &self.body.basic_blocks()[from.block]; + let block = &self.body.basic_blocks[from.block]; if from.statement_index < block.statements.len() { let successor = from.successor_within_block(); @@ -568,7 +568,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { UseSpans::PatUse(span) | UseSpans::OtherUse(span) | UseSpans::FnSelfUse { var_span: span, .. } => { - let block = &self.body.basic_blocks()[location.block]; + let block = &self.body.basic_blocks[location.block]; let kind = if let Some(&Statement { kind: StatementKind::FakeRead(box (FakeReadCause::ForLet(_), _)), diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index cb3cd479ae2b6..16c2f9ccc6aa4 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -88,7 +88,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if let Some(StatementKind::Assign(box ( place, Rvalue::Use(Operand::Move(move_from)), - ))) = self.body.basic_blocks()[location.block] + ))) = self.body.basic_blocks[location.block] .statements .get(location.statement_index) .map(|stmt| &stmt.kind) diff --git a/compiler/rustc_borrowck/src/location.rs b/compiler/rustc_borrowck/src/location.rs index 70a3116949894..5ca3f2f4d033c 100644 --- a/compiler/rustc_borrowck/src/location.rs +++ b/compiler/rustc_borrowck/src/location.rs @@ -33,7 +33,7 @@ impl LocationTable { pub(crate) fn new(body: &Body<'_>) -> Self { let mut num_points = 0; let statements_before_block = body - .basic_blocks() + .basic_blocks .iter() .map(|block_data| { let v = num_points; diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs index c81ef10f7c740..de20a4bb465c2 100644 --- a/compiler/rustc_borrowck/src/region_infer/values.rs +++ b/compiler/rustc_borrowck/src/region_infer/values.rs @@ -25,7 +25,7 @@ impl RegionValueElements { pub(crate) fn new(body: &Body<'_>) -> Self { let mut num_points = 0; let statements_before_block: IndexVec = body - .basic_blocks() + .basic_blocks .iter() .map(|block_data| { let v = num_points; @@ -37,7 +37,7 @@ impl RegionValueElements { debug!("RegionValueElements: num_points={:#?}", num_points); let mut basic_blocks = IndexVec::with_capacity(num_points); - for (bb, bb_data) in body.basic_blocks().iter_enumerated() { + for (bb, bb_data) in body.basic_blocks.iter_enumerated() { basic_blocks.extend((0..=bb_data.statements.len()).map(|_| bb)); } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 293d847ec9ab7..c1812aa4bbab6 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -2633,7 +2633,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.check_local(&body, local, local_decl); } - for (block, block_data) in body.basic_blocks().iter_enumerated() { + for (block, block_data) in body.basic_blocks.iter_enumerated() { let mut location = Location { block, statement_index: 0 }; for stmt in &block_data.statements { if !stmt.source_info.span.is_dummy() { diff --git a/compiler/rustc_codegen_cranelift/src/analyze.rs b/compiler/rustc_codegen_cranelift/src/analyze.rs index 35b89358b1984..0cbb9f3ec2d80 100644 --- a/compiler/rustc_codegen_cranelift/src/analyze.rs +++ b/compiler/rustc_codegen_cranelift/src/analyze.rs @@ -26,7 +26,7 @@ pub(crate) fn analyze(fx: &FunctionCx<'_, '_, '_>) -> IndexVec { }) .collect::>(); - for bb in fx.mir.basic_blocks().iter() { + for bb in fx.mir.basic_blocks.iter() { for stmt in bb.statements.iter() { match &stmt.kind { Assign(place_and_rval) => match &place_and_rval.1 { diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 44c34d6c8cb79..3011813c7035b 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -73,7 +73,7 @@ pub(crate) fn codegen_fn<'tcx>( // Predefine blocks let start_block = bcx.create_block(); let block_map: IndexVec = - (0..mir.basic_blocks().len()).map(|_| bcx.create_block()).collect(); + (0..mir.basic_blocks.len()).map(|_| bcx.create_block()).collect(); // Make FunctionCx let target_config = module.target_config(); @@ -271,7 +271,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { } fx.tcx.sess.time("codegen prelude", || crate::abi::codegen_fn_prelude(fx, start_block)); - for (bb, bb_data) in fx.mir.basic_blocks().iter_enumerated() { + for (bb, bb_data) in fx.mir.basic_blocks.iter_enumerated() { let block = fx.get_block(bb); fx.bcx.switch_to_block(block); diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index 7f7fd0e9c579d..e2b68f24a21dc 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -505,7 +505,7 @@ pub(crate) fn mir_operand_get_const_val<'tcx>( return None; } let mut computed_const_val = None; - for bb_data in fx.mir.basic_blocks() { + for bb_data in fx.mir.basic_blocks.iter() { for stmt in &bb_data.statements { match &stmt.kind { StatementKind::Assign(local_and_rvalue) if &local_and_rvalue.0 == place => { diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs index 24da48ead63a2..c7617d2e464fa 100644 --- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs +++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs @@ -266,7 +266,7 @@ pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec, mir: &mir::Body<'tcx>, ) { - for (bb, data) in mir.basic_blocks().iter_enumerated() { + for (bb, data) in mir.basic_blocks.iter_enumerated() { match data.terminator().kind { TerminatorKind::Goto { .. } | TerminatorKind::Resume @@ -296,7 +296,7 @@ pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec(result: &mut IndexVec, mir: &mir::Body<'tcx>) { - let mut funclet_succs = IndexVec::from_elem(None, mir.basic_blocks()); + let mut funclet_succs = IndexVec::from_elem(None, &mir.basic_blocks); let mut set_successor = |funclet: mir::BasicBlock, succ| match funclet_succs[funclet] { ref mut s @ None => { @@ -359,7 +359,7 @@ pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec>( let start_llbb = Bx::append_block(cx, llfn, "start"); let mut bx = Bx::build(cx, start_llbb); - if mir.basic_blocks().iter().any(|bb| bb.is_cleanup) { + if mir.basic_blocks.iter().any(|bb| bb.is_cleanup) { bx.set_personality_fn(cx.eh_personality()); } let cleanup_kinds = analyze::cleanup_kinds(&mir); let cached_llbbs: IndexVec> = mir - .basic_blocks() + .basic_blocks .indices() .map(|bb| if bb == mir::START_BLOCK { Some(start_llbb) } else { None }) .collect(); @@ -172,8 +172,8 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( unreachable_block: None, double_unwind_guard: None, cleanup_kinds, - landing_pads: IndexVec::from_elem(None, mir.basic_blocks()), - funclets: IndexVec::from_fn_n(|_| None, mir.basic_blocks().len()), + landing_pads: IndexVec::from_elem(None, &mir.basic_blocks), + funclets: IndexVec::from_fn_n(|_| None, mir.basic_blocks.len()), locals: IndexVec::new(), debug_context, per_local_var_debug_info: None, diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 150d6589b0807..594bfd13f1d87 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -782,7 +782,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { assert_eq!( unwinding, match self.frame().loc { - Ok(loc) => self.body().basic_blocks()[loc.block].is_cleanup, + Ok(loc) => self.body().basic_blocks[loc.block].is_cleanup, Err(_) => true, } ); diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs index 5864b92155287..91f4f04251721 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs @@ -28,7 +28,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let mut source_info = *frame.body.source_info(loc); // If this is a `Call` terminator, use the `fn_span` instead. - let block = &frame.body.basic_blocks()[loc.block]; + let block = &frame.body.basic_blocks[loc.block]; if loc.statement_index == block.statements.len() { debug!( "find_closest_untracked_caller_location: got terminator {:?} ({:?})", diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index fea158a9fe450..683e11ff7e0e5 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -53,7 +53,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.pop_stack_frame(/* unwinding */ true)?; return Ok(true); }; - let basic_block = &self.body().basic_blocks()[loc.block]; + let basic_block = &self.body().basic_blocks[loc.block]; if let Some(stmt) = basic_block.statements.get(loc.statement_index) { let old_frames = self.frame_idx(); diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 0adb88a180f8b..cbfdb47dd1a40 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -135,7 +135,7 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> { // qualifs for the return type. let return_block = ccx .body - .basic_blocks() + .basic_blocks .iter_enumerated() .find(|(_, block)| matches!(block.terminator().kind, TerminatorKind::Return)) .map(|(bb, _)| bb); diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index 161c89e3242b9..6301388d1e840 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -710,7 +710,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { } fn assign(&mut self, dest: Local, rvalue: Rvalue<'tcx>, span: Span) { - let last = self.promoted.basic_blocks().last().unwrap(); + let last = self.promoted.basic_blocks.last().unwrap(); let data = &mut self.promoted[last]; data.statements.push(Statement { source_info: SourceInfo::outermost(span), @@ -803,7 +803,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { self.visit_operand(arg, loc); } - let last = self.promoted.basic_blocks().last().unwrap(); + let last = self.promoted.basic_blocks.last().unwrap(); let new_target = self.new_block(); *self.promoted[last].terminator_mut() = Terminator { @@ -1041,7 +1041,7 @@ pub fn is_const_fn_in_array_repeat_expression<'tcx>( _ => {} } - for block in body.basic_blocks() { + for block in body.basic_blocks.iter() { if let Some(Terminator { kind: TerminatorKind::Call { func, destination, .. }, .. }) = &block.terminator { diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 1a14cd79fa069..45a94972c1134 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -140,8 +140,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if bb == START_BLOCK { self.fail(location, "start block must not have predecessors") } - if let Some(bb) = self.body.basic_blocks().get(bb) { - let src = self.body.basic_blocks().get(location.block).unwrap(); + if let Some(bb) = self.body.basic_blocks.get(bb) { + let src = self.body.basic_blocks.get(location.block).unwrap(); match (src.is_cleanup, bb.is_cleanup, edge_kind) { // Non-cleanup blocks can jump to non-cleanup blocks along non-unwind edges (false, false, EdgeKind::Normal) @@ -881,13 +881,13 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } TerminatorKind::Resume | TerminatorKind::Abort => { let bb = location.block; - if !self.body.basic_blocks()[bb].is_cleanup { + if !self.body.basic_blocks[bb].is_cleanup { self.fail(location, "Cannot `Resume` or `Abort` from non-cleanup basic block") } } TerminatorKind::Return => { let bb = location.block; - if self.body.basic_blocks()[bb].is_cleanup { + if self.body.basic_blocks[bb].is_cleanup { self.fail(location, "Cannot `Return` from cleanup basic block") } } diff --git a/compiler/rustc_middle/src/mir/generic_graph.rs b/compiler/rustc_middle/src/mir/generic_graph.rs index f3621cd99d344..d1f3561c02c5d 100644 --- a/compiler/rustc_middle/src/mir/generic_graph.rs +++ b/compiler/rustc_middle/src/mir/generic_graph.rs @@ -12,14 +12,14 @@ pub fn mir_fn_to_generic_graph<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Grap // Nodes let nodes: Vec = body - .basic_blocks() + .basic_blocks .iter_enumerated() .map(|(block, _)| bb_to_graph_node(block, body, dark_mode)) .collect(); // Edges let mut edges = Vec::new(); - for (source, _) in body.basic_blocks().iter_enumerated() { + for (source, _) in body.basic_blocks.iter_enumerated() { let def_id = body.source.def_id(); let terminator = body[source].terminator(); let labels = terminator.kind.fmt_successor_labels(); diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 9da9b4e91f647..f7a1e9b286488 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -331,11 +331,6 @@ impl<'tcx> Body<'tcx> { body } - #[inline] - pub fn basic_blocks(&self) -> &IndexVec> { - &self.basic_blocks - } - #[inline] pub fn basic_blocks_mut(&mut self) -> &mut IndexVec> { self.basic_blocks.as_mut() @@ -490,7 +485,7 @@ impl<'tcx> Index for Body<'tcx> { #[inline] fn index(&self, index: BasicBlock) -> &BasicBlockData<'tcx> { - &self.basic_blocks()[index] + &self.basic_blocks[index] } } diff --git a/compiler/rustc_middle/src/mir/patch.rs b/compiler/rustc_middle/src/mir/patch.rs index 8aa761aae8d90..24fe3b47256e2 100644 --- a/compiler/rustc_middle/src/mir/patch.rs +++ b/compiler/rustc_middle/src/mir/patch.rs @@ -19,7 +19,7 @@ pub struct MirPatch<'tcx> { impl<'tcx> MirPatch<'tcx> { pub fn new(body: &Body<'tcx>) -> Self { let mut result = MirPatch { - patch_map: IndexVec::from_elem(None, body.basic_blocks()), + patch_map: IndexVec::from_elem(None, &body.basic_blocks), new_blocks: vec![], new_statements: vec![], new_locals: vec![], @@ -29,7 +29,7 @@ impl<'tcx> MirPatch<'tcx> { }; // Check if we already have a resume block - for (bb, block) in body.basic_blocks().iter_enumerated() { + for (bb, block) in body.basic_blocks.iter_enumerated() { if let TerminatorKind::Resume = block.terminator().kind && block.statements.is_empty() { result.resume_block = Some(bb); break; @@ -61,7 +61,7 @@ impl<'tcx> MirPatch<'tcx> { } pub fn terminator_loc(&self, body: &Body<'tcx>, bb: BasicBlock) -> Location { - let offset = match bb.index().checked_sub(body.basic_blocks().len()) { + let offset = match bb.index().checked_sub(body.basic_blocks.len()) { Some(index) => self.new_blocks[index].statements.len(), None => body[bb].statements.len(), }; @@ -129,7 +129,7 @@ impl<'tcx> MirPatch<'tcx> { debug!( "MirPatch: {} new blocks, starting from index {}", self.new_blocks.len(), - body.basic_blocks().len() + body.basic_blocks.len() ); let bbs = if self.patch_map.is_empty() && self.new_blocks.is_empty() { body.basic_blocks.as_mut_preserves_cfg() @@ -173,7 +173,7 @@ impl<'tcx> MirPatch<'tcx> { } pub fn source_info_for_location(&self, body: &Body<'tcx>, loc: Location) -> SourceInfo { - let data = match loc.block.index().checked_sub(body.basic_blocks().len()) { + let data = match loc.block.index().checked_sub(body.basic_blocks.len()) { Some(new) => &self.new_blocks[new], None => &body[loc.block], }; diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 0ce41337b910d..da6af89b09b9b 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -318,10 +318,10 @@ where F: FnMut(PassWhere, &mut dyn Write) -> io::Result<()>, { write_mir_intro(tcx, body, w)?; - for block in body.basic_blocks().indices() { + for block in body.basic_blocks.indices() { extra_data(PassWhere::BeforeBlock(block), w)?; write_basic_block(tcx, block, body, extra_data, w)?; - if block.index() + 1 != body.basic_blocks().len() { + if block.index() + 1 != body.basic_blocks.len() { writeln!(w)?; } } diff --git a/compiler/rustc_middle/src/mir/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs index 4418b848e512a..6e64a3b80c1fb 100644 --- a/compiler/rustc_middle/src/mir/spanview.rs +++ b/compiler/rustc_middle/src/mir/spanview.rs @@ -105,7 +105,7 @@ where } let body_span = hir_body.unwrap().value.span; let mut span_viewables = Vec::new(); - for (bb, data) in body.basic_blocks().iter_enumerated() { + for (bb, data) in body.basic_blocks.iter_enumerated() { match spanview { MirSpanview::Statement => { for (i, statement) in data.statements.iter().enumerate() { diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs index 627dc32f37eb5..55b2c592795bf 100644 --- a/compiler/rustc_middle/src/mir/traversal.rs +++ b/compiler/rustc_middle/src/mir/traversal.rs @@ -37,7 +37,7 @@ impl<'a, 'tcx> Preorder<'a, 'tcx> { Preorder { body, - visited: BitSet::new_empty(body.basic_blocks().len()), + visited: BitSet::new_empty(body.basic_blocks.len()), worklist, root_is_start_block: root == START_BLOCK, } @@ -71,7 +71,7 @@ impl<'a, 'tcx> Iterator for Preorder<'a, 'tcx> { fn size_hint(&self) -> (usize, Option) { // All the blocks, minus the number of blocks we've visited. - let upper = self.body.basic_blocks().len() - self.visited.count(); + let upper = self.body.basic_blocks.len() - self.visited.count(); let lower = if self.root_is_start_block { // We will visit all remaining blocks exactly once. diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 4a85defb1ed84..7bd65f42e3f92 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -951,7 +951,7 @@ macro_rules! basic_blocks { $body.basic_blocks.as_mut_preserves_cfg() }; ($body:ident,) => { - $body.basic_blocks() + $body.basic_blocks }; } diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 461c837f6df19..684b228e87fa9 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -272,7 +272,7 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> Body<'_ // by borrow checking. debug_assert!( !(body.local_decls.has_free_regions() - || body.basic_blocks().has_free_regions() + || body.basic_blocks.has_free_regions() || body.var_debug_info.has_free_regions() || body.yield_ty().has_free_regions()), "Unexpected free regions in MIR: {:?}", diff --git a/compiler/rustc_mir_dataflow/src/framework/engine.rs b/compiler/rustc_mir_dataflow/src/framework/engine.rs index f374658ceb691..ecfa90371f5ac 100644 --- a/compiler/rustc_mir_dataflow/src/framework/engine.rs +++ b/compiler/rustc_mir_dataflow/src/framework/engine.rs @@ -108,9 +108,9 @@ where // Otherwise, compute and store the cumulative transfer function for each block. let identity = GenKillSet::identity(analysis.bottom_value(body).domain_size()); - let mut trans_for_block = IndexVec::from_elem(identity, body.basic_blocks()); + let mut trans_for_block = IndexVec::from_elem(identity, &body.basic_blocks); - for (block, block_data) in body.basic_blocks().iter_enumerated() { + for (block, block_data) in body.basic_blocks.iter_enumerated() { let trans = &mut trans_for_block[block]; A::Direction::gen_kill_effects_in_block(&analysis, trans, block, block_data); } @@ -144,7 +144,7 @@ where apply_trans_for_block: Option>, ) -> Self { let bottom_value = analysis.bottom_value(body); - let mut entry_sets = IndexVec::from_elem(bottom_value.clone(), body.basic_blocks()); + let mut entry_sets = IndexVec::from_elem(bottom_value.clone(), &body.basic_blocks); analysis.initialize_start_block(body, &mut entry_sets[mir::START_BLOCK]); if A::Direction::IS_BACKWARD && entry_sets[mir::START_BLOCK] != bottom_value { @@ -197,8 +197,7 @@ where .. } = self; - let mut dirty_queue: WorkQueue = - WorkQueue::with_none(body.basic_blocks().len()); + let mut dirty_queue: WorkQueue = WorkQueue::with_none(body.basic_blocks.len()); if A::Direction::IS_FORWARD { for (bb, _) in traversal::reverse_postorder(body) { diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index c94198c56a8d1..579fe68a14935 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -108,12 +108,12 @@ where type Edge = CfgEdge; fn nodes(&self) -> dot::Nodes<'_, Self::Node> { - self.body.basic_blocks().indices().collect::>().into() + self.body.basic_blocks.indices().collect::>().into() } fn edges(&self) -> dot::Edges<'_, Self::Edge> { self.body - .basic_blocks() + .basic_blocks .indices() .flat_map(|bb| dataflow_successors(self.body, bb)) .collect::>() diff --git a/compiler/rustc_mir_dataflow/src/framework/tests.rs b/compiler/rustc_mir_dataflow/src/framework/tests.rs index d9461fd3abd81..17102454a88de 100644 --- a/compiler/rustc_mir_dataflow/src/framework/tests.rs +++ b/compiler/rustc_mir_dataflow/src/framework/tests.rs @@ -100,9 +100,9 @@ impl MockAnalysis<'_, D> { fn mock_entry_sets(&self) -> IndexVec> { let empty = self.bottom_value(self.body); - let mut ret = IndexVec::from_elem(empty, &self.body.basic_blocks()); + let mut ret = IndexVec::from_elem(empty, &self.body.basic_blocks); - for (bb, _) in self.body.basic_blocks().iter_enumerated() { + for (bb, _) in self.body.basic_blocks.iter_enumerated() { ret[bb] = self.mock_entry_set(bb); } @@ -169,7 +169,7 @@ impl<'tcx, D: Direction> AnalysisDomain<'tcx> for MockAnalysis<'tcx, D> { const NAME: &'static str = "mock"; fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain { - BitSet::new_empty(Self::BASIC_BLOCK_OFFSET + body.basic_blocks().len()) + BitSet::new_empty(Self::BASIC_BLOCK_OFFSET + body.basic_blocks.len()) } fn initialize_start_block(&self, _: &mir::Body<'tcx>, _: &mut Self::Domain) { @@ -271,9 +271,7 @@ fn test_cursor(analysis: MockAnalysis<'_, D>) { cursor.allow_unreachable(); let every_target = || { - body.basic_blocks() - .iter_enumerated() - .flat_map(|(bb, _)| SeekTarget::iter_in_block(body, bb)) + body.basic_blocks.iter_enumerated().flat_map(|(bb, _)| SeekTarget::iter_in_block(body, bb)) }; let mut seek_to_target = |targ| { diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index 116e5c1f3ce0a..c325838622399 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -243,7 +243,7 @@ pub(super) fn gather_moves<'tcx>( builder.gather_args(); - for (bb, block) in body.basic_blocks().iter_enumerated() { + for (bb, block) in body.basic_blocks.iter_enumerated() { for (i, stmt) in block.statements.iter().enumerate() { let source = Location { block: bb, statement_index: i }; builder.gather_statement(source, stmt); diff --git a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs index a951c5b0b1c94..b36e268cf8bf7 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs @@ -217,7 +217,7 @@ where fn new(body: &Body<'_>) -> Self { LocationMap { map: body - .basic_blocks() + .basic_blocks .iter() .map(|block| vec![T::default(); block.statements.len() + 1]) .collect(), diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs index f2471f37a5266..382d371840fa9 100644 --- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs +++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs @@ -97,7 +97,7 @@ pub fn sanity_check_via_rustc_peek<'tcx, A>( let mut cursor = ResultsCursor::new(body, results); - let peek_calls = body.basic_blocks().iter_enumerated().filter_map(|(bb, block_data)| { + let peek_calls = body.basic_blocks.iter_enumerated().filter_map(|(bb, block_data)| { PeekCall::from_terminator(tcx, block_data.terminator()).map(|call| (bb, block_data, call)) }); diff --git a/compiler/rustc_mir_dataflow/src/storage.rs b/compiler/rustc_mir_dataflow/src/storage.rs index c909648ea017e..e5a0e1d312eae 100644 --- a/compiler/rustc_mir_dataflow/src/storage.rs +++ b/compiler/rustc_mir_dataflow/src/storage.rs @@ -7,7 +7,7 @@ use rustc_middle::mir::{self, Local}; pub fn always_storage_live_locals(body: &mir::Body<'_>) -> BitSet { let mut always_live_locals = BitSet::new_filled(body.local_decls.len()); - for block in body.basic_blocks() { + for block in &*body.basic_blocks { for statement in &block.statements { use mir::StatementKind::{StorageDead, StorageLive}; if let StorageLive(l) | StorageDead(l) = statement.kind { diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs index 2502e8b603c3e..d8f85d2e37982 100644 --- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs +++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs @@ -56,7 +56,7 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls { // example. let mut calls_to_terminate = Vec::new(); let mut cleanups_to_remove = Vec::new(); - for (id, block) in body.basic_blocks().iter_enumerated() { + for (id, block) in body.basic_blocks.iter_enumerated() { if block.is_cleanup { continue; } diff --git a/compiler/rustc_mir_transform/src/add_call_guards.rs b/compiler/rustc_mir_transform/src/add_call_guards.rs index f12c8560c0e82..30966d22e2f6d 100644 --- a/compiler/rustc_mir_transform/src/add_call_guards.rs +++ b/compiler/rustc_mir_transform/src/add_call_guards.rs @@ -45,7 +45,7 @@ impl AddCallGuards { // We need a place to store the new blocks generated let mut new_blocks = Vec::new(); - let cur_len = body.basic_blocks().len(); + let cur_len = body.basic_blocks.len(); for block in body.basic_blocks_mut() { match block.terminator { diff --git a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs index 8de0aad041cc3..ffb5d8c6d95f2 100644 --- a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs +++ b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs @@ -55,7 +55,7 @@ fn add_moves_for_packed_drops_patch<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) let mut patch = MirPatch::new(body); let param_env = tcx.param_env(def_id); - for (bb, data) in body.basic_blocks().iter_enumerated() { + for (bb, data) in body.basic_blocks.iter_enumerated() { let loc = Location { block: bb, statement_index: data.statements.len() }; let terminator = data.terminator(); diff --git a/compiler/rustc_mir_transform/src/const_goto.rs b/compiler/rustc_mir_transform/src/const_goto.rs index 5acf939f06bf6..0a305a402095d 100644 --- a/compiler/rustc_mir_transform/src/const_goto.rs +++ b/compiler/rustc_mir_transform/src/const_goto.rs @@ -61,14 +61,14 @@ impl<'tcx> Visitor<'tcx> for ConstGotoOptimizationFinder<'_, 'tcx> { let _: Option<_> = try { let target = terminator.kind.as_goto()?; // We only apply this optimization if the last statement is a const assignment - let last_statement = self.body.basic_blocks()[location.block].statements.last()?; + let last_statement = self.body.basic_blocks[location.block].statements.last()?; if let (place, Rvalue::Use(Operand::Constant(_const))) = last_statement.kind.as_assign()? { // We found a constant being assigned to `place`. // Now check that the target of this Goto switches on this place. - let target_bb = &self.body.basic_blocks()[target]; + let target_bb = &self.body.basic_blocks[target]; // The `StorageDead(..)` statement does not affect the functionality of mir. // We can move this part of the statement up to the predecessor. diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index 1c087b93b4965..fdcc065f112b6 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -131,7 +131,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp { let dummy_body = &Body::new( body.source, - body.basic_blocks().clone(), + (*body.basic_blocks).clone(), body.source_scopes.clone(), body.local_decls.clone(), Default::default(), diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index c2ea55af48a1e..1254aee39942e 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -106,7 +106,7 @@ impl<'tcx> MirLint<'tcx> for ConstProp { let dummy_body = &Body::new( body.source, - body.basic_blocks().clone(), + (*body.basic_blocks).clone(), body.source_scopes.clone(), body.local_decls.clone(), Default::default(), @@ -524,7 +524,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> { fn visit_body(&mut self, body: &Body<'tcx>) { - for (bb, data) in body.basic_blocks().iter_enumerated() { + for (bb, data) in body.basic_blocks.iter_enumerated() { self.visit_basic_block_data(bb, data); } } diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs index 759ea7cd32820..782129be088b6 100644 --- a/compiler/rustc_mir_transform/src/coverage/graph.rs +++ b/compiler/rustc_mir_transform/src/coverage/graph.rs @@ -713,7 +713,7 @@ impl< ShortCircuitPreorder { body, - visited: BitSet::new_empty(body.basic_blocks().len()), + visited: BitSet::new_empty(body.basic_blocks.len()), worklist, filtered_successors, } @@ -747,7 +747,7 @@ impl< } fn size_hint(&self) -> (usize, Option) { - let size = self.body.basic_blocks().len() - self.visited.count(); + let size = self.body.basic_blocks.len() - self.visited.count(); (size, Some(size)) } } diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 2619626a5675f..299a8067b28ff 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -80,7 +80,7 @@ impl<'tcx> MirPass<'tcx> for InstrumentCoverage { return; } - match mir_body.basic_blocks()[mir::START_BLOCK].terminator().kind { + match mir_body.basic_blocks[mir::START_BLOCK].terminator().kind { TerminatorKind::Unreachable => { trace!("InstrumentCoverage skipped for unreachable `START_BLOCK`"); return; diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs index 9d02f58ae65ee..dc1e68b253e72 100644 --- a/compiler/rustc_mir_transform/src/coverage/query.rs +++ b/compiler/rustc_mir_transform/src/coverage/query.rs @@ -84,7 +84,7 @@ impl CoverageVisitor { } fn visit_body(&mut self, body: &Body<'_>) { - for bb_data in body.basic_blocks().iter() { + for bb_data in body.basic_blocks.iter() { for statement in bb_data.statements.iter() { if let StatementKind::Coverage(box ref coverage) = statement.kind { if is_inlined(body, statement) { @@ -138,7 +138,7 @@ fn coverageinfo<'tcx>(tcx: TyCtxt<'tcx>, instance_def: ty::InstanceDef<'tcx>) -> fn covered_code_regions<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Vec<&'tcx CodeRegion> { let body = mir_body(tcx, def_id); - body.basic_blocks() + body.basic_blocks .iter() .flat_map(|data| { data.statements.iter().filter_map(|statement| match statement.kind { diff --git a/compiler/rustc_mir_transform/src/coverage/tests.rs b/compiler/rustc_mir_transform/src/coverage/tests.rs index 6380f03528ae8..9c9ed5fa5105e 100644 --- a/compiler/rustc_mir_transform/src/coverage/tests.rs +++ b/compiler/rustc_mir_transform/src/coverage/tests.rs @@ -176,7 +176,7 @@ fn debug_basic_blocks<'tcx>(mir_body: &Body<'tcx>) -> String { format!( "{:?}", mir_body - .basic_blocks() + .basic_blocks .iter_enumerated() .map(|(bb, data)| { let term = &data.terminator(); @@ -213,7 +213,7 @@ fn print_mir_graphviz(name: &str, mir_body: &Body<'_>) { "digraph {} {{\n{}\n}}", name, mir_body - .basic_blocks() + .basic_blocks .iter_enumerated() .map(|(bb, data)| { format!( @@ -653,7 +653,7 @@ fn test_traverse_coverage_with_loops() { fn synthesize_body_span_from_terminators(mir_body: &Body<'_>) -> Span { let mut some_span: Option = None; - for (_, data) in mir_body.basic_blocks().iter_enumerated() { + for (_, data) in mir_body.basic_blocks.iter_enumerated() { let term_span = data.terminator().source_info.span; if let Some(span) = some_span.as_mut() { *span = span.to(term_span); diff --git a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs index d1977ed49fe15..909116a77f54f 100644 --- a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs +++ b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs @@ -58,7 +58,7 @@ fn find_duplicates(body: &Body<'_>) -> FxHashMap { let mut duplicates = FxHashMap::default(); let bbs_to_go_through = - body.basic_blocks().iter_enumerated().filter(|(_, bbd)| !bbd.is_cleanup).count(); + body.basic_blocks.iter_enumerated().filter(|(_, bbd)| !bbd.is_cleanup).count(); let mut same_hashes = FxHashMap::with_capacity_and_hasher(bbs_to_go_through, Default::default()); @@ -71,8 +71,7 @@ fn find_duplicates(body: &Body<'_>) -> FxHashMap { // When we see bb1, we see that it is a duplicate of bb3, and therefore insert it in the duplicates list // with replacement bb3. // When the duplicates are removed, we will end up with only bb3. - for (bb, bbd) in body.basic_blocks().iter_enumerated().rev().filter(|(_, bbd)| !bbd.is_cleanup) - { + for (bb, bbd) in body.basic_blocks.iter_enumerated().rev().filter(|(_, bbd)| !bbd.is_cleanup) { // Basic blocks can get really big, so to avoid checking for duplicates in basic blocks // that are unlikely to have duplicates, we stop early. The early bail number has been // found experimentally by eprintln while compiling the crates in the rustc-perf suite. diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index 33572068f5cd9..da55510920e12 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -150,7 +150,7 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation { def_id, body.local_decls.len(), relevant, - body.basic_blocks().len() + body.basic_blocks.len() ); if relevant > MAX_LOCALS { warn!( @@ -159,11 +159,11 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation { ); return; } - if body.basic_blocks().len() > MAX_BLOCKS { + if body.basic_blocks.len() > MAX_BLOCKS { warn!( "too many blocks in {:?} ({}, max is {}), not optimizing", def_id, - body.basic_blocks().len(), + body.basic_blocks.len(), MAX_BLOCKS ); return; diff --git a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs index dba42f7aff033..32e738bbcea44 100644 --- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs +++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs @@ -104,8 +104,8 @@ impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch { let mut should_cleanup = false; // Also consider newly generated bbs in the same pass - for i in 0..body.basic_blocks().len() { - let bbs = body.basic_blocks(); + for i in 0..body.basic_blocks.len() { + let bbs = &*body.basic_blocks; let parent = BasicBlock::from_usize(i); let Some(opt_data) = evaluate_candidate(tcx, body, parent) else { continue @@ -316,7 +316,7 @@ fn evaluate_candidate<'tcx>( body: &Body<'tcx>, parent: BasicBlock, ) -> Option> { - let bbs = body.basic_blocks(); + let bbs = &body.basic_blocks; let TerminatorKind::SwitchInt { targets, switch_ty: parent_ty, diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index 9c1fcbaa69d6b..61118ecc8ed51 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -89,13 +89,13 @@ fn find_dead_unwinds<'tcx>( debug!("find_dead_unwinds({:?})", body.span); // We only need to do this pass once, because unwind edges can only // reach cleanup blocks, which can't have unwind edges themselves. - let mut dead_unwinds = BitSet::new_empty(body.basic_blocks().len()); + let mut dead_unwinds = BitSet::new_empty(body.basic_blocks.len()); let mut flow_inits = MaybeInitializedPlaces::new(tcx, body, &env) .into_engine(tcx, body) .pass_name("find_dead_unwinds") .iterate_to_fixpoint() .into_results_cursor(body); - for (bb, bb_data) in body.basic_blocks().iter_enumerated() { + for (bb, bb_data) in body.basic_blocks.iter_enumerated() { let place = match bb_data.terminator().kind { TerminatorKind::Drop { ref place, unwind: Some(_), .. } | TerminatorKind::DropAndReplace { ref place, unwind: Some(_), .. } => { @@ -303,7 +303,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { } fn collect_drop_flags(&mut self) { - for (bb, data) in self.body.basic_blocks().iter_enumerated() { + for (bb, data) in self.body.basic_blocks.iter_enumerated() { let terminator = data.terminator(); let place = match terminator.kind { TerminatorKind::Drop { ref place, .. } @@ -358,7 +358,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { } fn elaborate_drops(&mut self) { - for (bb, data) in self.body.basic_blocks().iter_enumerated() { + for (bb, data) in self.body.basic_blocks.iter_enumerated() { let loc = Location { block: bb, statement_index: data.statements.len() }; let terminator = data.terminator(); @@ -515,7 +515,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { } fn drop_flags_for_fn_rets(&mut self) { - for (bb, data) in self.body.basic_blocks().iter_enumerated() { + for (bb, data) in self.body.basic_blocks.iter_enumerated() { if let TerminatorKind::Call { destination, target: Some(tgt), cleanup: Some(_), .. } = data.terminator().kind @@ -550,7 +550,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { // drop flags by themselves, to avoid the drop flags being // clobbered before they are read. - for (bb, data) in self.body.basic_blocks().iter_enumerated() { + for (bb, data) in self.body.basic_blocks.iter_enumerated() { debug!("drop_flags_for_locs({:?})", data); for i in 0..(data.statements.len() + 1) { debug!("drop_flag_for_locs: stmt {}", i); diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs index 7728fdaffb0dc..7522a50a8c643 100644 --- a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs +++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs @@ -65,7 +65,7 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool { let mut tainted = false; - for block in body.basic_blocks() { + for block in body.basic_blocks.iter() { if block.is_cleanup { continue; } diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index 5b0d9900c0fb5..c260611b40712 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -490,12 +490,12 @@ fn locals_live_across_suspend_points<'tcx>( .iterate_to_fixpoint() .into_results_cursor(body_ref); - let mut storage_liveness_map = IndexVec::from_elem(None, body.basic_blocks()); + let mut storage_liveness_map = IndexVec::from_elem(None, &body.basic_blocks); let mut live_locals_at_suspension_points = Vec::new(); let mut source_info_at_suspension_points = Vec::new(); let mut live_locals_at_any_suspension_point = BitSet::new_empty(body.local_decls.len()); - for (block, data) in body.basic_blocks().iter_enumerated() { + for (block, data) in body.basic_blocks.iter_enumerated() { if let TerminatorKind::Yield { .. } = data.terminator().kind { let loc = Location { block, statement_index: data.statements.len() }; @@ -704,7 +704,7 @@ impl<'mir, 'tcx> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx> impl StorageConflictVisitor<'_, '_, '_> { fn apply_state(&mut self, flow_state: &BitSet, loc: Location) { // Ignore unreachable blocks. - if self.body.basic_blocks()[loc.block].terminator().kind == TerminatorKind::Unreachable { + if self.body.basic_blocks[loc.block].terminator().kind == TerminatorKind::Unreachable { return; } @@ -886,7 +886,7 @@ fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let mut elaborator = DropShimElaborator { body, patch: MirPatch::new(body), tcx, param_env }; - for (block, block_data) in body.basic_blocks().iter_enumerated() { + for (block, block_data) in body.basic_blocks.iter_enumerated() { let (target, unwind, source_info) = match block_data.terminator() { Terminator { source_info, kind: TerminatorKind::Drop { place, target, unwind } } => { if let Some(local) = place.as_local() { @@ -991,7 +991,7 @@ fn insert_panic_block<'tcx>( body: &mut Body<'tcx>, message: AssertMessage<'tcx>, ) -> BasicBlock { - let assert_block = BasicBlock::new(body.basic_blocks().len()); + let assert_block = BasicBlock::new(body.basic_blocks.len()); let term = TerminatorKind::Assert { cond: Operand::Constant(Box::new(Constant { span: body.span, @@ -1021,7 +1021,7 @@ fn can_return<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, param_env: ty::ParamEn } // If there's a return terminator the function may return. - for block in body.basic_blocks() { + for block in body.basic_blocks.iter() { if let TerminatorKind::Return = block.terminator().kind { return true; } @@ -1038,7 +1038,7 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool { } // Unwinds can only start at certain terminators. - for block in body.basic_blocks() { + for block in body.basic_blocks.iter() { match block.terminator().kind { // These never unwind. TerminatorKind::Goto { .. } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index d7d2984018804..ba00f16308eae 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -95,7 +95,7 @@ fn inline<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool { history: Vec::new(), changed: false, }; - let blocks = BasicBlock::new(0)..body.basic_blocks().next_index(); + let blocks = BasicBlock::new(0)..body.basic_blocks.next_index(); this.process_blocks(body, blocks); this.changed } @@ -217,9 +217,9 @@ impl<'tcx> Inliner<'tcx> { } } - let old_blocks = caller_body.basic_blocks().next_index(); + let old_blocks = caller_body.basic_blocks.next_index(); self.inline_call(caller_body, &callsite, callee_body); - let new_blocks = old_blocks..caller_body.basic_blocks().next_index(); + let new_blocks = old_blocks..caller_body.basic_blocks.next_index(); Ok(new_blocks) } @@ -409,14 +409,14 @@ impl<'tcx> Inliner<'tcx> { // Give a bonus functions with a small number of blocks, // We normally have two or three blocks for even // very small functions. - if callee_body.basic_blocks().len() <= 3 { + if callee_body.basic_blocks.len() <= 3 { threshold += threshold / 4; } debug!(" final inline threshold = {}", threshold); // FIXME: Give a bonus to functions with only a single caller let diverges = matches!( - callee_body.basic_blocks()[START_BLOCK].terminator().kind, + callee_body.basic_blocks[START_BLOCK].terminator().kind, TerminatorKind::Unreachable | TerminatorKind::Call { target: None, .. } ); if diverges && !matches!(callee_attrs.inline, InlineAttr::Always) { @@ -434,13 +434,13 @@ impl<'tcx> Inliner<'tcx> { // Traverse the MIR manually so we can account for the effects of inlining on the CFG. let mut work_list = vec![START_BLOCK]; - let mut visited = BitSet::new_empty(callee_body.basic_blocks().len()); + let mut visited = BitSet::new_empty(callee_body.basic_blocks.len()); while let Some(bb) = work_list.pop() { if !visited.insert(bb.index()) { continue; } - let blk = &callee_body.basic_blocks()[bb]; + let blk = &callee_body.basic_blocks[bb]; checker.visit_basic_block_data(bb, blk); let term = blk.terminator(); @@ -541,7 +541,7 @@ impl<'tcx> Inliner<'tcx> { args: &args, new_locals: Local::new(caller_body.local_decls.len()).., new_scopes: SourceScope::new(caller_body.source_scopes.len()).., - new_blocks: BasicBlock::new(caller_body.basic_blocks().len()).., + new_blocks: BasicBlock::new(caller_body.basic_blocks.len()).., destination: dest, callsite_scope: caller_body.source_scopes[callsite.source_info.scope].clone(), callsite, diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs index 7810218fd6744..b027f94925d2f 100644 --- a/compiler/rustc_mir_transform/src/inline/cycle.rs +++ b/compiler/rustc_mir_transform/src/inline/cycle.rs @@ -153,7 +153,7 @@ pub(crate) fn mir_inliner_callees<'tcx>( _ => tcx.instance_mir(instance), }; let mut calls = FxIndexSet::default(); - for bb_data in body.basic_blocks() { + for bb_data in body.basic_blocks.iter() { let terminator = bb_data.terminator(); if let TerminatorKind::Call { func, .. } = &terminator.kind { let ty = func.ty(&body.local_decls, tcx); diff --git a/compiler/rustc_mir_transform/src/multiple_return_terminators.rs b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs index 22b6dead99c50..3957cd92c4e39 100644 --- a/compiler/rustc_mir_transform/src/multiple_return_terminators.rs +++ b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs @@ -15,7 +15,7 @@ impl<'tcx> MirPass<'tcx> for MultipleReturnTerminators { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // find basic blocks with no statement and a return terminator - let mut bbs_simple_returns = BitSet::new_empty(body.basic_blocks().len()); + let mut bbs_simple_returns = BitSet::new_empty(body.basic_blocks.len()); let def_id = body.source.def_id(); let bbs = body.basic_blocks_mut(); for idx in bbs.indices() { diff --git a/compiler/rustc_mir_transform/src/normalize_array_len.rs b/compiler/rustc_mir_transform/src/normalize_array_len.rs index c0217a105414b..a159e61717823 100644 --- a/compiler/rustc_mir_transform/src/normalize_array_len.rs +++ b/compiler/rustc_mir_transform/src/normalize_array_len.rs @@ -21,10 +21,10 @@ impl<'tcx> MirPass<'tcx> for NormalizeArrayLen { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // early returns for edge cases of highly unrolled functions - if body.basic_blocks().len() > MAX_NUM_BLOCKS { + if body.basic_blocks.len() > MAX_NUM_BLOCKS { return; } - if body.local_decls().len() > MAX_NUM_LOCALS { + if body.local_decls.len() > MAX_NUM_LOCALS { return; } normalize_array_len_calls(tcx, body) diff --git a/compiler/rustc_mir_transform/src/nrvo.rs b/compiler/rustc_mir_transform/src/nrvo.rs index 42d732730eccc..4291e81c78c25 100644 --- a/compiler/rustc_mir_transform/src/nrvo.rs +++ b/compiler/rustc_mir_transform/src/nrvo.rs @@ -89,7 +89,7 @@ fn local_eligible_for_nrvo(body: &mut mir::Body<'_>) -> Option { } let mut copied_to_return_place = None; - for block in body.basic_blocks().indices() { + for block in body.basic_blocks.indices() { // Look for blocks with a `Return` terminator. if !matches!(body[block].terminator().kind, mir::TerminatorKind::Return) { continue; @@ -122,7 +122,7 @@ fn find_local_assigned_to_return_place( body: &mut mir::Body<'_>, ) -> Option { let mut block = start; - let mut seen = HybridBitSet::new_empty(body.basic_blocks().len()); + let mut seen = HybridBitSet::new_empty(body.basic_blocks.len()); // Iterate as long as `block` has exactly one predecessor that we have not yet visited. while seen.insert(block) { diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs index 5c441c5b19492..41a0bfac41aed 100644 --- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs +++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs @@ -94,7 +94,7 @@ impl RemoveNoopLandingPads { let mut jumps_folded = 0; let mut landing_pads_removed = 0; - let mut nop_landing_pads = BitSet::new_empty(body.basic_blocks().len()); + let mut nop_landing_pads = BitSet::new_empty(body.basic_blocks.len()); // This is a post-order traversal, so that if A post-dominates B // then A will be visited before B. diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs index 96b715402e772..78b6f714a9b0b 100644 --- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs @@ -35,7 +35,7 @@ impl<'tcx> MirPass<'tcx> for RemoveUninitDrops { .into_results_cursor(body); let mut to_remove = vec![]; - for (bb, block) in body.basic_blocks().iter_enumerated() { + for (bb, block) in body.basic_blocks.iter_enumerated() { let terminator = block.terminator(); let (TerminatorKind::Drop { place, .. } | TerminatorKind::DropAndReplace { place, .. }) = &terminator.kind diff --git a/compiler/rustc_mir_transform/src/separate_const_switch.rs b/compiler/rustc_mir_transform/src/separate_const_switch.rs index 925eb10a1f75f..190f9c1ac158c 100644 --- a/compiler/rustc_mir_transform/src/separate_const_switch.rs +++ b/compiler/rustc_mir_transform/src/separate_const_switch.rs @@ -62,7 +62,7 @@ impl<'tcx> MirPass<'tcx> for SeparateConstSwitch { pub fn separate_const_switch(body: &mut Body<'_>) -> usize { let mut new_blocks: SmallVec<[(BasicBlock, BasicBlock); 6]> = SmallVec::new(); let predecessors = body.basic_blocks.predecessors(); - 'block_iter: for (block_id, block) in body.basic_blocks().iter_enumerated() { + 'block_iter: for (block_id, block) in body.basic_blocks.iter_enumerated() { if let TerminatorKind::SwitchInt { discr: Operand::Copy(switch_place) | Operand::Move(switch_place), .. @@ -90,7 +90,7 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize { let mut predecessors_left = predecessors[block_id].len(); 'predec_iter: for predecessor_id in predecessors[block_id].iter().copied() { - let predecessor = &body.basic_blocks()[predecessor_id]; + let predecessor = &body.basic_blocks[predecessor_id]; // First we make sure the predecessor jumps // in a reasonable way diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index 7a6ca917d0ffd..bed48db959a53 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -74,7 +74,7 @@ pub struct CfgSimplifier<'a, 'tcx> { impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { pub fn new(body: &'a mut Body<'tcx>) -> Self { - let mut pred_count = IndexVec::from_elem(0u32, body.basic_blocks()); + let mut pred_count = IndexVec::from_elem(0u32, &body.basic_blocks); // we can't use mir.predecessors() here because that counts // dead blocks, which we don't want to. @@ -263,7 +263,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { pub fn remove_dead_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let reachable = traversal::reachable_as_bitset(body); - let num_blocks = body.basic_blocks().len(); + let num_blocks = body.basic_blocks.len(); if num_blocks == reachable.count() { return; } diff --git a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs index bbfaace7041ec..321d8c63b6e02 100644 --- a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs +++ b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs @@ -151,7 +151,7 @@ struct OptimizationFinder<'a, 'tcx> { impl<'tcx> OptimizationFinder<'_, 'tcx> { fn find_optimizations(&self) -> Vec> { self.body - .basic_blocks() + .basic_blocks .iter_enumerated() .filter_map(|(bb_idx, bb)| { // find switch diff --git a/compiler/rustc_mir_transform/src/simplify_try.rs b/compiler/rustc_mir_transform/src/simplify_try.rs index d52f1261b23a2..baeb620ef2403 100644 --- a/compiler/rustc_mir_transform/src/simplify_try.rs +++ b/compiler/rustc_mir_transform/src/simplify_try.rs @@ -596,7 +596,7 @@ struct SimplifyBranchSameOptimizationFinder<'a, 'tcx> { impl<'tcx> SimplifyBranchSameOptimizationFinder<'_, 'tcx> { fn find(&self) -> Vec { self.body - .basic_blocks() + .basic_blocks .iter_enumerated() .filter_map(|(bb_idx, bb)| { let (discr_switched_on, targets_and_values) = match &bb.terminator().kind { @@ -632,7 +632,7 @@ impl<'tcx> SimplifyBranchSameOptimizationFinder<'_, 'tcx> { let mut iter_bbs_reachable = targets_and_values .iter() - .map(|target_and_value| (target_and_value, &self.body.basic_blocks()[target_and_value.target])) + .map(|target_and_value| (target_and_value, &self.body.basic_blocks[target_and_value.target])) .filter(|(_, bb)| { // Reaching `unreachable` is UB so assume it doesn't happen. bb.terminator().kind != TerminatorKind::Unreachable diff --git a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs index 30be64f5b2f2e..96ea15f1b8097 100644 --- a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs +++ b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs @@ -79,7 +79,7 @@ fn ensure_otherwise_unreachable<'tcx>( targets: &SwitchTargets, ) -> Option> { let otherwise = targets.otherwise(); - let bb = &body.basic_blocks()[otherwise]; + let bb = &body.basic_blocks[otherwise]; if bb.terminator().kind == TerminatorKind::Unreachable && bb.statements.iter().all(|s| matches!(&s.kind, StatementKind::StorageDead(_))) { @@ -102,10 +102,10 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { trace!("UninhabitedEnumBranching starting for {:?}", body.source); - for bb in body.basic_blocks().indices() { + for bb in body.basic_blocks.indices() { trace!("processing block {:?}", bb); - let Some(discriminant_ty) = get_switched_on_type(&body.basic_blocks()[bb], tcx, body) else { + let Some(discriminant_ty) = get_switched_on_type(&body.basic_blocks[bb], tcx, body) else { continue; }; diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs index ff2d386932858..43319dc5862e6 100644 --- a/compiler/rustc_monomorphize/src/partitioning/mod.rs +++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs @@ -481,7 +481,7 @@ fn codegened_and_inlined_items<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> &'tcx DefIdSe continue; } let body = tcx.instance_mir(instance.def); - for block in body.basic_blocks() { + for block in body.basic_blocks.iter() { for statement in &block.statements { let mir::StatementKind::Coverage(_) = statement.kind else { continue }; let scope = statement.source_info.scope; diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index db0d45b86fc03..acfeefb4d12d5 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -348,7 +348,7 @@ fn instance_def_size_estimate<'tcx>( match instance_def { InstanceDef::Item(..) | InstanceDef::DropGlue(..) => { let mir = tcx.instance_mir(instance_def); - mir.basic_blocks().iter().map(|bb| bb.statements.len() + 1).sum() + mir.basic_blocks.iter().map(|bb| bb.statements.len() + 1).sum() } // Estimate the size of other compiler-generated shims to be 1. _ => 1, diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs index eddca60457574..9fd86331ec755 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs @@ -105,7 +105,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone { vis.into_map(cx, maybe_storage_live_result) }; - for (bb, bbdata) in mir.basic_blocks().iter_enumerated() { + for (bb, bbdata) in mir.basic_blocks.iter_enumerated() { let terminator = bbdata.terminator(); if terminator.source_info.span.from_expansion() { @@ -186,7 +186,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone { unwrap_or_continue!(find_stmt_assigns_to(cx, mir, pred_arg, true, ps[0])); let loc = mir::Location { block: bb, - statement_index: mir.basic_blocks()[bb].statements.len(), + statement_index: mir.basic_blocks[bb].statements.len(), }; // This can be turned into `res = move local` if `arg` and `cloned` are not borrowed @@ -310,7 +310,7 @@ fn find_stmt_assigns_to<'tcx>( by_ref: bool, bb: mir::BasicBlock, ) -> Option<(mir::Local, CannotMoveOut)> { - let rvalue = mir.basic_blocks()[bb].statements.iter().rev().find_map(|stmt| { + let rvalue = mir.basic_blocks[bb].statements.iter().rev().find_map(|stmt| { if let mir::StatementKind::Assign(box (mir::Place { local, .. }, v)) = &stmt.kind { return if *local == to_local { Some(v) } else { None }; } diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 3bf75bcbee83e..74c222bbcbeb9 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -55,7 +55,7 @@ pub fn is_min_const_fn<'a, 'tcx>(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, msrv: body.local_decls.iter().next().unwrap().source_info.span, )?; - for bb in body.basic_blocks() { + for bb in body.basic_blocks.iter() { check_terminator(tcx, body, bb.terminator(), msrv)?; for stmt in &bb.statements { check_statement(tcx, body, def_id, stmt)?; From 9678751a880bc87a9beae7585ace926306a291e6 Mon Sep 17 00:00:00 2001 From: yukang Date: Mon, 22 Aug 2022 21:45:05 +0800 Subject: [PATCH 20/25] pretty printing give proper erro message without panic --- compiler/rustc_driver/src/pretty.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_driver/src/pretty.rs b/compiler/rustc_driver/src/pretty.rs index f66b1a2976f1c..21a3a077a10c4 100644 --- a/compiler/rustc_driver/src/pretty.rs +++ b/compiler/rustc_driver/src/pretty.rs @@ -357,12 +357,16 @@ fn get_source(input: &Input, sess: &Session) -> (String, FileName) { (src, src_name) } -fn write_or_print(out: &str, ofile: Option<&Path>) { +fn write_or_print(out: &str, ofile: Option<&Path>, sess: &Session) { match ofile { None => print!("{}", out), Some(p) => { if let Err(e) = std::fs::write(p, out) { - panic!("print-print failed to write {} due to {}", p.display(), e); + let mut err = sess.struct_fatal(&format!( + "pretty-print failed to write {} due to error `{e}`", + p.display() + )); + err.emit(); } } } @@ -402,7 +406,7 @@ pub fn print_after_parsing( _ => unreachable!(), }; - write_or_print(&out, ofile); + write_or_print(&out, ofile, sess); } pub fn print_after_hir_lowering<'tcx>( @@ -468,7 +472,7 @@ pub fn print_after_hir_lowering<'tcx>( _ => unreachable!(), }; - write_or_print(&out, ofile); + write_or_print(&out, ofile, tcx.sess); } // In an ideal world, this would be a public function called by the driver after @@ -512,7 +516,7 @@ fn print_with_analysis( _ => unreachable!(), }; - write_or_print(&out, ofile); + write_or_print(&out, ofile, tcx.sess); Ok(()) } From 2237c6c29505d45bbb7403f515b359944a95c5e0 Mon Sep 17 00:00:00 2001 From: yukang Date: Sun, 28 Aug 2022 11:17:28 +0800 Subject: [PATCH 21/25] add UI test for unpretty --- compiler/rustc_driver/src/pretty.rs | 10 +++++----- compiler/rustc_driver/src/session_diagnostics.rs | 7 +++++++ compiler/rustc_error_messages/locales/en-US/driver.ftl | 2 ++ src/test/ui/unpretty/avoid-crash.rs | 3 +++ src/test/ui/unpretty/avoid-crash.stderr | 4 ++++ 5 files changed, 21 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/unpretty/avoid-crash.rs create mode 100644 src/test/ui/unpretty/avoid-crash.stderr diff --git a/compiler/rustc_driver/src/pretty.rs b/compiler/rustc_driver/src/pretty.rs index 21a3a077a10c4..faeacd3e41040 100644 --- a/compiler/rustc_driver/src/pretty.rs +++ b/compiler/rustc_driver/src/pretty.rs @@ -1,5 +1,6 @@ //! The various pretty-printing routines. +use crate::session_diagnostics::UnprettyDumpFail; use rustc_ast as ast; use rustc_ast_pretty::pprust; use rustc_errors::ErrorGuaranteed; @@ -362,11 +363,10 @@ fn write_or_print(out: &str, ofile: Option<&Path>, sess: &Session) { None => print!("{}", out), Some(p) => { if let Err(e) = std::fs::write(p, out) { - let mut err = sess.struct_fatal(&format!( - "pretty-print failed to write {} due to error `{e}`", - p.display() - )); - err.emit(); + sess.emit_fatal(UnprettyDumpFail { + path: p.display().to_string(), + err: e.to_string(), + }); } } } diff --git a/compiler/rustc_driver/src/session_diagnostics.rs b/compiler/rustc_driver/src/session_diagnostics.rs index fe64d0fca9b20..e9696792d051f 100644 --- a/compiler/rustc_driver/src/session_diagnostics.rs +++ b/compiler/rustc_driver/src/session_diagnostics.rs @@ -31,3 +31,10 @@ pub(crate) struct RLinkRustcVersionMismatch<'a> { #[derive(SessionDiagnostic)] #[diag(driver::rlink_no_a_file)] pub(crate) struct RlinkNotAFile; + +#[derive(SessionDiagnostic)] +#[diag(driver::unpretty_dump_fail)] +pub(crate) struct UnprettyDumpFail { + pub path: String, + pub err: String, +} diff --git a/compiler/rustc_error_messages/locales/en-US/driver.ftl b/compiler/rustc_error_messages/locales/en-US/driver.ftl index 73f084cf3290b..8ad198c86c933 100644 --- a/compiler/rustc_error_messages/locales/en-US/driver.ftl +++ b/compiler/rustc_error_messages/locales/en-US/driver.ftl @@ -9,3 +9,5 @@ driver_rlink_encoding_version_mismatch = .rlink file was produced with encoding driver_rlink_rustc_version_mismatch = .rlink file was produced by rustc version `{$rustc_version}`, but the current version is `{$current_version}` driver_rlink_no_a_file = rlink must be a file + +driver_unpretty_dump_fail = pretty-print failed to write `{$path}` due to error `{$err}` diff --git a/src/test/ui/unpretty/avoid-crash.rs b/src/test/ui/unpretty/avoid-crash.rs new file mode 100644 index 0000000000000..daa073b75dd17 --- /dev/null +++ b/src/test/ui/unpretty/avoid-crash.rs @@ -0,0 +1,3 @@ +// compile-flags: -o/tmp/ -Zunpretty=ast-tree + +fn main() {} diff --git a/src/test/ui/unpretty/avoid-crash.stderr b/src/test/ui/unpretty/avoid-crash.stderr new file mode 100644 index 0000000000000..fb52d648adb6c --- /dev/null +++ b/src/test/ui/unpretty/avoid-crash.stderr @@ -0,0 +1,4 @@ +error: pretty-print failed to write `/tmp/` due to error `Is a directory (os error 21)` + +error: aborting due to previous error + From 1e005af31b078f584f7adbdebc505ba0cca52706 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 28 Aug 2022 10:34:19 +0200 Subject: [PATCH 22/25] Remove Attrs type alias --- src/librustdoc/clean/inline.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index f367edcbf5a81..31b805f2ed7ed 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -24,8 +24,6 @@ use crate::clean::{ use crate::core::DocContext; use crate::formats::item_type::ItemType; -type Attrs<'hir> = &'hir [ast::Attribute]; - /// Attempt to inline a definition into this AST. /// /// This function will fetch the definition specified, and if it is @@ -46,7 +44,7 @@ pub(crate) fn try_inline( import_def_id: Option, res: Res, name: Symbol, - attrs: Option>, + attrs: Option<&[ast::Attribute]>, visited: &mut FxHashSet, ) -> Option> { let did = res.opt_def_id()?; @@ -172,7 +170,7 @@ pub(crate) fn try_inline_glob( } } -pub(crate) fn load_attrs<'hir>(cx: &DocContext<'hir>, did: DefId) -> Attrs<'hir> { +pub(crate) fn load_attrs<'hir>(cx: &DocContext<'hir>, did: DefId) -> &'hir [ast::Attribute] { cx.tcx.get_attrs_unchecked(did) } @@ -287,7 +285,7 @@ pub(crate) fn build_impls( cx: &mut DocContext<'_>, parent_module: Option, did: DefId, - attrs: Option>, + attrs: Option<&[ast::Attribute]>, ret: &mut Vec, ) { let _prof_timer = cx.tcx.sess.prof.generic_activity("build_inherent_impls"); @@ -303,8 +301,8 @@ pub(crate) fn build_impls( pub(crate) fn merge_attrs( cx: &mut DocContext<'_>, parent_module: Option, - old_attrs: Attrs<'_>, - new_attrs: Option>, + old_attrs: &[ast::Attribute], + new_attrs: Option<&[ast::Attribute]>, ) -> (clean::Attributes, Option>) { // NOTE: If we have additional attributes (from a re-export), // always insert them first. This ensure that re-export @@ -331,7 +329,7 @@ pub(crate) fn build_impl( cx: &mut DocContext<'_>, parent_module: Option, did: DefId, - attrs: Option>, + attrs: Option<&[ast::Attribute]>, ret: &mut Vec, ) { if !cx.inlined.insert(did.into()) { From 484fd898e76c221946fc002d40c8c7cd31225989 Mon Sep 17 00:00:00 2001 From: Nixon Enraght-Moony Date: Sun, 28 Aug 2022 02:35:44 +0100 Subject: [PATCH 23/25] Rustdoc-Json: Retain Stripped Modules when they are imported, not when they have items. Fixes #101103 Fixes #100973 --- src/librustdoc/json/conversions.rs | 8 +++- src/librustdoc/json/import_finder.rs | 38 +++++++++++++++++++ src/librustdoc/json/mod.rs | 8 +++- .../rustdoc-json/reexport/glob_collision.rs | 28 ++++++++++++++ .../rustdoc-json/reexport/glob_empty_mod.rs | 8 ++++ .../rustdoc-json/reexport/in_root_and_mod.rs | 3 +- .../rustdoc-json/reexport/mod_not_included.rs | 14 +++++++ .../reexport/private_two_names.rs | 3 +- .../rustdoc-json/reexport/rename_private.rs | 3 +- .../rustdoc-json/reexport/simple_private.rs | 5 +-- src/test/rustdoc-json/stripped_modules.rs | 2 +- 11 files changed, 107 insertions(+), 13 deletions(-) create mode 100644 src/librustdoc/json/import_finder.rs create mode 100644 src/test/rustdoc-json/reexport/glob_collision.rs create mode 100644 src/test/rustdoc-json/reexport/glob_empty_mod.rs create mode 100644 src/test/rustdoc-json/reexport/mod_not_included.rs diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index c4e8b6f5f8449..20b9eb1c27e92 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -46,10 +46,14 @@ impl JsonRenderer<'_> { clean::KeywordItem => return None, clean::StrippedItem(ref inner) => { match &**inner { - // We document non-empty stripped modules as with `Module::is_stripped` set to + // We document stripped modules as with `Module::is_stripped` set to // `true`, to prevent contained items from being orphaned for downstream users, // as JSON does no inlining. - clean::ModuleItem(m) if !m.items.is_empty() => from_clean_item(item, self.tcx), + clean::ModuleItem(_) + if self.imported_items.contains(&item_id.expect_def_id()) => + { + from_clean_item(item, self.tcx) + } _ => return None, } } diff --git a/src/librustdoc/json/import_finder.rs b/src/librustdoc/json/import_finder.rs new file mode 100644 index 0000000000000..d5be3e3bf3de0 --- /dev/null +++ b/src/librustdoc/json/import_finder.rs @@ -0,0 +1,38 @@ +use rustc_data_structures::fx::FxHashSet; +use rustc_hir::def_id::DefId; + +use crate::{ + clean::{self, Import, ImportSource, Item}, + fold::DocFolder, +}; + +/// Get the id's of all items that are `pub use`d in the crate. +/// +/// We need this to know if a stripped module is `pub use mod::*`, to decide +/// if it needs to be kept in the index, despite being stripped. +/// +/// See https://github.com/rust-lang/rust/issues/100973 and +/// https://github.com/rust-lang/rust/issues/101103 for times when this +/// information is needed. +pub(crate) fn get_imports(krate: clean::Crate) -> (clean::Crate, FxHashSet) { + let mut finder = ImportFinder { imported: FxHashSet::default() }; + let krate = finder.fold_crate(krate); + (krate, finder.imported) +} + +struct ImportFinder { + imported: FxHashSet, +} + +impl DocFolder for ImportFinder { + fn fold_item(&mut self, i: Item) -> Option { + match *i.kind { + clean::ImportItem(Import { source: ImportSource { did: Some(did), .. }, .. }) => { + self.imported.insert(did); + Some(i) + } + + _ => Some(self.fold_item_recur(i)), + } + } +} diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index 7b1b059e14dcb..577aad8f3bb93 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -5,6 +5,7 @@ //! docs for usage and details. mod conversions; +mod import_finder; use std::cell::RefCell; use std::fs::{create_dir_all, File}; @@ -12,7 +13,7 @@ use std::io::{BufWriter, Write}; use std::path::PathBuf; use std::rc::Rc; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::def_id::DefId; use rustc_middle::ty::TyCtxt; use rustc_session::Session; @@ -39,6 +40,7 @@ pub(crate) struct JsonRenderer<'tcx> { /// The directory where the blob will be written to. out_path: PathBuf, cache: Rc, + imported_items: FxHashSet, } impl<'tcx> JsonRenderer<'tcx> { @@ -157,12 +159,16 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { tcx: TyCtxt<'tcx>, ) -> Result<(Self, clean::Crate), Error> { debug!("Initializing json renderer"); + + let (krate, imported_items) = import_finder::get_imports(krate); + Ok(( JsonRenderer { tcx, index: Rc::new(RefCell::new(FxHashMap::default())), out_path: options.output, cache: Rc::new(cache), + imported_items, }, krate, )) diff --git a/src/test/rustdoc-json/reexport/glob_collision.rs b/src/test/rustdoc-json/reexport/glob_collision.rs new file mode 100644 index 0000000000000..f91144dbfad50 --- /dev/null +++ b/src/test/rustdoc-json/reexport/glob_collision.rs @@ -0,0 +1,28 @@ +// Regression test for https://github.com/rust-lang/rust/issues/100973 + +#![feature(no_core)] +#![no_core] + +// @set m1 = "$.index[*][?(@.name == 'm1' && @.kind == 'module')].id" +// @is "$.index[*][?(@.name == 'm1' && @.kind == 'module')].inner.items" [] +// @is "$.index[*][?(@.name == 'm1' && @.kind == 'module')].inner.is_stripped" true +mod m1 { + pub fn f() {} +} +// @set m2 = "$.index[*][?(@.name == 'm2' && @.kind == 'module')].id" +// @is "$.index[*][?(@.name == 'm2' && @.kind == 'module')].inner.items" [] +// @is "$.index[*][?(@.name == 'm2' && @.kind == 'module')].inner.is_stripped" true +mod m2 { + pub fn f(_: u8) {} +} + +// @set m1_use = "$.index[*][?(@.inner.name=='m1')].id" +// @is "$.index[*][?(@.inner.name=='m1')].inner.id" $m1 +// @is "$.index[*][?(@.inner.name=='m1')].inner.glob" true +pub use m1::*; +// @set m2_use = "$.index[*][?(@.inner.name=='m2')].id" +// @is "$.index[*][?(@.inner.name=='m2')].inner.id" $m2 +// @is "$.index[*][?(@.inner.name=='m2')].inner.glob" true +pub use m2::*; + +// @ismany "$.index[*][?(@.inner.is_crate==true)].inner.items[*]" $m1_use $m2_use diff --git a/src/test/rustdoc-json/reexport/glob_empty_mod.rs b/src/test/rustdoc-json/reexport/glob_empty_mod.rs new file mode 100644 index 0000000000000..da68228352c1c --- /dev/null +++ b/src/test/rustdoc-json/reexport/glob_empty_mod.rs @@ -0,0 +1,8 @@ +// Regression test for https://github.com/rust-lang/rust/issues/100973 + +// @is "$.index[*][?(@.name=='m1' && @.kind == 'module')].inner.is_stripped" true +// @set m1 = "$.index[*][?(@.name=='m1')].id" +mod m1 {} + +// @is "$.index[*][?(@.inner.name=='m1' && @.kind=='import')].inner.id" $m1 +pub use m1::*; diff --git a/src/test/rustdoc-json/reexport/in_root_and_mod.rs b/src/test/rustdoc-json/reexport/in_root_and_mod.rs index 68cb694f49949..7b97ebf2129eb 100644 --- a/src/test/rustdoc-json/reexport/in_root_and_mod.rs +++ b/src/test/rustdoc-json/reexport/in_root_and_mod.rs @@ -1,8 +1,7 @@ #![feature(no_core)] #![no_core] -// @is "$.index[*][?(@.name=='foo')].kind" \"module\" -// @is "$.index[*][?(@.name=='foo')].inner.is_stripped" "true" +// @!has "$.index[*][?(@.name=='foo')]" mod foo { // @has "$.index[*][?(@.name=='Foo')]" pub struct Foo; diff --git a/src/test/rustdoc-json/reexport/mod_not_included.rs b/src/test/rustdoc-json/reexport/mod_not_included.rs new file mode 100644 index 0000000000000..7b7600ef20f08 --- /dev/null +++ b/src/test/rustdoc-json/reexport/mod_not_included.rs @@ -0,0 +1,14 @@ +// Regression test for https://github.com/rust-lang/rust/issues/101103 + +#![feature(no_core)] +#![no_core] + +mod m1 { + pub fn x() {} +} + +pub use m1::x; + +// @has "$.index[*][?(@.name=='x' && @.kind=='function')]" +// @has "$.index[*][?(@.kind=='import' && @.inner.name=='x')].inner.source" '"m1::x"' +// @!has "$.index[*][?(@.name=='m1')]" diff --git a/src/test/rustdoc-json/reexport/private_two_names.rs b/src/test/rustdoc-json/reexport/private_two_names.rs index ec78b06d09ac8..9858538a9d046 100644 --- a/src/test/rustdoc-json/reexport/private_two_names.rs +++ b/src/test/rustdoc-json/reexport/private_two_names.rs @@ -6,8 +6,7 @@ #![no_core] #![feature(no_core)] -// @is "$.index[*][?(@.name=='style')].kind" \"module\" -// @is "$.index[*][?(@.name=='style')].inner.is_stripped" "true" +// @!has "$.index[*][?(@.name=='style')]" mod style { // @set color_struct_id = "$.index[*][?(@.kind=='struct' && @.name=='Color')].id" pub struct Color; diff --git a/src/test/rustdoc-json/reexport/rename_private.rs b/src/test/rustdoc-json/reexport/rename_private.rs index 1537f834481f4..8fd850f9b1370 100644 --- a/src/test/rustdoc-json/reexport/rename_private.rs +++ b/src/test/rustdoc-json/reexport/rename_private.rs @@ -3,8 +3,7 @@ #![no_core] #![feature(no_core)] -// @is "$.index[*][?(@.name=='inner')].kind" \"module\" -// @is "$.index[*][?(@.name=='inner')].inner.is_stripped" "true" +// @!has "$.index[*][?(@.kind=='inner')]" mod inner { // @has "$.index[*][?(@.name=='Public')]" pub struct Public; diff --git a/src/test/rustdoc-json/reexport/simple_private.rs b/src/test/rustdoc-json/reexport/simple_private.rs index 82348b383c363..d058ce0598d43 100644 --- a/src/test/rustdoc-json/reexport/simple_private.rs +++ b/src/test/rustdoc-json/reexport/simple_private.rs @@ -2,16 +2,15 @@ #![no_core] #![feature(no_core)] -// @is "$.index[*][?(@.name=='inner')].kind" \"module\" -// @is "$.index[*][?(@.name=='inner')].inner.is_stripped" "true" +// @!has "$.index[*][?(@.name=='inner')]" mod inner { // @set pub_id = "$.index[*][?(@.name=='Public')].id" pub struct Public; } // @is "$.index[*][?(@.kind=='import')].inner.name" \"Public\" +// @is "$.index[*][?(@.kind=='import')].inner.id" $pub_id // @set use_id = "$.index[*][?(@.kind=='import')].id" pub use inner::Public; -// @ismany "$.index[*][?(@.name=='inner')].inner.items[*]" $pub_id // @ismany "$.index[*][?(@.name=='simple_private')].inner.items[*]" $use_id diff --git a/src/test/rustdoc-json/stripped_modules.rs b/src/test/rustdoc-json/stripped_modules.rs index 33e95ce69d059..d2664b49e9c29 100644 --- a/src/test/rustdoc-json/stripped_modules.rs +++ b/src/test/rustdoc-json/stripped_modules.rs @@ -12,7 +12,7 @@ mod pub_inner_unreachable { pub fn pub_inner_1() {} } -// @has "$.index[*][?(@.name=='pub_inner_reachable')]" +// @!has "$.index[*][?(@.name=='pub_inner_reachable')]" mod pub_inner_reachable { // @has "$.index[*][?(@.name=='pub_inner_2')]" pub fn pub_inner_2() {} From 785101d7850f2e2d500496a28d0813f866ab52ca Mon Sep 17 00:00:00 2001 From: Nixon Enraght-Moony Date: Sun, 28 Aug 2022 02:43:13 +0100 Subject: [PATCH 24/25] check_missing_items.py: Check imports --- src/etc/check_missing_items.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/etc/check_missing_items.py b/src/etc/check_missing_items.py index ce06a79a21c3f..025f320e3a103 100644 --- a/src/etc/check_missing_items.py +++ b/src/etc/check_missing_items.py @@ -187,3 +187,9 @@ def check_type(ty): check_generic_bound(bound) if item["inner"]["default"]: check_type(item["inner"]["default"]) + elif item["kind"] == "import": + if item["inner"]["id"]: + inner_id = item["inner"]["id"] + assert valid_id(inner_id) + if inner_id in crate["index"] and inner_id not in visited: + work_list.add(inner_id) From cd1a42a95d1fa9b5f67eda4b17b702c9521bf1f4 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sun, 28 Aug 2022 01:39:59 -0400 Subject: [PATCH 25/25] Use the declaration's SourceInfo for FnEntry retags, not the outermost --- compiler/rustc_mir_transform/src/add_retag.rs | 19 ++++++++----------- ...soundness.retags.DeadStoreElimination.diff | 2 +- .../inline/inline_retag.bar.Inline.after.mir | 4 ++-- ...e#0}.SimplifyCfg-elaborate-drops.after.mir | 2 +- ...-foo.SimplifyCfg-elaborate-drops.after.mir | 4 ++-- ..._shr.SimplifyCfg-elaborate-drops.after.mir | 4 ++-- 6 files changed, 16 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs index 9c5896c4e4aed..036b5589849a2 100644 --- a/compiler/rustc_mir_transform/src/add_retag.rs +++ b/compiler/rustc_mir_transform/src/add_retag.rs @@ -66,7 +66,6 @@ impl<'tcx> MirPass<'tcx> for AddRetag { // We need an `AllCallEdges` pass before we can do any work. super::add_call_guards::AllCallEdges.run_pass(tcx, body); - let (span, arg_count) = (body.span, body.arg_count); let basic_blocks = body.basic_blocks.as_mut(); let local_decls = &body.local_decls; let needs_retag = |place: &Place<'tcx>| { @@ -90,20 +89,18 @@ impl<'tcx> MirPass<'tcx> for AddRetag { // PART 1 // Retag arguments at the beginning of the start block. { - // FIXME: Consider using just the span covering the function - // argument declaration. - let source_info = SourceInfo::outermost(span); // Gather all arguments, skip return value. - let places = local_decls - .iter_enumerated() - .skip(1) - .take(arg_count) - .map(|(local, _)| Place::from(local)) - .filter(needs_retag); + let places = local_decls.iter_enumerated().skip(1).take(body.arg_count).filter_map( + |(local, decl)| { + let place = Place::from(local); + needs_retag(&place).then_some((place, decl.source_info)) + }, + ); + // Emit their retags. basic_blocks[START_BLOCK].statements.splice( 0..0, - places.map(|place| Statement { + places.map(|(place, source_info)| Statement { source_info, kind: StatementKind::Retag(RetagKind::FnEntry, Box::new(place)), }), diff --git a/src/test/mir-opt/dead-store-elimination/provenance_soundness.retags.DeadStoreElimination.diff b/src/test/mir-opt/dead-store-elimination/provenance_soundness.retags.DeadStoreElimination.diff index 300f0d5dcaa98..b5f98233b3d7a 100644 --- a/src/test/mir-opt/dead-store-elimination/provenance_soundness.retags.DeadStoreElimination.diff +++ b/src/test/mir-opt/dead-store-elimination/provenance_soundness.retags.DeadStoreElimination.diff @@ -6,7 +6,7 @@ let mut _0: (); // return place in scope 0 at $DIR/provenance_soundness.rs:+0:25: +0:25 bb0: { - Retag([fn entry] _1); // scope 0 at $DIR/provenance_soundness.rs:+0:1: +0:27 + Retag([fn entry] _1); // scope 0 at $DIR/provenance_soundness.rs:+0:11: +0:13 _0 = const (); // scope 0 at $DIR/provenance_soundness.rs:+0:25: +0:27 return; // scope 0 at $DIR/provenance_soundness.rs:+0:27: +0:27 } diff --git a/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir b/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir index 989fe2785869c..d5410d3afd4a5 100644 --- a/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir +++ b/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir @@ -52,8 +52,8 @@ fn bar() -> bool { Retag(_7); // scope 1 at $DIR/inline-retag.rs:+2:11: +2:14 _6 = &(*_7); // scope 1 at $DIR/inline-retag.rs:+2:11: +2:14 Retag(_6); // scope 1 at $DIR/inline-retag.rs:+2:11: +2:14 - Retag(_3); // scope 2 at $DIR/inline-retag.rs:16:1: 18:2 - Retag(_6); // scope 2 at $DIR/inline-retag.rs:16:1: 18:2 + Retag(_3); // scope 2 at $DIR/inline-retag.rs:16:8: 16:9 + Retag(_6); // scope 2 at $DIR/inline-retag.rs:16:17: 16:18 StorageLive(_11); // scope 2 at $DIR/inline-retag.rs:17:5: 17:7 _11 = (*_3); // scope 2 at $DIR/inline-retag.rs:17:5: 17:7 StorageLive(_12); // scope 2 at $DIR/inline-retag.rs:17:11: 17:13 diff --git a/src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir index faaacc67ea81f..d254a95e06bea 100644 --- a/src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir @@ -10,7 +10,7 @@ fn main::{closure#0}(_1: &[closure@main::{closure#0}], _2: &i32) -> &i32 { bb0: { Retag([fn entry] _1); // scope 0 at $DIR/retag.rs:+0:31: +0:48 - Retag([fn entry] _2); // scope 0 at $DIR/retag.rs:+0:31: +0:48 + Retag([fn entry] _2); // scope 0 at $DIR/retag.rs:+0:32: +0:33 StorageLive(_3); // scope 0 at $DIR/retag.rs:42:13: 42:15 _3 = _2; // scope 0 at $DIR/retag.rs:42:18: 42:19 Retag(_3); // scope 0 at $DIR/retag.rs:42:18: 42:19 diff --git a/src/test/mir-opt/retag.{impl#0}-foo.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.{impl#0}-foo.SimplifyCfg-elaborate-drops.after.mir index 25d400f0c9fb2..08fd655ae29bb 100644 --- a/src/test/mir-opt/retag.{impl#0}-foo.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/retag.{impl#0}-foo.SimplifyCfg-elaborate-drops.after.mir @@ -7,8 +7,8 @@ fn ::foo(_1: &Test, _2: &mut i32) -> &mut i32 let mut _3: &mut i32; // in scope 0 at $DIR/retag.rs:+1:9: +1:10 bb0: { - Retag([fn entry] _1); // scope 0 at $DIR/retag.rs:+0:5: +2:6 - Retag([fn entry] _2); // scope 0 at $DIR/retag.rs:+0:5: +2:6 + Retag([fn entry] _1); // scope 0 at $DIR/retag.rs:+0:16: +0:21 + Retag([fn entry] _2); // scope 0 at $DIR/retag.rs:+0:23: +0:24 StorageLive(_3); // scope 0 at $DIR/retag.rs:+1:9: +1:10 _3 = &mut (*_2); // scope 0 at $DIR/retag.rs:+1:9: +1:10 Retag(_3); // scope 0 at $DIR/retag.rs:+1:9: +1:10 diff --git a/src/test/mir-opt/retag.{impl#0}-foo_shr.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.{impl#0}-foo_shr.SimplifyCfg-elaborate-drops.after.mir index 84ad8afc35760..f32a84e4c791b 100644 --- a/src/test/mir-opt/retag.{impl#0}-foo_shr.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/retag.{impl#0}-foo_shr.SimplifyCfg-elaborate-drops.after.mir @@ -6,8 +6,8 @@ fn ::foo_shr(_1: &Test, _2: &i32) -> &i32 { let mut _0: &i32; // return place in scope 0 at $DIR/retag.rs:+0:42: +0:49 bb0: { - Retag([fn entry] _1); // scope 0 at $DIR/retag.rs:+0:5: +2:6 - Retag([fn entry] _2); // scope 0 at $DIR/retag.rs:+0:5: +2:6 + Retag([fn entry] _1); // scope 0 at $DIR/retag.rs:+0:20: +0:25 + Retag([fn entry] _2); // scope 0 at $DIR/retag.rs:+0:27: +0:28 _0 = _2; // scope 0 at $DIR/retag.rs:+1:9: +1:10 Retag(_0); // scope 0 at $DIR/retag.rs:+1:9: +1:10 return; // scope 0 at $DIR/retag.rs:+2:6: +2:6