From 4df78a07e5c3ad032d59941b77ab394e4a75c7c1 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 13 Dec 2024 18:23:32 +0100 Subject: [PATCH 01/35] make rustc_encodable_decodable feature properly unstable --- library/core/src/macros/mod.rs | 6 +- library/core/src/prelude/mod.rs | 3 +- library/std/src/prelude/mod.rs | 3 +- .../derives/rustc-decodable-issue-123156.rs | 11 ---- .../rustc-decodable-issue-123156.stderr | 10 --- .../feature-gate-rustc_encodable_decodable.rs | 16 ----- ...ture-gate-rustc_encodable_decodable.stderr | 66 ------------------- 7 files changed, 4 insertions(+), 111 deletions(-) delete mode 100644 tests/ui/derives/rustc-decodable-issue-123156.rs delete mode 100644 tests/ui/derives/rustc-decodable-issue-123156.stderr delete mode 100644 tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.rs delete mode 100644 tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.stderr diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 402b436d28e6..ed79ceeb6db3 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1773,8 +1773,7 @@ pub(crate) mod builtin { #[rustc_builtin_macro] #[unstable( feature = "rustc_encodable_decodable", - issue = "none", - soft, + issue = "134301", reason = "derive macro for `rustc-serialize`; should not be used in new code" )] #[deprecated(since = "1.52.0", note = "rustc-serialize is deprecated and no longer supported")] @@ -1787,8 +1786,7 @@ pub(crate) mod builtin { #[rustc_builtin_macro] #[unstable( feature = "rustc_encodable_decodable", - issue = "none", - soft, + issue = "134301", reason = "derive macro for `rustc-serialize`; should not be used in new code" )] #[deprecated(since = "1.52.0", note = "rustc-serialize is deprecated and no longer supported")] diff --git a/library/core/src/prelude/mod.rs b/library/core/src/prelude/mod.rs index d3fda1cd273f..98f061d463a0 100644 --- a/library/core/src/prelude/mod.rs +++ b/library/core/src/prelude/mod.rs @@ -22,8 +22,7 @@ pub mod v1 { // Do not `doc(inline)` these `doc(hidden)` items. #[unstable( feature = "rustc_encodable_decodable", - issue = "none", - soft, + issue = "134301", reason = "derive macro for `rustc-serialize`; should not be used in new code" )] #[allow(deprecated)] diff --git a/library/std/src/prelude/mod.rs b/library/std/src/prelude/mod.rs index 4ec328208f01..b7efffcc4466 100644 --- a/library/std/src/prelude/mod.rs +++ b/library/std/src/prelude/mod.rs @@ -124,8 +124,7 @@ pub mod v1 { // Do not `doc(inline)` these `doc(hidden)` items. #[unstable( feature = "rustc_encodable_decodable", - issue = "none", - soft, + issue = "134301", reason = "derive macro for `rustc-serialize`; should not be used in new code" )] #[allow(deprecated)] diff --git a/tests/ui/derives/rustc-decodable-issue-123156.rs b/tests/ui/derives/rustc-decodable-issue-123156.rs deleted file mode 100644 index 1983837ed8d4..000000000000 --- a/tests/ui/derives/rustc-decodable-issue-123156.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ check-pass -//@ edition:2021 -//@ aux-build:rustc-serialize.rs - -#![crate_type = "lib"] -#![allow(deprecated, soft_unstable)] - -extern crate rustc_serialize; - -#[derive(RustcDecodable)] -pub enum Foo {} diff --git a/tests/ui/derives/rustc-decodable-issue-123156.stderr b/tests/ui/derives/rustc-decodable-issue-123156.stderr deleted file mode 100644 index 93a993b90d81..000000000000 --- a/tests/ui/derives/rustc-decodable-issue-123156.stderr +++ /dev/null @@ -1,10 +0,0 @@ -Future incompatibility report: Future breakage diagnostic: -warning: use of unstable library feature `rustc_encodable_decodable`: derive macro for `rustc-serialize`; should not be used in new code - --> $DIR/rustc-decodable-issue-123156.rs:10:10 - | -LL | #[derive(RustcDecodable)] - | ^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #64266 - diff --git a/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.rs b/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.rs deleted file mode 100644 index 71caf43806d0..000000000000 --- a/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.rs +++ /dev/null @@ -1,16 +0,0 @@ -#![crate_type = "lib"] - -// This isn't intended to compile, so it's easiest to just ignore this error. -extern crate rustc_serialize; //~ERROR can't find crate for `rustc_serialize` - -#[derive( - RustcEncodable, - //~^ ERROR use of unstable library feature `rustc_encodable_decodable` - //~^^ WARNING this was previously accepted by the compiler - //~^^^ WARNING use of deprecated macro `RustcEncodable` - RustcDecodable, - //~^ ERROR use of unstable library feature `rustc_encodable_decodable` - //~^^ WARNING this was previously accepted by the compiler - //~^^^ WARNING use of deprecated macro `RustcDecodable` -)] -struct S; diff --git a/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.stderr b/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.stderr deleted file mode 100644 index b949dbb9da21..000000000000 --- a/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.stderr +++ /dev/null @@ -1,66 +0,0 @@ -error[E0463]: can't find crate for `rustc_serialize` - --> $DIR/feature-gate-rustc_encodable_decodable.rs:4:1 - | -LL | extern crate rustc_serialize; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't find crate - | - = help: maybe you need to install the missing components with: `rustup component add rust-src rustc-dev llvm-tools-preview` - -error: use of unstable library feature `rustc_encodable_decodable`: derive macro for `rustc-serialize`; should not be used in new code - --> $DIR/feature-gate-rustc_encodable_decodable.rs:7:5 - | -LL | RustcEncodable, - | ^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #64266 - = note: `#[deny(soft_unstable)]` on by default - -warning: use of deprecated macro `RustcEncodable`: rustc-serialize is deprecated and no longer supported - --> $DIR/feature-gate-rustc_encodable_decodable.rs:7:5 - | -LL | RustcEncodable, - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(deprecated)]` on by default - -error: use of unstable library feature `rustc_encodable_decodable`: derive macro for `rustc-serialize`; should not be used in new code - --> $DIR/feature-gate-rustc_encodable_decodable.rs:11:5 - | -LL | RustcDecodable, - | ^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #64266 - -warning: use of deprecated macro `RustcDecodable`: rustc-serialize is deprecated and no longer supported - --> $DIR/feature-gate-rustc_encodable_decodable.rs:11:5 - | -LL | RustcDecodable, - | ^^^^^^^^^^^^^^ - -error: aborting due to 3 previous errors; 2 warnings emitted - -For more information about this error, try `rustc --explain E0463`. -Future incompatibility report: Future breakage diagnostic: -error: use of unstable library feature `rustc_encodable_decodable`: derive macro for `rustc-serialize`; should not be used in new code - --> $DIR/feature-gate-rustc_encodable_decodable.rs:7:5 - | -LL | RustcEncodable, - | ^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #64266 - = note: `#[deny(soft_unstable)]` on by default - -Future breakage diagnostic: -error: use of unstable library feature `rustc_encodable_decodable`: derive macro for `rustc-serialize`; should not be used in new code - --> $DIR/feature-gate-rustc_encodable_decodable.rs:11:5 - | -LL | RustcDecodable, - | ^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #64266 - = note: `#[deny(soft_unstable)]` on by default - From 9ac62f972fd47705f9d229e854772194565071eb Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 7 Jan 2025 18:28:42 +0100 Subject: [PATCH 02/35] remove Rustc{En,De}codable from library and compiler --- .../src/deriving/debug.rs | 2 +- .../src/deriving/decodable.rs | 215 ------------- .../src/deriving/default.rs | 2 +- .../src/deriving/encodable.rs | 284 ------------------ .../src/deriving/generic/mod.rs | 26 +- .../src/deriving/generic/ty.rs | 2 - .../rustc_builtin_macros/src/deriving/mod.rs | 2 - compiler/rustc_builtin_macros/src/lib.rs | 2 - compiler/rustc_span/src/symbol.rs | 2 - library/core/src/macros/mod.rs | 26 -- library/core/src/prelude/mod.rs | 9 - library/std/src/prelude/mod.rs | 9 - 12 files changed, 10 insertions(+), 571 deletions(-) delete mode 100644 compiler/rustc_builtin_macros/src/deriving/decodable.rs delete mode 100644 compiler/rustc_builtin_macros/src/deriving/encodable.rs diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index eb01ca3941d8..8ab21986e68a 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -56,7 +56,7 @@ fn show_substructure(cx: &ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> let (ident, vdata, fields) = match substr.fields { Struct(vdata, fields) => (substr.type_ident, *vdata, fields), - EnumMatching(_, v, fields) => (v.ident, &v.data, fields), + EnumMatching(v, fields) => (v.ident, &v.data, fields), AllFieldlessEnum(enum_def) => return show_fieldless_enum(cx, span, enum_def, substr), EnumDiscr(..) | StaticStruct(..) | StaticEnum(..) => { cx.dcx().span_bug(span, "nonsensical .fields in `#[derive(Debug)]`") diff --git a/compiler/rustc_builtin_macros/src/deriving/decodable.rs b/compiler/rustc_builtin_macros/src/deriving/decodable.rs deleted file mode 100644 index 6348560496e9..000000000000 --- a/compiler/rustc_builtin_macros/src/deriving/decodable.rs +++ /dev/null @@ -1,215 +0,0 @@ -//! The compiler code necessary for `#[derive(RustcDecodable)]`. See encodable.rs for more. - -use rustc_ast::ptr::P; -use rustc_ast::{self as ast, Expr, MetaItem, Mutability}; -use rustc_expand::base::{Annotatable, ExtCtxt}; -use rustc_span::{Ident, Span, Symbol, sym}; -use thin_vec::{ThinVec, thin_vec}; - -use crate::deriving::generic::ty::*; -use crate::deriving::generic::*; -use crate::deriving::pathvec_std; - -pub(crate) fn expand_deriving_rustc_decodable( - cx: &ExtCtxt<'_>, - span: Span, - mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable), - is_const: bool, -) { - let krate = sym::rustc_serialize; - let typaram = sym::__D; - - let trait_def = TraitDef { - span, - path: Path::new_(vec![krate, sym::Decodable], vec![], PathKind::Global), - skip_path_as_bound: false, - needs_copy_as_bound_if_packed: true, - additional_bounds: Vec::new(), - supports_unions: false, - methods: vec![MethodDef { - name: sym::decode, - generics: Bounds { - bounds: vec![(typaram, vec![Path::new_( - vec![krate, sym::Decoder], - vec![], - PathKind::Global, - )])], - }, - explicit_self: false, - nonself_args: vec![( - Ref(Box::new(Path(Path::new_local(typaram))), Mutability::Mut), - sym::d, - )], - ret_ty: Path(Path::new_( - pathvec_std!(result::Result), - vec![ - Box::new(Self_), - Box::new(Path(Path::new_(vec![typaram, sym::Error], vec![], PathKind::Local))), - ], - PathKind::Std, - )), - attributes: ast::AttrVec::new(), - fieldless_variants_strategy: FieldlessVariantsStrategy::Default, - combine_substructure: combine_substructure(Box::new(|a, b, c| { - decodable_substructure(a, b, c, krate) - })), - }], - associated_types: Vec::new(), - is_const, - }; - - trait_def.expand(cx, mitem, item, push) -} - -fn decodable_substructure( - cx: &ExtCtxt<'_>, - trait_span: Span, - substr: &Substructure<'_>, - krate: Symbol, -) -> BlockOrExpr { - let decoder = substr.nonselflike_args[0].clone(); - let recurse = vec![ - Ident::new(krate, trait_span), - Ident::new(sym::Decodable, trait_span), - Ident::new(sym::decode, trait_span), - ]; - let exprdecode = cx.expr_path(cx.path_global(trait_span, recurse)); - // throw an underscore in front to suppress unused variable warnings - let blkarg = Ident::new(sym::_d, trait_span); - let blkdecoder = cx.expr_ident(trait_span, blkarg); - - let expr = match substr.fields { - StaticStruct(_, summary) => { - let nfields = match summary { - Unnamed(fields, _) => fields.len(), - Named(fields) => fields.len(), - }; - let fn_read_struct_field_path: Vec<_> = - cx.def_site_path(&[sym::rustc_serialize, sym::Decoder, sym::read_struct_field]); - - let path = cx.path_ident(trait_span, substr.type_ident); - let result = - decode_static_fields(cx, trait_span, path, summary, |cx, span, name, field| { - cx.expr_try( - span, - cx.expr_call_global(span, fn_read_struct_field_path.clone(), thin_vec![ - blkdecoder.clone(), - cx.expr_str(span, name), - cx.expr_usize(span, field), - exprdecode.clone(), - ]), - ) - }); - let result = cx.expr_ok(trait_span, result); - let fn_read_struct_path: Vec<_> = - cx.def_site_path(&[sym::rustc_serialize, sym::Decoder, sym::read_struct]); - - cx.expr_call_global(trait_span, fn_read_struct_path, thin_vec![ - decoder, - cx.expr_str(trait_span, substr.type_ident.name), - cx.expr_usize(trait_span, nfields), - cx.lambda1(trait_span, result, blkarg), - ]) - } - StaticEnum(_, fields) => { - let variant = Ident::new(sym::i, trait_span); - - let mut arms = ThinVec::with_capacity(fields.len() + 1); - let mut variants = ThinVec::with_capacity(fields.len()); - - let fn_read_enum_variant_arg_path: Vec<_> = - cx.def_site_path(&[sym::rustc_serialize, sym::Decoder, sym::read_enum_variant_arg]); - - for (i, &(ident, v_span, ref parts)) in fields.iter().enumerate() { - variants.push(cx.expr_str(v_span, ident.name)); - - let path = cx.path(trait_span, vec![substr.type_ident, ident]); - let decoded = - decode_static_fields(cx, v_span, path, parts, |cx, span, _, field| { - let idx = cx.expr_usize(span, field); - cx.expr_try( - span, - cx.expr_call_global( - span, - fn_read_enum_variant_arg_path.clone(), - thin_vec![blkdecoder.clone(), idx, exprdecode.clone()], - ), - ) - }); - - arms.push(cx.arm(v_span, cx.pat_lit(v_span, cx.expr_usize(v_span, i)), decoded)); - } - - arms.push(cx.arm_unreachable(trait_span)); - - let result = cx.expr_ok( - trait_span, - cx.expr_match(trait_span, cx.expr_ident(trait_span, variant), arms), - ); - let lambda = cx.lambda(trait_span, vec![blkarg, variant], result); - let variant_array_ref = cx.expr_array_ref(trait_span, variants); - let fn_read_enum_variant_path: Vec<_> = - cx.def_site_path(&[sym::rustc_serialize, sym::Decoder, sym::read_enum_variant]); - let result = cx.expr_call_global(trait_span, fn_read_enum_variant_path, thin_vec![ - blkdecoder, - variant_array_ref, - lambda - ]); - let fn_read_enum_path: Vec<_> = - cx.def_site_path(&[sym::rustc_serialize, sym::Decoder, sym::read_enum]); - - cx.expr_call_global(trait_span, fn_read_enum_path, thin_vec![ - decoder, - cx.expr_str(trait_span, substr.type_ident.name), - cx.lambda1(trait_span, result, blkarg), - ]) - } - _ => cx.dcx().bug("expected StaticEnum or StaticStruct in derive(Decodable)"), - }; - BlockOrExpr::new_expr(expr) -} - -/// Creates a decoder for a single enum variant/struct: -/// - `outer_pat_path` is the path to this enum variant/struct -/// - `getarg` should retrieve the `usize`-th field with name `@str`. -fn decode_static_fields( - cx: &ExtCtxt<'_>, - trait_span: Span, - outer_pat_path: ast::Path, - fields: &StaticFields, - mut getarg: F, -) -> P -where - F: FnMut(&ExtCtxt<'_>, Span, Symbol, usize) -> P, -{ - match fields { - Unnamed(fields, is_tuple) => { - let path_expr = cx.expr_path(outer_pat_path); - if matches!(is_tuple, IsTuple::No) { - path_expr - } else { - let fields = fields - .iter() - .enumerate() - .map(|(i, &span)| getarg(cx, span, Symbol::intern(&format!("_field{i}")), i)) - .collect(); - - cx.expr_call(trait_span, path_expr, fields) - } - } - Named(fields) => { - // use the field's span to get nicer error messages. - let fields = fields - .iter() - .enumerate() - .map(|(i, &(ident, span, _))| { - let arg = getarg(cx, span, ident.name, i); - cx.field_imm(span, ident, arg) - }) - .collect(); - cx.expr_struct(trait_span, outer_pat_path, fields) - } - } -} diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index 3c7bebd0f192..2388b7dd6482 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -42,7 +42,7 @@ pub(crate) fn expand_deriving_default( StaticStruct(_, fields) => { default_struct_substructure(cx, trait_span, substr, fields) } - StaticEnum(enum_def, _) => { + StaticEnum(enum_def) => { default_enum_substructure(cx, trait_span, enum_def, item.span()) } _ => cx.dcx().span_bug(trait_span, "method in `derive(Default)`"), diff --git a/compiler/rustc_builtin_macros/src/deriving/encodable.rs b/compiler/rustc_builtin_macros/src/deriving/encodable.rs deleted file mode 100644 index 20aacb2caca2..000000000000 --- a/compiler/rustc_builtin_macros/src/deriving/encodable.rs +++ /dev/null @@ -1,284 +0,0 @@ -//! The compiler code necessary to implement the `#[derive(RustcEncodable)]` -//! (and `RustcDecodable`, in `decodable.rs`) extension. The idea here is that -//! type-defining items may be tagged with -//! `#[derive(RustcEncodable, RustcDecodable)]`. -//! -//! For example, a type like: -//! -//! ```ignore (old code) -//! #[derive(RustcEncodable, RustcDecodable)] -//! struct Node { id: usize } -//! ``` -//! -//! would generate two implementations like: -//! -//! ```ignore (old code) -//! # struct Node { id: usize } -//! impl, E> Encodable for Node { -//! fn encode(&self, s: &mut S) -> Result<(), E> { -//! s.emit_struct("Node", 1, |this| { -//! this.emit_struct_field("id", 0, |this| { -//! Encodable::encode(&self.id, this) -//! /* this.emit_usize(self.id) can also be used */ -//! }) -//! }) -//! } -//! } -//! -//! impl, E> Decodable for Node { -//! fn decode(d: &mut D) -> Result { -//! d.read_struct("Node", 1, |this| { -//! match this.read_struct_field("id", 0, |this| Decodable::decode(this)) { -//! Ok(id) => Ok(Node { id: id }), -//! Err(e) => Err(e), -//! } -//! }) -//! } -//! } -//! ``` -//! -//! Other interesting scenarios are when the item has type parameters or -//! references other non-built-in types. A type definition like: -//! -//! ```ignore (old code) -//! # #[derive(RustcEncodable, RustcDecodable)] -//! # struct Span; -//! #[derive(RustcEncodable, RustcDecodable)] -//! struct Spanned { node: T, span: Span } -//! ``` -//! -//! would yield functions like: -//! -//! ```ignore (old code) -//! # #[derive(RustcEncodable, RustcDecodable)] -//! # struct Span; -//! # struct Spanned { node: T, span: Span } -//! impl< -//! S: Encoder, -//! E, -//! T: Encodable -//! > Encodable for Spanned { -//! fn encode(&self, s: &mut S) -> Result<(), E> { -//! s.emit_struct("Spanned", 2, |this| { -//! this.emit_struct_field("node", 0, |this| self.node.encode(this)) -//! .unwrap(); -//! this.emit_struct_field("span", 1, |this| self.span.encode(this)) -//! }) -//! } -//! } -//! -//! impl< -//! D: Decoder, -//! E, -//! T: Decodable -//! > Decodable for Spanned { -//! fn decode(d: &mut D) -> Result, E> { -//! d.read_struct("Spanned", 2, |this| { -//! Ok(Spanned { -//! node: this.read_struct_field("node", 0, |this| Decodable::decode(this)) -//! .unwrap(), -//! span: this.read_struct_field("span", 1, |this| Decodable::decode(this)) -//! .unwrap(), -//! }) -//! }) -//! } -//! } -//! ``` - -use rustc_ast::{AttrVec, ExprKind, MetaItem, Mutability}; -use rustc_expand::base::{Annotatable, ExtCtxt}; -use rustc_span::{Ident, Span, Symbol, sym}; -use thin_vec::{ThinVec, thin_vec}; - -use crate::deriving::generic::ty::*; -use crate::deriving::generic::*; -use crate::deriving::pathvec_std; - -pub(crate) fn expand_deriving_rustc_encodable( - cx: &ExtCtxt<'_>, - span: Span, - mitem: &MetaItem, - item: &Annotatable, - push: &mut dyn FnMut(Annotatable), - is_const: bool, -) { - let krate = sym::rustc_serialize; - let typaram = sym::__S; - - let trait_def = TraitDef { - span, - path: Path::new_(vec![krate, sym::Encodable], vec![], PathKind::Global), - skip_path_as_bound: false, - needs_copy_as_bound_if_packed: true, - additional_bounds: Vec::new(), - supports_unions: false, - methods: vec![MethodDef { - name: sym::encode, - generics: Bounds { - bounds: vec![(typaram, vec![Path::new_( - vec![krate, sym::Encoder], - vec![], - PathKind::Global, - )])], - }, - explicit_self: true, - nonself_args: vec![( - Ref(Box::new(Path(Path::new_local(typaram))), Mutability::Mut), - sym::s, - )], - ret_ty: Path(Path::new_( - pathvec_std!(result::Result), - vec![ - Box::new(Unit), - Box::new(Path(Path::new_(vec![typaram, sym::Error], vec![], PathKind::Local))), - ], - PathKind::Std, - )), - attributes: AttrVec::new(), - fieldless_variants_strategy: FieldlessVariantsStrategy::Default, - combine_substructure: combine_substructure(Box::new(|a, b, c| { - encodable_substructure(a, b, c, krate) - })), - }], - associated_types: Vec::new(), - is_const, - }; - - trait_def.expand(cx, mitem, item, push) -} - -fn encodable_substructure( - cx: &ExtCtxt<'_>, - trait_span: Span, - substr: &Substructure<'_>, - krate: Symbol, -) -> BlockOrExpr { - let encoder = substr.nonselflike_args[0].clone(); - // throw an underscore in front to suppress unused variable warnings - let blkarg = Ident::new(sym::_e, trait_span); - let blkencoder = cx.expr_ident(trait_span, blkarg); - let fn_path = cx.expr_path(cx.path_global(trait_span, vec![ - Ident::new(krate, trait_span), - Ident::new(sym::Encodable, trait_span), - Ident::new(sym::encode, trait_span), - ])); - - match substr.fields { - Struct(_, fields) => { - let fn_emit_struct_field_path = - cx.def_site_path(&[sym::rustc_serialize, sym::Encoder, sym::emit_struct_field]); - let mut stmts = ThinVec::new(); - for (i, &FieldInfo { name, ref self_expr, span, .. }) in fields.iter().enumerate() { - let name = match name { - Some(id) => id.name, - None => Symbol::intern(&format!("_field{i}")), - }; - let self_ref = cx.expr_addr_of(span, self_expr.clone()); - let enc = - cx.expr_call(span, fn_path.clone(), thin_vec![self_ref, blkencoder.clone()]); - let lambda = cx.lambda1(span, enc, blkarg); - let call = cx.expr_call_global(span, fn_emit_struct_field_path.clone(), thin_vec![ - blkencoder.clone(), - cx.expr_str(span, name), - cx.expr_usize(span, i), - lambda, - ]); - - // last call doesn't need a try! - let last = fields.len() - 1; - let call = if i != last { - cx.expr_try(span, call) - } else { - cx.expr(span, ExprKind::Ret(Some(call))) - }; - - let stmt = cx.stmt_expr(call); - stmts.push(stmt); - } - - // unit structs have no fields and need to return Ok() - let blk = if stmts.is_empty() { - let ok = cx.expr_ok(trait_span, cx.expr_tuple(trait_span, ThinVec::new())); - cx.lambda1(trait_span, ok, blkarg) - } else { - cx.lambda_stmts_1(trait_span, stmts, blkarg) - }; - - let fn_emit_struct_path = - cx.def_site_path(&[sym::rustc_serialize, sym::Encoder, sym::emit_struct]); - - let expr = cx.expr_call_global(trait_span, fn_emit_struct_path, thin_vec![ - encoder, - cx.expr_str(trait_span, substr.type_ident.name), - cx.expr_usize(trait_span, fields.len()), - blk, - ]); - BlockOrExpr::new_expr(expr) - } - - EnumMatching(idx, variant, fields) => { - // We're not generating an AST that the borrow checker is expecting, - // so we need to generate a unique local variable to take the - // mutable loan out on, otherwise we get conflicts which don't - // actually exist. - let me = cx.stmt_let(trait_span, false, blkarg, encoder); - let encoder = cx.expr_ident(trait_span, blkarg); - - let fn_emit_enum_variant_arg_path: Vec<_> = - cx.def_site_path(&[sym::rustc_serialize, sym::Encoder, sym::emit_enum_variant_arg]); - - let mut stmts = ThinVec::new(); - if !fields.is_empty() { - let last = fields.len() - 1; - for (i, &FieldInfo { ref self_expr, span, .. }) in fields.iter().enumerate() { - let self_ref = cx.expr_addr_of(span, self_expr.clone()); - let enc = cx - .expr_call(span, fn_path.clone(), thin_vec![self_ref, blkencoder.clone()]); - let lambda = cx.lambda1(span, enc, blkarg); - - let call = cx.expr_call_global( - span, - fn_emit_enum_variant_arg_path.clone(), - thin_vec![blkencoder.clone(), cx.expr_usize(span, i), lambda], - ); - let call = if i != last { - cx.expr_try(span, call) - } else { - cx.expr(span, ExprKind::Ret(Some(call))) - }; - stmts.push(cx.stmt_expr(call)); - } - } else { - let ok = cx.expr_ok(trait_span, cx.expr_tuple(trait_span, ThinVec::new())); - let ret_ok = cx.expr(trait_span, ExprKind::Ret(Some(ok))); - stmts.push(cx.stmt_expr(ret_ok)); - } - - let blk = cx.lambda_stmts_1(trait_span, stmts, blkarg); - let name = cx.expr_str(trait_span, variant.ident.name); - - let fn_emit_enum_variant_path: Vec<_> = - cx.def_site_path(&[sym::rustc_serialize, sym::Encoder, sym::emit_enum_variant]); - - let call = cx.expr_call_global(trait_span, fn_emit_enum_variant_path, thin_vec![ - blkencoder, - name, - cx.expr_usize(trait_span, *idx), - cx.expr_usize(trait_span, fields.len()), - blk, - ]); - - let blk = cx.lambda1(trait_span, call, blkarg); - let fn_emit_enum_path: Vec<_> = - cx.def_site_path(&[sym::rustc_serialize, sym::Encoder, sym::emit_enum]); - let expr = cx.expr_call_global(trait_span, fn_emit_enum_path, thin_vec![ - encoder, - cx.expr_str(trait_span, substr.type_ident.name), - blk - ]); - BlockOrExpr::new_mixed(thin_vec![me], Some(expr)) - } - - _ => cx.dcx().bug("expected Struct or EnumMatching in derive(Encodable)"), - } -} diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index f0a5e44e066e..755a733286ce 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -311,7 +311,7 @@ pub(crate) enum SubstructureFields<'a> { /// Matching variants of the enum: variant index, ast::Variant, /// fields: the field name is only non-`None` in the case of a struct /// variant. - EnumMatching(usize, &'a ast::Variant, Vec), + EnumMatching(&'a ast::Variant, Vec), /// The discriminant of an enum. The first field is a `FieldInfo` for the discriminants, as /// if they were fields. The second field is the expression to combine the @@ -322,7 +322,7 @@ pub(crate) enum SubstructureFields<'a> { StaticStruct(&'a ast::VariantData, StaticFields), /// A static method where `Self` is an enum. - StaticEnum(&'a ast::EnumDef, Vec<(Ident, Span, StaticFields)>), + StaticEnum(&'a ast::EnumDef), } /// Combine the values of all the fields together. The last argument is @@ -1270,7 +1270,7 @@ impl<'a> MethodDef<'a> { trait_, type_ident, nonselflike_args, - &EnumMatching(0, variant, Vec::new()), + &EnumMatching(variant, Vec::new()), ); } } @@ -1282,9 +1282,8 @@ impl<'a> MethodDef<'a> { // where each tuple has length = selflike_args.len() let mut match_arms: ThinVec = variants .iter() - .enumerate() - .filter(|&(_, v)| !(unify_fieldless_variants && v.data.fields().is_empty())) - .map(|(index, variant)| { + .filter(|&v| !(unify_fieldless_variants && v.data.fields().is_empty())) + .map(|variant| { // A single arm has form (&VariantK, &VariantK, ...) => BodyK // (see "Final wrinkle" note below for why.) @@ -1316,7 +1315,7 @@ impl<'a> MethodDef<'a> { // expressions for referencing every field of every // Self arg, assuming all are instances of VariantK. // Build up code associated with such a case. - let substructure = EnumMatching(index, variant, fields); + let substructure = EnumMatching(variant, fields); let arm_expr = self .call_substructure_method( cx, @@ -1344,7 +1343,7 @@ impl<'a> MethodDef<'a> { trait_, type_ident, nonselflike_args, - &EnumMatching(0, v, Vec::new()), + &EnumMatching(v, Vec::new()), ) .into_expr(cx, span), ) @@ -1407,21 +1406,12 @@ impl<'a> MethodDef<'a> { type_ident: Ident, nonselflike_args: &[P], ) -> BlockOrExpr { - let summary = enum_def - .variants - .iter() - .map(|v| { - let sp = v.span.with_ctxt(trait_.span.ctxt()); - let summary = trait_.summarise_struct(cx, &v.data); - (v.ident, sp, summary) - }) - .collect(); self.call_substructure_method( cx, trait_, type_ident, nonselflike_args, - &StaticEnum(enum_def, summary), + &StaticEnum(enum_def), ) } } diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs index af6dc62db7a9..f34a6ae1d982 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs @@ -21,7 +21,6 @@ pub(crate) struct Path { #[derive(Clone)] pub(crate) enum PathKind { Local, - Global, Std, } @@ -57,7 +56,6 @@ impl Path { let params = tys.map(GenericArg::Type).collect(); match self.kind { - PathKind::Global => cx.path_all(span, true, idents, params), PathKind::Local => cx.path_all(span, false, idents, params), PathKind::Std => { let def_site = cx.with_def_site_ctxt(DUMMY_SP); diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs index ec058b413137..c112589b1319 100644 --- a/compiler/rustc_builtin_macros/src/deriving/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs @@ -23,9 +23,7 @@ pub(crate) mod bounds; pub(crate) mod clone; pub(crate) mod coerce_pointee; pub(crate) mod debug; -pub(crate) mod decodable; pub(crate) mod default; -pub(crate) mod encodable; pub(crate) mod hash; #[path = "cmp/eq.rs"] diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 6071d36f8ebb..dfc8fe2d7f0f 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -131,8 +131,6 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { Ord: ord::expand_deriving_ord, PartialEq: partial_eq::expand_deriving_partial_eq, PartialOrd: partial_ord::expand_deriving_partial_ord, - RustcDecodable: decodable::expand_deriving_rustc_decodable, - RustcEncodable: encodable::expand_deriving_rustc_encodable, CoercePointee: coerce_pointee::expand_deriving_coerce_pointee, } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index a5bf5e06485a..7e09adbea2bd 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -314,8 +314,6 @@ symbols! { Right, Rust, RustaceansAreAwesome, - RustcDecodable, - RustcEncodable, RwLock, RwLockReadGuard, RwLockWriteGuard, diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index ed79ceeb6db3..205e9014c624 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1768,30 +1768,4 @@ pub(crate) mod builtin { pub macro deref($pat:pat) { builtin # deref($pat) } - - /// Derive macro for `rustc-serialize`. Should not be used in new code. - #[rustc_builtin_macro] - #[unstable( - feature = "rustc_encodable_decodable", - issue = "134301", - reason = "derive macro for `rustc-serialize`; should not be used in new code" - )] - #[deprecated(since = "1.52.0", note = "rustc-serialize is deprecated and no longer supported")] - #[doc(hidden)] // While technically stable, using it is unstable, and deprecated. Hide it. - pub macro RustcDecodable($item:item) { - /* compiler built-in */ - } - - /// Derive macro for `rustc-serialize`. Should not be used in new code. - #[rustc_builtin_macro] - #[unstable( - feature = "rustc_encodable_decodable", - issue = "134301", - reason = "derive macro for `rustc-serialize`; should not be used in new code" - )] - #[deprecated(since = "1.52.0", note = "rustc-serialize is deprecated and no longer supported")] - #[doc(hidden)] // While technically stable, using it is unstable, and deprecated. Hide it. - pub macro RustcEncodable($item:item) { - /* compiler built-in */ - } } diff --git a/library/core/src/prelude/mod.rs b/library/core/src/prelude/mod.rs index 98f061d463a0..0ab97f5bbd50 100644 --- a/library/core/src/prelude/mod.rs +++ b/library/core/src/prelude/mod.rs @@ -18,15 +18,6 @@ mod common; pub mod v1 { #[stable(feature = "rust1", since = "1.0.0")] pub use super::common::*; - - // Do not `doc(inline)` these `doc(hidden)` items. - #[unstable( - feature = "rustc_encodable_decodable", - issue = "134301", - reason = "derive macro for `rustc-serialize`; should not be used in new code" - )] - #[allow(deprecated)] - pub use crate::macros::builtin::{RustcDecodable, RustcEncodable}; } /// The 2015 version of the core prelude. diff --git a/library/std/src/prelude/mod.rs b/library/std/src/prelude/mod.rs index b7efffcc4466..14e6c2715df0 100644 --- a/library/std/src/prelude/mod.rs +++ b/library/std/src/prelude/mod.rs @@ -120,15 +120,6 @@ mod common; pub mod v1 { #[stable(feature = "rust1", since = "1.0.0")] pub use super::common::*; - - // Do not `doc(inline)` these `doc(hidden)` items. - #[unstable( - feature = "rustc_encodable_decodable", - issue = "134301", - reason = "derive macro for `rustc-serialize`; should not be used in new code" - )] - #[allow(deprecated)] - pub use core::prelude::v1::{RustcDecodable, RustcEncodable}; } /// The 2015 version of the prelude of The Rust Standard Library. From b20bc53c3d0566f681ad1686ae53216f1c1bee3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Wed, 20 Nov 2024 22:05:31 +0100 Subject: [PATCH 03/35] ci: fix explanation why LLVM download is disabled for windows-gnu --- src/ci/github-actions/jobs.yml | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 7730d29d28f6..54d6fb0a5022 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -525,8 +525,7 @@ auto: env: RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu SCRIPT: make ci-mingw - # We are intentionally allowing an old toolchain on this builder (and that's - # incompatible with LLVM downloads today). + # There is no dist-i686-mingw-alt, so there is no prebuilt LLVM with assertions NO_DOWNLOAD_CI_LLVM: 1 <<: *job-windows-8c @@ -535,8 +534,7 @@ auto: env: SCRIPT: make ci-mingw-x RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu - # We are intentionally allowing an old toolchain on this builder (and that's - # incompatible with LLVM downloads today). + # There is no dist-x86_64-mingw-alt, so there is no prebuilt LLVM with assertions NO_DOWNLOAD_CI_LLVM: 1 <<: *job-windows @@ -544,8 +542,7 @@ auto: env: SCRIPT: make ci-mingw-bootstrap RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu - # We are intentionally allowing an old toolchain on this builder (and that's - # incompatible with LLVM downloads today). + # There is no dist-x86_64-mingw-alt, so there is no prebuilt LLVM with assertions NO_DOWNLOAD_CI_LLVM: 1 <<: *job-windows @@ -593,9 +590,6 @@ auto: RUST_CONFIGURE_ARGS: >- --build=i686-pc-windows-gnu --enable-full-tools - # We are intentionally allowing an old toolchain on this builder (and that's - # incompatible with LLVM downloads today). - NO_DOWNLOAD_CI_LLVM: 1 SCRIPT: python x.py dist bootstrap --include-default-paths DIST_REQUIRE_ALL_TOOLS: 1 CODEGEN_BACKENDS: llvm,cranelift @@ -607,9 +601,6 @@ auto: RUST_CONFIGURE_ARGS: >- --build=x86_64-pc-windows-gnu --enable-full-tools - # We are intentionally allowing an old toolchain on this builder (and that's - # incompatible with LLVM downloads today). - NO_DOWNLOAD_CI_LLVM: 1 DIST_REQUIRE_ALL_TOOLS: 1 CODEGEN_BACKENDS: llvm,cranelift <<: *job-windows From 4d42046719835a201599354b1a5a82d7bd00ab45 Mon Sep 17 00:00:00 2001 From: Veera Date: Fri, 31 Jan 2025 06:09:29 +0000 Subject: [PATCH 04/35] CompileTest: Add Directives to Ignore `arm-unknown-*` Tests --- src/tools/compiletest/src/directive-list.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/tools/compiletest/src/directive-list.rs b/src/tools/compiletest/src/directive-list.rs index 71496444660f..a7ac875d0a36 100644 --- a/src/tools/compiletest/src/directive-list.rs +++ b/src/tools/compiletest/src/directive-list.rs @@ -39,6 +39,10 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "ignore-android", "ignore-apple", "ignore-arm", + "ignore-arm-unknown-linux-gnueabi", + "ignore-arm-unknown-linux-gnueabihf", + "ignore-arm-unknown-linux-musleabi", + "ignore-arm-unknown-linux-musleabihf", "ignore-avr", "ignore-beta", "ignore-cdb", From 860476f6e0b400994caa09878646d4d9fd91b7b5 Mon Sep 17 00:00:00 2001 From: Marijn Schouten Date: Thu, 30 Jan 2025 09:13:21 +0100 Subject: [PATCH 05/35] Update encode_utf16 to mention it is native endian --- library/alloc/src/string.rs | 16 ++++++++-------- library/core/src/char/methods.rs | 6 +++--- library/core/src/str/mod.rs | 3 ++- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 0c9535dfaa62..b29f740ef0f2 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -712,8 +712,8 @@ impl String { } } - /// Decode a UTF-16–encoded vector `v` into a `String`, returning [`Err`] - /// if `v` contains any invalid data. + /// Decode a native endian UTF-16–encoded vector `v` into a `String`, + /// returning [`Err`] if `v` contains any invalid data. /// /// # Examples /// @@ -745,8 +745,8 @@ impl String { Ok(ret) } - /// Decode a UTF-16–encoded slice `v` into a `String`, replacing - /// invalid data with [the replacement character (`U+FFFD`)][U+FFFD]. + /// Decode a native endian UTF-16–encoded slice `v` into a `String`, + /// replacing invalid data with [the replacement character (`U+FFFD`)][U+FFFD]. /// /// Unlike [`from_utf8_lossy`] which returns a [`Cow<'a, str>`], /// `from_utf16_lossy` returns a `String` since the UTF-16 to UTF-8 @@ -777,8 +777,8 @@ impl String { .collect() } - /// Decode a UTF-16LE–encoded vector `v` into a `String`, returning [`Err`] - /// if `v` contains any invalid data. + /// Decode a UTF-16LE–encoded vector `v` into a `String`, + /// returning [`Err`] if `v` contains any invalid data. /// /// # Examples /// @@ -852,8 +852,8 @@ impl String { } } - /// Decode a UTF-16BE–encoded vector `v` into a `String`, returning [`Err`] - /// if `v` contains any invalid data. + /// Decode a UTF-16BE–encoded vector `v` into a `String`, + /// returning [`Err`] if `v` contains any invalid data. /// /// # Examples /// diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index fb8a740aced1..ccfdbf0eb704 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -92,7 +92,7 @@ impl char { #[stable(feature = "assoc_char_consts", since = "1.52.0")] pub const UNICODE_VERSION: (u8, u8, u8) = crate::unicode::UNICODE_VERSION; - /// Creates an iterator over the UTF-16 encoded code points in `iter`, + /// Creates an iterator over the native endian UTF-16 encoded code points in `iter`, /// returning unpaired surrogates as `Err`s. /// /// # Examples @@ -704,7 +704,7 @@ impl char { unsafe { from_utf8_unchecked_mut(encode_utf8_raw(self as u32, dst)) } } - /// Encodes this character as UTF-16 into the provided `u16` buffer, + /// Encodes this character as native endian UTF-16 into the provided `u16` buffer, /// and then returns the subslice of the buffer that contains the encoded character. /// /// # Panics @@ -1828,7 +1828,7 @@ pub const fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut [u8] { unsafe { slice::from_raw_parts_mut(dst.as_mut_ptr(), len) } } -/// Encodes a raw `u32` value as UTF-16 into the provided `u16` buffer, +/// Encodes a raw `u32` value as native endian UTF-16 into the provided `u16` buffer, /// and then returns the subslice of the buffer that contains the encoded character. /// /// Unlike `char::encode_utf16`, this method also handles codepoints in the surrogate range. diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 8a473b398bb5..39fa6c1a25fe 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -1108,7 +1108,8 @@ impl str { LinesAny(self.lines()) } - /// Returns an iterator of `u16` over the string encoded as UTF-16. + /// Returns an iterator of `u16` over the string encoded + /// as native endian UTF-16 (without byte-order mark). /// /// # Examples /// From 2c35bd0499130af395bdbb49a49d5a019599d22e Mon Sep 17 00:00:00 2001 From: clubby789 Date: Fri, 31 Jan 2025 16:10:21 +0000 Subject: [PATCH 06/35] `#[optimize(none)]` implies `#[inline(never)]` --- compiler/rustc_mir_transform/src/inline.rs | 6 +++++- .../issues/issue-136329-optnone-noinline.rs | 21 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 tests/codegen/issues/issue-136329-optnone-noinline.rs diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 95aeccfdda66..f8b0688dfdcc 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -4,7 +4,7 @@ use std::iter; use std::ops::{Range, RangeFrom}; use rustc_abi::{ExternAbi, FieldIdx}; -use rustc_attr_parsing::InlineAttr; +use rustc_attr_parsing::{InlineAttr, OptimizeAttr}; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_index::Idx; @@ -770,6 +770,10 @@ fn check_codegen_attributes<'tcx, I: Inliner<'tcx>>( return Err("never inline attribute"); } + if let OptimizeAttr::DoNotOptimize = callee_attrs.optimize { + return Err("has DoNotOptimize attribute"); + } + // Reachability pass defines which functions are eligible for inlining. Generally inlining // other functions is incorrect because they could reference symbols that aren't exported. let is_generic = callsite.callee.args.non_erasable_generics().next().is_some(); diff --git a/tests/codegen/issues/issue-136329-optnone-noinline.rs b/tests/codegen/issues/issue-136329-optnone-noinline.rs new file mode 100644 index 000000000000..57c9e47a4992 --- /dev/null +++ b/tests/codegen/issues/issue-136329-optnone-noinline.rs @@ -0,0 +1,21 @@ +//! Ensure that `#[optimize(none)]` functions are never inlined + +//@ compile-flags: -Copt-level=3 + +#![feature(optimize_attribute)] + +#[optimize(none)] +pub fn foo() { + let _x = 123; +} + +// CHECK-LABEL: define{{.*}}void @bar +// CHECK: start: +// CHECK: {{.*}}call {{.*}}void +// CHECK: ret void +#[no_mangle] +pub fn bar() { + foo(); +} + +fn main() {} From 8e9422f94e6717721ffbad50862fcef9822c2537 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 31 Jan 2025 20:36:44 +0000 Subject: [PATCH 07/35] Make comma separated lists of anything easier to make for errors Provide a new function `listify`, meant to be used in cases similar to `pluralize!`. When you have a slice of arbitrary elements that need to be presented to the user, `listify` allows you to turn that into a list of comma separated strings. This reduces a lot of redundant logic that happens often in diagnostics. --- .../rustc_borrowck/src/diagnostics/mod.rs | 20 ++++---- compiler/rustc_builtin_macros/src/format.rs | 18 ++++---- compiler/rustc_errors/src/lib.rs | 14 +----- .../src/hir_ty_lowering/errors.rs | 46 ++++--------------- compiler/rustc_hir_typeck/src/demand.rs | 20 ++++---- compiler/rustc_hir_typeck/src/expr.rs | 35 +++++--------- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 12 +++-- .../src/fn_ctxt/suggestions.rs | 14 ++---- compiler/rustc_lint_defs/src/lib.rs | 17 +++++++ compiler/rustc_middle/src/ty/diagnostics.rs | 16 +++---- compiler/rustc_privacy/src/lib.rs | 24 ++-------- 11 files changed, 88 insertions(+), 148 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index bd6f77156ca9..d13b4bde5765 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -4,7 +4,7 @@ use std::collections::BTreeMap; use rustc_abi::{FieldIdx, VariantIdx}; use rustc_data_structures::fx::FxIndexMap; -use rustc_errors::{Applicability, Diag, EmissionGuarantee, MultiSpan}; +use rustc_errors::{Applicability, Diag, EmissionGuarantee, MultiSpan, listify}; use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::{self as hir, CoroutineKind, LangItem}; use rustc_index::IndexSlice; @@ -29,7 +29,7 @@ use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::error_reporting::traits::call_kind::{CallDesugaringKind, call_kind}; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::{ - FulfillmentErrorCode, type_known_to_meet_bound_modulo_regions, + FulfillmentError, FulfillmentErrorCode, type_known_to_meet_bound_modulo_regions, }; use tracing::debug; @@ -1436,17 +1436,15 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { error.obligation.predicate, ) } - [errors @ .., last] => { + _ => { format!( "you could `clone` the value and consume it, if the \ - following trait bounds could be satisfied: \ - {} and `{}`", - errors - .iter() - .map(|e| format!("`{}`", e.obligation.predicate)) - .collect::>() - .join(", "), - last.obligation.predicate, + following trait bounds could be satisfied: {}", + listify(&errors, |e: &FulfillmentError<'tcx>| format!( + "`{}`", + e.obligation.predicate + )) + .unwrap(), ) } }; diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 7c746bd719f3..90447da66807 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -8,7 +8,9 @@ use rustc_ast::{ token, }; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::{Applicability, Diag, MultiSpan, PResult, SingleLabelManySpans}; +use rustc_errors::{ + Applicability, Diag, MultiSpan, PResult, SingleLabelManySpans, listify, pluralize, +}; use rustc_expand::base::*; use rustc_lint_defs::builtin::NAMED_ARGUMENTS_USED_POSITIONALLY; use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiag, LintId}; @@ -975,15 +977,11 @@ fn report_invalid_references( } else { MultiSpan::from_spans(invalid_refs.iter().filter_map(|&(_, span, _, _)| span).collect()) }; - let arg_list = if let &[index] = &indexes[..] { - format!("argument {index}") - } else { - let tail = indexes.pop().unwrap(); - format!( - "arguments {head} and {tail}", - head = indexes.into_iter().map(|i| i.to_string()).collect::>().join(", ") - ) - }; + let arg_list = format!( + "argument{} {}", + pluralize!(indexes.len()), + listify(&indexes, |i: &usize| i.to_string()).unwrap_or_default() + ); e = ecx.dcx().struct_span_err( span, format!("invalid reference to positional {arg_list} ({num_args_desc})"), diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 549729548f53..a6458c9ffdcd 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -65,7 +65,7 @@ pub use rustc_error_messages::{ SubdiagMessage, fallback_fluent_bundle, fluent_bundle, }; use rustc_lint_defs::LintExpectationId; -pub use rustc_lint_defs::{Applicability, pluralize}; +pub use rustc_lint_defs::{Applicability, listify, pluralize}; use rustc_macros::{Decodable, Encodable}; pub use rustc_span::ErrorGuaranteed; pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker}; @@ -1999,18 +1999,6 @@ pub fn a_or_an(s: &str) -> &'static str { } } -/// Grammatical tool for displaying messages to end users in a nice form. -/// -/// Take a list ["a", "b", "c"] and output a display friendly version "a, b and c" -pub fn display_list_with_comma_and(v: &[T]) -> String { - match v { - [] => "".to_string(), - [a] => a.to_string(), - [a, b] => format!("{a} and {b}"), - [a, v @ ..] => format!("{a}, {}", display_list_with_comma_and(v)), - } -} - #[derive(Clone, Copy, PartialEq, Hash, Debug)] pub enum TerminalUrl { No, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 36b214b6ae73..79aa2f4b8ccd 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -3,7 +3,7 @@ use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::unord::UnordMap; use rustc_errors::codes::*; use rustc_errors::{ - Applicability, Diag, ErrorGuaranteed, MultiSpan, pluralize, struct_span_code_err, + Applicability, Diag, ErrorGuaranteed, MultiSpan, listify, pluralize, struct_span_code_err, }; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -808,14 +808,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .map(|(trait_, mut assocs)| { assocs.sort(); let trait_ = trait_.print_trait_sugared(); - format!("{} in `{trait_}`", match &assocs[..] { - [] => String::new(), - [only] => format!("`{only}`"), - [assocs @ .., last] => format!( - "{} and `{last}`", - assocs.iter().map(|a| format!("`{a}`")).collect::>().join(", ") - ), - }) + format!( + "{} in `{trait_}`", + listify(&assocs[..], |a| format!("`{a}`")).unwrap_or_default() + ) }) .collect::>(); names.sort(); @@ -1075,18 +1071,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } }) .collect(); - let this_type = match &types_and_spans[..] { - [.., _, (last, _)] => format!( - "{} and {last}", - types_and_spans[..types_and_spans.len() - 1] - .iter() - .map(|(x, _)| x.as_str()) - .intersperse(", ") - .collect::() - ), - [(only, _)] => only.to_string(), - [] => bug!("expected one segment to deny"), - }; + let this_type = listify(&types_and_spans, |(t, _)| t.to_string()) + .expect("expected one segment to deny"); let arg_spans: Vec = segments .clone() @@ -1102,21 +1088,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ProhibitGenericsArg::Infer => kinds.push("generic"), }); - let (kind, s) = match kinds[..] { - [.., _, last] => ( - format!( - "{} and {last}", - kinds[..kinds.len() - 1] - .iter() - .map(|&x| x) - .intersperse(", ") - .collect::() - ), - "s", - ), - [only] => (only.to_string(), ""), - [] => bug!("expected at least one generic to prohibit"), - }; + let s = pluralize!(kinds.len()); + let kind = + listify(&kinds, |k| k.to_string()).expect("expected at least one generic to prohibit"); let last_span = *arg_spans.last().unwrap(); let span: MultiSpan = arg_spans.into(); let mut err = struct_span_code_err!( diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index bc0766705854..85e949952f8d 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -1,4 +1,4 @@ -use rustc_errors::{Applicability, Diag, MultiSpan}; +use rustc_errors::{Applicability, Diag, MultiSpan, listify}; use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::intravisit::Visitor; @@ -1016,18 +1016,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }, self.tcx.def_path_str(candidate.item.container_id(self.tcx)) ), - [.., last] if other_methods_in_scope.len() < 5 => { + _ if other_methods_in_scope.len() < 5 => { format!( - "the methods of the same name on {} and `{}`", - other_methods_in_scope[..other_methods_in_scope.len() - 1] - .iter() - .map(|c| format!( - "`{}`", - self.tcx.def_path_str(c.item.container_id(self.tcx)) - )) - .collect::>() - .join(", "), - self.tcx.def_path_str(last.item.container_id(self.tcx)) + "the methods of the same name on {}", + listify( + &other_methods_in_scope[..other_methods_in_scope.len() - 1], + |c| format!("`{}`", self.tcx.def_path_str(c.item.container_id(self.tcx))) + ) + .unwrap_or_default(), ) } _ => format!( diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index f79667e59bae..0582a7dcee17 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -11,7 +11,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::unord::UnordMap; use rustc_errors::codes::*; use rustc_errors::{ - Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey, Subdiagnostic, pluralize, + Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey, Subdiagnostic, listify, pluralize, struct_span_code_err, }; use rustc_hir::def::{CtorKind, DefKind, Res}; @@ -2190,13 +2190,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if !missing_mandatory_fields.is_empty() { let s = pluralize!(missing_mandatory_fields.len()); - let fields: Vec<_> = - missing_mandatory_fields.iter().map(|f| format!("`{f}`")).collect(); - let fields = match &fields[..] { - [] => unreachable!(), - [only] => only.to_string(), - [start @ .., last] => format!("{} and {last}", start.join(", ")), - }; + let fields = listify(&missing_mandatory_fields, |f| format!("`{f}`")).unwrap(); self.dcx() .struct_span_err( span.shrink_to_hi(), @@ -2553,25 +2547,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .partition(|field| field.2); err.span_labels(used_private_fields.iter().map(|(_, span, _)| *span), "private field"); if !remaining_private_fields.is_empty() { - let remaining_private_fields_len = remaining_private_fields.len(); - let names = match &remaining_private_fields - .iter() - .map(|(name, _, _)| name) - .collect::>()[..] - { - _ if remaining_private_fields_len > 6 => String::new(), - [name] => format!("`{name}` "), - [names @ .., last] => { - let names = names.iter().map(|name| format!("`{name}`")).collect::>(); - format!("{} and `{last}` ", names.join(", ")) - } - [] => bug!("expected at least one private field to report"), + let names = if remaining_private_fields.len() > 6 { + String::new() + } else { + format!( + "{} ", + listify(&remaining_private_fields, |(name, _, _)| format!("`{name}`")) + .expect("expected at least one private field to report") + ) }; err.note(format!( "{}private field{s} {names}that {were} not provided", if used_fields.is_empty() { "" } else { "...and other " }, - s = pluralize!(remaining_private_fields_len), - were = pluralize!("was", remaining_private_fields_len), + s = pluralize!(remaining_private_fields.len()), + were = pluralize!("was", remaining_private_fields.len()), )); } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index fb5fc109ce46..bbe653714962 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -4,8 +4,7 @@ use itertools::Itertools; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::codes::*; use rustc_errors::{ - Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey, a_or_an, - display_list_with_comma_and, pluralize, + Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey, a_or_an, listify, pluralize, }; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; @@ -2462,7 +2461,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { param.span, format!( "{} need{} to match the {} type of this parameter", - display_list_with_comma_and(&other_param_matched_names), + listify(&other_param_matched_names, |n| n.to_string()) + .unwrap_or_default(), pluralize!(if other_param_matched_names.len() == 1 { 0 } else { @@ -2477,7 +2477,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { format!( "this parameter needs to match the {} type of {}", matched_ty, - display_list_with_comma_and(&other_param_matched_names), + listify(&other_param_matched_names, |n| n.to_string()) + .unwrap_or_default(), ), ); } @@ -2523,7 +2524,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { generic_param.span, format!( "{} {} reference this parameter `{}`", - display_list_with_comma_and(¶m_idents_matching), + listify(¶m_idents_matching, |n| n.to_string()) + .unwrap_or_default(), if param_idents_matching.len() == 2 { "both" } else { "all" }, generic_param.name.ident().name, ), diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 60f9265bfcc0..beddbf971fd3 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -4,7 +4,7 @@ use core::iter; use hir::def_id::LocalDefId; use rustc_ast::util::parser::ExprPrecedence; use rustc_data_structures::packed::Pu128; -use rustc_errors::{Applicability, Diag, MultiSpan}; +use rustc_errors::{Applicability, Diag, MultiSpan, listify}; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::lang_items::LangItem; use rustc_hir::{ @@ -1836,16 +1836,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { error.obligation.predicate, )); } - [errors @ .., last] => { + _ => { diag.help(format!( "`Clone` is not implemented because the following trait bounds \ - could not be satisfied: {} and `{}`", - errors - .iter() - .map(|e| format!("`{}`", e.obligation.predicate)) - .collect::>() - .join(", "), - last.obligation.predicate, + could not be satisfied: {}", + listify(&errors, |e| format!("`{}`", e.obligation.predicate)) + .unwrap(), )); } } diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 3f1e98556ef0..7ffe4e4e4901 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -42,6 +42,23 @@ macro_rules! pluralize { }; } +/// Grammatical tool for displaying messages to end users in a nice form. +/// +/// Take a list of items and a function to turn those items into a `String`, and output a display +/// friendly comma separated list of those items. +// FIXME(estebank): this needs to be changed to go through the translation machinery. +pub fn listify(list: &[T], fmt: impl Fn(&T) -> String) -> Option { + Some(match list { + [only] => fmt(&only), + [others @ .., last] => format!( + "{} and {}", + others.iter().map(|i| fmt(i)).collect::>().join(", "), + fmt(&last), + ), + [] => return None, + }) +} + /// Indicates the confidence in the correctness of a suggestion. /// /// All suggestions are marked with an `Applicability`. Tools use the applicability of a suggestion diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index b4b66a8133a3..cb218a27e623 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -5,7 +5,7 @@ use std::ops::ControlFlow; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{ - Applicability, Diag, DiagArgValue, IntoDiagArg, into_diag_arg_using_display, pluralize, + Applicability, Diag, DiagArgValue, IntoDiagArg, into_diag_arg_using_display, listify, pluralize, }; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; @@ -362,11 +362,8 @@ pub fn suggest_constraining_type_params<'a>( let n = trait_names.len(); let stable = if all_stable { "" } else { "unstable " }; let trait_ = if all_known { format!("trait{}", pluralize!(n)) } else { String::new() }; - format!("{stable}{trait_}{}", match &trait_names[..] { - [t] => format!(" {t}"), - [ts @ .., last] => format!(" {} and {last}", ts.join(", ")), - [] => return false, - },) + let Some(trait_names) = listify(&trait_names, |n| n.to_string()) else { return false }; + format!("{stable}{trait_} {trait_names}") } else { // We're more explicit when there's a mix of stable and unstable traits. let mut trait_names = constraints @@ -378,10 +375,9 @@ pub fn suggest_constraining_type_params<'a>( .collect::>(); trait_names.sort(); trait_names.dedup(); - match &trait_names[..] { - [t] => t.to_string(), - [ts @ .., last] => format!("{} and {last}", ts.join(", ")), - [] => return false, + match listify(&trait_names, |t| t.to_string()) { + Some(names) => names, + None => return false, } }; let constraint = constraint.join(" + "); diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index d19df08519d2..3842b7035e53 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -24,7 +24,7 @@ use rustc_ast::MacroDef; use rustc_ast::visit::{VisitorResult, try_visit}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::intern::Interned; -use rustc_errors::MultiSpan; +use rustc_errors::{MultiSpan, listify}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId, LocalModDefId}; use rustc_hir::intravisit::{self, InferKind, Visitor}; @@ -958,29 +958,15 @@ impl<'tcx> NamePrivacyVisitor<'tcx> { // | ^^ field `gamma` is private # `fields.2` is `false` // Get the list of all private fields for the main message. - let field_names: Vec<_> = fields.iter().map(|(name, _, _)| name).collect(); - let field_names = match &field_names[..] { - [] => return, - [name] => format!("`{name}`"), - [fields @ .., last] => format!( - "{} and `{last}`", - fields.iter().map(|f| format!("`{f}`")).collect::>().join(", "), - ), - }; + let Some(field_names) = listify(&fields[..], |(n, _, _)| format!("`{n}`")) else { return }; let span: MultiSpan = fields.iter().map(|(_, span, _)| *span).collect::>().into(); // Get the list of all private fields when pointing at the `..rest`. let rest_field_names: Vec<_> = fields.iter().filter(|(_, _, is_present)| !is_present).map(|(n, _, _)| n).collect(); let rest_len = rest_field_names.len(); - let rest_field_names = match &rest_field_names[..] { - [] => String::new(), - [name] => format!("`{name}`"), - [fields @ .., last] => format!( - "{} and `{last}`", - fields.iter().map(|f| format!("`{f}`")).collect::>().join(", "), - ), - }; + let rest_field_names = + listify(&rest_field_names[..], |n| format!("`{n}`")).unwrap_or_default(); // Get all the labels for each field or `..rest` in the primary MultiSpan. let labels = fields .iter() @@ -1005,7 +991,7 @@ impl<'tcx> NamePrivacyVisitor<'tcx> { } else { None }, - field_names: field_names.clone(), + field_names, variant_descr: def.variant_descr(), def_path_str: self.tcx.def_path_str(def.did()), labels, From 0751e9036af0525c3e42b74cce5597ed66dd7849 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 31 Jan 2025 03:26:56 +0000 Subject: [PATCH 08/35] Rework "long type names" printing logic Make it so more type-system types can be printed in a shortened version (like `Predicate`s). Centralize printing the information about the "full type name path". Make the "long type path" for the file where long types are written part of `Diag`, so that it becomes easier to keep track of it, and ensure it will always will be printed out last in the diagnostic by making its addition to the output implicit. Tweak the shortening of types in "expected/found" labels. Remove dead file `note.rs`. --- compiler/rustc_borrowck/messages.ftl | 3 - .../src/diagnostics/conflict_errors.rs | 8 +- .../src/diagnostics/move_errors.rs | 24 +- .../rustc_borrowck/src/session_diagnostics.rs | 7 - compiler/rustc_errors/src/diagnostic.rs | 31 ++ .../rustc_hir_typeck/src/method/suggest.rs | 39 +- compiler/rustc_middle/src/ty/error.rs | 37 +- compiler/rustc_middle/src/ty/print/mod.rs | 4 + compiler/rustc_middle/src/ty/print/pretty.rs | 95 ++-- compiler/rustc_mir_build/messages.ftl | 2 - compiler/rustc_mir_build/src/errors.rs | 4 - .../src/thir/pattern/check_match.rs | 8 +- .../src/error_reporting/infer/mod.rs | 47 +- .../error_reporting/infer/need_type_info.rs | 2 +- .../src/error_reporting/infer/note.rs | 422 ------------------ .../src/error_reporting/infer/region.rs | 10 +- .../src/error_reporting/traits/ambiguity.rs | 20 +- .../traits/fulfillment_errors.rs | 82 ++-- .../src/error_reporting/traits/mod.rs | 11 - .../traits/on_unimplemented.rs | 2 +- .../src/error_reporting/traits/overflow.rs | 11 - .../src/error_reporting/traits/suggestions.rs | 54 +-- .../coerce-expect-unsized-ascribed.stderr | 6 +- tests/ui/diagnostic-width/E0271.ascii.stderr | 8 +- tests/ui/diagnostic-width/E0271.rs | 4 +- .../ui/diagnostic-width/E0271.unicode.stderr | 8 +- .../diagnostic-width/long-E0308.ascii.stderr | 28 +- .../long-E0308.unicode.stderr | 28 +- tests/ui/diagnostic-width/long-e0277.rs | 15 + tests/ui/diagnostic-width/long-e0277.stderr | 23 + .../non-copy-type-moved.stderr | 4 +- .../secondary-label-with-long-type.rs | 2 +- .../secondary-label-with-long-type.stderr | 2 +- .../hang-on-deeply-nested-dyn.stderr | 2 +- .../box-future-wrong-output.stderr | 2 +- .../expected-boxed-future-isnt-pinned.stderr | 2 +- tests/ui/suggestions/issue-107860.stderr | 2 +- .../traits/ice-with-dyn-pointee-errors.stderr | 2 +- tests/ui/traits/object/pretty.stderr | 4 +- .../traits/on_unimplemented_long_types.stderr | 2 - tests/ui/typeck/issue-107775.stderr | 2 +- .../typeck/return_type_containing_closure.rs | 2 +- .../return_type_containing_closure.stderr | 2 +- 43 files changed, 332 insertions(+), 741 deletions(-) delete mode 100644 compiler/rustc_trait_selection/src/error_reporting/infer/note.rs create mode 100644 tests/ui/diagnostic-width/long-e0277.rs create mode 100644 tests/ui/diagnostic-width/long-e0277.stderr diff --git a/compiler/rustc_borrowck/messages.ftl b/compiler/rustc_borrowck/messages.ftl index c00e6dde9196..ada20e5c614f 100644 --- a/compiler/rustc_borrowck/messages.ftl +++ b/compiler/rustc_borrowck/messages.ftl @@ -92,9 +92,6 @@ borrowck_lifetime_constraints_error = borrowck_limitations_implies_static = due to current limitations in the borrow checker, this implies a `'static` lifetime -borrowck_long_type_consider_verbose = consider using `--verbose` to print the full type name to the console -borrowck_long_type_full_path = the full type name has been written to '{$path}' - borrowck_move_closure_suggestion = consider adding 'move' keyword before the nested closure diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 07dcbba019ad..c6439da33d6d 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -289,8 +289,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { None => "value".to_owned(), }; if needs_note { - let mut path = None; - let ty = self.infcx.tcx.short_ty_string(ty, &mut path); + let ty = self.infcx.tcx.short_string(ty, err.long_ty_path()); if let Some(local) = place.as_local() { let span = self.body.local_decls[local].source_info.span; err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { @@ -306,11 +305,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { place: ¬e_msg, }); }; - if let Some(path) = path { - err.subdiagnostic(crate::session_diagnostics::LongTypePath { - path: path.display().to_string(), - }); - } } if let UseSpans::FnSelfUse { diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 14a900f38e92..58c5c2fd7742 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -596,19 +596,13 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { self.suggest_cloning(err, place_ty, expr, None); } - let mut path = None; - let ty = self.infcx.tcx.short_ty_string(place_ty, &mut path); + let ty = self.infcx.tcx.short_string(place_ty, err.long_ty_path()); err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { is_partial_move: false, ty, place: &place_desc, span, }); - if let Some(path) = path { - err.subdiagnostic(crate::session_diagnostics::LongTypePath { - path: path.display().to_string(), - }); - } } else { binds_to.sort(); binds_to.dedup(); @@ -635,19 +629,13 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { self.suggest_cloning(err, place_ty, expr, Some(use_spans)); } - let mut path = None; - let ty = self.infcx.tcx.short_ty_string(place_ty, &mut path); + let ty = self.infcx.tcx.short_string(place_ty, err.long_ty_path()); err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { is_partial_move: false, ty, place: &place_desc, span: use_span, }); - if let Some(path) = path { - err.subdiagnostic(crate::session_diagnostics::LongTypePath { - path: path.display().to_string(), - }); - } use_spans.args_subdiag(err, |args_span| { crate::session_diagnostics::CaptureArgLabel::MoveOutPlace { @@ -845,19 +833,13 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { self.suggest_cloning(err, bind_to.ty, expr, None); } - let mut path = None; - let ty = self.infcx.tcx.short_ty_string(bind_to.ty, &mut path); + let ty = self.infcx.tcx.short_string(bind_to.ty, err.long_ty_path()); err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { is_partial_move: false, ty, place: place_desc, span: binding_span, }); - if let Some(path) = path { - err.subdiagnostic(crate::session_diagnostics::LongTypePath { - path: path.display().to_string(), - }); - } } } diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs index 2c37d2bc1236..11b30c145c2c 100644 --- a/compiler/rustc_borrowck/src/session_diagnostics.rs +++ b/compiler/rustc_borrowck/src/session_diagnostics.rs @@ -458,13 +458,6 @@ pub(crate) enum OnClosureNote<'a> { }, } -#[derive(Subdiagnostic)] -#[note(borrowck_long_type_full_path)] -#[note(borrowck_long_type_consider_verbose)] -pub(crate) struct LongTypePath { - pub(crate) path: String, -} - #[derive(Subdiagnostic)] pub(crate) enum TypeNoCopy<'a> { #[label(borrowck_ty_no_impl_copy)] diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 797dcd7b4d1d..b96df8148529 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -4,6 +4,7 @@ use std::hash::{Hash, Hasher}; use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; use std::panic; +use std::path::PathBuf; use std::thread::panicking; use rustc_data_structures::fx::FxIndexMap; @@ -301,6 +302,7 @@ pub struct DiagInner { pub is_lint: Option, + pub long_ty_path: Option, /// With `-Ztrack_diagnostics` enabled, /// we print where in rustc this error was emitted. pub(crate) emitted_at: DiagLocation, @@ -324,6 +326,7 @@ impl DiagInner { args: Default::default(), sort_span: DUMMY_SP, is_lint: None, + long_ty_path: None, emitted_at: DiagLocation::caller(), } } @@ -1293,9 +1296,37 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// `cancel`, etc. Afterwards, `drop` is the only code that will be run on /// `self`. fn take_diag(&mut self) -> DiagInner { + if let Some(path) = &self.long_ty_path { + self.note(format!( + "the full name for the type has been written to '{}'", + path.display() + )); + self.note("consider using `--verbose` to print the full type name to the console"); + } Box::into_inner(self.diag.take().unwrap()) } + /// This method allows us to access the path of the file where "long types" are written to. + /// + /// When calling `Diag::emit`, as part of that we will check if a `long_ty_path` has been set, + /// and if it has been then we add a note mentioning the file where the "long types" were + /// written to. + /// + /// When calling `tcx.short_string()` after a `Diag` is constructed, the preferred way of doing + /// so is `tcx.short_string(ty, diag.long_ty_path())`. The diagnostic itself is the one that + /// keeps the existence of a "long type" anywhere in the diagnostic, so the note telling the + /// user where we wrote the file to is only printed once at most, *and* it makes it much harder + /// to forget to set it. + /// + /// If the diagnostic hasn't been created before a "short ty string" is created, then you should + /// ensure that this method is called to set it `*diag.long_ty_path() = path`. + /// + /// As a rule of thumb, if you see or add at least one `tcx.short_string()` call anywhere, in a + /// scope, `diag.long_ty_path()` should be called once somewhere close by. + pub fn long_ty_path(&mut self) -> &mut Option { + &mut self.long_ty_path + } + /// Most `emit_producing_guarantee` functions use this as a starting point. fn emit_producing_nothing(mut self) { let diag = self.take_diag(); diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index e4a6a0fedc5a..920418407c0f 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -5,6 +5,7 @@ use core::ops::ControlFlow; use std::borrow::Cow; +use std::path::PathBuf; use hir::Expr; use rustc_ast::ast::Mutability; @@ -362,14 +363,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn suggest_missing_writer(&self, rcvr_ty: Ty<'tcx>, rcvr_expr: &hir::Expr<'tcx>) -> Diag<'_> { let mut file = None; - let ty_str = self.tcx.short_ty_string(rcvr_ty, &mut file); let mut err = struct_span_code_err!( self.dcx(), rcvr_expr.span, E0599, "cannot write into `{}`", - ty_str + self.tcx.short_string(rcvr_ty, &mut file), ); + *err.long_ty_path() = file; err.span_note( rcvr_expr.span, "must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method", @@ -380,11 +381,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "a writer is needed before this format string", ); }; - if let Some(file) = file { - err.note(format!("the full type name has been written to '{}'", file.display())); - err.note("consider using `--verbose` to print the full type name to the console"); - } - err } @@ -595,7 +591,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (predicates.to_string(), with_forced_trimmed_paths!(predicates.to_string())) } else { ( - tcx.short_ty_string(rcvr_ty, &mut ty_file), + tcx.short_string(rcvr_ty, &mut ty_file), with_forced_trimmed_paths!(rcvr_ty.to_string()), ) }; @@ -624,6 +620,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span, item_name, &short_ty_str, + &mut ty_file, ) { return guar; } @@ -635,6 +632,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item_kind, item_name, &short_ty_str, + &mut ty_file, ) { return guar; } @@ -728,10 +726,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty_str = short_ty_str; } - if let Some(file) = ty_file { - err.note(format!("the full type name has been written to '{}'", file.display(),)); - err.note("consider using `--verbose` to print the full type name to the console"); - } if rcvr_ty.references_error() { err.downgrade_to_delayed_bug(); } @@ -1314,7 +1308,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { bound_list.into_iter().map(|(_, path)| path).collect::>().join("\n"); let actual_prefix = rcvr_ty.prefix_string(self.tcx); info!("unimplemented_traits.len() == {}", unimplemented_traits.len()); - let mut long_ty_file = None; let (primary_message, label, notes) = if unimplemented_traits.len() == 1 && unimplemented_traits_only { @@ -1329,7 +1322,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let OnUnimplementedNote { message, label, notes, .. } = self .err_ctxt() - .on_unimplemented_note(trait_ref, &obligation, &mut long_ty_file); + .on_unimplemented_note(trait_ref, &obligation, &mut ty_file); (message, label, notes) }) .unwrap() @@ -1343,15 +1336,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) }); err.primary_message(primary_message); - if let Some(file) = long_ty_file { - err.note(format!( - "the full name for the type has been written to '{}'", - file.display(), - )); - err.note( - "consider using `--verbose` to print the full type name to the console", - ); - } if let Some(label) = label { custom_span_label = true; err.span_label(span, label); @@ -2403,6 +2387,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, item_name: Ident, ty_str: &str, + long_ty_path: &mut Option, ) -> Result<(), ErrorGuaranteed> { if let SelfSource::MethodCall(expr) = source { for (_, parent) in tcx.hir().parent_iter(expr.hir_id).take(5) { @@ -2460,7 +2445,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); if pick.is_ok() { let range_span = parent_expr.span.with_hi(expr.span.hi()); - return Err(self.dcx().emit_err(errors::MissingParenthesesInRange { + let mut err = self.dcx().create_err(errors::MissingParenthesesInRange { span, ty_str: ty_str.to_string(), method_name: item_name.as_str().to_string(), @@ -2469,7 +2454,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { left: range_span.shrink_to_lo(), right: range_span.shrink_to_hi(), }), - })); + }); + *err.long_ty_path() = long_ty_path.take(); + return Err(err.emit()); } } } @@ -2486,6 +2473,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item_kind: &str, item_name: Ident, ty_str: &str, + long_ty_path: &mut Option, ) -> Result<(), ErrorGuaranteed> { let found_candidate = all_traits(self.tcx) .into_iter() @@ -2526,6 +2514,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item_name, ty_str ); + *err.long_ty_path() = long_ty_path.take(); let concrete_type = if actual.is_integral() { "i32" } else { "f32" }; match expr.kind { ExprKind::Lit(lit) => { diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 35fbaa99569c..8c1991ddb36e 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -10,8 +10,8 @@ use rustc_hir::def::{CtorOf, DefKind}; use rustc_macros::extension; pub use rustc_type_ir::error::ExpectedFound; -use crate::ty::print::{FmtPrinter, PrettyPrinter, with_forced_trimmed_paths}; -use crate::ty::{self, Ty, TyCtxt}; +use crate::ty::print::{FmtPrinter, Print, with_forced_trimmed_paths}; +use crate::ty::{self, Lift, Ty, TyCtxt}; pub type TypeError<'tcx> = rustc_type_ir::error::TypeError>; @@ -159,8 +159,8 @@ impl<'tcx> Ty<'tcx> { ty::Error(_) => "type error".into(), _ => { let width = tcx.sess.diagnostic_width(); - let length_limit = std::cmp::max(width / 4, 15); - format!("`{}`", tcx.ty_string_with_limit(self, length_limit)).into() + let length_limit = std::cmp::max(width / 4, 40); + format!("`{}`", tcx.string_with_limit(self, length_limit)).into() } } } @@ -213,10 +213,14 @@ impl<'tcx> Ty<'tcx> { } impl<'tcx> TyCtxt<'tcx> { - pub fn ty_string_with_limit(self, ty: Ty<'tcx>, length_limit: usize) -> String { + pub fn string_with_limit<'a, T>(self, p: T, length_limit: usize) -> String + where + T: Print<'tcx, FmtPrinter<'a, 'tcx>> + Lift> + Copy, + >>::Lifted: Print<'tcx, FmtPrinter<'a, 'tcx>>, + { let mut type_limit = 50; let regular = FmtPrinter::print_string(self, hir::def::Namespace::TypeNS, |cx| { - cx.pretty_print_type(ty) + self.lift(p).expect("could not lift for printing").print(cx) }) .expect("could not write to `String`"); if regular.len() <= length_limit { @@ -231,7 +235,10 @@ impl<'tcx> TyCtxt<'tcx> { hir::def::Namespace::TypeNS, rustc_session::Limit(type_limit), ); - cx.pretty_print_type(ty).expect("could not write to `String`"); + self.lift(p) + .expect("could not lift for printing") + .print(&mut cx) + .expect("could not print type"); cx.into_buffer() }); if short.len() <= length_limit || type_limit == 0 { @@ -242,9 +249,17 @@ impl<'tcx> TyCtxt<'tcx> { short } - pub fn short_ty_string(self, ty: Ty<'tcx>, path: &mut Option) -> String { + /// When calling this after a `Diag` is constructed, the preferred way of doing so is + /// `tcx.short_string(ty, diag.long_ty_path())`. The diagnostic itself is the one that keeps + /// the existence of a "long type" anywhere in the diagnostic, so the note telling the user + /// where we wrote the file to is only printed once. + pub fn short_string<'a, T>(self, p: T, path: &mut Option) -> String + where + T: Print<'tcx, FmtPrinter<'a, 'tcx>> + Lift> + Copy + Hash, + >>::Lifted: Print<'tcx, FmtPrinter<'a, 'tcx>>, + { let regular = FmtPrinter::print_string(self, hir::def::Namespace::TypeNS, |cx| { - cx.pretty_print_type(ty) + self.lift(p).expect("could not lift for printing").print(cx) }) .expect("could not write to `String`"); @@ -257,13 +272,13 @@ impl<'tcx> TyCtxt<'tcx> { if regular.len() <= width * 2 / 3 { return regular; } - let short = self.ty_string_with_limit(ty, length_limit); + let short = self.string_with_limit(p, length_limit); if regular == short { return regular; } // Ensure we create an unique file for the type passed in when we create a file. let mut s = DefaultHasher::new(); - ty.hash(&mut s); + p.hash(&mut s); let hash = s.finish(); *path = Some(path.take().unwrap_or_else(|| { self.output_filenames(()).temp_path_ext(&format!("long-type-{hash}.txt"), None) diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 72f353f06ff5..dc2040aa5cf8 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -105,6 +105,10 @@ pub trait Printer<'tcx>: Sized { args: &[GenericArg<'tcx>], ) -> Result<(), PrintError>; + fn should_truncate(&mut self) -> bool { + false + } + // Defaults (should not be overridden): #[instrument(skip(self), level = "debug")] diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 018fcc66aeed..6c8591dae895 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -865,7 +865,6 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { p!(write("{{")); if !self.tcx().sess.verbose_internals() { p!("coroutine witness"); - // FIXME(eddyb) should use `def_span`. if let Some(did) = did.as_local() { let span = self.tcx().def_span(did); p!(write( @@ -887,26 +886,30 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { p!(write("{{")); if !self.should_print_verbose() { p!(write("closure")); - // FIXME(eddyb) should use `def_span`. - if let Some(did) = did.as_local() { - if self.tcx().sess.opts.unstable_opts.span_free_formats { - p!("@", print_def_path(did.to_def_id(), args)); - } else { - let span = self.tcx().def_span(did); - let preference = if with_forced_trimmed_paths() { - FileNameDisplayPreference::Short - } else { - FileNameDisplayPreference::Remapped - }; - p!(write( - "@{}", - // This may end up in stderr diagnostics but it may also be emitted - // into MIR. Hence we use the remapped path if available - self.tcx().sess.source_map().span_to_string(span, preference) - )); - } + if self.should_truncate() { + write!(self, "@...}}")?; + return Ok(()); } else { - p!(write("@"), print_def_path(did, args)); + if let Some(did) = did.as_local() { + if self.tcx().sess.opts.unstable_opts.span_free_formats { + p!("@", print_def_path(did.to_def_id(), args)); + } else { + let span = self.tcx().def_span(did); + let preference = if with_forced_trimmed_paths() { + FileNameDisplayPreference::Short + } else { + FileNameDisplayPreference::Remapped + }; + p!(write( + "@{}", + // This may end up in stderr diagnostics but it may also be emitted + // into MIR. Hence we use the remapped path if available + self.tcx().sess.source_map().span_to_string(span, preference) + )); + } + } else { + p!(write("@"), print_def_path(did, args)); + } } } else { p!(print_def_path(did, args)); @@ -942,7 +945,6 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { "coroutine from coroutine-closure should have CoroutineSource::Closure" ), } - // FIXME(eddyb) should use `def_span`. if let Some(did) = did.as_local() { if self.tcx().sess.opts.unstable_opts.span_free_formats { p!("@", print_def_path(did.to_def_id(), args)); @@ -1994,7 +1996,6 @@ pub struct FmtPrinterData<'a, 'tcx> { binder_depth: usize, printed_type_count: usize, type_length_limit: Limit, - truncated: bool, pub region_highlight_mode: RegionHighlightMode<'tcx>, @@ -2046,7 +2047,6 @@ impl<'a, 'tcx> FmtPrinter<'a, 'tcx> { binder_depth: 0, printed_type_count: 0, type_length_limit, - truncated: false, region_highlight_mode: RegionHighlightMode::default(), ty_infer_name_resolver: None, const_infer_name_resolver: None, @@ -2183,16 +2183,49 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { } fn print_type(&mut self, ty: Ty<'tcx>) -> Result<(), PrintError> { - if self.type_length_limit.value_within_limit(self.printed_type_count) { - self.printed_type_count += 1; - self.pretty_print_type(ty) - } else { - self.truncated = true; - write!(self, "...")?; - Ok(()) + match ty.kind() { + ty::Tuple(tys) if tys.len() == 0 && self.should_truncate() => { + // Don't truncate `()`. + self.printed_type_count += 1; + self.pretty_print_type(ty) + } + ty::Adt(..) + | ty::Foreign(_) + | ty::Pat(..) + | ty::RawPtr(..) + | ty::Ref(..) + | ty::FnDef(..) + | ty::FnPtr(..) + | ty::UnsafeBinder(..) + | ty::Dynamic(..) + | ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Coroutine(..) + | ty::CoroutineWitness(..) + | ty::Tuple(_) + | ty::Alias(..) + | ty::Param(_) + | ty::Bound(..) + | ty::Placeholder(_) + | ty::Error(_) + if self.should_truncate() => + { + // We only truncate types that we know are likely to be much longer than 3 chars. + // There's no point in replacing `i32` or `!`. + write!(self, "...")?; + Ok(()) + } + _ => { + self.printed_type_count += 1; + self.pretty_print_type(ty) + } } } + fn should_truncate(&mut self) -> bool { + !self.type_length_limit.value_within_limit(self.printed_type_count) + } + fn print_dyn_existential( &mut self, predicates: &'tcx ty::List>, @@ -2942,7 +2975,7 @@ impl<'tcx> ty::TraitPredicate<'tcx> { } } -#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)] +#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift, Hash)] pub struct TraitPredPrintWithBoundConstness<'tcx>( ty::TraitPredicate<'tcx>, Option, diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 053775b49378..ffdb721fb18b 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -25,8 +25,6 @@ mir_build_borrow_of_moved_value = borrow of moved value .occurs_because_label = move occurs because `{$name}` has type `{$ty}`, which does not implement the `Copy` trait .value_borrowed_label = value borrowed here after move .suggestion = borrow this binding in the pattern to avoid moving the value - .full_type_name = the full type name has been written to '{$path}' - .consider_verbose = consider using `--verbose` to print the full type name to the console mir_build_call_to_deprecated_safe_fn_requires_unsafe = call to deprecated safe function `{$function}` is unsafe and requires unsafe block diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 1f87bf0dbbbd..c13db27dae85 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -801,10 +801,6 @@ pub(crate) struct BorrowOfMovedValue { pub(crate) ty: String, #[suggestion(code = "ref ", applicability = "machine-applicable")] pub(crate) suggest_borrowing: Option, - #[note(mir_build_full_type_name)] - #[note(mir_build_consider_verbose)] - pub(crate) has_path: bool, - pub(crate) path: String, } #[derive(Diagnostic)] diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index e0a1117f905c..a237124a2113 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -796,16 +796,16 @@ fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, 'tcx>, pat: }); if !conflicts_ref.is_empty() { let mut path = None; - let ty = cx.tcx.short_ty_string(ty, &mut path); - sess.dcx().emit_err(BorrowOfMovedValue { + let ty = cx.tcx.short_string(ty, &mut path); + let mut err = sess.dcx().create_err(BorrowOfMovedValue { binding_span: pat.span, conflicts_ref, name: Ident::new(name, pat.span), ty, suggest_borrowing: Some(pat.span.shrink_to_lo()), - has_path: path.is_some(), - path: path.map(|p| p.display().to_string()).unwrap_or_default(), }); + *err.long_ty_path() = path; + err.emit(); } return; } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index db4a14356cc9..ac72774027cf 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -435,7 +435,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { exp_found: Option>>, terr: TypeError<'tcx>, param_env: Option>, - path: &mut Option, ) { match *cause.code() { ObligationCauseCode::Pattern { @@ -458,7 +457,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { format!("this is an iterator with items of type `{}`", args.type_at(0)), ); } else { - let expected_ty = self.tcx.short_ty_string(expected_ty, path); + let expected_ty = self.tcx.short_string(expected_ty, err.long_ty_path()); err.span_label(span, format!("this expression has type `{expected_ty}`")); } } @@ -1545,7 +1544,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { (false, Mismatch::Fixed("existential projection")) } }; - let Some(vals) = self.values_str(values, cause) else { + let Some(vals) = self.values_str(values, cause, diag.long_ty_path()) else { // Derived error. Cancel the emitter. // NOTE(eddyb) this was `.cancel()`, but `diag` // is borrowed, so we can't fully defuse it. @@ -1600,9 +1599,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { return; } - let mut path = None; - if let Some((expected, found, p)) = expected_found { - path = p; + if let Some((expected, found)) = expected_found { let (expected_label, found_label, exp_found) = match exp_found { Mismatch::Variable(ef) => ( ef.expected.prefix_string(self.tcx), @@ -1878,11 +1875,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // It reads better to have the error origin as the final // thing. - self.note_error_origin(diag, cause, exp_found, terr, param_env, &mut path); - if let Some(path) = path { - diag.note(format!("the full type name has been written to '{}'", path.display())); - diag.note("consider using `--verbose` to print the full type name to the console"); - } + self.note_error_origin(diag, cause, exp_found, terr, param_env); debug!(?diag); } @@ -1891,6 +1884,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { &self, trace: &TypeTrace<'tcx>, terr: TypeError<'tcx>, + path: &mut Option, ) -> Vec { let mut suggestions = Vec::new(); let span = trace.cause.span; @@ -1969,7 +1963,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }) | ObligationCauseCode::BlockTailExpression(.., source)) = code && let hir::MatchSource::TryDesugar(_) = source - && let Some((expected_ty, found_ty, _)) = self.values_str(trace.values, &trace.cause) + && let Some((expected_ty, found_ty)) = self.values_str(trace.values, &trace.cause, path) { suggestions.push(TypeErrorAdditionalDiags::TryCannotConvert { found: found_ty.content(), @@ -2048,12 +2042,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { debug!("report_and_explain_type_error(trace={:?}, terr={:?})", trace, terr); let span = trace.cause.span; + let mut path = None; let failure_code = trace.cause.as_failure_code_diag( terr, span, - self.type_error_additional_suggestions(&trace, terr), + self.type_error_additional_suggestions(&trace, terr, &mut path), ); let mut diag = self.dcx().create_err(failure_code); + *diag.long_ty_path() = path; self.note_type_err( &mut diag, &trace.cause, @@ -2098,10 +2094,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { &self, values: ValuePairs<'tcx>, cause: &ObligationCause<'tcx>, - ) -> Option<(DiagStyledString, DiagStyledString, Option)> { + file: &mut Option, + ) -> Option<(DiagStyledString, DiagStyledString)> { match values { ValuePairs::Regions(exp_found) => self.expected_found_str(exp_found), - ValuePairs::Terms(exp_found) => self.expected_found_str_term(exp_found), + ValuePairs::Terms(exp_found) => self.expected_found_str_term(exp_found, file), ValuePairs::Aliases(exp_found) => self.expected_found_str(exp_found), ValuePairs::ExistentialTraitRef(exp_found) => self.expected_found_str(exp_found), ValuePairs::ExistentialProjection(exp_found) => self.expected_found_str(exp_found), @@ -2111,7 +2108,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { found: exp_found.found.print_trait_sugared(), }; match self.expected_found_str(pretty_exp_found) { - Some((expected, found, _)) if expected == found => { + Some((expected, found)) if expected == found => { self.expected_found_str(exp_found) } ret => ret, @@ -2133,9 +2130,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { (None, None) }; - let (exp, fnd) = - self.cmp_fn_sig(&exp_found.expected, fn_def1, &exp_found.found, fn_def2); - Some((exp, fnd, None)) + Some(self.cmp_fn_sig(&exp_found.expected, fn_def1, &exp_found.found, fn_def2)) } } } @@ -2143,7 +2138,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { fn expected_found_str_term( &self, exp_found: ty::error::ExpectedFound>, - ) -> Option<(DiagStyledString, DiagStyledString, Option)> { + path: &mut Option, + ) -> Option<(DiagStyledString, DiagStyledString)> { let exp_found = self.resolve_vars_if_possible(exp_found); if exp_found.references_error() { return None; @@ -2158,21 +2154,19 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let len = self.tcx.sess().diagnostic_width() + 40; let exp_s = exp.content(); let fnd_s = fnd.content(); - let mut path = None; if exp_s.len() > len { - let exp_s = self.tcx.short_ty_string(expected, &mut path); + let exp_s = self.tcx.short_string(expected, path); exp = DiagStyledString::highlighted(exp_s); } if fnd_s.len() > len { - let fnd_s = self.tcx.short_ty_string(found, &mut path); + let fnd_s = self.tcx.short_string(found, path); fnd = DiagStyledString::highlighted(fnd_s); } - (exp, fnd, path) + (exp, fnd) } _ => ( DiagStyledString::highlighted(exp_found.expected.to_string()), DiagStyledString::highlighted(exp_found.found.to_string()), - None, ), }) } @@ -2181,7 +2175,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { fn expected_found_str>>( &self, exp_found: ty::error::ExpectedFound, - ) -> Option<(DiagStyledString, DiagStyledString, Option)> { + ) -> Option<(DiagStyledString, DiagStyledString)> { let exp_found = self.resolve_vars_if_possible(exp_found); if exp_found.references_error() { return None; @@ -2190,7 +2184,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { Some(( DiagStyledString::highlighted(exp_found.expected.to_string()), DiagStyledString::highlighted(exp_found.found.to_string()), - None, )) } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs index 68a533812304..99b70c87ccd1 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs @@ -713,7 +713,7 @@ impl<'tcx> InferSourceKind<'tcx> { if ty.is_closure() { ("closure", closure_as_fn_str(infcx, ty), path) } else if !ty.is_ty_or_numeric_infer() { - ("normal", infcx.tcx.short_ty_string(ty, &mut path), path) + ("normal", infcx.tcx.short_string(ty, &mut path), path) } else { ("other", String::new(), path) } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note.rs deleted file mode 100644 index beae9962f7f2..000000000000 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/note.rs +++ /dev/null @@ -1,422 +0,0 @@ -use rustc_errors::{Diag, Subdiagnostic}; -use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_middle::traits::ObligationCauseCode; -use rustc_middle::ty::error::TypeError; -use rustc_middle::ty::{self, IsSuggestable, Region, Ty}; -use rustc_span::kw; -use tracing::debug; - -use super::ObligationCauseAsDiagArg; -use crate::error_reporting::infer::{TypeErrCtxt, note_and_explain_region}; -use crate::errors::{ - FulfillReqLifetime, LfBoundNotSatisfied, OutlivesBound, OutlivesContent, RefLongerThanData, - RegionOriginNote, WhereClauseSuggestions, note_and_explain, -}; -use crate::fluent_generated as fluent; -use crate::infer::{self, SubregionOrigin}; - -impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { - pub(super) fn note_region_origin(&self, err: &mut Diag<'_>, origin: &SubregionOrigin<'tcx>) { - match *origin { - infer::Subtype(ref trace) => RegionOriginNote::WithRequirement { - span: trace.cause.span, - requirement: ObligationCauseAsDiagArg(trace.cause.clone()), - expected_found: self.values_str(trace.values).map(|(e, f, _)| (e, f)), - } - .add_to_diag(err), - infer::Reborrow(span) => { - RegionOriginNote::Plain { span, msg: fluent::infer_reborrow }.add_to_diag(err) - } - infer::RelateObjectBound(span) => { - RegionOriginNote::Plain { span, msg: fluent::infer_relate_object_bound } - .add_to_diag(err); - } - infer::ReferenceOutlivesReferent(ty, span) => { - RegionOriginNote::WithName { - span, - msg: fluent::infer_reference_outlives_referent, - name: &self.ty_to_string(ty), - continues: false, - } - .add_to_diag(err); - } - infer::RelateParamBound(span, ty, opt_span) => { - RegionOriginNote::WithName { - span, - msg: fluent::infer_relate_param_bound, - name: &self.ty_to_string(ty), - continues: opt_span.is_some(), - } - .add_to_diag(err); - if let Some(span) = opt_span { - RegionOriginNote::Plain { span, msg: fluent::infer_relate_param_bound_2 } - .add_to_diag(err); - } - } - infer::RelateRegionParamBound(span, _) => { - RegionOriginNote::Plain { span, msg: fluent::infer_relate_region_param_bound } - .add_to_diag(err); - } - infer::CompareImplItemObligation { span, .. } => { - RegionOriginNote::Plain { span, msg: fluent::infer_compare_impl_item_obligation } - .add_to_diag(err); - } - infer::CheckAssociatedTypeBounds { ref parent, .. } => { - self.note_region_origin(err, parent); - } - infer::AscribeUserTypeProvePredicate(span) => { - RegionOriginNote::Plain { - span, - msg: fluent::infer_ascribe_user_type_prove_predicate, - } - .add_to_diag(err); - } - } - } - - pub(super) fn report_concrete_failure( - &self, - generic_param_scope: LocalDefId, - origin: SubregionOrigin<'tcx>, - sub: Region<'tcx>, - sup: Region<'tcx>, - ) -> Diag<'a> { - let mut err = match origin { - infer::Subtype(box trace) => { - let terr = TypeError::RegionsDoesNotOutlive(sup, sub); - let mut err = self.report_and_explain_type_error(trace, terr); - match (*sub, *sup) { - (ty::RePlaceholder(_), ty::RePlaceholder(_)) => {} - (ty::RePlaceholder(_), _) => { - note_and_explain_region( - self.tcx, - &mut err, - generic_param_scope, - "", - sup, - " doesn't meet the lifetime requirements", - None, - ); - } - (_, ty::RePlaceholder(_)) => { - note_and_explain_region( - self.tcx, - &mut err, - generic_param_scope, - "the required lifetime does not necessarily outlive ", - sub, - "", - None, - ); - } - _ => { - note_and_explain_region( - self.tcx, - &mut err, - generic_param_scope, - "", - sup, - "...", - None, - ); - note_and_explain_region( - self.tcx, - &mut err, - generic_param_scope, - "...does not necessarily outlive ", - sub, - "", - None, - ); - } - } - err - } - infer::Reborrow(span) => { - let reference_valid = note_and_explain::RegionExplanation::new( - self.tcx, - generic_param_scope, - sub, - None, - note_and_explain::PrefixKind::RefValidFor, - note_and_explain::SuffixKind::Continues, - ); - let content_valid = note_and_explain::RegionExplanation::new( - self.tcx, - generic_param_scope, - sup, - None, - note_and_explain::PrefixKind::ContentValidFor, - note_and_explain::SuffixKind::Empty, - ); - self.dcx().create_err(OutlivesContent { - span, - notes: reference_valid.into_iter().chain(content_valid).collect(), - }) - } - infer::RelateObjectBound(span) => { - let object_valid = note_and_explain::RegionExplanation::new( - self.tcx, - generic_param_scope, - sub, - None, - note_and_explain::PrefixKind::TypeObjValidFor, - note_and_explain::SuffixKind::Empty, - ); - let pointer_valid = note_and_explain::RegionExplanation::new( - self.tcx, - generic_param_scope, - sup, - None, - note_and_explain::PrefixKind::SourcePointerValidFor, - note_and_explain::SuffixKind::Empty, - ); - self.dcx().create_err(OutlivesBound { - span, - notes: object_valid.into_iter().chain(pointer_valid).collect(), - }) - } - infer::RelateParamBound(span, ty, opt_span) => { - let prefix = match *sub { - ty::ReStatic => note_and_explain::PrefixKind::TypeSatisfy, - _ => note_and_explain::PrefixKind::TypeOutlive, - }; - let suffix = if opt_span.is_some() { - note_and_explain::SuffixKind::ReqByBinding - } else { - note_and_explain::SuffixKind::Empty - }; - let note = note_and_explain::RegionExplanation::new( - self.tcx, - generic_param_scope, - sub, - opt_span, - prefix, - suffix, - ); - self.dcx().create_err(FulfillReqLifetime { - span, - ty: self.resolve_vars_if_possible(ty), - note, - }) - } - infer::RelateRegionParamBound(span, _) => { - let param_instantiated = note_and_explain::RegionExplanation::new( - self.tcx, - generic_param_scope, - sup, - None, - note_and_explain::PrefixKind::LfParamInstantiatedWith, - note_and_explain::SuffixKind::Empty, - ); - let param_must_outlive = note_and_explain::RegionExplanation::new( - self.tcx, - generic_param_scope, - sub, - None, - note_and_explain::PrefixKind::LfParamMustOutlive, - note_and_explain::SuffixKind::Empty, - ); - self.dcx().create_err(LfBoundNotSatisfied { - span, - notes: param_instantiated.into_iter().chain(param_must_outlive).collect(), - }) - } - infer::ReferenceOutlivesReferent(ty, span) => { - let pointer_valid = note_and_explain::RegionExplanation::new( - self.tcx, - generic_param_scope, - sub, - None, - note_and_explain::PrefixKind::PointerValidFor, - note_and_explain::SuffixKind::Empty, - ); - let data_valid = note_and_explain::RegionExplanation::new( - self.tcx, - generic_param_scope, - sup, - None, - note_and_explain::PrefixKind::DataValidFor, - note_and_explain::SuffixKind::Empty, - ); - self.dcx().create_err(RefLongerThanData { - span, - ty: self.resolve_vars_if_possible(ty), - notes: pointer_valid.into_iter().chain(data_valid).collect(), - }) - } - infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => { - let mut err = self.infcx.report_extra_impl_obligation( - span, - impl_item_def_id, - trait_item_def_id, - &format!("`{sup}: {sub}`"), - ); - // We should only suggest rewriting the `where` clause if the predicate is within that `where` clause - if let Some(generics) = self.tcx.hir().get_generics(impl_item_def_id) - && generics.where_clause_span.contains(span) - { - self.suggest_copy_trait_method_bounds( - trait_item_def_id, - impl_item_def_id, - &mut err, - ); - } - err - } - infer::CheckAssociatedTypeBounds { impl_item_def_id, trait_item_def_id, parent } => { - let mut err = self.report_concrete_failure(generic_param_scope, *parent, sub, sup); - - // Don't mention the item name if it's an RPITIT, since that'll just confuse - // folks. - if !self.tcx.is_impl_trait_in_trait(impl_item_def_id.to_def_id()) { - let trait_item_span = self.tcx.def_span(trait_item_def_id); - let item_name = self.tcx.item_name(impl_item_def_id.to_def_id()); - err.span_label( - trait_item_span, - format!("definition of `{item_name}` from trait"), - ); - } - - self.suggest_copy_trait_method_bounds( - trait_item_def_id, - impl_item_def_id, - &mut err, - ); - err - } - infer::AscribeUserTypeProvePredicate(span) => { - let instantiated = note_and_explain::RegionExplanation::new( - self.tcx, - generic_param_scope, - sup, - None, - note_and_explain::PrefixKind::LfInstantiatedWith, - note_and_explain::SuffixKind::Empty, - ); - let must_outlive = note_and_explain::RegionExplanation::new( - self.tcx, - generic_param_scope, - sub, - None, - note_and_explain::PrefixKind::LfMustOutlive, - note_and_explain::SuffixKind::Empty, - ); - self.dcx().create_err(LfBoundNotSatisfied { - span, - notes: instantiated.into_iter().chain(must_outlive).collect(), - }) - } - }; - if sub.is_error() || sup.is_error() { - err.downgrade_to_delayed_bug(); - } - err - } - - pub fn suggest_copy_trait_method_bounds( - &self, - trait_item_def_id: DefId, - impl_item_def_id: LocalDefId, - err: &mut Diag<'_>, - ) { - // FIXME(compiler-errors): Right now this is only being used for region - // predicate mismatches. Ideally, we'd use it for *all* predicate mismatches, - // but right now it's not really very smart when it comes to implicit `Sized` - // predicates and bounds on the trait itself. - - let Some(impl_def_id) = self.tcx.associated_item(impl_item_def_id).impl_container(self.tcx) - else { - return; - }; - let Some(trait_ref) = self.tcx.impl_trait_ref(impl_def_id) else { - return; - }; - let trait_args = trait_ref - .instantiate_identity() - // Replace the explicit self type with `Self` for better suggestion rendering - .with_self_ty(self.tcx, Ty::new_param(self.tcx, 0, kw::SelfUpper)) - .args; - let trait_item_args = ty::GenericArgs::identity_for_item(self.tcx, impl_item_def_id) - .rebase_onto(self.tcx, impl_def_id, trait_args); - - let Ok(trait_predicates) = - self.tcx - .explicit_predicates_of(trait_item_def_id) - .instantiate_own(self.tcx, trait_item_args) - .map(|(pred, _)| { - if pred.is_suggestable(self.tcx, false) { - Ok(pred.to_string()) - } else { - Err(()) - } - }) - .collect::, ()>>() - else { - return; - }; - - let Some(generics) = self.tcx.hir().get_generics(impl_item_def_id) else { - return; - }; - - let suggestion = if trait_predicates.is_empty() { - WhereClauseSuggestions::Remove { span: generics.where_clause_span } - } else { - let space = if generics.where_clause_span.is_empty() { " " } else { "" }; - WhereClauseSuggestions::CopyPredicates { - span: generics.where_clause_span, - space, - trait_predicates: trait_predicates.join(", "), - } - }; - err.subdiagnostic(suggestion); - } - - pub(super) fn report_placeholder_failure( - &self, - generic_param_scope: LocalDefId, - placeholder_origin: SubregionOrigin<'tcx>, - sub: Region<'tcx>, - sup: Region<'tcx>, - ) -> Diag<'a> { - // I can't think how to do better than this right now. -nikomatsakis - debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure"); - match placeholder_origin { - infer::Subtype(box ref trace) - if matches!( - &trace.cause.code().peel_derives(), - ObligationCauseCode::WhereClause(..) - | ObligationCauseCode::WhereClauseInExpr(..) - ) => - { - // Hack to get around the borrow checker because trace.cause has an `Rc`. - if let ObligationCauseCode::WhereClause(_, span) - | ObligationCauseCode::WhereClauseInExpr(_, span, ..) = - &trace.cause.code().peel_derives() - && !span.is_dummy() - { - let span = *span; - self.report_concrete_failure(generic_param_scope, placeholder_origin, sub, sup) - .with_span_note(span, "the lifetime requirement is introduced here") - } else { - unreachable!( - "control flow ensures we have a `BindingObligation` or `WhereClauseInExpr` here..." - ) - } - } - infer::Subtype(box trace) => { - let terr = TypeError::RegionsPlaceholderMismatch; - return self.report_and_explain_type_error(trace, terr); - } - _ => { - return self.report_concrete_failure( - generic_param_scope, - placeholder_origin, - sub, - sup, - ); - } - } - } -} diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index 3acca47025cb..f35a5349ecb3 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -221,7 +221,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { infer::Subtype(ref trace) => RegionOriginNote::WithRequirement { span: trace.cause.span, requirement: ObligationCauseAsDiagArg(trace.cause.clone()), - expected_found: self.values_str(trace.values, &trace.cause).map(|(e, f, _)| (e, f)), + expected_found: self.values_str(trace.values, &trace.cause, err.long_ty_path()), } .add_to_diag(err), infer::Reborrow(span) => { @@ -946,10 +946,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let infer::Subtype(ref sup_trace) = sup_origin && let infer::Subtype(ref sub_trace) = sub_origin - && let Some((sup_expected, sup_found, _)) = - self.values_str(sup_trace.values, &sup_trace.cause) - && let Some((sub_expected, sub_found, _)) = - self.values_str(sub_trace.values, &sup_trace.cause) + && let Some((sup_expected, sup_found)) = + self.values_str(sup_trace.values, &sup_trace.cause, err.long_ty_path()) + && let Some((sub_expected, sub_found)) = + self.values_str(sub_trace.values, &sup_trace.cause, err.long_ty_path()) && sub_expected == sup_expected && sub_found == sup_found { diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs index b4d294a70c07..a92f8752a97d 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -163,6 +163,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let predicate = self.resolve_vars_if_possible(obligation.predicate); let span = obligation.cause.span; + let mut file = None; debug!(?predicate, obligation.cause.code = ?obligation.cause.code()); @@ -245,7 +246,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { span, E0283, "type annotations needed: cannot satisfy `{}`", - predicate, + self.tcx.short_string(predicate, &mut file), ) }; @@ -292,7 +293,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { err.cancel(); return e; } - err.note(format!("cannot satisfy `{predicate}`")); + let pred = self.tcx.short_string(predicate, &mut file); + err.note(format!("cannot satisfy `{pred}`")); let impl_candidates = self.find_similar_impl_candidates(predicate.as_trait_clause().unwrap()); if impl_candidates.len() < 40 { @@ -524,6 +526,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .iter() .chain(Some(data.term.into_arg())) .find(|g| g.has_non_region_infer()); + let predicate = self.tcx.short_string(predicate, &mut file); if let Some(arg) = arg { self.emit_inference_failure_err( obligation.cause.body_id, @@ -539,8 +542,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { self.dcx(), span, E0284, - "type annotations needed: cannot satisfy `{}`", - predicate, + "type annotations needed: cannot satisfy `{predicate}`", ) .with_span_label(span, format!("cannot satisfy `{predicate}`")) } @@ -565,12 +567,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { err } else { // If we can't find a generic parameter, just print a generic error + let predicate = self.tcx.short_string(predicate, &mut file); struct_span_code_err!( self.dcx(), span, E0284, - "type annotations needed: cannot satisfy `{}`", - predicate, + "type annotations needed: cannot satisfy `{predicate}`", ) .with_span_label(span, format!("cannot satisfy `{predicate}`")) } @@ -590,6 +592,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let Some(e) = self.tainted_by_errors() { return e; } + let alias = self.tcx.short_string(alias, &mut file); struct_span_code_err!( self.dcx(), span, @@ -603,16 +606,17 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let Some(e) = self.tainted_by_errors() { return e; } + let predicate = self.tcx.short_string(predicate, &mut file); struct_span_code_err!( self.dcx(), span, E0284, - "type annotations needed: cannot satisfy `{}`", - predicate, + "type annotations needed: cannot satisfy `{predicate}`", ) .with_span_label(span, format!("cannot satisfy `{predicate}`")) } }; + *err.long_ty_path() = file; self.note_obligation_cause(&mut err, obligation); err.emit() } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 6416c539f261..d0a193e8bd52 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -1,5 +1,6 @@ use core::ops::ControlFlow; use std::borrow::Cow; +use std::path::PathBuf; use rustc_ast::TraitObjectSyntax; use rustc_data_structures::fx::FxHashMap; @@ -9,7 +10,6 @@ use rustc_errors::{ Applicability, Diag, ErrorGuaranteed, Level, MultiSpan, StashKey, StringPart, Suggestions, pluralize, struct_span_code_err, }; -use rustc_hir::def::Namespace; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; use rustc_hir::intravisit::Visitor; use rustc_hir::{self as hir, LangItem, Node}; @@ -20,8 +20,8 @@ use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::print::{ - FmtPrinter, Print, PrintPolyTraitPredicateExt, PrintTraitPredicateExt as _, - PrintTraitRefExt as _, with_forced_trimmed_paths, + PrintPolyTraitPredicateExt, PrintTraitPredicateExt as _, PrintTraitRefExt as _, + with_forced_trimmed_paths, }; use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, Upcast}; use rustc_middle::{bug, span_bug}; @@ -60,6 +60,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ) -> ErrorGuaranteed { let tcx = self.tcx; let mut span = obligation.cause.span; + let mut long_ty_file = None; let mut err = match *error { SelectionError::Unimplemented => { @@ -169,11 +170,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let Err(guar) = self.fn_arg_obligation(&obligation) { return guar; } - let mut file = None; let (post_message, pre_message, type_def) = self .get_parent_trait_ref(obligation.cause.code()) .map(|(t, s)| { - let t = self.tcx.short_ty_string(t, &mut file); + let t = self.tcx.short_string(t, &mut long_ty_file); ( format!(" in `{t}`"), format!("within `{t}`, "), @@ -181,12 +181,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ) }) .unwrap_or_default(); - let file_note = file.as_ref().map(|file| format!( - "the full trait has been written to '{}'", - file.display(), - )); - - let mut long_ty_file = None; let OnUnimplementedNote { message, @@ -223,6 +217,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { None, append_const_msg, post_message, + &mut long_ty_file, ); let (err_msg, safe_transmute_explanation) = if self.tcx.is_lang_item(main_trait_predicate.def_id(), LangItem::TransmuteTrait) @@ -251,14 +246,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }; let mut err = struct_span_code_err!(self.dcx(), span, E0277, "{}", err_msg); + *err.long_ty_path() = long_ty_file; - if let Some(long_ty_file) = long_ty_file { - err.note(format!( - "the full name for the type has been written to '{}'", - long_ty_file.display(), - )); - err.note("consider using `--verbose` to print the full type name to the console"); - } let mut suggested = false; if is_try_conversion { suggested = self.try_conversion_context(&obligation, main_trait_predicate, &mut err); @@ -309,7 +298,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { return err.emit(); } - file_note.map(|note| err.note(note)); if let Some(s) = label { // If it has a custom `#[rustc_on_unimplemented]` // error message, let's display it as the label! @@ -762,14 +750,17 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { trait_ref: predicate.trait_ref, polarity: ty::PredicatePolarity::Positive, }); + let mut file = None; let err_msg = self.get_standard_error_message( trait_ref, None, Some(predicate.constness()), None, String::new(), + &mut file, ); let mut diag = struct_span_code_err!(self.dcx(), span, E0277, "{}", err_msg); + *diag.long_ty_path() = file; if !self.predicate_may_hold(&Obligation::new( self.tcx, ObligationCause::dummy(), @@ -1381,6 +1372,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { _ => (None, error.err), }; + let mut file = None; let (msg, span, closure_span) = values .and_then(|(predicate, normalized_term, expected_term)| { self.maybe_detailed_projection_msg( @@ -1388,24 +1380,22 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { predicate, normalized_term, expected_term, + &mut file, ) }) .unwrap_or_else(|| { - let mut cx = FmtPrinter::new_with_limit( - self.tcx, - Namespace::TypeNS, - rustc_session::Limit(10), - ); ( - with_forced_trimmed_paths!(format!("type mismatch resolving `{}`", { - self.resolve_vars_if_possible(predicate).print(&mut cx).unwrap(); - cx.into_buffer() - })), + with_forced_trimmed_paths!(format!( + "type mismatch resolving `{}`", + self.tcx + .short_string(self.resolve_vars_if_possible(predicate), &mut file), + )), obligation.cause.span, None, ) }); let mut diag = struct_span_code_err!(self.dcx(), span, E0271, "{msg}"); + *diag.long_ty_path() = file; if let Some(span) = closure_span { // Mark the closure decl so that it is seen even if we are pointing at the return // type or expression. @@ -1471,15 +1461,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ty.span, with_forced_trimmed_paths!(Cow::from(format!( "type mismatch resolving `{}`", - { - let mut cx = FmtPrinter::new_with_limit( - self.tcx, - Namespace::TypeNS, - rustc_session::Limit(5), - ); - self.resolve_vars_if_possible(predicate).print(&mut cx).unwrap(); - cx.into_buffer() - } + self.tcx.short_string( + self.resolve_vars_if_possible(predicate), + diag.long_ty_path() + ), ))), true, )), @@ -1512,6 +1497,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { projection_term: ty::AliasTerm<'tcx>, normalized_ty: ty::Term<'tcx>, expected_ty: ty::Term<'tcx>, + file: &mut Option, ) -> Option<(String, Span, Option)> { let trait_def_id = projection_term.trait_def_id(self.tcx); let self_ty = projection_term.self_ty(); @@ -1552,7 +1538,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }; let item = match self_ty.kind() { ty::FnDef(def, _) => self.tcx.item_name(*def).to_string(), - _ => self_ty.to_string(), + _ => self.tcx.short_string(self_ty, file), }; Some((format!( "expected `{item}` to be a {fn_kind} that returns `{expected_ty}`, but it \ @@ -1984,8 +1970,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { StringPart::normal(" implemented for `"), ]); if types_content.0 == types_content.1 { - let ty = - self.tcx.short_ty_string(obligation_trait_ref.self_ty(), &mut None); + let ty = self + .tcx + .short_string(obligation_trait_ref.self_ty(), err.long_ty_path()); msg.push(StringPart::normal(ty)); } else { msg.extend(types.0.0); @@ -2342,7 +2329,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // First, attempt to add note to this error with an async-await-specific // message, and fall back to regular note otherwise. if !self.maybe_note_obligation_cause_for_async_await(err, obligation) { - let mut long_ty_file = None; self.note_obligation_cause_code( obligation.cause.body_id, err, @@ -2351,15 +2337,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { obligation.cause.code(), &mut vec![], &mut Default::default(), - &mut long_ty_file, ); - if let Some(file) = long_ty_file { - err.note(format!( - "the full name for the type has been written to '{}'", - file.display(), - )); - err.note("consider using `--verbose` to print the full type name to the console"); - } self.suggest_unsized_bound_if_applicable(err, obligation); if let Some(span) = err.span.primary_span() && let Some(mut diag) = @@ -2403,6 +2381,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { predicate_constness: Option, append_const_msg: Option, post_message: String, + long_ty_file: &mut Option, ) -> String { message .and_then(|cannot_do_this| { @@ -2426,7 +2405,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .unwrap_or_else(|| { format!( "the trait bound `{}` is not satisfied{post_message}", - trait_predicate.print_with_bound_constness(predicate_constness) + self.tcx.short_string( + trait_predicate.print_with_bound_constness(predicate_constness), + long_ty_file, + ), ) }) } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs index 8111983c5398..d1bd23bf8266 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs @@ -306,7 +306,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let ObligationCauseCode::WhereClause(..) | ObligationCauseCode::WhereClauseInExpr(..) = code { - let mut long_ty_file = None; self.note_obligation_cause_code( error.obligation.cause.body_id, &mut diag, @@ -315,17 +314,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { code, &mut vec![], &mut Default::default(), - &mut long_ty_file, ); - if let Some(file) = long_ty_file { - diag.note(format!( - "the full name for the type has been written to '{}'", - file.display(), - )); - diag.note( - "consider using `--verbose` to print the full type name to the console", - ); - } } diag.emit() } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs index 3d79b0acf83a..518323f6526a 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs @@ -932,7 +932,7 @@ impl<'tcx> OnUnimplementedFormatString { let value = match param.kind { GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { if let Some(ty) = trait_ref.args[param.index as usize].as_type() { - tcx.short_ty_string(ty, long_ty_file) + tcx.short_string(ty, long_ty_file) } else { trait_ref.args[param.index as usize].to_string() } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs index d82acc4e0543..fad03b5e9bf5 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs @@ -141,7 +141,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { obligation.cause.span, suggest_increasing_limit, |err| { - let mut long_ty_file = None; self.note_obligation_cause_code( obligation.cause.body_id, err, @@ -150,17 +149,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { obligation.cause.code(), &mut vec![], &mut Default::default(), - &mut long_ty_file, ); - if let Some(file) = long_ty_file { - err.note(format!( - "the full name for the type has been written to '{}'", - file.display(), - )); - err.note( - "consider using `--verbose` to print the full type name to the console", - ); - } }, ); } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index ab25bef4120e..24ca7bb7fc20 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3,7 +3,6 @@ use std::assert_matches::debug_assert_matches; use std::borrow::Cow; use std::iter; -use std::path::PathBuf; use itertools::{EitherOrBoth, Itertools}; use rustc_abi::ExternAbi; @@ -1297,30 +1296,24 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // Because of this, we modify the error to refer to the original obligation and // return early in the caller. - let msg = format!("the trait bound `{old_pred}` is not satisfied"); + let msg = format!( + "the trait bound `{}` is not satisfied", + self.tcx.short_string(old_pred, err.long_ty_path()), + ); + let self_ty_str = + self.tcx.short_string(old_pred.self_ty().skip_binder(), err.long_ty_path()); if has_custom_message { err.note(msg); } else { err.messages = vec![(rustc_errors::DiagMessage::from(msg), Style::NoStyle)]; } - let mut file = None; err.span_label( span, format!( - "the trait `{}` is not implemented for `{}`", - old_pred.print_modifiers_and_trait_path(), - self.tcx.short_ty_string(old_pred.self_ty().skip_binder(), &mut file), + "the trait `{}` is not implemented for `{self_ty_str}`", + old_pred.print_modifiers_and_trait_path() ), ); - if let Some(file) = file { - err.note(format!( - "the full type name has been written to '{}'", - file.display() - )); - err.note( - "consider using `--verbose` to print full type name to the console", - ); - } if imm_ref_self_ty_satisfies_pred && mut_ref_self_ty_satisfies_pred { err.span_suggestions( @@ -2689,7 +2682,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // Add a note for the item obligation that remains - normally a note pointing to the // bound that introduced the obligation (e.g. `T: Send`). debug!(?next_code); - let mut long_ty_file = None; self.note_obligation_cause_code( obligation.cause.body_id, err, @@ -2698,7 +2690,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { next_code.unwrap(), &mut Vec::new(), &mut Default::default(), - &mut long_ty_file, ); } @@ -2711,7 +2702,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { cause_code: &ObligationCauseCode<'tcx>, obligated_types: &mut Vec>, seen_requirements: &mut FxHashSet, - long_ty_file: &mut Option, ) where T: Upcast, ty::Predicate<'tcx>>, { @@ -2965,9 +2955,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } ObligationCauseCode::Coercion { source, target } => { let source = - tcx.short_ty_string(self.resolve_vars_if_possible(source), long_ty_file); + tcx.short_string(self.resolve_vars_if_possible(source), err.long_ty_path()); let target = - tcx.short_ty_string(self.resolve_vars_if_possible(target), long_ty_file); + tcx.short_string(self.resolve_vars_if_possible(target), err.long_ty_path()); err.note(with_forced_trimmed_paths!(format!( "required for the cast from `{source}` to `{target}`", ))); @@ -3252,7 +3242,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }; if !is_upvar_tys_infer_tuple { - let ty_str = tcx.short_ty_string(ty, long_ty_file); + let ty_str = tcx.short_string(ty, err.long_ty_path()); let msg = format!("required because it appears within the type `{ty_str}`"); match ty.kind() { ty::Adt(def, _) => match tcx.opt_item_ident(def.did()) { @@ -3330,7 +3320,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { &data.parent_code, obligated_types, seen_requirements, - long_ty_file, ) }); } else { @@ -3343,7 +3332,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { cause_code.peel_derives(), obligated_types, seen_requirements, - long_ty_file, ) }); } @@ -3353,7 +3341,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { self.resolve_vars_if_possible(data.derived.parent_trait_pred); let parent_def_id = parent_trait_pred.def_id(); let self_ty_str = - tcx.short_ty_string(parent_trait_pred.skip_binder().self_ty(), long_ty_file); + tcx.short_string(parent_trait_pred.skip_binder().self_ty(), err.long_ty_path()); let trait_name = parent_trait_pred.print_modifiers_and_trait_path().to_string(); let msg = format!("required for `{self_ty_str}` to implement `{trait_name}`"); let mut is_auto_trait = false; @@ -3449,8 +3437,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { count, pluralize!(count) )); - let self_ty = tcx - .short_ty_string(parent_trait_pred.skip_binder().self_ty(), long_ty_file); + let self_ty = tcx.short_string( + parent_trait_pred.skip_binder().self_ty(), + err.long_ty_path(), + ); err.note(format!( "required for `{self_ty}` to implement `{}`", parent_trait_pred.print_modifiers_and_trait_path() @@ -3466,7 +3456,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { &data.parent_code, obligated_types, seen_requirements, - long_ty_file, ) }); } @@ -3505,7 +3494,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { &data.derived.parent_code, obligated_types, seen_requirements, - long_ty_file, ) }); } @@ -3519,7 +3507,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { &data.parent_code, obligated_types, seen_requirements, - long_ty_file, ) }); } @@ -3536,7 +3523,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { &data.parent_code, obligated_types, seen_requirements, - long_ty_file, ) }); } @@ -3551,7 +3537,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { nested, obligated_types, seen_requirements, - long_ty_file, ) }); let mut multispan = MultiSpan::from(span); @@ -3582,7 +3567,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { parent_code, obligated_types, seen_requirements, - long_ty_file, ) }); } @@ -3622,7 +3606,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } ObligationCauseCode::OpaqueReturnType(expr_info) => { let (expr_ty, expr) = if let Some((expr_ty, hir_id)) = expr_info { - let expr_ty = tcx.short_ty_string(expr_ty, long_ty_file); + let expr_ty = tcx.short_string(expr_ty, err.long_ty_path()); let expr = tcx.hir().expect_expr(hir_id); (expr_ty, expr) } else if let Some(body_id) = tcx.hir_node_by_def_id(body_id).body_id() @@ -3637,7 +3621,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { && let ty::ClauseKind::Trait(pred) = pred.kind().skip_binder() && self.can_eq(param_env, pred.self_ty(), expr_ty) { - let expr_ty = tcx.short_ty_string(expr_ty, long_ty_file); + let expr_ty = tcx.short_string(expr_ty, err.long_ty_path()); (expr_ty, expr) } else { return; @@ -5231,7 +5215,7 @@ pub(super) fn get_explanation_based_on_obligation<'tcx>( format!( "{pre_message}the trait `{}` is not implemented for{desc} `{}`", trait_predicate.print_modifiers_and_trait_path(), - tcx.short_ty_string(trait_predicate.self_ty().skip_binder(), &mut None), + tcx.short_string(trait_predicate.self_ty().skip_binder(), &mut None), ) } else { // "the trait bound `T: !Send` is not satisfied" reads better than "`!Send` is diff --git a/tests/ui/coercion/coerce-expect-unsized-ascribed.stderr b/tests/ui/coercion/coerce-expect-unsized-ascribed.stderr index 0c220a13876b..b682bdac0341 100644 --- a/tests/ui/coercion/coerce-expect-unsized-ascribed.stderr +++ b/tests/ui/coercion/coerce-expect-unsized-ascribed.stderr @@ -29,7 +29,7 @@ error[E0308]: mismatched types --> $DIR/coerce-expect-unsized-ascribed.rs:14:27 | LL | let _ = type_ascribe!(Box::new( { |x| (x as u8) }), Box _>); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Box u8>`, found `Box<{closure@coerce-expect-unsized-ascribed.rs:14:39}>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Box u8>`, found `Box<{closure@...}>` | = note: expected struct `Box u8>` found struct `Box<{closure@$DIR/coerce-expect-unsized-ascribed.rs:14:39: 14:42}>` @@ -85,7 +85,7 @@ error[E0308]: mismatched types --> $DIR/coerce-expect-unsized-ascribed.rs:22:27 | LL | let _ = type_ascribe!(&{ |x| (x as u8) }, &dyn Fn(i32) -> _); - | ^^^^^^^^^^^^^^^^^^ expected `&dyn Fn(i32) -> u8`, found `&{closure@coerce-expect-unsized-ascribed.rs:22:30}` + | ^^^^^^^^^^^^^^^^^^ expected `&dyn Fn(i32) -> u8`, found `&{closure@...}` | = note: expected reference `&dyn Fn(i32) -> u8` found reference `&{closure@$DIR/coerce-expect-unsized-ascribed.rs:22:30: 22:33}` @@ -123,7 +123,7 @@ error[E0308]: mismatched types --> $DIR/coerce-expect-unsized-ascribed.rs:27:27 | LL | let _ = type_ascribe!(Box::new(|x| (x as u8)), Box _>); - | ^^^^^^^^^^^^^^^^^^^^^^^ expected `Box u8>`, found `Box<{closure@coerce-expect-unsized-ascribed.rs:27:36}>` + | ^^^^^^^^^^^^^^^^^^^^^^^ expected `Box u8>`, found `Box<{closure@...}>` | = note: expected struct `Box u8>` found struct `Box<{closure@$DIR/coerce-expect-unsized-ascribed.rs:27:36: 27:39}>` diff --git a/tests/ui/diagnostic-width/E0271.ascii.stderr b/tests/ui/diagnostic-width/E0271.ascii.stderr index 7446b1a543e7..93555b336a66 100644 --- a/tests/ui/diagnostic-width/E0271.ascii.stderr +++ b/tests/ui/diagnostic-width/E0271.ascii.stderr @@ -1,4 +1,4 @@ -error[E0271]: type mismatch resolving `>, ...>>, ...>>, ...> as Future>::Error == Foo` +error[E0271]: type mismatch resolving ` as Future>::Error == Foo` --> $DIR/E0271.rs:20:5 | LL | / Box::new( @@ -7,14 +7,16 @@ LL | | Err::<(), _>( LL | | Ok::<_, ()>( ... | LL | | ) - | |_____^ type mismatch resolving `, ...>>, ...> as Future>::Error == Foo` + | |_____^ type mismatch resolving ` as Future>::Error == Foo` | note: expected this to be `Foo` --> $DIR/E0271.rs:10:18 | LL | type Error = E; | ^ - = note: required for the cast from `Box>, ()>>, ()>>, ()>>` to `Box<(dyn Future + 'static)>` + = note: required for the cast from `Box>` to `Box<...>` + = note: the full name for the type has been written to '$TEST_BUILD_DIR/diagnostic-width/E0271.ascii/E0271.long-type-hash.txt' + = note: consider using `--verbose` to print the full type name to the console error: aborting due to 1 previous error diff --git a/tests/ui/diagnostic-width/E0271.rs b/tests/ui/diagnostic-width/E0271.rs index 061ba45c2198..2faf09d46c6e 100644 --- a/tests/ui/diagnostic-width/E0271.rs +++ b/tests/ui/diagnostic-width/E0271.rs @@ -1,6 +1,6 @@ //@ revisions: ascii unicode -//@[ascii] compile-flags: --diagnostic-width=40 -//@[unicode] compile-flags: -Zunstable-options --error-format=human-unicode --diagnostic-width=40 +//@[ascii] compile-flags: --diagnostic-width=40 -Zwrite-long-types-to-disk=yes +//@[unicode] compile-flags: -Zunstable-options --error-format=human-unicode --diagnostic-width=40 -Zwrite-long-types-to-disk=yes //@ normalize-stderr: "long-type-\d+" -> "long-type-hash" trait Future { type Error; diff --git a/tests/ui/diagnostic-width/E0271.unicode.stderr b/tests/ui/diagnostic-width/E0271.unicode.stderr index 72df2a381a42..1e9acf603b2b 100644 --- a/tests/ui/diagnostic-width/E0271.unicode.stderr +++ b/tests/ui/diagnostic-width/E0271.unicode.stderr @@ -1,4 +1,4 @@ -error[E0271]: type mismatch resolving `>, ...>>, ...>>, ...> as Future>::Error == Foo` +error[E0271]: type mismatch resolving ` as Future>::Error == Foo` ╭▸ $DIR/E0271.rs:20:5 │ LL │ ┏ Box::new( @@ -7,14 +7,16 @@ LL │ ┃ Err::<(), _>( LL │ ┃ Ok::<_, ()>( ‡ ┃ LL │ ┃ ) - │ ┗━━━━━┛ type mismatch resolving `, ...>>, ...> as Future>::Error == Foo` + │ ┗━━━━━┛ type mismatch resolving ` as Future>::Error == Foo` ╰╴ note: expected this to be `Foo` ╭▸ $DIR/E0271.rs:10:18 │ LL │ type Error = E; │ ━ - ╰ note: required for the cast from `Box>, ()>>, ()>>, ()>>` to `Box<(dyn Future + 'static)>` + ├ note: required for the cast from `Box>` to `Box<...>` + ├ note: the full name for the type has been written to '$TEST_BUILD_DIR/diagnostic-width/E0271.unicode/E0271.long-type-hash.txt' + ╰ note: consider using `--verbose` to print the full type name to the console error: aborting due to 1 previous error diff --git a/tests/ui/diagnostic-width/long-E0308.ascii.stderr b/tests/ui/diagnostic-width/long-E0308.ascii.stderr index 3053e37a87a7..83da55861887 100644 --- a/tests/ui/diagnostic-width/long-E0308.ascii.stderr +++ b/tests/ui/diagnostic-width/long-E0308.ascii.stderr @@ -16,11 +16,11 @@ LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok... LL | | Ok("") LL | | )))))))))))))))))))))))))))))) LL | | )))))))))))))))))))))))))))))); - | |__________________________________^ expected `Atype, ...>`, found `Result, ...>` + | |__________________________________^ expected `Atype, i32>, i32>`, found `Result, _>, _>` | - = note: expected struct `Atype, ...>` - found enum `Result, ...>` - = note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt' + = note: expected struct `Atype, i32>` + found enum `Result, _>` + = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt' = note: consider using `--verbose` to print the full type name to the console error[E0308]: mismatched types @@ -32,11 +32,11 @@ LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(... LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(""))))))) LL | | )))))))))))))))))))))))))))))) LL | | )))))))))))))))))))))))); - | |____________________________^ expected `Option>`, found `Result, ...>` + | |____________________________^ expected `Option>, _>>`, found `Result, _>, _>` | - = note: expected enum `Option>` - found enum `Result, ...>` - = note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt' + = note: expected enum `Option, _>>` + found enum `Result, _>` + = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt' = note: consider using `--verbose` to print the full type name to the console error[E0308]: mismatched types @@ -50,13 +50,13 @@ LL | | Atype< ... | LL | | i32 LL | | > = (); - | | - ^^ expected `Atype, ...>`, found `()` + | | - ^^ expected `Atype, i32>, i32>`, found `()` | |_____| | expected due to this | - = note: expected struct `Atype, ...>` + = note: expected struct `Atype, i32>` found unit type `()` - = note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt' + = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt' = note: consider using `--verbose` to print the full type name to the console error[E0308]: mismatched types @@ -70,11 +70,11 @@ LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(... LL | | Ok(Ok(Ok(Ok(Ok(Ok(Ok(""))))))) LL | | )))))))))))))))))))))))))))))) LL | | )))))))))))))))))))))))); - | |____________________________^ expected `()`, found `Result, ...>` + | |____________________________^ expected `()`, found `Result, _>, _>` | = note: expected unit type `()` - found enum `Result, ...>` - = note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt' + found enum `Result, _>` + = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt' = note: consider using `--verbose` to print the full type name to the console error: aborting due to 4 previous errors diff --git a/tests/ui/diagnostic-width/long-E0308.unicode.stderr b/tests/ui/diagnostic-width/long-E0308.unicode.stderr index 50b386325b93..54abf576dbd0 100644 --- a/tests/ui/diagnostic-width/long-E0308.unicode.stderr +++ b/tests/ui/diagnostic-width/long-E0308.unicode.stderr @@ -16,11 +16,11 @@ LL │ ┃ Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O… LL │ ┃ Ok("") LL │ ┃ )))))))))))))))))))))))))))))) LL │ ┃ )))))))))))))))))))))))))))))); - │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ expected `Atype, ...>`, found `Result, ...>` + │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ expected `Atype, i32>, i32>`, found `Result, _>, _>` │ - ├ note: expected struct `Atype, ...>` - │ found enum `Result, ...>` - ├ note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt' + ├ note: expected struct `Atype, i32>` + │ found enum `Result, _>` + ├ note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt' ╰ note: consider using `--verbose` to print the full type name to the console error[E0308]: mismatched types @@ -32,11 +32,11 @@ LL │ ┃ Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok… LL │ ┃ Ok(Ok(Ok(Ok(Ok(Ok(Ok(""))))))) LL │ ┃ )))))))))))))))))))))))))))))) LL │ ┃ )))))))))))))))))))))))); - │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ expected `Option>`, found `Result, ...>` + │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ expected `Option>, _>>`, found `Result, _>, _>` │ - ├ note: expected enum `Option>` - │ found enum `Result, ...>` - ├ note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt' + ├ note: expected enum `Option, _>>` + │ found enum `Result, _>` + ├ note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt' ╰ note: consider using `--verbose` to print the full type name to the console error[E0308]: mismatched types @@ -50,13 +50,13 @@ LL │ │ Atype< ‡ │ LL │ │ i32 LL │ │ > = (); - │ │ │ ━━ expected `Atype, ...>`, found `()` + │ │ │ ━━ expected `Atype, i32>, i32>`, found `()` │ └─────┤ │ expected due to this │ - ├ note: expected struct `Atype, ...>` + ├ note: expected struct `Atype, i32>` │ found unit type `()` - ├ note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt' + ├ note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt' ╰ note: consider using `--verbose` to print the full type name to the console error[E0308]: mismatched types @@ -70,11 +70,11 @@ LL │ ┃ Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok… LL │ ┃ Ok(Ok(Ok(Ok(Ok(Ok(Ok(""))))))) LL │ ┃ )))))))))))))))))))))))))))))) LL │ ┃ )))))))))))))))))))))))); - │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ expected `()`, found `Result, ...>` + │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ expected `()`, found `Result, _>, _>` │ ├ note: expected unit type `()` - │ found enum `Result, ...>` - ├ note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt' + │ found enum `Result, _>` + ├ note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt' ╰ note: consider using `--verbose` to print the full type name to the console error: aborting due to 4 previous errors diff --git a/tests/ui/diagnostic-width/long-e0277.rs b/tests/ui/diagnostic-width/long-e0277.rs new file mode 100644 index 000000000000..9b3bd8bb7289 --- /dev/null +++ b/tests/ui/diagnostic-width/long-e0277.rs @@ -0,0 +1,15 @@ +//@ compile-flags: --diagnostic-width=60 -Zwrite-long-types-to-disk=yes +// The regex below normalizes the long type file name to make it suitable for compare-modes. +//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type-\d+.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type-hash.txt'" +type A = (i32, i32, i32, i32); +type B = (A, A, A, A); +type C = (B, B, B, B); +type D = (C, C, C, C); + +trait Trait {} + +fn require_trait() {} + +fn main() { + require_trait::(); //~ ERROR the trait bound `(... +} diff --git a/tests/ui/diagnostic-width/long-e0277.stderr b/tests/ui/diagnostic-width/long-e0277.stderr new file mode 100644 index 000000000000..a57270df7e25 --- /dev/null +++ b/tests/ui/diagnostic-width/long-e0277.stderr @@ -0,0 +1,23 @@ +error[E0277]: the trait bound `(..., ..., ..., ...): Trait` is not satisfied + --> $DIR/long-e0277.rs:14:21 + | +LL | require_trait::(); + | ^ unsatisfied trait bound + | + = help: the trait `Trait` is not implemented for `(..., ..., ..., ...)` +help: this trait has no implementations, consider adding one + --> $DIR/long-e0277.rs:9:1 + | +LL | trait Trait {} + | ^^^^^^^^^^^ +note: required by a bound in `require_trait` + --> $DIR/long-e0277.rs:11:21 + | +LL | fn require_trait() {} + | ^^^^^ required by this bound in `require_trait` + = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt' + = note: consider using `--verbose` to print the full type name to the console + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic-width/non-copy-type-moved.stderr b/tests/ui/diagnostic-width/non-copy-type-moved.stderr index 889a2b3666dd..254542c7b390 100644 --- a/tests/ui/diagnostic-width/non-copy-type-moved.stderr +++ b/tests/ui/diagnostic-width/non-copy-type-moved.stderr @@ -2,13 +2,13 @@ error[E0382]: use of moved value: `x` --> $DIR/non-copy-type-moved.rs:16:14 | LL | fn foo(x: D) { - | - move occurs because `x` has type `((..., ..., ..., ...), ..., ..., ...)`, which does not implement the `Copy` trait + | - move occurs because `x` has type `(..., ..., ..., ...)`, which does not implement the `Copy` trait LL | let _a = x; | - value moved here LL | let _b = x; | ^ value used here after move | - = note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt' + = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt' = note: consider using `--verbose` to print the full type name to the console help: consider cloning the value if the performance cost is acceptable | diff --git a/tests/ui/diagnostic-width/secondary-label-with-long-type.rs b/tests/ui/diagnostic-width/secondary-label-with-long-type.rs index 4caa94244250..c8845af31835 100644 --- a/tests/ui/diagnostic-width/secondary-label-with-long-type.rs +++ b/tests/ui/diagnostic-width/secondary-label-with-long-type.rs @@ -12,7 +12,7 @@ fn foo(x: D) { //~^ NOTE this expression has type `((..., //~| NOTE expected `((..., //~| NOTE expected tuple - //~| NOTE the full type name has been written to + //~| NOTE the full name for the type has been written to //~| NOTE consider using `--verbose` to print the full type name to the console } diff --git a/tests/ui/diagnostic-width/secondary-label-with-long-type.stderr b/tests/ui/diagnostic-width/secondary-label-with-long-type.stderr index 346b112019fa..a95e17091489 100644 --- a/tests/ui/diagnostic-width/secondary-label-with-long-type.stderr +++ b/tests/ui/diagnostic-width/secondary-label-with-long-type.stderr @@ -8,7 +8,7 @@ LL | let () = x; | = note: expected tuple `((..., ..., ..., ...), ..., ..., ...)` found unit type `()` - = note: the full type name has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt' + = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt' = note: consider using `--verbose` to print the full type name to the console error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/trait-bounds/hang-on-deeply-nested-dyn.stderr b/tests/ui/higher-ranked/trait-bounds/hang-on-deeply-nested-dyn.stderr index 67417a5e525c..be2eca3e61ad 100644 --- a/tests/ui/higher-ranked/trait-bounds/hang-on-deeply-nested-dyn.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hang-on-deeply-nested-dyn.stderr @@ -11,7 +11,7 @@ LL | | ), LL | | ) { | |_- expected `&dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn Fn(u32) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a))` because of return type LL | f - | ^ expected `&dyn Fn(&dyn Fn(&dyn Fn(&...)))`, found `&dyn Fn(u32)` + | ^ expected `&dyn Fn(&dyn Fn(&dyn Fn(&dyn Fn(&...))))`, found `&dyn Fn(u32)` | = note: expected reference `&dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn for<'a> Fn(&'a (dyn Fn(u32) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a)) + 'a))` found reference `&dyn Fn(u32)` diff --git a/tests/ui/suggestions/box-future-wrong-output.stderr b/tests/ui/suggestions/box-future-wrong-output.stderr index 6a232c3444d9..bac26ae8fb5d 100644 --- a/tests/ui/suggestions/box-future-wrong-output.stderr +++ b/tests/ui/suggestions/box-future-wrong-output.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/box-future-wrong-output.rs:20:39 | LL | let _: BoxFuture<'static, bool> = async {}.boxed(); - | ------------------------ ^^^^^^^^^^^^^^^^ expected `bool`, found `()` + | ------------------------ ^^^^^^^^^^^^^^^^ expected `Pin>`, found `Pin + Send>>` | | | expected due to this | diff --git a/tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr b/tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr index 42bc094859a9..61a1d30d31d4 100644 --- a/tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr +++ b/tests/ui/suggestions/expected-boxed-future-isnt-pinned.stderr @@ -32,7 +32,7 @@ error[E0308]: mismatched types LL | fn baz + Send + 'static>(x: F) -> BoxFuture<'static, i32> { | - found this type parameter LL | Pin::new(x) - | -------- ^ expected `Box + Send>`, found type parameter `F` + | -------- ^ expected `Box + Send>`, found type parameter `F` | | | arguments to this function are incorrect | help: use `Box::pin` to pin and box this expression: `Box::pin` diff --git a/tests/ui/suggestions/issue-107860.stderr b/tests/ui/suggestions/issue-107860.stderr index 4be495da46b1..2bfd21939814 100644 --- a/tests/ui/suggestions/issue-107860.stderr +++ b/tests/ui/suggestions/issue-107860.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-107860.rs:3:36 | LL | async fn str(T: &str) -> &str { &str } - | ^^^^ expected `&str`, found `&fn(&str) -> ... {str::<...>}` + | ^^^^ expected `&str`, found `&fn(&str) -> ... {str::<_>}` | = note: expected reference `&str` found reference `&for<'a> fn(&'a str) -> impl Future {str::<_>}` diff --git a/tests/ui/traits/ice-with-dyn-pointee-errors.stderr b/tests/ui/traits/ice-with-dyn-pointee-errors.stderr index 8bfda71bac1f..5299236026d7 100644 --- a/tests/ui/traits/ice-with-dyn-pointee-errors.stderr +++ b/tests/ui/traits/ice-with-dyn-pointee-errors.stderr @@ -2,7 +2,7 @@ error[E0271]: type mismatch resolving ` as Pointee>:: --> $DIR/ice-with-dyn-pointee-errors.rs:9:33 | LL | unknown_sized_object_ptr_in(x) - | --------------------------- ^ expected `()`, found `DynMetadata>` + | --------------------------- ^ expected `()`, found `DynMetadata>` | | | required by a bound introduced by this call | diff --git a/tests/ui/traits/object/pretty.stderr b/tests/ui/traits/object/pretty.stderr index af941e69c5f8..2f9fdf151f08 100644 --- a/tests/ui/traits/object/pretty.stderr +++ b/tests/ui/traits/object/pretty.stderr @@ -110,7 +110,7 @@ error[E0308]: mismatched types --> $DIR/pretty.rs:36:79 | LL | fn dyn_fixed_generic_multi(x: &dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>) { x } - | - ^ expected `()`, found `&dyn FixedGeneric1<'a, Assoc2 = ...>` + | - ^ expected `()`, found `&dyn FixedGeneric1<'a, Assoc2 = &u8>` | | | help: try adding a return type: `-> &dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>` | @@ -132,7 +132,7 @@ error[E0308]: mismatched types --> $DIR/pretty.rs:38:73 | LL | fn dyn_any_different_binders(x: &dyn AnyDifferentBinders) { x } - | - ^ expected `()`, found `&dyn AnyDifferentBinders` + | - ^ expected `()`, found `&dyn AnyDifferentBinders` | | | help: try adding a return type: `-> &dyn AnyDifferentBinders` | diff --git a/tests/ui/traits/on_unimplemented_long_types.stderr b/tests/ui/traits/on_unimplemented_long_types.stderr index 5722f4006ffd..2705d7c501ec 100644 --- a/tests/ui/traits/on_unimplemented_long_types.stderr +++ b/tests/ui/traits/on_unimplemented_long_types.stderr @@ -13,8 +13,6 @@ LL | | ))))))))))), LL | | ))))))))))) | |_______________- return type was inferred to be `Option>>` here | - = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt' - = note: consider using `--verbose` to print the full type name to the console = help: the trait `std::fmt::Display` is not implemented for `Option>>` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt' diff --git a/tests/ui/typeck/issue-107775.stderr b/tests/ui/typeck/issue-107775.stderr index dad7e1581e79..1be268974694 100644 --- a/tests/ui/typeck/issue-107775.stderr +++ b/tests/ui/typeck/issue-107775.stderr @@ -6,7 +6,7 @@ LL | map.insert(1, Struct::do_something); | | | ... which causes `map` to have type `HashMap<{integer}, fn(u8) -> Pin + Send>> {::do_something::<'_>}>` LL | Self { map } - | ^^^ expected `HashMap Pin<...>>`, found `HashMap<{integer}, ...>` + | ^^^ expected `HashMap Pin>>`, found `HashMap<{integer}, ...>` | = note: expected struct `HashMap Pin + Send + 'static)>>>` found struct `HashMap<{integer}, fn(_) -> Pin + Send>> {::do_something::<'_>}>` diff --git a/tests/ui/typeck/return_type_containing_closure.rs b/tests/ui/typeck/return_type_containing_closure.rs index b81cac0a58ab..a9bb89bae2d6 100644 --- a/tests/ui/typeck/return_type_containing_closure.rs +++ b/tests/ui/typeck/return_type_containing_closure.rs @@ -2,7 +2,7 @@ fn foo() { //~ HELP try adding a return type vec!['a'].iter().map(|c| c) //~^ ERROR mismatched types [E0308] - //~| NOTE expected `()`, found `Map, ...>` + //~| NOTE expected `()`, found `Map, {closure@...}>` //~| NOTE expected unit type `()` //~| HELP consider using a semicolon here } diff --git a/tests/ui/typeck/return_type_containing_closure.stderr b/tests/ui/typeck/return_type_containing_closure.stderr index 3f14650a82cc..a60bf79a57b8 100644 --- a/tests/ui/typeck/return_type_containing_closure.stderr +++ b/tests/ui/typeck/return_type_containing_closure.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/return_type_containing_closure.rs:3:5 | LL | vec!['a'].iter().map(|c| c) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Map, ...>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Map, {closure@...}>` | = note: expected unit type `()` found struct `Map, {closure@$DIR/return_type_containing_closure.rs:3:26: 3:29}>` From 24cdaa146a166e679cbc3fc5187315b043090af2 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 30 Jan 2025 16:20:09 +1100 Subject: [PATCH 09/35] Rename `tcx.ensure()` to `tcx.ensure_ok()` --- .../rustc_codegen_cranelift/src/driver/aot.rs | 2 +- compiler/rustc_codegen_ssa/src/base.rs | 2 +- compiler/rustc_driver_impl/src/lib.rs | 4 +- compiler/rustc_driver_impl/src/pretty.rs | 2 +- .../rustc_hir_analysis/src/check/check.rs | 10 +- .../src/check/compare_impl_item.rs | 2 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 16 +- .../src/coherence/builtin.rs | 2 +- .../rustc_hir_analysis/src/coherence/mod.rs | 4 +- compiler/rustc_hir_analysis/src/collect.rs | 150 +++++++++--------- .../rustc_hir_analysis/src/impl_wf_check.rs | 2 +- compiler/rustc_hir_analysis/src/lib.rs | 16 +- compiler/rustc_hir_typeck/src/callee.rs | 2 +- compiler/rustc_interface/src/passes.rs | 45 +++--- compiler/rustc_lint/src/late.rs | 2 +- .../src/rmeta/decoder/cstore_impl.rs | 2 +- .../rustc_middle/src/mir/interpret/queries.rs | 4 +- compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_middle/src/query/plumbing.rs | 45 ++++-- compiler/rustc_middle/src/ty/context.rs | 2 +- compiler/rustc_middle/src/ty/util.rs | 4 +- compiler/rustc_mir_build/src/builder/mod.rs | 2 +- compiler/rustc_monomorphize/src/collector.rs | 2 +- .../src/error_reporting/traits/ambiguity.rs | 8 +- .../src/traits/specialize/mod.rs | 2 +- .../traits/specialize/specialization_graph.rs | 4 +- compiler/rustc_ty_utils/src/instance.rs | 2 +- src/librustdoc/core.rs | 4 +- src/tools/clippy/clippy_lints/src/ctfe.rs | 2 +- 29 files changed, 186 insertions(+), 160 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index 27adf6318e22..a52b18573b15 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -692,7 +692,7 @@ pub(crate) fn run_aot( if tcx.dep_graph.is_fully_enabled() { for cgu in cgus { - tcx.ensure().codegen_unit(cgu.name()); + tcx.ensure_ok().codegen_unit(cgu.name()); } } diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 6e0333cf3cef..df945920ee8d 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -634,7 +634,7 @@ pub fn codegen_crate( // unnecessarily. if tcx.dep_graph.is_fully_enabled() { for cgu in codegen_units { - tcx.ensure().codegen_unit(cgu.name()); + tcx.ensure_ok().codegen_unit(cgu.name()); } } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index c9d38a0f9325..d48992614879 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -317,7 +317,7 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send)) if let Some(pp_mode) = sess.opts.pretty { if pp_mode.needs_ast_map() { create_and_enter_global_ctxt(compiler, krate, |tcx| { - tcx.ensure().early_lint_checks(()); + tcx.ensure_ok().early_lint_checks(()); pretty::print(sess, pp_mode, pretty::PrintExtra::NeedsAstMap { tcx }); passes::write_dep_info(tcx); }); @@ -365,7 +365,7 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send)) return early_exit(); } - tcx.ensure().analysis(()); + tcx.ensure_ok().analysis(()); if callbacks.after_analysis(compiler, tcx) == Compilation::Stop { return early_exit(); diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs index 699742aa0ea1..9ace486fa56f 100644 --- a/compiler/rustc_driver_impl/src/pretty.rs +++ b/compiler/rustc_driver_impl/src/pretty.rs @@ -222,7 +222,7 @@ impl<'tcx> PrintExtra<'tcx> { pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) { if ppm.needs_analysis() { - ex.tcx().ensure().analysis(()); + ex.tcx().ensure_ok().analysis(()); } let (src, src_name) = get_source(sess); diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 40049f96de4a..6c534d58a7da 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -778,13 +778,13 @@ fn check_static_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) { pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { match tcx.def_kind(def_id) { DefKind::Static { .. } => { - tcx.ensure().typeck(def_id); + tcx.ensure_ok().typeck(def_id); maybe_check_static_with_link_section(tcx, def_id); check_static_inhabited(tcx, def_id); check_static_linkage(tcx, def_id); } DefKind::Const => { - tcx.ensure().typeck(def_id); + tcx.ensure_ok().typeck(def_id); } DefKind::Enum => { check_enum(tcx, def_id); @@ -804,7 +804,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { DefKind::Impl { of_trait } => { if of_trait && let Some(impl_trait_header) = tcx.impl_trait_header(def_id) { if tcx - .ensure() + .ensure_ok() .coherent_trait(impl_trait_header.trait_ref.instantiate_identity().def_id) .is_ok() { @@ -1042,7 +1042,7 @@ fn check_impl_items_against_trait<'tcx>( continue; }; - let res = tcx.ensure().compare_impl_item(impl_item.expect_local()); + let res = tcx.ensure_ok().compare_impl_item(impl_item.expect_local()); if res.is_ok() { match ty_impl_item.kind { @@ -1488,7 +1488,7 @@ fn check_enum(tcx: TyCtxt<'_>, def_id: LocalDefId) { for v in def.variants() { if let ty::VariantDiscr::Explicit(discr_def_id) = v.discr { - tcx.ensure().typeck(discr_def_id.expect_local()); + tcx.ensure_ok().typeck(discr_def_id.expect_local()); } } diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 3bff5fe02c03..a91d72e92251 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -2034,7 +2034,7 @@ pub(super) fn check_type_bounds<'tcx>( ) -> Result<(), ErrorGuaranteed> { // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case // other `Foo` impls are incoherent. - tcx.ensure().coherent_trait(impl_trait_ref.def_id)?; + tcx.ensure_ok().coherent_trait(impl_trait_ref.def_id)?; let param_env = tcx.param_env(impl_ty.def_id); debug!(?param_env); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index c9837ca3716c..79e2d764ac59 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1046,7 +1046,7 @@ fn check_associated_item( // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case // other `Foo` impls are incoherent. - tcx.ensure() + tcx.ensure_ok() .coherent_trait(tcx.parent(item.trait_item_def_id.unwrap_or(item_id.into())))?; let self_ty = match item.container { @@ -1354,7 +1354,7 @@ fn check_impl<'tcx>( let trait_ref = tcx.impl_trait_ref(item.owner_id).unwrap().instantiate_identity(); // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case // other `Foo` impls are incoherent. - tcx.ensure().coherent_trait(trait_ref.def_id)?; + tcx.ensure_ok().coherent_trait(trait_ref.def_id)?; let trait_span = hir_trait_ref.path.span; let trait_ref = wfcx.normalize( trait_span, @@ -2268,11 +2268,13 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalModDefId) -> Result<(), ErrorGuaranteed> { let items = tcx.hir_module_items(module); let res = items - .par_items(|item| tcx.ensure().check_well_formed(item.owner_id.def_id)) - .and(items.par_impl_items(|item| tcx.ensure().check_well_formed(item.owner_id.def_id))) - .and(items.par_trait_items(|item| tcx.ensure().check_well_formed(item.owner_id.def_id))) - .and(items.par_foreign_items(|item| tcx.ensure().check_well_formed(item.owner_id.def_id))) - .and(items.par_opaques(|item| tcx.ensure().check_well_formed(item))); + .par_items(|item| tcx.ensure_ok().check_well_formed(item.owner_id.def_id)) + .and(items.par_impl_items(|item| tcx.ensure_ok().check_well_formed(item.owner_id.def_id))) + .and(items.par_trait_items(|item| tcx.ensure_ok().check_well_formed(item.owner_id.def_id))) + .and( + items.par_foreign_items(|item| tcx.ensure_ok().check_well_formed(item.owner_id.def_id)), + ) + .and(items.par_opaques(|item| tcx.ensure_ok().check_well_formed(item))); if module == LocalModDefId::CRATE_DEF_ID { super::entry::check_for_entry_fn(tcx); } diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 30f51fe17246..3511dbc62529 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -192,7 +192,7 @@ fn visit_implementation_of_coerce_unsized(checker: &Checker<'_>) -> Result<(), E // errors; other parts of the code may demand it for the info of // course. let span = tcx.def_span(impl_did); - tcx.at(span).ensure().coerce_unsized_info(impl_did) + tcx.at(span).ensure_ok().coerce_unsized_info(impl_did) } fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> { diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index b9ef166fc3f1..1bc60087ab5e 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -151,7 +151,7 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed> let Some(impls) = tcx.all_local_trait_impls(()).get(&def_id) else { return Ok(()) }; // Trigger building the specialization graph for the trait. This will detect and report any // overlap errors. - let mut res = tcx.ensure().specialization_graph_of(def_id); + let mut res = tcx.ensure_ok().specialization_graph_of(def_id); for &impl_def_id in impls { let trait_header = tcx.impl_trait_header(impl_def_id).unwrap(); @@ -162,7 +162,7 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed> .and(check_impl(tcx, impl_def_id, trait_ref, trait_def)) .and(check_object_overlap(tcx, impl_def_id, trait_ref)) .and(unsafety::check_item(tcx, impl_def_id, trait_header, trait_def)) - .and(tcx.ensure().orphan_check_impl(impl_def_id)) + .and(tcx.ensure_ok().orphan_check_impl(impl_def_id)) .and(builtin::check_trait(tcx, def_id, impl_def_id, trait_header)); } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 226370fccadd..ce7319f65619 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -292,16 +292,16 @@ impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> { match param.kind { hir::GenericParamKind::Lifetime { .. } => {} hir::GenericParamKind::Type { default: Some(_), .. } => { - self.tcx.ensure().type_of(param.def_id); + self.tcx.ensure_ok().type_of(param.def_id); } hir::GenericParamKind::Type { .. } => {} hir::GenericParamKind::Const { default, .. } => { - self.tcx.ensure().type_of(param.def_id); + self.tcx.ensure_ok().type_of(param.def_id); if let Some(default) = default { // need to store default and type of default - self.tcx.ensure().const_param_default(param.def_id); + self.tcx.ensure_ok().const_param_default(param.def_id); if let hir::ConstArgKind::Anon(ac) = default.kind { - self.tcx.ensure().type_of(ac.def_id); + self.tcx.ensure_ok().type_of(ac.def_id); } } } @@ -312,8 +312,8 @@ impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> { fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { if let hir::ExprKind::Closure(closure) = expr.kind { - self.tcx.ensure().generics_of(closure.def_id); - self.tcx.ensure().codegen_fn_attrs(closure.def_id); + self.tcx.ensure_ok().generics_of(closure.def_id); + self.tcx.ensure_ok().codegen_fn_attrs(closure.def_id); // We do not call `type_of` for closures here as that // depends on typecheck and would therefore hide // any further errors in case one typeck fails. @@ -325,15 +325,15 @@ impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> { /// `check_item_type` ensures that it's called instead. fn visit_opaque_ty(&mut self, opaque: &'tcx hir::OpaqueTy<'tcx>) { let def_id = opaque.def_id; - self.tcx.ensure().generics_of(def_id); - self.tcx.ensure().predicates_of(def_id); - self.tcx.ensure().explicit_item_bounds(def_id); - self.tcx.ensure().explicit_item_self_bounds(def_id); - self.tcx.ensure().item_bounds(def_id); - self.tcx.ensure().item_self_bounds(def_id); + self.tcx.ensure_ok().generics_of(def_id); + self.tcx.ensure_ok().predicates_of(def_id); + self.tcx.ensure_ok().explicit_item_bounds(def_id); + self.tcx.ensure_ok().explicit_item_self_bounds(def_id); + self.tcx.ensure_ok().item_bounds(def_id); + self.tcx.ensure_ok().item_self_bounds(def_id); if self.tcx.is_conditionally_const(def_id) { - self.tcx.ensure().explicit_implied_const_bounds(def_id); - self.tcx.ensure().const_conditions(def_id); + self.tcx.ensure_ok().explicit_implied_const_bounds(def_id); + self.tcx.ensure_ok().const_conditions(def_id); } intravisit::walk_opaque_ty(self, opaque); } @@ -683,20 +683,20 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { hir::ItemKind::ForeignMod { items, .. } => { for item in *items { let item = tcx.hir().foreign_item(item.id); - tcx.ensure().generics_of(item.owner_id); - tcx.ensure().type_of(item.owner_id); - tcx.ensure().predicates_of(item.owner_id); + tcx.ensure_ok().generics_of(item.owner_id); + tcx.ensure_ok().type_of(item.owner_id); + tcx.ensure_ok().predicates_of(item.owner_id); if tcx.is_conditionally_const(def_id) { - tcx.ensure().explicit_implied_const_bounds(def_id); - tcx.ensure().const_conditions(def_id); + tcx.ensure_ok().explicit_implied_const_bounds(def_id); + tcx.ensure_ok().const_conditions(def_id); } match item.kind { hir::ForeignItemKind::Fn(..) => { - tcx.ensure().codegen_fn_attrs(item.owner_id); - tcx.ensure().fn_sig(item.owner_id) + tcx.ensure_ok().codegen_fn_attrs(item.owner_id); + tcx.ensure_ok().fn_sig(item.owner_id) } hir::ForeignItemKind::Static(..) => { - tcx.ensure().codegen_fn_attrs(item.owner_id); + tcx.ensure_ok().codegen_fn_attrs(item.owner_id); let mut visitor = HirPlaceholderCollector::default(); visitor.visit_foreign_item(item); placeholder_type_error( @@ -713,40 +713,40 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { } } hir::ItemKind::Enum(..) => { - tcx.ensure().generics_of(def_id); - tcx.ensure().type_of(def_id); - tcx.ensure().predicates_of(def_id); + tcx.ensure_ok().generics_of(def_id); + tcx.ensure_ok().type_of(def_id); + tcx.ensure_ok().predicates_of(def_id); lower_enum_variant_types(tcx, def_id.to_def_id()); } hir::ItemKind::Impl { .. } => { - tcx.ensure().generics_of(def_id); - tcx.ensure().type_of(def_id); - tcx.ensure().impl_trait_header(def_id); - tcx.ensure().predicates_of(def_id); - tcx.ensure().associated_items(def_id); + tcx.ensure_ok().generics_of(def_id); + tcx.ensure_ok().type_of(def_id); + tcx.ensure_ok().impl_trait_header(def_id); + tcx.ensure_ok().predicates_of(def_id); + tcx.ensure_ok().associated_items(def_id); } hir::ItemKind::Trait(..) => { - tcx.ensure().generics_of(def_id); - tcx.ensure().trait_def(def_id); + tcx.ensure_ok().generics_of(def_id); + tcx.ensure_ok().trait_def(def_id); tcx.at(it.span).explicit_super_predicates_of(def_id); - tcx.ensure().predicates_of(def_id); - tcx.ensure().associated_items(def_id); + tcx.ensure_ok().predicates_of(def_id); + tcx.ensure_ok().associated_items(def_id); } hir::ItemKind::TraitAlias(..) => { - tcx.ensure().generics_of(def_id); + tcx.ensure_ok().generics_of(def_id); tcx.at(it.span).explicit_implied_predicates_of(def_id); tcx.at(it.span).explicit_super_predicates_of(def_id); - tcx.ensure().predicates_of(def_id); + tcx.ensure_ok().predicates_of(def_id); } hir::ItemKind::Struct(struct_def, _) | hir::ItemKind::Union(struct_def, _) => { - tcx.ensure().generics_of(def_id); - tcx.ensure().type_of(def_id); - tcx.ensure().predicates_of(def_id); + tcx.ensure_ok().generics_of(def_id); + tcx.ensure_ok().type_of(def_id); + tcx.ensure_ok().predicates_of(def_id); for f in struct_def.fields() { - tcx.ensure().generics_of(f.def_id); - tcx.ensure().type_of(f.def_id); - tcx.ensure().predicates_of(f.def_id); + tcx.ensure_ok().generics_of(f.def_id); + tcx.ensure_ok().type_of(f.def_id); + tcx.ensure_ok().predicates_of(f.def_id); } if let Some(ctor_def_id) = struct_def.ctor_def_id() { @@ -755,15 +755,15 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { } hir::ItemKind::TyAlias(..) => { - tcx.ensure().generics_of(def_id); - tcx.ensure().type_of(def_id); - tcx.ensure().predicates_of(def_id); + tcx.ensure_ok().generics_of(def_id); + tcx.ensure_ok().type_of(def_id); + tcx.ensure_ok().predicates_of(def_id); } hir::ItemKind::Static(ty, ..) | hir::ItemKind::Const(ty, ..) => { - tcx.ensure().generics_of(def_id); - tcx.ensure().type_of(def_id); - tcx.ensure().predicates_of(def_id); + tcx.ensure_ok().generics_of(def_id); + tcx.ensure_ok().type_of(def_id); + tcx.ensure_ok().predicates_of(def_id); if !ty.is_suggestable_infer_ty() { let mut visitor = HirPlaceholderCollector::default(); visitor.visit_item(it); @@ -779,11 +779,11 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { } hir::ItemKind::Fn { .. } => { - tcx.ensure().generics_of(def_id); - tcx.ensure().type_of(def_id); - tcx.ensure().predicates_of(def_id); - tcx.ensure().fn_sig(def_id); - tcx.ensure().codegen_fn_attrs(def_id); + tcx.ensure_ok().generics_of(def_id); + tcx.ensure_ok().type_of(def_id); + tcx.ensure_ok().predicates_of(def_id); + tcx.ensure_ok().fn_sig(def_id); + tcx.ensure_ok().codegen_fn_attrs(def_id); } } } @@ -791,18 +791,18 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { fn lower_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) { let trait_item = tcx.hir().trait_item(trait_item_id); let def_id = trait_item_id.owner_id; - tcx.ensure().generics_of(def_id); + tcx.ensure_ok().generics_of(def_id); let icx = ItemCtxt::new(tcx, def_id.def_id); match trait_item.kind { hir::TraitItemKind::Fn(..) => { - tcx.ensure().codegen_fn_attrs(def_id); - tcx.ensure().type_of(def_id); - tcx.ensure().fn_sig(def_id); + tcx.ensure_ok().codegen_fn_attrs(def_id); + tcx.ensure_ok().type_of(def_id); + tcx.ensure_ok().fn_sig(def_id); } hir::TraitItemKind::Const(ty, body_id) => { - tcx.ensure().type_of(def_id); + tcx.ensure_ok().type_of(def_id); if !tcx.dcx().has_stashed_diagnostic(ty.span, StashKey::ItemNoType) && !(ty.is_suggestable_infer_ty() && body_id.is_some()) { @@ -821,9 +821,9 @@ fn lower_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) { } hir::TraitItemKind::Type(_, Some(_)) => { - tcx.ensure().item_bounds(def_id); - tcx.ensure().item_self_bounds(def_id); - tcx.ensure().type_of(def_id); + tcx.ensure_ok().item_bounds(def_id); + tcx.ensure_ok().item_self_bounds(def_id); + tcx.ensure_ok().type_of(def_id); // Account for `type T = _;`. let mut visitor = HirPlaceholderCollector::default(); visitor.visit_trait_item(trait_item); @@ -838,8 +838,8 @@ fn lower_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) { } hir::TraitItemKind::Type(_, None) => { - tcx.ensure().item_bounds(def_id); - tcx.ensure().item_self_bounds(def_id); + tcx.ensure_ok().item_bounds(def_id); + tcx.ensure_ok().item_self_bounds(def_id); // #74612: Visit and try to find bad placeholders // even if there is no concrete type. let mut visitor = HirPlaceholderCollector::default(); @@ -856,20 +856,20 @@ fn lower_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) { } }; - tcx.ensure().predicates_of(def_id); + tcx.ensure_ok().predicates_of(def_id); } fn lower_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) { let def_id = impl_item_id.owner_id; - tcx.ensure().generics_of(def_id); - tcx.ensure().type_of(def_id); - tcx.ensure().predicates_of(def_id); + tcx.ensure_ok().generics_of(def_id); + tcx.ensure_ok().type_of(def_id); + tcx.ensure_ok().predicates_of(def_id); let impl_item = tcx.hir().impl_item(impl_item_id); let icx = ItemCtxt::new(tcx, def_id.def_id); match impl_item.kind { hir::ImplItemKind::Fn(..) => { - tcx.ensure().codegen_fn_attrs(def_id); - tcx.ensure().fn_sig(def_id); + tcx.ensure_ok().codegen_fn_attrs(def_id); + tcx.ensure_ok().fn_sig(def_id); } hir::ImplItemKind::Type(_) => { // Account for `type T = _;` @@ -904,9 +904,9 @@ fn lower_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) { } fn lower_variant_ctor(tcx: TyCtxt<'_>, def_id: LocalDefId) { - tcx.ensure().generics_of(def_id); - tcx.ensure().type_of(def_id); - tcx.ensure().predicates_of(def_id); + tcx.ensure_ok().generics_of(def_id); + tcx.ensure_ok().type_of(def_id); + tcx.ensure_ok().predicates_of(def_id); } fn lower_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) { @@ -937,9 +937,9 @@ fn lower_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) { ); for f in &variant.fields { - tcx.ensure().generics_of(f.did); - tcx.ensure().type_of(f.did); - tcx.ensure().predicates_of(f.did); + tcx.ensure_ok().generics_of(f.did); + tcx.ensure_ok().type_of(f.did); + tcx.ensure_ok().predicates_of(f.did); } // Lower the ctor, if any. This also registers the variant as an item. diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs index fd5a7089b4cf..c30b39dfe765 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs @@ -62,7 +62,7 @@ pub(crate) fn check_impl_wf( // Check that the args are constrained. We queryfied the check for ty/const params // since unconstrained type/const params cause ICEs in projection, so we want to // detect those specifically and project those to `TyKind::Error`. - let mut res = tcx.ensure().enforce_impl_non_lifetime_params_are_constrained(impl_def_id); + let mut res = tcx.ensure_ok().enforce_impl_non_lifetime_params_are_constrained(impl_def_id); res = res.and(enforce_impl_lifetime_params_are_constrained(tcx, impl_def_id)); if tcx.features().min_specialization() { diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index ae054a9eaeb7..274dbb1ec1c8 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -140,15 +140,15 @@ pub fn check_crate(tcx: TyCtxt<'_>) { tcx.sess.time("coherence_checking", || { tcx.hir().par_for_each_module(|module| { - let _ = tcx.ensure().check_mod_type_wf(module); + let _ = tcx.ensure_ok().check_mod_type_wf(module); }); for &trait_def_id in tcx.all_local_trait_impls(()).keys() { - let _ = tcx.ensure().coherent_trait(trait_def_id); + let _ = tcx.ensure_ok().coherent_trait(trait_def_id); } // these queries are executed for side-effects (error reporting): - let _ = tcx.ensure().crate_inherent_impls_validity_check(()); - let _ = tcx.ensure().crate_inherent_impls_overlap_check(()); + let _ = tcx.ensure_ok().crate_inherent_impls_validity_check(()); + let _ = tcx.ensure_ok().crate_inherent_impls_overlap_check(()); }); if tcx.features().rustc_attrs() { @@ -167,12 +167,12 @@ pub fn check_crate(tcx: TyCtxt<'_>) { tcx.hir().par_body_owners(|item_def_id| { let def_kind = tcx.def_kind(item_def_id); match def_kind { - DefKind::Static { .. } => tcx.ensure().eval_static_initializer(item_def_id), + DefKind::Static { .. } => tcx.ensure_ok().eval_static_initializer(item_def_id), DefKind::Const if tcx.generics_of(item_def_id).is_empty() => { let instance = ty::Instance::new(item_def_id.into(), ty::GenericArgs::empty()); let cid = GlobalId { instance, promoted: None }; let typing_env = ty::TypingEnv::fully_monomorphized(); - tcx.ensure().eval_to_const_value_raw(typing_env.as_query_input(cid)); + tcx.ensure_ok().eval_to_const_value_raw(typing_env.as_query_input(cid)); } _ => (), } @@ -185,11 +185,11 @@ pub fn check_crate(tcx: TyCtxt<'_>) { tcx.hir().par_body_owners(|item_def_id| { let def_kind = tcx.def_kind(item_def_id); if !matches!(def_kind, DefKind::AnonConst) { - tcx.ensure().typeck(item_def_id); + tcx.ensure_ok().typeck(item_def_id); } }); - tcx.ensure().check_unused_traits(()); + tcx.ensure_ok().check_unused_traits(()); } /// Lower a [`hir::Ty`] to a [`Ty`]. diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 28b1a823daea..edc3702d90b5 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -49,7 +49,7 @@ pub(crate) fn check_legal_trait_for_method_call( }; return Err(tcx.dcx().emit_err(errors::ExplicitDestructorCall { span, sugg })); } - tcx.ensure().coherent_trait(trait_id) + tcx.ensure_ok().coherent_trait(trait_id) } #[derive(Debug)] diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 0b91c023cfc8..57a8c272c5cb 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -832,20 +832,20 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { sess.time("misc_checking_1", || { parallel!( { - sess.time("looking_for_entry_point", || tcx.ensure().entry_fn(())); + sess.time("looking_for_entry_point", || tcx.ensure_ok().entry_fn(())); sess.time("looking_for_derive_registrar", || { - tcx.ensure().proc_macro_decls_static(()) + tcx.ensure_ok().proc_macro_decls_static(()) }); CStore::from_tcx(tcx).report_unused_deps(tcx); }, { tcx.hir().par_for_each_module(|module| { - tcx.ensure().check_mod_loops(module); - tcx.ensure().check_mod_attrs(module); - tcx.ensure().check_mod_naked_functions(module); - tcx.ensure().check_mod_unstable_api_usage(module); + tcx.ensure_ok().check_mod_loops(module); + tcx.ensure_ok().check_mod_attrs(module); + tcx.ensure_ok().check_mod_naked_functions(module); + tcx.ensure_ok().check_mod_unstable_api_usage(module); }); }, { @@ -858,8 +858,8 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { // since they might not otherwise get called. // This marks the corresponding crate-level attributes // as used, and ensures that their values are valid. - tcx.ensure().limits(()); - tcx.ensure().stability_index(()); + tcx.ensure_ok().limits(()); + tcx.ensure_ok().stability_index(()); } ); }); @@ -883,13 +883,13 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { tcx.hir().par_body_owners(|def_id| { // Run unsafety check because it's responsible for stealing and // deallocating THIR. - tcx.ensure().check_unsafety(def_id); - tcx.ensure().mir_borrowck(def_id) + tcx.ensure_ok().check_unsafety(def_id); + tcx.ensure_ok().mir_borrowck(def_id) }); }); sess.time("MIR_effect_checking", || { tcx.hir().par_body_owners(|def_id| { - tcx.ensure().has_ffi_unwind_calls(def_id); + tcx.ensure_ok().has_ffi_unwind_calls(def_id); // If we need to codegen, ensure that we emit all errors from // `mir_drops_elaborated_and_const_checked` now, to avoid discovering @@ -897,15 +897,15 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { if tcx.sess.opts.output_types.should_codegen() || tcx.hir().body_const_context(def_id).is_some() { - tcx.ensure().mir_drops_elaborated_and_const_checked(def_id); + tcx.ensure_ok().mir_drops_elaborated_and_const_checked(def_id); } }); }); sess.time("coroutine_obligations", || { tcx.hir().par_body_owners(|def_id| { if tcx.is_coroutine(def_id.to_def_id()) { - tcx.ensure().mir_coroutine_witnesses(def_id); - tcx.ensure().check_coroutine_obligations( + tcx.ensure_ok().mir_coroutine_witnesses(def_id); + tcx.ensure_ok().check_coroutine_obligations( tcx.typeck_root_def_id(def_id.to_def_id()).expect_local(), ); } @@ -950,15 +950,16 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) { sess.time("misc_checking_3", || { parallel!( { - tcx.ensure().effective_visibilities(()); + tcx.ensure_ok().effective_visibilities(()); parallel!( { - tcx.ensure().check_private_in_public(()); + tcx.ensure_ok().check_private_in_public(()); }, { - tcx.hir() - .par_for_each_module(|module| tcx.ensure().check_mod_deathness(module)); + tcx.hir().par_for_each_module(|module| { + tcx.ensure_ok().check_mod_deathness(module) + }); }, { sess.time("lint_checking", || { @@ -966,14 +967,14 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) { }); }, { - tcx.ensure().clashing_extern_declarations(()); + tcx.ensure_ok().clashing_extern_declarations(()); } ); }, { sess.time("privacy_checking_modules", || { tcx.hir().par_for_each_module(|module| { - tcx.ensure().check_mod_privacy(module); + tcx.ensure_ok().check_mod_privacy(module); }); }); } @@ -981,7 +982,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) { // This check has to be run after all lints are done processing. We don't // define a lint filter, as all lint checks should have finished at this point. - sess.time("check_lint_expectations", || tcx.ensure().check_expectations(None)); + sess.time("check_lint_expectations", || tcx.ensure_ok().check_expectations(None)); // This query is only invoked normally if a diagnostic is emitted that needs any // diagnostic item. If the crate compiles without checking any diagnostic items, @@ -1006,7 +1007,7 @@ fn check_for_rustc_errors_attr(tcx: TyCtxt<'_>) { ) }) => { - tcx.ensure().trigger_delayed_bug(def_id); + tcx.ensure_ok().trigger_delayed_bug(def_id); } // Bare `#[rustc_error]`. diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index c6d7b839e197..826ecc22c24b 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -458,7 +458,7 @@ pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>) { || { tcx.sess.time("module_lints", || { // Run per-module lints - tcx.hir().par_for_each_module(|module| tcx.ensure().lint_mod(module)); + tcx.hir().par_for_each_module(|module| tcx.ensure_ok().lint_mod(module)); }); }, ); diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index da07ad8f6c07..5fcb9c850356 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -165,7 +165,7 @@ macro_rules! provide_one { // doesn't need to do this (and can't, as it would cause a query cycle). use rustc_middle::dep_graph::dep_kinds; if dep_kinds::$name != dep_kinds::crate_hash && $tcx.dep_graph.is_fully_enabled() { - $tcx.ensure().crate_hash($def_id.krate); + $tcx.ensure_ok().crate_hash($def_id.krate); } let cdata = rustc_data_structures::sync::FreezeReadGuard::map(CStore::from_tcx($tcx), |c| { diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index 4c47d9636d3f..78749428c6df 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -9,7 +9,7 @@ use super::{ ReportedErrorInfo, }; use crate::mir; -use crate::query::TyCtxtEnsure; +use crate::query::TyCtxtEnsureOk; use crate::ty::visit::TypeVisitableExt; use crate::ty::{self, GenericArgs, TyCtxt}; @@ -198,7 +198,7 @@ impl<'tcx> TyCtxt<'tcx> { } } -impl<'tcx> TyCtxtEnsure<'tcx> { +impl<'tcx> TyCtxtEnsureOk<'tcx> { /// Evaluates a constant without providing any generic parameters. This is useful to evaluate consts /// that can't take any generic arguments like const items or enum discriminants. If a /// generic parameter is used within the constant `ErrorHandled::TooGeneric` will be returned. diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 41e9858030c8..bdd24d3977fe 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -91,7 +91,7 @@ pub use keys::{AsLocalKey, Key, LocalCrate}; pub mod on_disk_cache; #[macro_use] pub mod plumbing; -pub use plumbing::{IntoQueryParam, TyCtxtAt, TyCtxtEnsure, TyCtxtEnsureWithValue}; +pub use plumbing::{IntoQueryParam, TyCtxtAt, TyCtxtEnsureOk, TyCtxtEnsureWithValue}; // Each of these queries corresponds to a function pointer field in the // `Providers` struct for requesting a value of that type, and a method diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 1c157f33a813..16660d7a1f99 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -88,7 +88,7 @@ impl<'tcx> Deref for TyCtxtAt<'tcx> { } #[derive(Copy, Clone)] -pub struct TyCtxtEnsure<'tcx> { +pub struct TyCtxtEnsureOk<'tcx> { pub tcx: TyCtxt<'tcx>, } @@ -98,11 +98,29 @@ pub struct TyCtxtEnsureWithValue<'tcx> { } impl<'tcx> TyCtxt<'tcx> { - /// Returns a transparent wrapper for `TyCtxt`, which ensures queries - /// are executed instead of just returning their results. + /// Wrapper that calls queries in a special "ensure OK" mode, for callers + /// that don't need the return value and just want to invoke a query for + /// its potential side-effect of emitting fatal errors. + /// + /// This can be more efficient than a normal query call, because if the + /// query's inputs are all green, the call can return immediately without + /// needing to obtain a value (by decoding one from disk or by executing + /// the query). + /// + /// (As with all query calls, execution is also skipped if the query result + /// is already cached in memory.) + /// + /// ## WARNING + /// A subsequent normal call to the same query might still cause it to be + /// executed! This can occur when the inputs are all green, but the query's + /// result is not cached on disk, so the query must be executed to obtain a + /// return value. + /// + /// Therefore, this call mode is not appropriate for callers that want to + /// ensure that the query is _never_ executed in the future. #[inline(always)] - pub fn ensure(self) -> TyCtxtEnsure<'tcx> { - TyCtxtEnsure { tcx: self } + pub fn ensure_ok(self) -> TyCtxtEnsureOk<'tcx> { + TyCtxtEnsureOk { tcx: self } } /// Returns a transparent wrapper for `TyCtxt`, which ensures queries @@ -248,15 +266,15 @@ macro_rules! separate_provide_extern_decl { }; } -macro_rules! ensure_result { - ([][$ty:ty]) => { +macro_rules! ensure_ok_result { + ( [] ) => { () }; - ([(ensure_forwards_result_if_red) $($rest:tt)*][$ty:ty]) => { + ( [(ensure_forwards_result_if_red) $($rest:tt)*] ) => { Result<(), ErrorGuaranteed> }; - ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => { - ensure_result!([$($modifiers)*][$($args)*]) + ( [$other:tt $($modifiers:tt)*] ) => { + ensure_ok_result!( [$($modifiers)*] ) }; } @@ -383,10 +401,13 @@ macro_rules! define_callbacks { $($(#[$attr])* pub $name: queries::$name::Storage<'tcx>,)* } - impl<'tcx> TyCtxtEnsure<'tcx> { + impl<'tcx> TyCtxtEnsureOk<'tcx> { $($(#[$attr])* #[inline(always)] - pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> ensure_result!([$($modifiers)*][$V]) { + pub fn $name( + self, + key: query_helper_param_ty!($($K)*), + ) -> ensure_ok_result!([$($modifiers)*]) { query_ensure!( [$($modifiers)*] self.tcx, diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 69f6fc0ad8a6..522a553d2432 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1957,7 +1957,7 @@ impl<'tcx> TyCtxt<'tcx> { ) -> &'tcx rustc_hir::def_path_hash_map::DefPathHashMap { // Create a dependency to the crate to be sure we re-execute this when the amount of // definitions change. - self.ensure().hir_crate(()); + self.ensure_ok().hir_crate(()); // Freeze definitions once we start iterating on them, to prevent adding new ones // while iterating. If some query needs to add definitions, it should be `ensure`d above. self.untracked.definitions.freeze().def_path_hash_to_def_index_map() diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 7d5e5c2e8237..318bd0c7ec02 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -367,7 +367,7 @@ impl<'tcx> TyCtxt<'tcx> { validate: impl Fn(Self, DefId) -> Result<(), ErrorGuaranteed>, ) -> Option { let drop_trait = self.lang_items().drop_trait()?; - self.ensure().coherent_trait(drop_trait).ok()?; + self.ensure_ok().coherent_trait(drop_trait).ok()?; let ty = self.type_of(adt_did).instantiate_identity(); let mut dtor_candidate = None; @@ -404,7 +404,7 @@ impl<'tcx> TyCtxt<'tcx> { validate: impl Fn(Self, DefId) -> Result<(), ErrorGuaranteed>, ) -> Option { let async_drop_trait = self.lang_items().async_drop_trait()?; - self.ensure().coherent_trait(async_drop_trait).ok()?; + self.ensure_ok().coherent_trait(async_drop_trait).ok()?; let ty = self.type_of(adt_did).instantiate_identity(); let mut dtor_candidate = None; diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs index 93fb9873e80a..8eb9f786c59e 100644 --- a/compiler/rustc_mir_build/src/builder/mod.rs +++ b/compiler/rustc_mir_build/src/builder/mod.rs @@ -68,7 +68,7 @@ pub fn build_mir<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Body<'tcx> { // "not all control paths return a value" is reported here. // // maybe move the check to a MIR pass? - tcx.ensure().check_liveness(def); + tcx.ensure_ok().check_liveness(def); // Don't steal here, instead steal in unsafeck. This is so that // pattern inline constants can be evaluated as part of building the diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 246faed50e36..de8a20c5deee 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1222,7 +1222,7 @@ fn collect_items_of_instance<'tcx>( mode: CollectionMode, ) -> (MonoItems<'tcx>, MonoItems<'tcx>) { // This item is getting monomorphized, do mono-time checks. - tcx.ensure().check_mono_item(instance); + tcx.ensure_ok().check_mono_item(instance); let body = tcx.instance_mir(instance.def); // Naively, in "used" collection mode, all functions get added to *both* `used_items` and diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs index b4d294a70c07..b798853a1dbe 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -179,7 +179,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { return e; } - if let Err(guar) = self.tcx.ensure().coherent_trait(trait_pred.def_id()) { + if let Err(guar) = self.tcx.ensure_ok().coherent_trait(trait_pred.def_id()) { // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case // other `Foo` impls are incoherent. return guar; @@ -511,8 +511,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { return e; } - if let Err(guar) = - self.tcx.ensure().coherent_trait(self.tcx.parent(data.projection_term.def_id)) + if let Err(guar) = self + .tcx + .ensure_ok() + .coherent_trait(self.tcx.parent(data.projection_term.def_id)) { // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case // other `Foo` impls are incoherent. diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 401b41c796da..cb3e81f5477f 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -575,7 +575,7 @@ fn report_conflicting_impls<'tcx>( match used_to_be_allowed { None => { let reported = if overlap.with_impl.is_local() - || tcx.ensure().orphan_check_impl(impl_def_id).is_ok() + || tcx.ensure_ok().orphan_check_impl(impl_def_id).is_ok() { let mut err = tcx.dcx().struct_span_err(impl_span, msg()); err.code(E0119); diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs index c351cf5aaac6..f39c611d19fe 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs @@ -379,7 +379,7 @@ pub(crate) fn assoc_def( // Ensure that the impl is constrained, otherwise projection may give us // bad unconstrained infer vars. if let Some(impl_def_id) = impl_def_id.as_local() { - tcx.ensure().enforce_impl_non_lifetime_params_are_constrained(impl_def_id)?; + tcx.ensure_ok().enforce_impl_non_lifetime_params_are_constrained(impl_def_id)?; } let item = tcx.associated_item(impl_item_id); @@ -402,7 +402,7 @@ pub(crate) fn assoc_def( if assoc_item.item.container == ty::AssocItemContainer::Impl && let Some(impl_def_id) = assoc_item.item.container_id(tcx).as_local() { - tcx.ensure().enforce_impl_non_lifetime_params_are_constrained(impl_def_id)?; + tcx.ensure_ok().enforce_impl_non_lifetime_params_are_constrained(impl_def_id)?; } Ok(assoc_item) diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index d5e1937efaa4..8c6e3c86bf5c 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -225,7 +225,7 @@ fn resolve_associated_item<'tcx>( if trait_item_id != leaf_def.item.def_id && let Some(leaf_def_item) = leaf_def.item.def_id.as_local() { - tcx.ensure().compare_impl_item(leaf_def_item)?; + tcx.ensure_ok().compare_impl_item(leaf_def_item)?; } Some(ty::Instance::new(leaf_def.item.def_id, args)) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 0437ebb58576..a072b1256f47 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -336,14 +336,14 @@ pub(crate) fn run_global_ctxt( // NOTE: These are copy/pasted from typeck/lib.rs and should be kept in sync with those changes. let _ = tcx.sess.time("wf_checking", || { - tcx.hir().try_par_for_each_module(|module| tcx.ensure().check_mod_type_wf(module)) + tcx.hir().try_par_for_each_module(|module| tcx.ensure_ok().check_mod_type_wf(module)) }); tcx.dcx().abort_if_errors(); tcx.sess.time("missing_docs", || rustc_lint::check_crate(tcx)); tcx.sess.time("check_mod_attrs", || { - tcx.hir().for_each_module(|module| tcx.ensure().check_mod_attrs(module)) + tcx.hir().for_each_module(|module| tcx.ensure_ok().check_mod_attrs(module)) }); rustc_passes::stability::check_unused_or_stable_features(tcx); diff --git a/src/tools/clippy/clippy_lints/src/ctfe.rs b/src/tools/clippy/clippy_lints/src/ctfe.rs index 589b99518a09..7bae04a10f10 100644 --- a/src/tools/clippy/clippy_lints/src/ctfe.rs +++ b/src/tools/clippy/clippy_lints/src/ctfe.rs @@ -21,6 +21,6 @@ impl<'tcx> LateLintPass<'tcx> for ClippyCtfe { _: Span, defid: LocalDefId, ) { - cx.tcx.ensure().mir_drops_elaborated_and_const_checked(defid); // Lint + cx.tcx.ensure_ok().mir_drops_elaborated_and_const_checked(defid); // Lint } } From 9e4f10db658700a191bcb6dba9e4e285297a5683 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 30 Jan 2025 16:28:44 +1100 Subject: [PATCH 10/35] Rename `tcx.ensure_with_value()` to `tcx.ensure_done()` --- compiler/rustc_ast_lowering/src/lib.rs | 8 +++--- compiler/rustc_interface/src/passes.rs | 2 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 6 ++--- compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_middle/src/query/plumbing.rs | 26 ++++++++++++++----- compiler/rustc_mir_build/src/builder/mod.rs | 2 +- .../rustc_mir_build/src/check_unsafety.rs | 4 +-- compiler/rustc_mir_transform/src/lib.rs | 12 ++++----- 8 files changed, 37 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index b9f1a4220b80..893da9308553 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -418,10 +418,10 @@ fn compute_hir_hash( pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> { let sess = tcx.sess; // Queries that borrow `resolver_for_lowering`. - tcx.ensure_with_value().output_filenames(()); - tcx.ensure_with_value().early_lint_checks(()); - tcx.ensure_with_value().debugger_visualizers(LOCAL_CRATE); - tcx.ensure_with_value().get_lang_items(()); + tcx.ensure_done().output_filenames(()); + tcx.ensure_done().early_lint_checks(()); + tcx.ensure_done().debugger_visualizers(LOCAL_CRATE); + tcx.ensure_done().get_lang_items(()); let (mut resolver, krate) = tcx.resolver_for_lowering().steal(); let ast_index = index_crate(&resolver.node_id_to_def_id, &krate); diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 57a8c272c5cb..0324ebf9fd21 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -868,7 +868,7 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { sess.time("MIR_coroutine_by_move_body", || { tcx.hir().par_body_owners(|def_id| { if tcx.needs_coroutine_by_move_body_def_id(def_id.to_def_id()) { - tcx.ensure_with_value().coroutine_by_move_body_def_id(def_id); + tcx.ensure_done().coroutine_by_move_body_def_id(def_id); } }); }); diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 43372154b2ce..6e562e457d21 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -2191,13 +2191,13 @@ fn prefetch_mir(tcx: TyCtxt<'_>) { let (encode_const, encode_opt) = should_encode_mir(tcx, reachable_set, def_id); if encode_const { - tcx.ensure_with_value().mir_for_ctfe(def_id); + tcx.ensure_done().mir_for_ctfe(def_id); } if encode_opt { - tcx.ensure_with_value().optimized_mir(def_id); + tcx.ensure_done().optimized_mir(def_id); } if encode_opt || encode_const { - tcx.ensure_with_value().promoted_mir(def_id); + tcx.ensure_done().promoted_mir(def_id); } }) } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index bdd24d3977fe..934593dfb797 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -91,7 +91,7 @@ pub use keys::{AsLocalKey, Key, LocalCrate}; pub mod on_disk_cache; #[macro_use] pub mod plumbing; -pub use plumbing::{IntoQueryParam, TyCtxtAt, TyCtxtEnsureOk, TyCtxtEnsureWithValue}; +pub use plumbing::{IntoQueryParam, TyCtxtAt, TyCtxtEnsureDone, TyCtxtEnsureOk}; // Each of these queries corresponds to a function pointer field in the // `Providers` struct for requesting a value of that type, and a method diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 16660d7a1f99..6648e3d9d53b 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -93,7 +93,7 @@ pub struct TyCtxtEnsureOk<'tcx> { } #[derive(Copy, Clone)] -pub struct TyCtxtEnsureWithValue<'tcx> { +pub struct TyCtxtEnsureDone<'tcx> { pub tcx: TyCtxt<'tcx>, } @@ -123,13 +123,25 @@ impl<'tcx> TyCtxt<'tcx> { TyCtxtEnsureOk { tcx: self } } - /// Returns a transparent wrapper for `TyCtxt`, which ensures queries - /// are executed instead of just returning their results. + /// Wrapper that calls queries in a special "ensure done" mode, for callers + /// that don't need the return value and just want to guarantee that the + /// query won't be executed in the future, by executing it now if necessary. /// - /// This version verifies that the computed result exists in the cache before returning. + /// This is useful for queries that read from a [`Steal`] value, to ensure + /// that they are executed before the query that will steal the value. + /// + /// Unlike [`Self::ensure_ok`], a query with all-green inputs will only be + /// skipped if its return value is stored in the disk-cache. This is still + /// more efficient than a regular query, because in that situation the + /// return value doesn't necessarily need to be decoded. + /// + /// (As with all query calls, execution is also skipped if the query result + /// is already cached in memory.) + /// + /// [`Steal`]: rustc_data_structures::steal::Steal #[inline(always)] - pub fn ensure_with_value(self) -> TyCtxtEnsureWithValue<'tcx> { - TyCtxtEnsureWithValue { tcx: self } + pub fn ensure_done(self) -> TyCtxtEnsureDone<'tcx> { + TyCtxtEnsureDone { tcx: self } } /// Returns a transparent wrapper for `TyCtxt` which uses @@ -419,7 +431,7 @@ macro_rules! define_callbacks { })* } - impl<'tcx> TyCtxtEnsureWithValue<'tcx> { + impl<'tcx> TyCtxtEnsureDone<'tcx> { $($(#[$attr])* #[inline(always)] pub fn $name(self, key: query_helper_param_ty!($($K)*)) { diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs index 8eb9f786c59e..e04c70b58837 100644 --- a/compiler/rustc_mir_build/src/builder/mod.rs +++ b/compiler/rustc_mir_build/src/builder/mod.rs @@ -47,7 +47,7 @@ pub(crate) fn closure_saved_names_of_captured_variables<'tcx>( /// Create the MIR for a given `DefId`, including unreachable code. Do not call /// this directly; instead use the cached version via `mir_built`. pub fn build_mir<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Body<'tcx> { - tcx.ensure_with_value().thir_abstract_const(def); + tcx.ensure_done().thir_abstract_const(def); if let Err(e) = tcx.check_match(def) { return construct_error(tcx, def, e); } diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 995bc311b7c4..0cca0a43143f 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -200,7 +200,7 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { fn visit_inner_body(&mut self, def: LocalDefId) { if let Ok((inner_thir, expr)) = self.tcx.thir_body(def) { // Runs all other queries that depend on THIR. - self.tcx.ensure_with_value().mir_built(def); + self.tcx.ensure_done().mir_built(def); let inner_thir = &inner_thir.steal(); let hir_context = self.tcx.local_def_id_to_hir_id(def); let safety_context = mem::replace(&mut self.safety_context, SafetyContext::Safe); @@ -1112,7 +1112,7 @@ pub(crate) fn check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) { let Ok((thir, expr)) = tcx.thir_body(def) else { return }; // Runs all other queries that depend on THIR. - tcx.ensure_with_value().mir_built(def); + tcx.ensure_done().mir_built(def); let thir = &thir.steal(); let hir_id = tcx.local_def_id_to_hir_id(def); diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 4af9a111bdf9..b572f6ca0b36 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -421,11 +421,11 @@ fn mir_promoted( }; // the `has_ffi_unwind_calls` query uses the raw mir, so make sure it is run. - tcx.ensure_with_value().has_ffi_unwind_calls(def); + tcx.ensure_done().has_ffi_unwind_calls(def); // the `by_move_body` query uses the raw mir, so make sure it is run. if tcx.needs_coroutine_by_move_body_def_id(def.to_def_id()) { - tcx.ensure_with_value().coroutine_by_move_body_def_id(def); + tcx.ensure_done().coroutine_by_move_body_def_id(def); } let mut body = tcx.mir_built(def).steal(); @@ -488,7 +488,7 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> { /// end up missing the source MIR due to stealing happening. fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal> { if tcx.is_coroutine(def.to_def_id()) { - tcx.ensure_with_value().mir_coroutine_witnesses(def); + tcx.ensure_done().mir_coroutine_witnesses(def); } // We only need to borrowck non-synthetic MIR. @@ -501,7 +501,7 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> & if pm::should_run_pass(tcx, &inline::Inline, pm::Optimizations::Allowed) || inline::ForceInline::should_run_pass_for_callee(tcx, def.to_def_id()) { - tcx.ensure_with_value().mir_inliner_callees(ty::InstanceKind::Item(def.to_def_id())); + tcx.ensure_done().mir_inliner_callees(ty::InstanceKind::Item(def.to_def_id())); } } @@ -733,7 +733,7 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> { // Run the `mir_for_ctfe` query, which depends on `mir_drops_elaborated_and_const_checked` // which we are going to steal below. Thus we need to run `mir_for_ctfe` first, so it // computes and caches its result. - Some(hir::ConstContext::ConstFn) => tcx.ensure_with_value().mir_for_ctfe(did), + Some(hir::ConstContext::ConstFn) => tcx.ensure_done().mir_for_ctfe(did), None => {} Some(other) => panic!("do not use `optimized_mir` for constants: {other:?}"), } @@ -772,7 +772,7 @@ fn promoted_mir(tcx: TyCtxt<'_>, def: LocalDefId) -> &IndexVec Date: Thu, 30 Jan 2025 16:41:12 +1100 Subject: [PATCH 11/35] Rename `ensure_forwards_result_if_red` to `return_result_from_ensure_ok` --- compiler/rustc_macros/src/query.rs | 26 +++++++++++++-------- compiler/rustc_middle/src/query/mod.rs | 20 ++++++++-------- compiler/rustc_middle/src/query/plumbing.rs | 10 ++++++-- 3 files changed, 34 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 88ea6e07d6eb..62bf34ad5adc 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -118,11 +118,17 @@ struct QueryModifiers { /// Generate a `feed` method to set the query's value from another query. feedable: Option, - /// Forward the result on ensure if the query gets recomputed, and - /// return `Ok(())` otherwise. Only applicable to queries returning - /// `Result`. The `T` is not returned from `ensure` - /// invocations. - ensure_forwards_result_if_red: Option, + /// When this query is called via `tcx.ensure_ok()`, it returns + /// `Result<(), ErrorGuaranteed>` instead of `()`. If the query needs to + /// be executed, and that execution returns an error, the error result is + /// returned to the caller. + /// + /// If execution is skipped, a synthetic `Ok(())` is returned, on the + /// assumption that a query with all-green inputs must have succeeded. + /// + /// Can only be applied to queries with a return value of + /// `Result<_, ErrorGuaranteed>`. + return_result_from_ensure_ok: Option, } fn parse_query_modifiers(input: ParseStream<'_>) -> Result { @@ -138,7 +144,7 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result { let mut depth_limit = None; let mut separate_provide_extern = None; let mut feedable = None; - let mut ensure_forwards_result_if_red = None; + let mut return_result_from_ensure_ok = None; while !input.is_empty() { let modifier: Ident = input.parse()?; @@ -200,8 +206,8 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result { try_insert!(separate_provide_extern = modifier); } else if modifier == "feedable" { try_insert!(feedable = modifier); - } else if modifier == "ensure_forwards_result_if_red" { - try_insert!(ensure_forwards_result_if_red = modifier); + } else if modifier == "return_result_from_ensure_ok" { + try_insert!(return_result_from_ensure_ok = modifier); } else { return Err(Error::new(modifier.span(), "unknown query modifier")); } @@ -222,7 +228,7 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result { depth_limit, separate_provide_extern, feedable, - ensure_forwards_result_if_red, + return_result_from_ensure_ok, }) } @@ -354,7 +360,7 @@ pub(super) fn rustc_queries(input: TokenStream) -> TokenStream { eval_always, depth_limit, separate_provide_extern, - ensure_forwards_result_if_red, + return_result_from_ensure_ok, ); if modifiers.cache.is_some() { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 934593dfb797..6c442fc1047f 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1087,7 +1087,7 @@ rustc_queries! { query check_mod_type_wf(key: LocalModDefId) -> Result<(), ErrorGuaranteed> { desc { |tcx| "checking that types are well-formed in {}", describe_as_module(key, tcx) } - ensure_forwards_result_if_red + return_result_from_ensure_ok } /// Caches `CoerceUnsized` kinds for impls on custom types. @@ -1095,7 +1095,7 @@ rustc_queries! { desc { |tcx| "computing CoerceUnsized info for `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } separate_provide_extern - ensure_forwards_result_if_red + return_result_from_ensure_ok } query typeck(key: LocalDefId) -> &'tcx ty::TypeckResults<'tcx> { @@ -1110,7 +1110,7 @@ rustc_queries! { query coherent_trait(def_id: DefId) -> Result<(), ErrorGuaranteed> { desc { |tcx| "coherence checking all impls of trait `{}`", tcx.def_path_str(def_id) } - ensure_forwards_result_if_red + return_result_from_ensure_ok } /// Borrow-checks the function body. If this is a closure, returns @@ -1140,7 +1140,7 @@ rustc_queries! { /// query crate_inherent_impls_validity_check(_: ()) -> Result<(), ErrorGuaranteed> { desc { "check for inherent impls that should not be defined in crate" } - ensure_forwards_result_if_red + return_result_from_ensure_ok } /// Checks all types in the crate for overlap in their inherent impls. Reports errors. @@ -1152,7 +1152,7 @@ rustc_queries! { /// query crate_inherent_impls_overlap_check(_: ()) -> Result<(), ErrorGuaranteed> { desc { "check for overlap between inherent impls defined in this crate" } - ensure_forwards_result_if_red + return_result_from_ensure_ok } /// Checks whether all impls in the crate pass the overlap check, returning @@ -1162,7 +1162,7 @@ rustc_queries! { "checking whether impl `{}` follows the orphan rules", tcx.def_path_str(key), } - ensure_forwards_result_if_red + return_result_from_ensure_ok } /// Check whether the function has any recursion that could cause the inliner to trigger @@ -1479,7 +1479,7 @@ rustc_queries! { query specialization_graph_of(trait_id: DefId) -> Result<&'tcx specialization_graph::Graph, ErrorGuaranteed> { desc { |tcx| "building specialization graph of trait `{}`", tcx.def_path_str(trait_id) } cache_on_disk_if { true } - ensure_forwards_result_if_red + return_result_from_ensure_ok } query dyn_compatibility_violations(trait_id: DefId) -> &'tcx [DynCompatibilityViolation] { desc { |tcx| "determining dyn-compatibility of trait `{}`", tcx.def_path_str(trait_id) } @@ -1715,12 +1715,12 @@ rustc_queries! { query check_well_formed(key: LocalDefId) -> Result<(), ErrorGuaranteed> { desc { |tcx| "checking that `{}` is well-formed", tcx.def_path_str(key) } - ensure_forwards_result_if_red + return_result_from_ensure_ok } query enforce_impl_non_lifetime_params_are_constrained(key: LocalDefId) -> Result<(), ErrorGuaranteed> { desc { |tcx| "checking that `{}`'s generics are constrained by the impl header", tcx.def_path_str(key) } - ensure_forwards_result_if_red + return_result_from_ensure_ok } // The `DefId`s of all non-generic functions and statics in the given crate @@ -2442,7 +2442,7 @@ rustc_queries! { /// Any other def id will ICE. query compare_impl_item(key: LocalDefId) -> Result<(), ErrorGuaranteed> { desc { |tcx| "checking assoc item `{}` is compatible with trait definition", tcx.def_path_str(key) } - ensure_forwards_result_if_red + return_result_from_ensure_ok } query deduced_param_attrs(def_id: DefId) -> &'tcx [ty::DeducedParamAttrs] { diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 6648e3d9d53b..6c1ef046a60a 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -118,6 +118,12 @@ impl<'tcx> TyCtxt<'tcx> { /// /// Therefore, this call mode is not appropriate for callers that want to /// ensure that the query is _never_ executed in the future. + /// + /// ## `return_result_from_ensure_ok` + /// If a query has the `return_result_from_ensure_ok` modifier, calls via + /// `ensure_ok` will instead return `Result<(), ErrorGuaranteed>`. If the + /// query needs to be executed, and execution returns an error, that error + /// is returned to the caller. #[inline(always)] pub fn ensure_ok(self) -> TyCtxtEnsureOk<'tcx> { TyCtxtEnsureOk { tcx: self } @@ -223,7 +229,7 @@ macro_rules! query_ensure { ([]$($args:tt)*) => { query_ensure($($args)*) }; - ([(ensure_forwards_result_if_red) $($rest:tt)*]$($args:tt)*) => { + ([(return_result_from_ensure_ok) $($rest:tt)*]$($args:tt)*) => { query_ensure_error_guaranteed($($args)*).map(|_| ()) }; ([$other:tt $($modifiers:tt)*]$($args:tt)*) => { @@ -282,7 +288,7 @@ macro_rules! ensure_ok_result { ( [] ) => { () }; - ( [(ensure_forwards_result_if_red) $($rest:tt)*] ) => { + ( [(return_result_from_ensure_ok) $($rest:tt)*] ) => { Result<(), ErrorGuaranteed> }; ( [$other:tt $($modifiers:tt)*] ) => { From 3581512fb897053099f5ee010bdf4527b0157b9e Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 30 Jan 2025 16:59:07 +1100 Subject: [PATCH 12/35] Use an explicit type when discarding the result of `tcx.ensure_ok()` --- compiler/rustc_hir_analysis/src/lib.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 274dbb1ec1c8..3af4318544e9 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -100,7 +100,7 @@ use rustc_middle::middle; use rustc_middle::mir::interpret::GlobalId; use rustc_middle::query::Providers; use rustc_middle::ty::{self, Const, Ty, TyCtxt}; -use rustc_span::Span; +use rustc_span::{ErrorGuaranteed, Span}; use rustc_trait_selection::traits; pub use crate::collect::suggest_impl_trait; @@ -139,16 +139,20 @@ pub fn check_crate(tcx: TyCtxt<'_>) { let _prof_timer = tcx.sess.timer("type_check_crate"); tcx.sess.time("coherence_checking", || { + // When discarding query call results, use an explicit type to indicate + // what we are intending to discard, to help future type-based refactoring. + type R = Result<(), ErrorGuaranteed>; + tcx.hir().par_for_each_module(|module| { - let _ = tcx.ensure_ok().check_mod_type_wf(module); + let _: R = tcx.ensure_ok().check_mod_type_wf(module); }); for &trait_def_id in tcx.all_local_trait_impls(()).keys() { - let _ = tcx.ensure_ok().coherent_trait(trait_def_id); + let _: R = tcx.ensure_ok().coherent_trait(trait_def_id); } // these queries are executed for side-effects (error reporting): - let _ = tcx.ensure_ok().crate_inherent_impls_validity_check(()); - let _ = tcx.ensure_ok().crate_inherent_impls_overlap_check(()); + let _: R = tcx.ensure_ok().crate_inherent_impls_validity_check(()); + let _: R = tcx.ensure_ok().crate_inherent_impls_overlap_check(()); }); if tcx.features().rustc_attrs() { From 3ae0239f85e13c07810d7d6f941ed319fccefb6e Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 30 Jan 2025 17:24:19 +1100 Subject: [PATCH 13/35] Mark the tcx-ensure wrapper types with `#[must_use]` --- compiler/rustc_middle/src/query/plumbing.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 6c1ef046a60a..6c019b427dbd 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -88,11 +88,13 @@ impl<'tcx> Deref for TyCtxtAt<'tcx> { } #[derive(Copy, Clone)] +#[must_use] pub struct TyCtxtEnsureOk<'tcx> { pub tcx: TyCtxt<'tcx>, } #[derive(Copy, Clone)] +#[must_use] pub struct TyCtxtEnsureDone<'tcx> { pub tcx: TyCtxt<'tcx>, } From 06171066d2ff8d71138c42f5f7c9c7e906be1102 Mon Sep 17 00:00:00 2001 From: Marijn Schouten Date: Mon, 27 Jan 2025 15:00:21 +0100 Subject: [PATCH 14/35] Fix sentence in process::abort --- library/std/src/process.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/library/std/src/process.rs b/library/std/src/process.rs index e0dd2e14817a..fd0fd1cb755e 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -2318,14 +2318,10 @@ pub fn exit(code: i32) -> ! { /// Terminates the process in an abnormal fashion. /// /// The function will never return and will immediately terminate the current -/// process in a platform specific "abnormal" manner. -/// -/// Note that because this function never returns, and that it terminates the -/// process, no destructors on the current stack or any other thread's stack -/// will be run. -/// -/// Rust IO buffers (eg, from `BufWriter`) will not be flushed. -/// Likewise, C stdio buffers will (on most platforms) not be flushed. +/// process in a platform specific "abnormal" manner. As a consequence, +/// no destructors on the current stack or any other thread's stack +/// will be run, Rust IO buffers (eg, from `BufWriter`) will not be flushed, +/// and C stdio buffers will (on most platforms) not be flushed. /// /// This is in contrast to the default behavior of [`panic!`] which unwinds /// the current thread's stack and calls all destructors. From eea88f5dcb317bfa4e54c904e9aafb9d3b9209ed Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sat, 1 Feb 2025 12:43:39 -0500 Subject: [PATCH 15/35] Clean up MonoItem::instantiation_mode --- compiler/rustc_middle/src/mir/mono.rs | 119 +++++++++++++++++--------- 1 file changed, 78 insertions(+), 41 deletions(-) diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index e49fc376a13c..75931956310c 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -92,51 +92,88 @@ impl<'tcx> MonoItem<'tcx> { } pub fn instantiation_mode(&self, tcx: TyCtxt<'tcx>) -> InstantiationMode { - let generate_cgu_internal_copies = - (tcx.sess.opts.optimize != OptLevel::No) && !tcx.sess.link_dead_code(); + // The case handling here is written in the same style as cross_crate_inlinable, we first + // handle the cases where we must use a particular instantiation mode, then cascade down + // through a sequence of heuristics. - match *self { - MonoItem::Fn(ref instance) => { - let entry_def_id = tcx.entry_fn(()).map(|(id, _)| id); - // If this function isn't inlined or otherwise has an extern - // indicator, then we'll be creating a globally shared version. - let codegen_fn_attrs = tcx.codegen_fn_attrs(instance.def_id()); - if codegen_fn_attrs.contains_extern_indicator() - || codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) - || !instance.def.generates_cgu_internal_copy(tcx) - || Some(instance.def_id()) == entry_def_id - { - return InstantiationMode::GloballyShared { may_conflict: false }; - } + // The first thing we do is detect MonoItems which we must instantiate exactly once in the + // whole program. - if let InlineAttr::Never = tcx.codegen_fn_attrs(instance.def_id()).inline - && self.is_generic_fn() - { - // Upgrade inline(never) to a globally shared instance. - return InstantiationMode::GloballyShared { may_conflict: true }; - } - - // At this point we don't have explicit linkage and we're an - // inlined function. If this crate's build settings permit, - // we'll be creating a local copy per CGU. - if generate_cgu_internal_copies { - return InstantiationMode::LocalCopy; - } - - // Finally, if this is `#[inline(always)]` we're sure to respect - // that with an inline copy per CGU, but otherwise we'll be - // creating one copy of this `#[inline]` function which may - // conflict with upstream crates as it could be an exported - // symbol. - if tcx.codegen_fn_attrs(instance.def_id()).inline.always() { - InstantiationMode::LocalCopy - } else { - InstantiationMode::GloballyShared { may_conflict: true } - } - } + // Statics and global_asm! must be instantiated exactly once. + let instance = match *self { + MonoItem::Fn(instance) => instance, MonoItem::Static(..) | MonoItem::GlobalAsm(..) => { - InstantiationMode::GloballyShared { may_conflict: false } + return InstantiationMode::GloballyShared { may_conflict: false }; } + }; + + // Similarly, the executable entrypoint must be instantiated exactly once. + if let Some((entry_def_id, _)) = tcx.entry_fn(()) { + if instance.def_id() == entry_def_id { + return InstantiationMode::GloballyShared { may_conflict: false }; + } + } + + // If the function is #[naked] or contains any other attribute that requires exactly-once + // instantiation: + let codegen_fn_attrs = tcx.codegen_fn_attrs(instance.def_id()); + if codegen_fn_attrs.contains_extern_indicator() + || codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) + { + return InstantiationMode::GloballyShared { may_conflict: false }; + } + + // FIXME: The logic for which functions are permitted to get LocalCopy is actually spread + // across 4 functions: + // * cross_crate_inlinable(def_id) + // * InstanceKind::requires_inline + // * InstanceKind::generate_cgu_internal_copy + // * MonoItem::instantiation_mode + // Since reachable_non_generics calls InstanceKind::generates_cgu_internal_copy to decide + // which symbols this crate exports, we are obligated to only generate LocalCopy when + // generates_cgu_internal_copy returns true. + if !instance.def.generates_cgu_internal_copy(tcx) { + return InstantiationMode::GloballyShared { may_conflict: false }; + } + + // Beginning of heuristics. The handling of link-dead-code and inline(always) are QoL only, + // the compiler should not crash and linkage should work, but codegen may be undesirable. + + // -Clink-dead-code was given an unfortunate name; the point of the flag is to assist + // coverage tools which rely on having every function in the program appear in the + // generated code. If we select LocalCopy, functions which are not used because they are + // missing test coverage will disappear from such coverage reports, defeating the point. + // Note that -Cinstrument-coverage does not require such assistance from us, only coverage + // tools implemented without compiler support ironically require a special compiler flag. + if tcx.sess.link_dead_code() { + return InstantiationMode::GloballyShared { may_conflict: true }; + } + + // To ensure that #[inline(always)] can be inlined as much as possible, especially in unoptimized + // builds, we always select LocalCopy. + if codegen_fn_attrs.inline.always() { + return InstantiationMode::LocalCopy; + } + + // #[inline(never)] functions in general are poor candidates for inlining and thus since + // LocalCopy generally increases code size for the benefit of optimizations from inlining, + // we want to give them GloballyShared codegen. + // The slight problem is that generic functions need to always support cross-crate + // compilation, so all previous stages of the compiler are obligated to treat generic + // functions the same as those that unconditionally get LocalCopy codegen. It's only when + // we get here that we can at least not codegen a #[inline(never)] generic function in all + // of our CGUs. + if let InlineAttr::Never = tcx.codegen_fn_attrs(instance.def_id()).inline + && self.is_generic_fn() + { + return InstantiationMode::GloballyShared { may_conflict: true }; + } + + // The fallthrough case is to generate LocalCopy for all optimized builds, and + // GloballyShared with conflict prevention when optimizations are disabled. + match tcx.sess.opts.optimize { + OptLevel::No => InstantiationMode::GloballyShared { may_conflict: true }, + _ => InstantiationMode::LocalCopy, } } From 43b729db2f248e3cd6daa113813c5bd2ef43e84f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Sat, 1 Feb 2025 22:26:07 +0100 Subject: [PATCH 16/35] Fix two malformed error annotations in a UI test --- tests/ui/typeck/path-to-method-sugg-unresolved-expr.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ui/typeck/path-to-method-sugg-unresolved-expr.rs b/tests/ui/typeck/path-to-method-sugg-unresolved-expr.rs index 7b4f62fea0c8..e095850879cd 100644 --- a/tests/ui/typeck/path-to-method-sugg-unresolved-expr.rs +++ b/tests/ui/typeck/path-to-method-sugg-unresolved-expr.rs @@ -5,6 +5,6 @@ fn main() { let page_size = page_size::get(); //~^ ERROR failed to resolve: use of unresolved module or unlinked crate `page_size` //~| NOTE use of unresolved module or unlinked crate `page_size` - //@[cargo-invoked]~^^^ HELP if you wanted to use a crate named `page_size`, use `cargo add - //@[only-rustc]~^^^^ HELP you might be missing a crate named `page_size` + //[cargo-invoked]~^^^ HELP if you wanted to use a crate named `page_size`, use `cargo add + //[only-rustc]~^^^^ HELP you might be missing a crate named `page_size` } From 649610bf2d356499b13d83441c3e5592a8eb05cb Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Sat, 1 Feb 2025 16:26:46 -0500 Subject: [PATCH 17/35] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index cecde95c119a..0e3d73849ab8 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit cecde95c119a456c30e57d3e4b31fff5a7d83df4 +Subproject commit 0e3d73849ab8cbbab3ec5c65cbd555586cb21339 From ecb2d5c43dc0f8bed05e23b6d84396457a376d4e Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 1 Feb 2025 14:35:18 -0700 Subject: [PATCH 18/35] diagnostics: fix borrowck suggestions for if/while let conditionals This code detects the case where one of the borrows is inside the let init expr while the other end is not. If that happens, we don't want to suggest adding a semicolon, because it won't work. --- .../src/diagnostics/explain_borrow.rs | 110 +++++++++++++++--- ...ready-borrowed-as-mutable-if-let-133941.rs | 46 ++++++++ ...y-borrowed-as-mutable-if-let-133941.stderr | 89 ++++++++++++++ 3 files changed, 227 insertions(+), 18 deletions(-) create mode 100644 tests/ui/borrowck/already-borrowed-as-mutable-if-let-133941.rs create mode 100644 tests/ui/borrowck/already-borrowed-as-mutable-if-let-133941.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 2656e0bb6a45..841cb782bc3b 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -248,7 +248,98 @@ impl<'tcx> BorrowExplanation<'tcx> { ); err.span_label(body.source_info(drop_loc).span, message); - if let LocalInfo::BlockTailTemp(info) = local_decl.local_info() { + struct FindLetExpr<'hir> { + span: Span, + result: Option<(Span, &'hir hir::Pat<'hir>, &'hir hir::Expr<'hir>)>, + tcx: TyCtxt<'hir>, + } + + impl<'hir> rustc_hir::intravisit::Visitor<'hir> for FindLetExpr<'hir> { + type NestedFilter = rustc_middle::hir::nested_filter::OnlyBodies; + fn nested_visit_map(&mut self) -> Self::Map { + self.tcx.hir() + } + fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) { + if let hir::ExprKind::If(cond, _conseq, _alt) + | hir::ExprKind::Loop( + hir::Block { + expr: + Some(&hir::Expr { + kind: hir::ExprKind::If(cond, _conseq, _alt), + .. + }), + .. + }, + _, + hir::LoopSource::While, + _, + ) = expr.kind + && let hir::ExprKind::Let(hir::LetExpr { + init: let_expr_init, + span: let_expr_span, + pat: let_expr_pat, + .. + }) = cond.kind + && let_expr_init.span.contains(self.span) + { + self.result = + Some((*let_expr_span, let_expr_pat, let_expr_init)) + } else { + hir::intravisit::walk_expr(self, expr); + } + } + } + + if let &LocalInfo::IfThenRescopeTemp { if_then } = local_decl.local_info() + && let hir::Node::Expr(expr) = tcx.hir_node(if_then) + && let hir::ExprKind::If(cond, conseq, alt) = expr.kind + && let hir::ExprKind::Let(&hir::LetExpr { + span: _, + pat, + init, + // FIXME(#101728): enable rewrite when type ascription is + // stabilized again. + ty: None, + recovered: _, + }) = cond.kind + && pat.span.can_be_used_for_suggestions() + && let Ok(pat) = tcx.sess.source_map().span_to_snippet(pat.span) + { + suggest_rewrite_if_let(tcx, expr, &pat, init, conseq, alt, err); + } else if let Some((old, new)) = multiple_borrow_span + && let def_id = body.source.def_id() + && let Some(node) = tcx.hir().get_if_local(def_id) + && let Some(body_id) = node.body_id() + && let hir_body = tcx.hir().body(body_id) + && let mut expr_finder = (FindLetExpr { span: old, result: None, tcx }) + && let Some((let_expr_span, let_expr_pat, let_expr_init)) = { + expr_finder.visit_expr(hir_body.value); + expr_finder.result + } + && !let_expr_span.contains(new) + { + // #133941: The `old` expression is at the conditional part of an + // if/while let expression. Adding a semicolon won't work. + // Instead, try suggesting the `matches!` macro or a temporary. + if let_expr_pat + .walk_short(|pat| !matches!(pat.kind, hir::PatKind::Binding(..))) + { + if let Ok(pat_snippet) = + tcx.sess.source_map().span_to_snippet(let_expr_pat.span) + && let Ok(init_snippet) = + tcx.sess.source_map().span_to_snippet(let_expr_init.span) + { + err.span_suggestion_verbose( + let_expr_span, + "consider using the `matches!` macro", + format!("matches!({init_snippet}, {pat_snippet})"), + Applicability::MaybeIncorrect, + ); + } else { + err.note("consider using the `matches!` macro"); + } + } + } else if let LocalInfo::BlockTailTemp(info) = local_decl.local_info() { if info.tail_result_is_ignored { // #85581: If the first mutable borrow's scope contains // the second borrow, this suggestion isn't helpful. @@ -281,23 +372,6 @@ impl<'tcx> BorrowExplanation<'tcx> { Applicability::MaybeIncorrect, ); }; - } else if let &LocalInfo::IfThenRescopeTemp { if_then } = - local_decl.local_info() - && let hir::Node::Expr(expr) = tcx.hir_node(if_then) - && let hir::ExprKind::If(cond, conseq, alt) = expr.kind - && let hir::ExprKind::Let(&hir::LetExpr { - span: _, - pat, - init, - // FIXME(#101728): enable rewrite when type ascription is - // stabilized again. - ty: None, - recovered: _, - }) = cond.kind - && pat.span.can_be_used_for_suggestions() - && let Ok(pat) = tcx.sess.source_map().span_to_snippet(pat.span) - { - suggest_rewrite_if_let(tcx, expr, &pat, init, conseq, alt, err); } } } diff --git a/tests/ui/borrowck/already-borrowed-as-mutable-if-let-133941.rs b/tests/ui/borrowck/already-borrowed-as-mutable-if-let-133941.rs new file mode 100644 index 000000000000..934aac8383db --- /dev/null +++ b/tests/ui/borrowck/already-borrowed-as-mutable-if-let-133941.rs @@ -0,0 +1,46 @@ +// https://github.com/rust-lang/rust/issues/133941 +use std::marker::PhantomData; + +struct Bar<'a>(PhantomData<&'a mut i32>); + +impl<'a> Drop for Bar<'a> { + fn drop(&mut self) {} +} + +struct Foo(); + +impl Foo { + fn f(&mut self) -> Option> { + None + } + + fn g(&mut self) {} +} + +fn main() { + let mut foo = Foo(); + while let Some(_) = foo.f() { + //~^ HELP matches! + foo.g(); + //~^ ERROR [E0499] + } + if let Some(_) = foo.f() { + //~^ HELP matches! + foo.g(); + //~^ ERROR [E0499] + } + while let Some(_x) = foo.f() { + foo.g(); + //~^ ERROR [E0499] + } + if let Some(_x) = foo.f() { + foo.g(); + //~^ ERROR [E0499] + } + while let Some(_x) = {let _x = foo.f(); foo.g(); None::<()>} { + //~^ ERROR [E0499] + } + if let Some(_x) = {let _x = foo.f(); foo.g(); None::<()>} { + //~^ ERROR [E0499] + } +} diff --git a/tests/ui/borrowck/already-borrowed-as-mutable-if-let-133941.stderr b/tests/ui/borrowck/already-borrowed-as-mutable-if-let-133941.stderr new file mode 100644 index 000000000000..bb21caccbaf9 --- /dev/null +++ b/tests/ui/borrowck/already-borrowed-as-mutable-if-let-133941.stderr @@ -0,0 +1,89 @@ +error[E0499]: cannot borrow `foo` as mutable more than once at a time + --> $DIR/already-borrowed-as-mutable-if-let-133941.rs:24:9 + | +LL | while let Some(_) = foo.f() { + | ------- + | | + | first mutable borrow occurs here + | a temporary with access to the first borrow is created here ... +LL | +LL | foo.g(); + | ^^^ second mutable borrow occurs here +LL | +LL | } + | - ... and the first borrow might be used here, when that temporary is dropped and runs the destructor for type `Option>` + | +help: consider using the `matches!` macro + | +LL | while matches!(foo.f(), Some(_)) { + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0499]: cannot borrow `foo` as mutable more than once at a time + --> $DIR/already-borrowed-as-mutable-if-let-133941.rs:29:9 + | +LL | if let Some(_) = foo.f() { + | ------- + | | + | first mutable borrow occurs here + | a temporary with access to the first borrow is created here ... +LL | +LL | foo.g(); + | ^^^ second mutable borrow occurs here +LL | +LL | } + | - ... and the first borrow might be used here, when that temporary is dropped and runs the destructor for type `Option>` + | +help: consider using the `matches!` macro + | +LL | if matches!(foo.f(), Some(_)) { + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0499]: cannot borrow `foo` as mutable more than once at a time + --> $DIR/already-borrowed-as-mutable-if-let-133941.rs:33:9 + | +LL | while let Some(_x) = foo.f() { + | ------- + | | + | first mutable borrow occurs here + | a temporary with access to the first borrow is created here ... +LL | foo.g(); + | ^^^ second mutable borrow occurs here +LL | +LL | } + | - ... and the first borrow might be used here, when that temporary is dropped and runs the destructor for type `Option>` + +error[E0499]: cannot borrow `foo` as mutable more than once at a time + --> $DIR/already-borrowed-as-mutable-if-let-133941.rs:37:9 + | +LL | if let Some(_x) = foo.f() { + | ------- + | | + | first mutable borrow occurs here + | a temporary with access to the first borrow is created here ... +LL | foo.g(); + | ^^^ second mutable borrow occurs here +LL | +LL | } + | - ... and the first borrow might be used here, when that temporary is dropped and runs the destructor for type `Option>` + +error[E0499]: cannot borrow `foo` as mutable more than once at a time + --> $DIR/already-borrowed-as-mutable-if-let-133941.rs:40:45 + | +LL | while let Some(_x) = {let _x = foo.f(); foo.g(); None::<()>} { + | --- ^^^ - first borrow might be used here, when `_x` is dropped and runs the destructor for type `Option>` + | | | + | | second mutable borrow occurs here + | first mutable borrow occurs here + +error[E0499]: cannot borrow `foo` as mutable more than once at a time + --> $DIR/already-borrowed-as-mutable-if-let-133941.rs:43:42 + | +LL | if let Some(_x) = {let _x = foo.f(); foo.g(); None::<()>} { + | --- ^^^ - first borrow might be used here, when `_x` is dropped and runs the destructor for type `Option>` + | | | + | | second mutable borrow occurs here + | first mutable borrow occurs here + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0499`. From b89263605a0e4c584f9fee40390cf224596420f3 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 31 Jan 2025 10:45:42 +0000 Subject: [PATCH 19/35] Explain why we retroactively change a static initializer to have a different type --- compiler/rustc_codegen_llvm/src/consts.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index c7114480d8bd..ca3813af1910 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -384,8 +384,14 @@ impl<'ll> CodegenCx<'ll, '_> { let g = if val_llty == llty { g } else { - // If we created the global with the wrong type, - // correct the type. + // codegen_static_initializer creates the global value just from the + // `Allocation` data by generating one big struct value that is just + // all the bytes and pointers after each other. This will almost never + // match the type that the static was declared with. Unfortunately + // we can't just LLVMConstBitCast our way out of it because that has very + // specific rules on what can be cast. So instead of adding a new way to + // generate static initializers that match the static's type, we picked + // the easier option and retroactively change the type of the static item itself. let name = llvm::get_value_name(g).to_vec(); llvm::set_value_name(g, b""); From 028a920c5310afc918c617e50074348976332a08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 2 Feb 2025 00:45:40 +0000 Subject: [PATCH 20/35] Tweak fn pointer suggestion span Use a more targeted span when suggesting casting an `fn` item to an `fn` pointer. ``` error[E0308]: cannot coerce functions which must be inlined to function pointers --> $DIR/cast.rs:10:33 | LL | let _: fn(isize) -> usize = callee; | ------------------ ^^^^^^ cannot coerce functions which must be inlined to function pointers | | | expected due to this | = note: expected fn pointer `fn(_) -> _` found fn item `fn(_) -> _ {callee}` = note: fn items are distinct from fn pointers help: consider casting to a fn pointer | LL | let _: fn(isize) -> usize = callee as fn(isize) -> usize; | +++++++++++++++++++++ ``` ``` error[E0308]: mismatched types --> $DIR/fn-pointer-mismatch.rs:42:30 | LL | let d: &fn(u32) -> u32 = foo; | --------------- ^^^ expected `&fn(u32) -> u32`, found fn item | | | expected due to this | = note: expected reference `&fn(_) -> _` found fn item `fn(_) -> _ {foo}` help: consider using a reference | LL | let d: &fn(u32) -> u32 = &foo; | + ``` Previously we'd point at the whole expression for replacement, instead of marking what was being added. We could also modify the suggestions for `&(name as fn())`, but for that we require storing more accurate spans than we have now. --- .../src/error_reporting/infer/suggest.rs | 9 +++++---- compiler/rustc_trait_selection/src/errors.rs | 12 +++--------- tests/ui/fn/fn-pointer-mismatch.stderr | 2 +- tests/ui/force-inlining/cast.stderr | 4 ++-- 4 files changed, 11 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs index 231fecf7a4a8..562000e28aca 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs @@ -418,7 +418,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { }; let sugg = match (expected.is_ref(), found.is_ref()) { - (true, false) => FunctionPointerSuggestion::UseRef { span, fn_name }, + (true, false) => { + FunctionPointerSuggestion::UseRef { span: span.shrink_to_lo() } + } (false, true) => FunctionPointerSuggestion::RemoveRef { span, fn_name }, (true, true) => { diag.subdiagnostic(FnItemsAreDistinct); @@ -426,7 +428,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } (false, false) => { diag.subdiagnostic(FnItemsAreDistinct); - FunctionPointerSuggestion::Cast { span, fn_name, sig } + FunctionPointerSuggestion::Cast { span: span.shrink_to_hi(), sig } } }; diag.subdiagnostic(sugg); @@ -466,8 +468,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } } else { FunctionPointerSuggestion::CastBoth { - span, - fn_name, + span: span.shrink_to_hi(), found_sig: *found_sig, expected_sig: *expected_sig, } diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index c5ab8a71c780..62cac5b17bd0 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -1391,15 +1391,13 @@ pub struct OpaqueCapturesLifetime<'tcx> { pub enum FunctionPointerSuggestion<'a> { #[suggestion( trait_selection_fps_use_ref, - code = "&{fn_name}", + code = "&", style = "verbose", applicability = "maybe-incorrect" )] UseRef { #[primary_span] span: Span, - #[skip_arg] - fn_name: String, }, #[suggestion( trait_selection_fps_remove_ref, @@ -1429,7 +1427,7 @@ pub enum FunctionPointerSuggestion<'a> { }, #[suggestion( trait_selection_fps_cast, - code = "{fn_name} as {sig}", + code = " as {sig}", style = "verbose", applicability = "maybe-incorrect" )] @@ -1437,13 +1435,11 @@ pub enum FunctionPointerSuggestion<'a> { #[primary_span] span: Span, #[skip_arg] - fn_name: String, - #[skip_arg] sig: Binder<'a, FnSig<'a>>, }, #[suggestion( trait_selection_fps_cast_both, - code = "{fn_name} as {found_sig}", + code = " as {found_sig}", style = "hidden", applicability = "maybe-incorrect" )] @@ -1451,8 +1447,6 @@ pub enum FunctionPointerSuggestion<'a> { #[primary_span] span: Span, #[skip_arg] - fn_name: String, - #[skip_arg] found_sig: Binder<'a, FnSig<'a>>, expected_sig: Binder<'a, FnSig<'a>>, }, diff --git a/tests/ui/fn/fn-pointer-mismatch.stderr b/tests/ui/fn/fn-pointer-mismatch.stderr index 9cda11639d0f..2aa840911f66 100644 --- a/tests/ui/fn/fn-pointer-mismatch.stderr +++ b/tests/ui/fn/fn-pointer-mismatch.stderr @@ -67,7 +67,7 @@ LL | let d: &fn(u32) -> u32 = foo; help: consider using a reference | LL | let d: &fn(u32) -> u32 = &foo; - | ~~~~ + | + error[E0308]: mismatched types --> $DIR/fn-pointer-mismatch.rs:48:30 diff --git a/tests/ui/force-inlining/cast.stderr b/tests/ui/force-inlining/cast.stderr index 116919e5fe7f..531329596595 100644 --- a/tests/ui/force-inlining/cast.stderr +++ b/tests/ui/force-inlining/cast.stderr @@ -12,7 +12,7 @@ LL | let _: fn(isize) -> usize = callee; help: consider casting to a fn pointer | LL | let _: fn(isize) -> usize = callee as fn(isize) -> usize; - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | +++++++++++++++++++++ error[E0605]: non-primitive cast: `fn(isize) -> usize {callee}` as `fn(isize) -> usize` --> $DIR/cast.rs:15:13 @@ -32,7 +32,7 @@ LL | callee, help: consider casting to a fn pointer | LL | callee as fn(isize) -> usize, - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | +++++++++++++++++++++ error: aborting due to 3 previous errors From 9ebbba4ad92ad800d5029fdae34f53aa1e57df5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 2 Feb 2025 01:00:12 +0000 Subject: [PATCH 21/35] Shorten error message for callable with wrong return type ``` error: expected `{closure@...}` to return `Ret`, but it returns `Other` ``` instead of ``` error: expected `{closure@...}` to be a closure that returns `Ret`, but it returns `Other` ``` --- .../src/error_reporting/traits/fulfillment_errors.rs | 4 +--- .../ui/async-await/async-closures/is-not-fn.current.stderr | 2 +- tests/ui/async-await/async-closures/is-not-fn.next.stderr | 2 +- tests/ui/async-await/async-closures/is-not-fn.rs | 2 +- .../dont-ice-for-type-mismatch-in-closure-in-async.stderr | 2 +- tests/ui/async-await/issue-98634.rs | 6 +++--- tests/ui/async-await/issue-98634.stderr | 6 +++--- tests/ui/closures/return-type-doesnt-match-bound.rs | 4 ++-- tests/ui/closures/return-type-doesnt-match-bound.stderr | 4 ++-- tests/ui/higher-ranked/trait-bounds/issue-62203-hrtb-ice.rs | 2 +- .../higher-ranked/trait-bounds/issue-62203-hrtb-ice.stderr | 2 +- tests/ui/intrinsics/const-eval-select-bad.rs | 2 +- tests/ui/intrinsics/const-eval-select-bad.stderr | 2 +- tests/ui/lint/issue-106991.rs | 2 +- tests/ui/lint/issue-106991.stderr | 2 +- tests/ui/never_type/fallback-closure-wrap.fallback.stderr | 2 +- tests/ui/never_type/fallback-closure-wrap.rs | 2 +- .../suggestions/dont-suggest-boxing-async-closure-body.rs | 2 +- .../dont-suggest-boxing-async-closure-body.stderr | 2 +- tests/ui/type-alias-impl-trait/issue-98604.rs | 2 +- tests/ui/type-alias-impl-trait/issue-98604.stderr | 2 +- tests/ui/type-alias-impl-trait/issue-98608.rs | 2 +- tests/ui/type-alias-impl-trait/issue-98608.stderr | 2 +- 23 files changed, 29 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 6416c539f261..bed0bec1ee82 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -1518,7 +1518,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { with_forced_trimmed_paths! { if self.tcx.is_lang_item(projection_term.def_id, LangItem::FnOnceOutput) { - let fn_kind = self_ty.prefix_string(self.tcx); let (span, closure_span) = if let ty::Closure(def_id, _) = self_ty.kind() { let def_span = self.tcx.def_span(def_id); if let Some(local_def_id) = def_id.as_local() @@ -1555,8 +1554,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { _ => self_ty.to_string(), }; Some((format!( - "expected `{item}` to be a {fn_kind} that returns `{expected_ty}`, but it \ - returns `{normalized_ty}`", + "expected `{item}` to return `{expected_ty}`, but it returns `{normalized_ty}`", ), span, closure_span)) } else if self.tcx.is_lang_item(trait_def_id, LangItem::Future) { Some((format!( diff --git a/tests/ui/async-await/async-closures/is-not-fn.current.stderr b/tests/ui/async-await/async-closures/is-not-fn.current.stderr index e7be1d5b10ef..0fab1c15f27d 100644 --- a/tests/ui/async-await/async-closures/is-not-fn.current.stderr +++ b/tests/ui/async-await/async-closures/is-not-fn.current.stderr @@ -1,4 +1,4 @@ -error[E0271]: expected `{async closure@is-not-fn.rs:8:14}` to be a closure that returns `()`, but it returns `{async closure body@$DIR/is-not-fn.rs:8:23: 8:25}` +error[E0271]: expected `{async closure@is-not-fn.rs:8:14}` to return `()`, but it returns `{async closure body@$DIR/is-not-fn.rs:8:23: 8:25}` --> $DIR/is-not-fn.rs:8:14 | LL | needs_fn(async || {}); diff --git a/tests/ui/async-await/async-closures/is-not-fn.next.stderr b/tests/ui/async-await/async-closures/is-not-fn.next.stderr index e7be1d5b10ef..0fab1c15f27d 100644 --- a/tests/ui/async-await/async-closures/is-not-fn.next.stderr +++ b/tests/ui/async-await/async-closures/is-not-fn.next.stderr @@ -1,4 +1,4 @@ -error[E0271]: expected `{async closure@is-not-fn.rs:8:14}` to be a closure that returns `()`, but it returns `{async closure body@$DIR/is-not-fn.rs:8:23: 8:25}` +error[E0271]: expected `{async closure@is-not-fn.rs:8:14}` to return `()`, but it returns `{async closure body@$DIR/is-not-fn.rs:8:23: 8:25}` --> $DIR/is-not-fn.rs:8:14 | LL | needs_fn(async || {}); diff --git a/tests/ui/async-await/async-closures/is-not-fn.rs b/tests/ui/async-await/async-closures/is-not-fn.rs index eacd07b7cdd8..e5ab4742daba 100644 --- a/tests/ui/async-await/async-closures/is-not-fn.rs +++ b/tests/ui/async-await/async-closures/is-not-fn.rs @@ -6,5 +6,5 @@ fn main() { fn needs_fn(x: impl FnOnce()) {} needs_fn(async || {}); - //~^ ERROR expected `{async closure@is-not-fn.rs:8:14}` to be a closure that returns `()` + //~^ ERROR expected `{async closure@is-not-fn.rs:8:14}` to return `()` } diff --git a/tests/ui/async-await/dont-ice-for-type-mismatch-in-closure-in-async.stderr b/tests/ui/async-await/dont-ice-for-type-mismatch-in-closure-in-async.stderr index f478d55d10e3..ce023397db90 100644 --- a/tests/ui/async-await/dont-ice-for-type-mismatch-in-closure-in-async.stderr +++ b/tests/ui/async-await/dont-ice-for-type-mismatch-in-closure-in-async.stderr @@ -20,7 +20,7 @@ LL | true = note: expected enum `Option<()>` found type `bool` -error[E0271]: expected `{closure@dont-ice-for-type-mismatch-in-closure-in-async.rs:6:10}` to be a closure that returns `bool`, but it returns `Option<()>` +error[E0271]: expected `{closure@dont-ice-for-type-mismatch-in-closure-in-async.rs:6:10}` to return `bool`, but it returns `Option<()>` --> $DIR/dont-ice-for-type-mismatch-in-closure-in-async.rs:6:16 | LL | call(|| -> Option<()> { diff --git a/tests/ui/async-await/issue-98634.rs b/tests/ui/async-await/issue-98634.rs index 02e869f4325f..3bfc2bf8a7ca 100644 --- a/tests/ui/async-await/issue-98634.rs +++ b/tests/ui/async-await/issue-98634.rs @@ -43,8 +43,8 @@ impl Runtime { fn main() { Runtime.block_on(async { StructAsync { callback }.await; - //~^ ERROR expected `callback` to be a fn item that returns `Pin>>`, but it returns `impl Future` - //~| ERROR expected `callback` to be a fn item that returns `Pin>>`, but it returns `impl Future` - //~| ERROR expected `callback` to be a fn item that returns `Pin>>`, but it returns `impl Future` + //~^ ERROR expected `callback` to return `Pin>>`, but it returns `impl Future` + //~| ERROR expected `callback` to return `Pin>>`, but it returns `impl Future` + //~| ERROR expected `callback` to return `Pin>>`, but it returns `impl Future` }); } diff --git a/tests/ui/async-await/issue-98634.stderr b/tests/ui/async-await/issue-98634.stderr index 574904ceafad..e0739ae3a9b8 100644 --- a/tests/ui/async-await/issue-98634.stderr +++ b/tests/ui/async-await/issue-98634.stderr @@ -1,4 +1,4 @@ -error[E0271]: expected `callback` to be a fn item that returns `Pin>>`, but it returns `impl Future` +error[E0271]: expected `callback` to return `Pin>>`, but it returns `impl Future` --> $DIR/issue-98634.rs:45:23 | LL | StructAsync { callback }.await; @@ -10,7 +10,7 @@ note: required by a bound in `StructAsync` LL | pub struct StructAsync Pin>>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StructAsync` -error[E0271]: expected `callback` to be a fn item that returns `Pin>>`, but it returns `impl Future` +error[E0271]: expected `callback` to return `Pin>>`, but it returns `impl Future` --> $DIR/issue-98634.rs:45:9 | LL | StructAsync { callback }.await; @@ -22,7 +22,7 @@ note: required by a bound in `StructAsync` LL | pub struct StructAsync Pin>>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StructAsync` -error[E0271]: expected `callback` to be a fn item that returns `Pin>>`, but it returns `impl Future` +error[E0271]: expected `callback` to return `Pin>>`, but it returns `impl Future` --> $DIR/issue-98634.rs:45:34 | LL | StructAsync { callback }.await; diff --git a/tests/ui/closures/return-type-doesnt-match-bound.rs b/tests/ui/closures/return-type-doesnt-match-bound.rs index f9098d0cb5cc..af15385d4b07 100644 --- a/tests/ui/closures/return-type-doesnt-match-bound.rs +++ b/tests/ui/closures/return-type-doesnt-match-bound.rs @@ -5,7 +5,7 @@ fn foo(f: F) -> () where F: FnOnce() -> Result<(), Box>, { - f().or_else(|e| -> ! { //~ ERROR to be a closure that returns + f().or_else(|e| -> ! { //~ ERROR to return eprintln!("{:?}", e); exit(1) }); @@ -15,7 +15,7 @@ fn bar(f: F) -> () where F: FnOnce() -> Result<(), Box>, { - let c = |e| -> ! { //~ ERROR to be a closure that returns + let c = |e| -> ! { //~ ERROR to return eprintln!("{:?}", e); exit(1) }; diff --git a/tests/ui/closures/return-type-doesnt-match-bound.stderr b/tests/ui/closures/return-type-doesnt-match-bound.stderr index f796a5552ac0..c0bc2f6084c9 100644 --- a/tests/ui/closures/return-type-doesnt-match-bound.stderr +++ b/tests/ui/closures/return-type-doesnt-match-bound.stderr @@ -1,4 +1,4 @@ -error[E0271]: expected `{closure@return-type-doesnt-match-bound.rs:8:17}` to be a closure that returns `Result<(), _>`, but it returns `!` +error[E0271]: expected `{closure@return-type-doesnt-match-bound.rs:8:17}` to return `Result<(), _>`, but it returns `!` --> $DIR/return-type-doesnt-match-bound.rs:8:24 | LL | f().or_else(|e| -> ! { @@ -13,7 +13,7 @@ LL | f().or_else(|e| -> ! { note: required by a bound in `Result::::or_else` --> $SRC_DIR/core/src/result.rs:LL:COL -error[E0271]: expected `{closure@return-type-doesnt-match-bound.rs:18:13}` to be a closure that returns `Result<(), _>`, but it returns `!` +error[E0271]: expected `{closure@return-type-doesnt-match-bound.rs:18:13}` to return `Result<(), _>`, but it returns `!` --> $DIR/return-type-doesnt-match-bound.rs:18:20 | LL | let c = |e| -> ! { diff --git a/tests/ui/higher-ranked/trait-bounds/issue-62203-hrtb-ice.rs b/tests/ui/higher-ranked/trait-bounds/issue-62203-hrtb-ice.rs index f2b73d692618..c8963e078f08 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-62203-hrtb-ice.rs +++ b/tests/ui/higher-ranked/trait-bounds/issue-62203-hrtb-ice.rs @@ -39,7 +39,7 @@ fn main() { L { //~ ERROR type mismatch f: |x| { drop(x); - Unit4 //~ ERROR to be a closure that returns `Unit3`, but it returns `Unit4` + Unit4 //~ ERROR to return `Unit3`, but it returns `Unit4` }, }, ); diff --git a/tests/ui/higher-ranked/trait-bounds/issue-62203-hrtb-ice.stderr b/tests/ui/higher-ranked/trait-bounds/issue-62203-hrtb-ice.stderr index d0675d5020c8..4302570cdbde 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-62203-hrtb-ice.stderr +++ b/tests/ui/higher-ranked/trait-bounds/issue-62203-hrtb-ice.stderr @@ -29,7 +29,7 @@ LL | where LL | F: for<'r> T0<'r, (>::V,), O = >::V>, | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `T1::m` -error[E0271]: expected `{closure@issue-62203-hrtb-ice.rs:40:16}` to be a closure that returns `Unit3`, but it returns `Unit4` +error[E0271]: expected `{closure@issue-62203-hrtb-ice.rs:40:16}` to return `Unit3`, but it returns `Unit4` --> $DIR/issue-62203-hrtb-ice.rs:42:17 | LL | let v = Unit2.m( diff --git a/tests/ui/intrinsics/const-eval-select-bad.rs b/tests/ui/intrinsics/const-eval-select-bad.rs index 7e75de88d292..3365d57af7ce 100644 --- a/tests/ui/intrinsics/const-eval-select-bad.rs +++ b/tests/ui/intrinsics/const-eval-select-bad.rs @@ -30,7 +30,7 @@ fn baz(n: bool) -> i32 { const fn return_ty_mismatch() { const_eval_select((1,), foo, bar); - //~^ ERROR expected `bar` to be a fn item that returns `i32`, but it returns `bool` + //~^ ERROR expected `bar` to return `i32`, but it returns `bool` } const fn args_ty_mismatch() { diff --git a/tests/ui/intrinsics/const-eval-select-bad.stderr b/tests/ui/intrinsics/const-eval-select-bad.stderr index e317ed23ab10..bb159bed2822 100644 --- a/tests/ui/intrinsics/const-eval-select-bad.stderr +++ b/tests/ui/intrinsics/const-eval-select-bad.stderr @@ -60,7 +60,7 @@ LL | const_eval_select((), 42, 0xDEADBEEF); = note: expected a function item, found {integer} = help: consult the documentation on `const_eval_select` for more information -error[E0271]: expected `bar` to be a fn item that returns `i32`, but it returns `bool` +error[E0271]: expected `bar` to return `i32`, but it returns `bool` --> $DIR/const-eval-select-bad.rs:32:34 | LL | const_eval_select((1,), foo, bar); diff --git a/tests/ui/lint/issue-106991.rs b/tests/ui/lint/issue-106991.rs index e4d7f765b4a8..b70f751195a5 100644 --- a/tests/ui/lint/issue-106991.rs +++ b/tests/ui/lint/issue-106991.rs @@ -3,7 +3,7 @@ fn foo(items: &mut Vec) { } fn bar() -> impl Iterator { - //~^ ERROR expected `foo` to be a fn item that returns `i32`, but it returns `()` [E0271] + //~^ ERROR expected `foo` to return `i32`, but it returns `()` [E0271] let mut x: Vec> = vec![vec![0, 2, 1], vec![5, 4, 3]]; x.iter_mut().map(foo) } diff --git a/tests/ui/lint/issue-106991.stderr b/tests/ui/lint/issue-106991.stderr index 0441a6377d08..15e0ba5337f1 100644 --- a/tests/ui/lint/issue-106991.stderr +++ b/tests/ui/lint/issue-106991.stderr @@ -1,4 +1,4 @@ -error[E0271]: expected `foo` to be a fn item that returns `i32`, but it returns `()` +error[E0271]: expected `foo` to return `i32`, but it returns `()` --> $DIR/issue-106991.rs:5:13 | LL | fn bar() -> impl Iterator { diff --git a/tests/ui/never_type/fallback-closure-wrap.fallback.stderr b/tests/ui/never_type/fallback-closure-wrap.fallback.stderr index a559a95a334a..ac99a1fc24cf 100644 --- a/tests/ui/never_type/fallback-closure-wrap.fallback.stderr +++ b/tests/ui/never_type/fallback-closure-wrap.fallback.stderr @@ -1,4 +1,4 @@ -error[E0271]: expected `{closure@fallback-closure-wrap.rs:18:40}` to be a closure that returns `()`, but it returns `!` +error[E0271]: expected `{closure@fallback-closure-wrap.rs:18:40}` to return `()`, but it returns `!` --> $DIR/fallback-closure-wrap.rs:19:9 | LL | let error = Closure::wrap(Box::new(move || { diff --git a/tests/ui/never_type/fallback-closure-wrap.rs b/tests/ui/never_type/fallback-closure-wrap.rs index e97505b6bc0c..e7f7d5aae3f8 100644 --- a/tests/ui/never_type/fallback-closure-wrap.rs +++ b/tests/ui/never_type/fallback-closure-wrap.rs @@ -17,7 +17,7 @@ use std::marker::PhantomData; fn main() { let error = Closure::wrap(Box::new(move || { panic!("Can't connect to server."); - //[fallback]~^ to be a closure that returns `()`, but it returns `!` + //[fallback]~^ to return `()`, but it returns `!` }) as Box); } diff --git a/tests/ui/suggestions/dont-suggest-boxing-async-closure-body.rs b/tests/ui/suggestions/dont-suggest-boxing-async-closure-body.rs index 47a590668dde..e03c43d15ee0 100644 --- a/tests/ui/suggestions/dont-suggest-boxing-async-closure-body.rs +++ b/tests/ui/suggestions/dont-suggest-boxing-async-closure-body.rs @@ -7,6 +7,6 @@ fn bar(x: Box X>) {} fn main() { foo(async move || {}); - //~^ ERROR expected `{async closure@dont-suggest-boxing-async-closure-body.rs:9:9}` to be a closure that returns `Box<_>` + //~^ ERROR expected `{async closure@dont-suggest-boxing-async-closure-body.rs:9:9}` to return `Box<_>` bar(async move || {}); //~ ERROR mismatched types } diff --git a/tests/ui/suggestions/dont-suggest-boxing-async-closure-body.stderr b/tests/ui/suggestions/dont-suggest-boxing-async-closure-body.stderr index db2a3b9a9c15..abf8e2d824b5 100644 --- a/tests/ui/suggestions/dont-suggest-boxing-async-closure-body.stderr +++ b/tests/ui/suggestions/dont-suggest-boxing-async-closure-body.stderr @@ -1,4 +1,4 @@ -error[E0271]: expected `{async closure@dont-suggest-boxing-async-closure-body.rs:9:9}` to be a closure that returns `Box<_>`, but it returns `{async closure body@$DIR/dont-suggest-boxing-async-closure-body.rs:9:23: 9:25}` +error[E0271]: expected `{async closure@dont-suggest-boxing-async-closure-body.rs:9:9}` to return `Box<_>`, but it returns `{async closure body@$DIR/dont-suggest-boxing-async-closure-body.rs:9:23: 9:25}` --> $DIR/dont-suggest-boxing-async-closure-body.rs:9:9 | LL | foo(async move || {}); diff --git a/tests/ui/type-alias-impl-trait/issue-98604.rs b/tests/ui/type-alias-impl-trait/issue-98604.rs index 9231e82d9f43..35c25c7f7267 100644 --- a/tests/ui/type-alias-impl-trait/issue-98604.rs +++ b/tests/ui/type-alias-impl-trait/issue-98604.rs @@ -7,5 +7,5 @@ async fn test() {} #[allow(unused_must_use)] fn main() { Box::new(test) as AsyncFnPtr; - //~^ ERROR expected `test` to be a fn item that returns `Pin>>`, but it returns `impl Future + //~^ ERROR expected `test` to return `Pin>>`, but it returns `impl Future } diff --git a/tests/ui/type-alias-impl-trait/issue-98604.stderr b/tests/ui/type-alias-impl-trait/issue-98604.stderr index 2390b7253562..77c6ba3003f0 100644 --- a/tests/ui/type-alias-impl-trait/issue-98604.stderr +++ b/tests/ui/type-alias-impl-trait/issue-98604.stderr @@ -1,4 +1,4 @@ -error[E0271]: expected `test` to be a fn item that returns `Pin>>`, but it returns `impl Future` +error[E0271]: expected `test` to return `Pin>>`, but it returns `impl Future` --> $DIR/issue-98604.rs:9:5 | LL | Box::new(test) as AsyncFnPtr; diff --git a/tests/ui/type-alias-impl-trait/issue-98608.rs b/tests/ui/type-alias-impl-trait/issue-98608.rs index 5e026ea4096c..5612ccd6caed 100644 --- a/tests/ui/type-alias-impl-trait/issue-98608.rs +++ b/tests/ui/type-alias-impl-trait/issue-98608.rs @@ -4,7 +4,7 @@ fn hi() -> impl Sized { fn main() { let b: Box Box> = Box::new(hi); - //~^ ERROR expected `hi` to be a fn item that returns `Box`, but it returns `impl Sized` + //~^ ERROR expected `hi` to return `Box`, but it returns `impl Sized` let boxed = b(); let null = *boxed; println!("{null:?}"); diff --git a/tests/ui/type-alias-impl-trait/issue-98608.stderr b/tests/ui/type-alias-impl-trait/issue-98608.stderr index d5c56636f66e..872a6ed43500 100644 --- a/tests/ui/type-alias-impl-trait/issue-98608.stderr +++ b/tests/ui/type-alias-impl-trait/issue-98608.stderr @@ -1,4 +1,4 @@ -error[E0271]: expected `hi` to be a fn item that returns `Box`, but it returns `impl Sized` +error[E0271]: expected `hi` to return `Box`, but it returns `impl Sized` --> $DIR/issue-98608.rs:6:39 | LL | fn hi() -> impl Sized { From c75e601543ebefb14796041a521b7a5c2ae917de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 2 Feb 2025 01:04:21 +0000 Subject: [PATCH 22/35] Highlight clarifying information in "expected/found" error When the expected and found types have the same textual representation, we add clarifying in parentheses. We now visually highlight it in the output. Detect a corner case where the clarifying information would be the same for both types and skip it, as it doesn't add anything useful. --- compiler/rustc_errors/src/diagnostic.rs | 20 +++- .../src/error_reporting/infer/mod.rs | 46 +++++---- tests/ui/error-emitter/E0308-clarification.rs | 16 +++ .../ui/error-emitter/E0308-clarification.svg | 97 +++++++++++++++++++ .../ui/impl-trait/impl-trait-in-macro.stderr | 4 +- .../universal-two-impl-traits.stderr | 4 +- 6 files changed, 160 insertions(+), 27 deletions(-) create mode 100644 tests/ui/error-emitter/E0308-clarification.rs create mode 100644 tests/ui/error-emitter/E0308-clarification.svg diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 797dcd7b4d1d..38b8ea220847 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -641,7 +641,14 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { found_label: &dyn fmt::Display, found: DiagStyledString, ) -> &mut Self { - self.note_expected_found_extra(expected_label, expected, found_label, found, &"", &"") + self.note_expected_found_extra( + expected_label, + expected, + found_label, + found, + DiagStyledString::normal(""), + DiagStyledString::normal(""), + ) } #[rustc_lint_diagnostics] @@ -651,8 +658,8 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { expected: DiagStyledString, found_label: &dyn fmt::Display, found: DiagStyledString, - expected_extra: &dyn fmt::Display, - found_extra: &dyn fmt::Display, + expected_extra: DiagStyledString, + found_extra: DiagStyledString, ) -> &mut Self { let expected_label = expected_label.to_string(); let expected_label = if expected_label.is_empty() { @@ -677,10 +684,13 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { expected_label ))]; msg.extend(expected.0); - msg.push(StringPart::normal(format!("`{expected_extra}\n"))); + msg.push(StringPart::normal(format!("`"))); + msg.extend(expected_extra.0); + msg.push(StringPart::normal(format!("\n"))); msg.push(StringPart::normal(format!("{}{} `", " ".repeat(found_padding), found_label))); msg.extend(found.0); - msg.push(StringPart::normal(format!("`{found_extra}"))); + msg.push(StringPart::normal(format!("`"))); + msg.extend(found_extra.0); // For now, just attach these as notes. self.highlighted_note(msg); diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index db4a14356cc9..75700fbc4c26 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -1725,32 +1725,42 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } TypeError::Sorts(values) => { - let extra = expected == found; + let extra = expected == found + // Ensure that we don't ever say something like + // expected `impl Trait` (opaque type `impl Trait`) + // found `impl Trait` (opaque type `impl Trait`) + && values.expected.sort_string(self.tcx) + != values.found.sort_string(self.tcx); let sort_string = |ty: Ty<'tcx>| match (extra, ty.kind()) { (true, ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) => { let sm = self.tcx.sess.source_map(); let pos = sm.lookup_char_pos(self.tcx.def_span(*def_id).lo()); - format!( + DiagStyledString::normal(format!( " (opaque type at <{}:{}:{}>)", sm.filename_for_diagnostics(&pos.file.name), pos.line, pos.col.to_usize() + 1, - ) + )) } (true, ty::Alias(ty::Projection, proj)) if self.tcx.is_impl_trait_in_trait(proj.def_id) => { let sm = self.tcx.sess.source_map(); let pos = sm.lookup_char_pos(self.tcx.def_span(proj.def_id).lo()); - format!( + DiagStyledString::normal(format!( " (trait associated opaque type at <{}:{}:{}>)", sm.filename_for_diagnostics(&pos.file.name), pos.line, pos.col.to_usize() + 1, - ) + )) } - (true, _) => format!(" ({})", ty.sort_string(self.tcx)), - (false, _) => "".to_string(), + (true, _) => { + let mut s = DiagStyledString::normal(" ("); + s.push_highlighted(ty.sort_string(self.tcx)); + s.push_normal(")"); + s + } + (false, _) => DiagStyledString::normal(""), }; if !(values.expected.is_simple_text() && values.found.is_simple_text()) || (exp_found.is_some_and(|ef| { @@ -1767,23 +1777,23 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } })) { - if let Some(ExpectedFound { found: found_ty, .. }) = exp_found { + if let Some(ExpectedFound { found: found_ty, .. }) = exp_found + && !self.tcx.ty_is_opaque_future(found_ty) + { // `Future` is a special opaque type that the compiler // will try to hide in some case such as `async fn`, so // to make an error more use friendly we will // avoid to suggest a mismatch type with a // type that the user usually are not using // directly such as `impl Future`. - if !self.tcx.ty_is_opaque_future(found_ty) { - diag.note_expected_found_extra( - &expected_label, - expected, - &found_label, - found, - &sort_string(values.expected), - &sort_string(values.found), - ); - } + diag.note_expected_found_extra( + &expected_label, + expected, + &found_label, + found, + sort_string(values.expected), + sort_string(values.found), + ); } } } diff --git a/tests/ui/error-emitter/E0308-clarification.rs b/tests/ui/error-emitter/E0308-clarification.rs new file mode 100644 index 000000000000..4c15ede00415 --- /dev/null +++ b/tests/ui/error-emitter/E0308-clarification.rs @@ -0,0 +1,16 @@ +//@ compile-flags: -Zunstable-options --error-format=human-unicode --color=always +//@ only-linux +// Ensure that when we have a type error where both types have the same textual representation, the +// diagnostic machinery highlights the clarifying comment that comes after in parentheses. +trait Foo: Copy + ToString {} + +impl Foo for T {} + +fn hide(x: T) -> impl Foo { + x +} + +fn main() { + let mut x = (hide(0_u32), hide(0_i32)); + x = (x.1, x.0); +} diff --git a/tests/ui/error-emitter/E0308-clarification.svg b/tests/ui/error-emitter/E0308-clarification.svg new file mode 100644 index 000000000000..9432e3a4ee91 --- /dev/null +++ b/tests/ui/error-emitter/E0308-clarification.svg @@ -0,0 +1,97 @@ + + + + + + + error[E0308]: mismatched types + + ╭▸ $DIR/E0308-clarification.rs:15:10 + + + + LL fn hide<T: Foo>(x: T) -> impl Foo { + + ┬─────── + + + + the expected opaque type + + the found opaque type + + + + LL x = (x.1, x.0); + + ━━━ expected `u32`, found `i32` + + + + note: expected opaque type `impl Foo` (`u32`) + + found opaque type `impl Foo` (`i32`) + + note: distinct uses of `impl Trait` result in different opaque types + + + + error[E0308]: mismatched types + + ╭▸ $DIR/E0308-clarification.rs:15:15 + + + + LL fn hide<T: Foo>(x: T) -> impl Foo { + + ┬─────── + + + + the expected opaque type + + the found opaque type + + + + LL x = (x.1, x.0); + + ━━━ expected `i32`, found `u32` + + + + note: expected opaque type `impl Foo` (`i32`) + + found opaque type `impl Foo` (`u32`) + + note: distinct uses of `impl Trait` result in different opaque types + + + + error: aborting due to 2 previous errors + + + + For more information about this error, try `rustc --explain E0308`. + + + + + + diff --git a/tests/ui/impl-trait/impl-trait-in-macro.stderr b/tests/ui/impl-trait/impl-trait-in-macro.stderr index 4380f47c5de4..2f934694f83f 100644 --- a/tests/ui/impl-trait/impl-trait-in-macro.stderr +++ b/tests/ui/impl-trait/impl-trait-in-macro.stderr @@ -12,8 +12,8 @@ LL | let mut a = x; LL | a = y; | ^ expected type parameter `impl Debug`, found a different type parameter `impl Debug` | - = note: expected type parameter `impl Debug` (type parameter `impl Debug`) - found type parameter `impl Debug` (type parameter `impl Debug`) + = note: expected type parameter `impl Debug` + found type parameter `impl Debug` = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters diff --git a/tests/ui/impl-trait/universal-two-impl-traits.stderr b/tests/ui/impl-trait/universal-two-impl-traits.stderr index 3b4844ab1333..f2f5dd0a0c84 100644 --- a/tests/ui/impl-trait/universal-two-impl-traits.stderr +++ b/tests/ui/impl-trait/universal-two-impl-traits.stderr @@ -10,8 +10,8 @@ LL | let mut a = x; LL | a = y; | ^ expected type parameter `impl Debug`, found a different type parameter `impl Debug` | - = note: expected type parameter `impl Debug` (type parameter `impl Debug`) - found type parameter `impl Debug` (type parameter `impl Debug`) + = note: expected type parameter `impl Debug` + found type parameter `impl Debug` = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters From 06090e89d3007b4877f14267ed9cc02447332a5a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sun, 2 Feb 2025 13:54:50 +1100 Subject: [PATCH 23/35] Convert two `rustc_middle::lint` functions to `Span` methods. `rustc_middle` is a huge crate and it's always good to move stuff out of it. There are lots of similar methods already on `Span`, so these two functions, `in_external_macro` and `is_from_async_await`, fit right in. The diff is big because `in_external_macro` is used a lot by clippy lints. --- compiler/rustc_hir_typeck/src/coercion.rs | 3 +- .../src/fn_ctxt/suggestions.rs | 10 ++--- compiler/rustc_lint/src/builtin.rs | 3 +- .../src/early/diagnostics/check_cfg.rs | 4 +- compiler/rustc_lint/src/non_fmt_panic.rs | 10 ++--- compiler/rustc_middle/src/lint.rs | 40 ++----------------- compiler/rustc_span/src/lib.rs | 32 +++++++++++++++ .../book/src/development/adding_lints.md | 2 +- .../development/common_tools_writing_lints.md | 6 +-- .../book/src/development/macro_expansions.md | 6 +-- .../clippy_lints/src/almost_complete_range.rs | 5 +-- .../src/arbitrary_source_item_ordering.rs | 11 +++-- .../clippy/clippy_lints/src/as_conversions.rs | 3 +- .../src/attrs/allow_attributes.rs | 3 +- .../attrs/allow_attributes_without_reason.rs | 3 +- .../src/attrs/useless_attribute.rs | 3 +- .../clippy_lints/src/blocks_in_conditions.rs | 3 +- .../clippy/clippy_lints/src/box_default.rs | 3 +- .../clippy/clippy_lints/src/casts/mod.rs | 3 +- .../src/casts/unnecessary_cast.rs | 3 +- .../clippy_lints/src/checked_conversions.rs | 3 +- .../clippy/clippy_lints/src/dbg_macro.rs | 3 +- .../src/default_numeric_fallback.rs | 3 +- src/tools/clippy/clippy_lints/src/doc/mod.rs | 9 ++--- .../clippy_lints/src/else_if_without_else.rs | 3 +- .../clippy/clippy_lints/src/endian_bytes.rs | 3 +- .../clippy_lints/src/equatable_if_let.rs | 3 +- .../clippy_lints/src/excessive_nesting.rs | 3 +- .../src/extra_unused_type_parameters.rs | 5 +-- .../clippy/clippy_lints/src/formatting.rs | 3 +- .../clippy_lints/src/functions/must_use.rs | 5 +-- .../clippy_lints/src/functions/result.rs | 3 +- .../src/functions/too_many_lines.rs | 3 +- .../src/if_then_some_else_none.rs | 3 +- .../clippy_lints/src/implicit_return.rs | 3 +- .../src/items_after_statements.rs | 3 +- .../src/iter_without_into_iter.rs | 5 +-- .../clippy_lints/src/large_enum_variant.rs | 3 +- .../src/legacy_numeric_constants.rs | 5 +-- .../clippy/clippy_lints/src/let_underscore.rs | 3 +- .../src/let_with_type_underscore.rs | 3 +- .../clippy/clippy_lints/src/lifetimes.rs | 3 +- .../src/literal_representation.rs | 5 +-- .../clippy_lints/src/loops/infinite_loop.rs | 3 +- .../clippy_lints/src/manual_float_methods.rs | 3 +- .../clippy_lints/src/manual_let_else.rs | 3 +- .../clippy_lints/src/manual_range_patterns.rs | 3 +- .../clippy_lints/src/manual_rem_euclid.rs | 3 +- .../clippy/clippy_lints/src/matches/mod.rs | 3 +- .../clippy/clippy_lints/src/mem_replace.rs | 3 +- .../src/methods/filter_map_bool_then.rs | 3 +- .../clippy_lints/src/methods/is_empty.rs | 3 +- .../src/methods/manual_try_fold.rs | 3 +- .../clippy/clippy_lints/src/methods/mod.rs | 5 +-- .../clippy_lints/src/min_ident_chars.rs | 3 +- src/tools/clippy/clippy_lints/src/misc.rs | 7 ++-- .../clippy/clippy_lints/src/misc_early/mod.rs | 5 +-- .../misc_early/redundant_at_rest_pattern.rs | 3 +- .../clippy_lints/src/missing_const_for_fn.rs | 3 +- .../clippy/clippy_lints/src/missing_inline.rs | 4 +- .../src/multiple_unsafe_ops_per_block.rs | 3 +- src/tools/clippy/clippy_lints/src/mut_mut.rs | 5 +-- .../clippy/clippy_lints/src/needless_if.rs | 3 +- .../src/neg_cmp_op_on_partial_ord.rs | 3 +- .../clippy_lints/src/new_without_default.rs | 3 +- .../clippy/clippy_lints/src/no_effect.rs | 3 +- .../clippy_lints/src/non_canonical_impls.rs | 3 +- .../clippy_lints/src/non_expressive_names.rs | 5 +-- .../src/non_send_fields_in_send_ty.rs | 3 +- .../clippy_lints/src/non_std_lazy_statics.rs | 3 +- .../clippy/clippy_lints/src/octal_escapes.rs | 3 +- .../src/panicking_overflow_checks.rs | 3 +- .../src/pathbuf_init_then_push.rs | 5 +-- .../clippy_lints/src/pattern_type_mismatch.rs | 5 +-- .../clippy/clippy_lints/src/raw_strings.rs | 5 +-- .../clippy_lints/src/redundant_async_block.rs | 3 +- .../src/redundant_closure_call.rs | 3 +- .../clippy/clippy_lints/src/redundant_else.rs | 3 +- .../clippy_lints/src/redundant_field_names.rs | 3 +- .../clippy_lints/src/redundant_locals.rs | 3 +- .../clippy_lints/src/redundant_pub_crate.rs | 3 +- .../src/reserve_after_initialization.rs | 5 +-- .../src/return_self_not_must_use.rs | 3 +- src/tools/clippy/clippy_lints/src/returns.rs | 7 ++-- .../clippy/clippy_lints/src/single_call_fn.rs | 3 +- .../src/single_char_lifetime_names.rs | 3 +- .../clippy_lints/src/std_instead_of_core.rs | 3 +- src/tools/clippy/clippy_lints/src/strings.rs | 5 +-- .../src/suspicious_xor_used_as_pow.rs | 3 +- src/tools/clippy/clippy_lints/src/swap.rs | 3 +- .../missing_transmute_annotations.rs | 3 +- .../src/tuple_array_conversions.rs | 3 +- .../src/undocumented_unsafe_blocks.rs | 9 ++--- .../src/uninhabited_references.rs | 5 +-- .../clippy/clippy_lints/src/uninit_vec.rs | 3 +- .../src/unit_types/let_unit_value.rs | 5 +-- .../clippy_lints/src/unused_result_ok.rs | 3 +- .../clippy_lints/src/unused_trait_names.rs | 3 +- src/tools/clippy/clippy_lints/src/unwrap.rs | 3 +- .../clippy_lints/src/upper_case_acronyms.rs | 3 +- .../clippy_lints/src/vec_init_then_push.rs | 5 +-- .../clippy/clippy_lints/src/visibility.rs | 3 +- 102 files changed, 179 insertions(+), 278 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 153fd6001bbc..83acc7dd6afc 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -50,7 +50,6 @@ use rustc_infer::traits::{ IfExpressionCause, MatchExpressionArmCause, Obligation, PredicateObligation, PredicateObligations, }; -use rustc_middle::lint::in_external_macro; use rustc_middle::span_bug; use rustc_middle::traits::BuiltinImplSource; use rustc_middle::ty::adjustment::{ @@ -1937,7 +1936,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { cond_expr.span.desugaring_kind(), None | Some(DesugaringKind::WhileLoop) ) - && !in_external_macro(fcx.tcx.sess, cond_expr.span) + && !cond_expr.span.in_external_macro(fcx.tcx.sess.source_map()) && !matches!( cond_expr.kind, hir::ExprKind::Match(.., hir::MatchSource::TryDesugar(_)) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 60f9265bfcc0..8537d18c2ffa 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -14,7 +14,6 @@ use rustc_hir::{ }; use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer; use rustc_hir_analysis::suggest_impl_trait; -use rustc_middle::lint::in_external_macro; use rustc_middle::middle::stability::EvalResult; use rustc_middle::span_bug; use rustc_middle::ty::print::with_no_trimmed_paths; @@ -770,7 +769,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If the expression is from an external macro, then do not suggest // adding a semicolon, because there's nowhere to put it. // See issue #81943. - && !in_external_macro(self.tcx.sess, expression.span) => + && !expression.span.in_external_macro(self.tcx.sess.source_map()) => { if needs_block { err.multipart_suggestion( @@ -2265,7 +2264,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Ty<'tcx>, expr_ty: Ty<'tcx>, ) -> bool { - if in_external_macro(self.tcx.sess, expr.span) { + if expr.span.in_external_macro(self.tcx.sess.source_map()) { return false; } if let ty::Adt(expected_adt, args) = expected.kind() { @@ -2593,14 +2592,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { )> { let sess = self.sess(); let sp = expr.span; + let sm = sess.source_map(); // If the span is from an external macro, there's no suggestion we can make. - if in_external_macro(sess, sp) { + if sp.in_external_macro(sm) { return None; } - let sm = sess.source_map(); - let replace_prefix = |s: &str, old: &str, new: &str| { s.strip_prefix(old).map(|stripped| new.to_string() + stripped) }; diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index e8a4e9a84c46..e2bafbed6e12 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -29,7 +29,6 @@ use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; use rustc_hir::intravisit::FnKind as HirFnKind; use rustc_hir::{Body, FnDecl, GenericParamKind, PatKind, PredicateOrigin}; use rustc_middle::bug; -use rustc_middle::lint::in_external_macro; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, Upcast, VariantDef}; @@ -2029,7 +2028,7 @@ impl ExplicitOutlivesRequirements { } let span = bound.span().find_ancestor_inside(predicate_span)?; - if in_external_macro(tcx.sess, span) { + if span.in_external_macro(tcx.sess.source_map()) { return None; } diff --git a/compiler/rustc_lint/src/early/diagnostics/check_cfg.rs b/compiler/rustc_lint/src/early/diagnostics/check_cfg.rs index da6dd8161ee5..946dbc34f713 100644 --- a/compiler/rustc_lint/src/early/diagnostics/check_cfg.rs +++ b/compiler/rustc_lint/src/early/diagnostics/check_cfg.rs @@ -135,7 +135,7 @@ pub(super) fn unexpected_cfg_name( }; let is_from_cargo = rustc_session::utils::was_invoked_from_cargo(); - let is_from_external_macro = rustc_middle::lint::in_external_macro(sess, name_span); + let is_from_external_macro = name_span.in_external_macro(sess.source_map()); let mut is_feature_cfg = name == sym::feature; let code_sugg = if is_feature_cfg && is_from_cargo { @@ -281,7 +281,7 @@ pub(super) fn unexpected_cfg_value( .collect(); let is_from_cargo = rustc_session::utils::was_invoked_from_cargo(); - let is_from_external_macro = rustc_middle::lint::in_external_macro(sess, name_span); + let is_from_external_macro = name_span.in_external_macro(sess.source_map()); // Show the full list if all possible values for a given name, but don't do it // for names as the possibilities could be very long diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs index 6f047b4da495..648d06756275 100644 --- a/compiler/rustc_lint/src/non_fmt_panic.rs +++ b/compiler/rustc_lint/src/non_fmt_panic.rs @@ -2,7 +2,6 @@ use rustc_ast as ast; use rustc_errors::Applicability; use rustc_hir::{self as hir, LangItem}; use rustc_infer::infer::TyCtxtInferExt; -use rustc_middle::lint::in_external_macro; use rustc_middle::{bug, ty}; use rustc_parse_format::{ParseMode, Parser, Piece}; use rustc_session::lint::FutureIncompatibilityReason; @@ -100,7 +99,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc let (span, panic, symbol) = panic_call(cx, f); - if in_external_macro(cx.sess(), span) { + if span.in_external_macro(cx.sess().source_map()) { // Nothing that can be done about it in the current crate. return; } @@ -229,14 +228,15 @@ fn check_panic_str<'tcx>( let (span, _, _) = panic_call(cx, f); - if in_external_macro(cx.sess(), span) && in_external_macro(cx.sess(), arg.span) { + let sm = cx.sess().source_map(); + if span.in_external_macro(sm) && arg.span.in_external_macro(sm) { // Nothing that can be done about it in the current crate. return; } let fmt_span = arg.span.source_callsite(); - let (snippet, style) = match cx.sess().psess.source_map().span_to_snippet(fmt_span) { + let (snippet, style) = match sm.span_to_snippet(fmt_span) { Ok(snippet) => { // Count the number of `#`s between the `r` and `"`. let style = snippet.strip_prefix('r').and_then(|s| s.find('"')); @@ -283,7 +283,7 @@ fn check_panic_str<'tcx>( /// Given the span of `some_macro!(args);`, gives the span of `(` and `)`, /// and the type of (opening) delimiter used. fn find_delimiters(cx: &LateContext<'_>, span: Span) -> Option<(Span, Span, char)> { - let snippet = cx.sess().psess.source_map().span_to_snippet(span).ok()?; + let snippet = cx.sess().source_map().span_to_snippet(span).ok()?; let (open, open_ch) = snippet.char_indices().find(|&(_, c)| "([{".contains(c))?; let close = snippet.rfind(|c| ")]}".contains(c))?; Some(( diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index cae980cde613..ab711aca573e 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -8,8 +8,7 @@ use rustc_macros::{Decodable, Encodable, HashStable}; use rustc_session::Session; use rustc_session::lint::builtin::{self, FORBIDDEN_LINT_GROUPS}; use rustc_session::lint::{FutureIncompatibilityReason, Level, Lint, LintExpectationId, LintId}; -use rustc_span::hygiene::{ExpnKind, MacroKind}; -use rustc_span::{DUMMY_SP, DesugaringKind, Span, Symbol, kw}; +use rustc_span::{DUMMY_SP, Span, Symbol, kw}; use tracing::instrument; use crate::ty::TyCtxt; @@ -201,7 +200,7 @@ impl LintExpectation { } } -pub fn explain_lint_level_source( +fn explain_lint_level_source( lint: &'static Lint, level: Level, src: LintLevelSource, @@ -325,7 +324,7 @@ pub fn lint_level( // If this code originates in a foreign macro, aka something that this crate // did not itself author, then it's likely that there's nothing this crate // can do about it. We probably want to skip the lint entirely. - if err.span.primary_spans().iter().any(|s| in_external_macro(sess, *s)) { + if err.span.primary_spans().iter().any(|s| s.in_external_macro(sess.source_map())) { // Any suggestions made here are likely to be incorrect, so anything we // emit shouldn't be automatically fixed by rustfix. err.disable_suggestions(); @@ -422,36 +421,3 @@ pub fn lint_level( } lint_level_impl(sess, lint, level, src, span, Box::new(decorate)) } - -/// Returns whether `span` originates in a foreign crate's external macro. -/// -/// This is used to test whether a lint should not even begin to figure out whether it should -/// be reported on the current node. -pub fn in_external_macro(sess: &Session, span: Span) -> bool { - let expn_data = span.ctxt().outer_expn_data(); - match expn_data.kind { - ExpnKind::Root - | ExpnKind::Desugaring( - DesugaringKind::ForLoop - | DesugaringKind::WhileLoop - | DesugaringKind::OpaqueTy - | DesugaringKind::Async - | DesugaringKind::Await, - ) => false, - ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external" - ExpnKind::Macro(MacroKind::Bang, _) => { - // Dummy span for the `def_site` means it's an external macro. - expn_data.def_site.is_dummy() || sess.source_map().is_imported(expn_data.def_site) - } - ExpnKind::Macro { .. } => true, // definitely a plugin - } -} - -/// Return whether `span` is generated by `async` or `await`. -pub fn is_from_async_await(span: Span) -> bool { - let expn_data = span.ctxt().outer_expn_data(); - match expn_data.kind { - ExpnKind::Desugaring(DesugaringKind::Async | DesugaringKind::Await) => true, - _ => false, - } -} diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 51d809bd65d4..b1f9f4a01c54 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -600,11 +600,43 @@ impl Span { !self.is_dummy() && sm.is_span_accessible(self) } + /// Returns whether `span` originates in a foreign crate's external macro. + /// + /// This is used to test whether a lint should not even begin to figure out whether it should + /// be reported on the current node. + pub fn in_external_macro(self, sm: &SourceMap) -> bool { + let expn_data = self.ctxt().outer_expn_data(); + match expn_data.kind { + ExpnKind::Root + | ExpnKind::Desugaring( + DesugaringKind::ForLoop + | DesugaringKind::WhileLoop + | DesugaringKind::OpaqueTy + | DesugaringKind::Async + | DesugaringKind::Await, + ) => false, + ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external" + ExpnKind::Macro(MacroKind::Bang, _) => { + // Dummy span for the `def_site` means it's an external macro. + expn_data.def_site.is_dummy() || sm.is_imported(expn_data.def_site) + } + ExpnKind::Macro { .. } => true, // definitely a plugin + } + } + /// Returns `true` if `span` originates in a derive-macro's expansion. pub fn in_derive_expansion(self) -> bool { matches!(self.ctxt().outer_expn_data().kind, ExpnKind::Macro(MacroKind::Derive, _)) } + /// Return whether `span` is generated by `async` or `await`. + pub fn is_from_async_await(self) -> bool { + matches!( + self.ctxt().outer_expn_data().kind, + ExpnKind::Desugaring(DesugaringKind::Async | DesugaringKind::Await), + ) + } + /// Gate suggestions that would not be appropriate in a context the user didn't write. pub fn can_be_used_for_suggestions(self) -> bool { !self.from_expansion() diff --git a/src/tools/clippy/book/src/development/adding_lints.md b/src/tools/clippy/book/src/development/adding_lints.md index c26ad319f4f5..48506127dee4 100644 --- a/src/tools/clippy/book/src/development/adding_lints.md +++ b/src/tools/clippy/book/src/development/adding_lints.md @@ -788,7 +788,7 @@ don't hesitate to ask on [Zulip] or in the issue/PR. [`snippet`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/source/fn.snippet.html [let-chains]: https://github.com/rust-lang/rust/pull/94927 [from_expansion]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.Span.html#method.from_expansion -[in_external_macro]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/lint/fn.in_external_macro.html +[in_external_macro]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.Span.html#method.in_external_macro [span]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.Span.html [applicability]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/enum.Applicability.html [rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/ diff --git a/src/tools/clippy/book/src/development/common_tools_writing_lints.md b/src/tools/clippy/book/src/development/common_tools_writing_lints.md index b44ad80a25cc..051febc2ca5d 100644 --- a/src/tools/clippy/book/src/development/common_tools_writing_lints.md +++ b/src/tools/clippy/book/src/development/common_tools_writing_lints.md @@ -218,7 +218,7 @@ functions to deal with macros: > context. And so just using `span.from_expansion()` is often good enough. -- `in_external_macro(span)`: detect if the given span is from a macro defined in +- `span.in_external_macro(sm)`: detect if the given span is from a macro defined in a foreign crate. If you want the lint to work with macro-generated code, this is the next line of defense to avoid macros not defined in the current crate. It doesn't make sense to lint code that the coder can't change. @@ -227,15 +227,13 @@ functions to deal with macros: crates ```rust - use rustc_middle::lint::in_external_macro; - use a_crate_with_macros::foo; // `foo` is defined in `a_crate_with_macros` foo!("bar"); // if we lint the `match` of `foo` call and test its span - assert_eq!(in_external_macro(cx.sess(), match_span), true); + assert_eq!(match_span.in_external_macro(cx.sess().source_map()), true); ``` - `span.ctxt()`: the span's context represents whether it is from expansion, and diff --git a/src/tools/clippy/book/src/development/macro_expansions.md b/src/tools/clippy/book/src/development/macro_expansions.md index 125b6c4bc5be..36092f82e260 100644 --- a/src/tools/clippy/book/src/development/macro_expansions.md +++ b/src/tools/clippy/book/src/development/macro_expansions.md @@ -120,7 +120,7 @@ assert_ne!(x_is_some_span.ctxt(), x_unwrap_span.ctxt()); ### The `in_external_macro` function -`rustc_middle::lint` provides a function ([`in_external_macro`]) that can +`Span` provides a method ([`in_external_macro`]) that can detect if the given span is from a macro defined in a foreign crate. Therefore, if we really want a new lint to work with macro-generated code, @@ -144,7 +144,7 @@ Also assume that we get the corresponding variable `foo_span` for the results in `true` (note that `cx` can be `EarlyContext` or `LateContext`): ```rust -if in_external_macro(cx.sess(), foo_span) { +if foo_span.in_external_macro(cx.sess().source_map()) { // We should ignore macro from a foreign crate. return; } @@ -153,6 +153,6 @@ if in_external_macro(cx.sess(), foo_span) { [`ctxt`]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_span/struct.Span.html#method.ctxt [expansion]: https://rustc-dev-guide.rust-lang.org/macro-expansion.html#expansion-and-ast-integration [`from_expansion`]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_span/struct.Span.html#method.from_expansion -[`in_external_macro`]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_middle/lint/fn.in_external_macro.html +[`in_external_macro`]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_span/struct.Span.html#method.in_external_macro [Span]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_span/struct.Span.html [SyntaxContext]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_span/hygiene/struct.SyntaxContext.html diff --git a/src/tools/clippy/clippy_lints/src/almost_complete_range.rs b/src/tools/clippy/clippy_lints/src/almost_complete_range.rs index 2af5178920d9..0f7f779e8ea7 100644 --- a/src/tools/clippy/clippy_lints/src/almost_complete_range.rs +++ b/src/tools/clippy/clippy_lints/src/almost_complete_range.rs @@ -5,7 +5,6 @@ use clippy_utils::source::{trim_span, walk_span_to_context}; use rustc_ast::ast::{Expr, ExprKind, LitKind, Pat, PatKind, RangeEnd, RangeLimits}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; declare_clippy_lint! { @@ -45,7 +44,7 @@ impl EarlyLintPass for AlmostCompleteRange { fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &Expr) { if let ExprKind::Range(Some(start), Some(end), RangeLimits::HalfOpen) = &e.kind && is_incomplete_range(start, end) - && !in_external_macro(cx.sess(), e.span) + && !e.span.in_external_macro(cx.sess().source_map()) { span_lint_and_then( cx, @@ -74,7 +73,7 @@ impl EarlyLintPass for AlmostCompleteRange { if let PatKind::Range(Some(start), Some(end), kind) = &p.kind && matches!(kind.node, RangeEnd::Excluded) && is_incomplete_range(start, end) - && !in_external_macro(cx.sess(), p.span) + && !p.span.in_external_macro(cx.sess().source_map()) { span_lint_and_then( cx, diff --git a/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs b/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs index 0389223c3e0f..f519a65fc272 100644 --- a/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs +++ b/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs @@ -9,7 +9,6 @@ use rustc_hir::{ Variant, VariantData, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; declare_clippy_lint! { @@ -248,7 +247,7 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering { ItemKind::Enum(enum_def, _generics) if self.enable_ordering_for_enum => { let mut cur_v: Option<&Variant<'_>> = None; for variant in enum_def.variants { - if in_external_macro(cx.sess(), variant.span) { + if variant.span.in_external_macro(cx.sess().source_map()) { continue; } @@ -263,7 +262,7 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering { ItemKind::Struct(VariantData::Struct { fields, .. }, _generics) if self.enable_ordering_for_struct => { let mut cur_f: Option<&FieldDef<'_>> = None; for field in *fields { - if in_external_macro(cx.sess(), field.span) { + if field.span.in_external_macro(cx.sess().source_map()) { continue; } @@ -281,7 +280,7 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering { let mut cur_t: Option<&TraitItemRef> = None; for item in *item_ref { - if in_external_macro(cx.sess(), item.span) { + if item.span.in_external_macro(cx.sess().source_map()) { continue; } @@ -304,7 +303,7 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering { let mut cur_t: Option<&ImplItemRef> = None; for item in trait_impl.items { - if in_external_macro(cx.sess(), item.span) { + if item.span.in_external_macro(cx.sess().source_map()) { continue; } @@ -348,7 +347,7 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering { // as no sorting by source map/line of code has to be applied. // for item in items { - if in_external_macro(cx.sess(), item.span) { + if item.span.in_external_macro(cx.sess().source_map()) { continue; } diff --git a/src/tools/clippy/clippy_lints/src/as_conversions.rs b/src/tools/clippy/clippy_lints/src/as_conversions.rs index fefd8195f8e7..847653ed6e98 100644 --- a/src/tools/clippy/clippy_lints/src/as_conversions.rs +++ b/src/tools/clippy/clippy_lints/src/as_conversions.rs @@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_from_proc_macro; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::declare_lint_pass; declare_clippy_lint! { @@ -49,7 +48,7 @@ declare_lint_pass!(AsConversions => [AS_CONVERSIONS]); impl<'tcx> LateLintPass<'tcx> for AsConversions { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { if let ExprKind::Cast(_, _) = expr.kind - && !in_external_macro(cx.sess(), expr.span) + && !expr.span.in_external_macro(cx.sess().source_map()) && !is_from_proc_macro(cx, expr) { #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")] diff --git a/src/tools/clippy/clippy_lints/src/attrs/allow_attributes.rs b/src/tools/clippy/clippy_lints/src/attrs/allow_attributes.rs index 1879391ec290..53d9725703c3 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/allow_attributes.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/allow_attributes.rs @@ -4,11 +4,10 @@ use clippy_utils::is_from_proc_macro; use rustc_ast::{AttrStyle, Attribute}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, LintContext}; -use rustc_middle::lint::in_external_macro; // Separate each crate's features. pub fn check<'cx>(cx: &EarlyContext<'cx>, attr: &'cx Attribute) { - if !in_external_macro(cx.sess(), attr.span) + if !attr.span.in_external_macro(cx.sess().source_map()) && let AttrStyle::Outer = attr.style && let Some(ident) = attr.ident() && !is_from_proc_macro(cx, attr) diff --git a/src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs b/src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs index 788377fe83ce..5bf077990e1f 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs @@ -3,7 +3,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_from_proc_macro; use rustc_ast::{MetaItemInner, MetaItemKind}; use rustc_lint::{EarlyContext, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_span::sym; use rustc_span::symbol::Symbol; @@ -17,7 +16,7 @@ pub(super) fn check<'cx>(cx: &EarlyContext<'cx>, name: Symbol, items: &[MetaItem } // Check if the attribute is in an external macro and therefore out of the developer's control - if in_external_macro(cx.sess(), attr.span) || is_from_proc_macro(cx, attr) { + if attr.span.in_external_macro(cx.sess().source_map()) || is_from_proc_macro(cx, attr) { return; } diff --git a/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs b/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs index e7158a6a6b6c..e3e081ce08e9 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs @@ -5,14 +5,13 @@ use clippy_utils::source::{SpanRangeExt, first_line_of_span}; use rustc_ast::{Attribute, Item, ItemKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_span::sym; pub(super) fn check(cx: &EarlyContext<'_>, item: &Item, attrs: &[Attribute]) { let skip_unused_imports = attrs.iter().any(|attr| attr.has_name(sym::macro_use)); for attr in attrs { - if in_external_macro(cx.sess(), attr.span) { + if attr.span.in_external_macro(cx.sess().source_map()) { return; } if let Some(lint_list) = &attr.meta_item_list() { diff --git a/src/tools/clippy/clippy_lints/src/blocks_in_conditions.rs b/src/tools/clippy/clippy_lints/src/blocks_in_conditions.rs index eb05dc96cdeb..aab0af0d743b 100644 --- a/src/tools/clippy/clippy_lints/src/blocks_in_conditions.rs +++ b/src/tools/clippy/clippy_lints/src/blocks_in_conditions.rs @@ -4,7 +4,6 @@ use clippy_utils::{higher, is_from_proc_macro}; use rustc_errors::Applicability; use rustc_hir::{BlockCheckMode, Expr, ExprKind, MatchSource}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::declare_lint_pass; declare_clippy_lint! { @@ -54,7 +53,7 @@ const BRACED_EXPR_MESSAGE: &str = "omit braces around single expression conditio impl<'tcx> LateLintPass<'tcx> for BlocksInConditions { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if in_external_macro(cx.sess(), expr.span) { + if expr.span.in_external_macro(cx.sess().source_map()) { return; } diff --git a/src/tools/clippy/clippy_lints/src/box_default.rs b/src/tools/clippy/clippy_lints/src/box_default.rs index 79fd6ffe46c3..3b861848f94a 100644 --- a/src/tools/clippy/clippy_lints/src/box_default.rs +++ b/src/tools/clippy/clippy_lints/src/box_default.rs @@ -7,7 +7,6 @@ use rustc_hir::def::Res; use rustc_hir::intravisit::{InferKind, Visitor, VisitorExt, walk_ty}; use rustc_hir::{AmbigArg, Block, Expr, ExprKind, HirId, LetStmt, Node, QPath, Ty, TyKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::declare_lint_pass; use rustc_span::{Span, sym}; @@ -50,7 +49,7 @@ impl LateLintPass<'_> for BoxDefault { // This is the `T::default()` (or default equivalent) of `Box::new(T::default())` && let ExprKind::Call(arg_path, _) = arg.kind // And we are not in a foreign crate's macro - && !in_external_macro(cx.sess(), expr.span) + && !expr.span.in_external_macro(cx.sess().source_map()) // And the argument expression has the same context as the outer call expression // or that we are inside a `vec!` macro expansion && (expr.span.eq_ctxt(arg.span) || is_local_vec_expn(cx, arg, expr)) diff --git a/src/tools/clippy/clippy_lints/src/casts/mod.rs b/src/tools/clippy/clippy_lints/src/casts/mod.rs index d90cf124fe42..521bd394901a 100644 --- a/src/tools/clippy/clippy_lints/src/casts/mod.rs +++ b/src/tools/clippy/clippy_lints/src/casts/mod.rs @@ -29,7 +29,6 @@ use clippy_utils::is_hir_ty_cfg_dependant; use clippy_utils::msrvs::{self, Msrv}; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; declare_clippy_lint! { @@ -796,7 +795,7 @@ impl_lint_pass!(Casts => [ impl<'tcx> LateLintPass<'tcx> for Casts { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if in_external_macro(cx.sess(), expr.span) { + if expr.span.in_external_macro(cx.sess().source_map()) { return; } diff --git a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs index 9e1876e40f99..7885f171461d 100644 --- a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs +++ b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs @@ -8,7 +8,6 @@ use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{Expr, ExprKind, Lit, Node, Path, QPath, TyKind, UnOp}; use rustc_lint::{LateContext, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, FloatTy, InferTy, Ty}; use std::ops::ControlFlow; @@ -142,7 +141,7 @@ pub(super) fn check<'tcx>( } } - if cast_from.kind() == cast_to.kind() && !in_external_macro(cx.sess(), expr.span) { + if cast_from.kind() == cast_to.kind() && !expr.span.in_external_macro(cx.sess().source_map()) { if let Some(id) = path_to_local(cast_expr) && !cx.tcx.hir().span(id).eq_ctxt(cast_expr.span) { diff --git a/src/tools/clippy/clippy_lints/src/checked_conversions.rs b/src/tools/clippy/clippy_lints/src/checked_conversions.rs index 1edfde974227..9516af7334d7 100644 --- a/src/tools/clippy/clippy_lints/src/checked_conversions.rs +++ b/src/tools/clippy/clippy_lints/src/checked_conversions.rs @@ -6,7 +6,6 @@ use clippy_utils::{SpanlessEq, is_in_const_context, is_integer_literal}; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, QPath, TyKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; declare_clippy_lint! { @@ -64,7 +63,7 @@ impl LateLintPass<'_> for CheckedConversions { }, _ => return, } - && !in_external_macro(cx.sess(), item.span) + && !item.span.in_external_macro(cx.sess().source_map()) && !is_in_const_context(cx) && self.msrv.meets(msrvs::TRY_FROM) && let Some(cv) = match op2 { diff --git a/src/tools/clippy/clippy_lints/src/dbg_macro.rs b/src/tools/clippy/clippy_lints/src/dbg_macro.rs index a96c86f07657..06376c57119d 100644 --- a/src/tools/clippy/clippy_lints/src/dbg_macro.rs +++ b/src/tools/clippy/clippy_lints/src/dbg_macro.rs @@ -7,7 +7,6 @@ use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, Node}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; use rustc_span::{Span, SyntaxContext, sym}; @@ -60,7 +59,7 @@ impl LateLintPass<'_> for DbgMacro { if cur_syntax_ctxt != self.prev_ctxt && let Some(macro_call) = first_dbg_macro_in_expansion(cx, expr.span) && - !in_external_macro(cx.sess(), macro_call.span) && + !macro_call.span.in_external_macro(cx.sess().source_map()) && self.checked_dbg_call_site.insert(macro_call.span) && // allows `dbg!` in test code if allow-dbg-in-test is set to true in clippy.toml !(self.allow_dbg_in_tests && is_in_test(cx.tcx, expr.hir_id)) diff --git a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs index ca3eaae7b85f..772268e7899e 100644 --- a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs +++ b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs @@ -9,7 +9,6 @@ use rustc_hir::{ StructTailExpr, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, FloatTy, IntTy, PolyFnSig, Ty}; use rustc_session::declare_lint_pass; use std::iter; @@ -86,7 +85,7 @@ impl<'a, 'tcx> NumericFallbackVisitor<'a, 'tcx> { /// Check whether a passed literal has potential to cause fallback or not. fn check_lit(&self, lit: &Lit, lit_ty: Ty<'tcx>, emit_hir_id: HirId) { - if !in_external_macro(self.cx.sess(), lit.span) + if !lit.span.in_external_macro(self.cx.sess().source_map()) && matches!(self.ty_bounds.last(), Some(ExplicitTyBound(false))) && matches!( lit.node, diff --git a/src/tools/clippy/clippy_lints/src/doc/mod.rs b/src/tools/clippy/clippy_lints/src/doc/mod.rs index 15530c3dbc50..3d8ce7becdbd 100644 --- a/src/tools/clippy/clippy_lints/src/doc/mod.rs +++ b/src/tools/clippy/clippy_lints/src/doc/mod.rs @@ -22,7 +22,6 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{AnonConst, Attribute, Expr, ImplItemKind, ItemKind, Node, Safety, TraitItemKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::hir::nested_filter; -use rustc_middle::lint::in_external_macro; use rustc_middle::ty; use rustc_resolve::rustdoc::{ DocFragment, add_doc_fragment, attrs_to_doc_fragments, main_body_opts, source_span_for_markdown_range, @@ -675,7 +674,7 @@ impl<'tcx> LateLintPass<'tcx> for Documentation { match item.kind { ItemKind::Fn { sig, body: body_id, .. } => { if !(is_entrypoint_fn(cx, item.owner_id.to_def_id()) - || in_external_macro(cx.tcx.sess, item.span)) + || item.span.in_external_macro(cx.tcx.sess.source_map())) { let body = cx.tcx.hir().body(body_id); @@ -711,7 +710,7 @@ impl<'tcx> LateLintPass<'tcx> for Documentation { }, Node::TraitItem(trait_item) => { if let TraitItemKind::Fn(sig, ..) = trait_item.kind - && !in_external_macro(cx.tcx.sess, trait_item.span) + && !trait_item.span.in_external_macro(cx.tcx.sess.source_map()) { missing_headers::check( cx, @@ -726,7 +725,7 @@ impl<'tcx> LateLintPass<'tcx> for Documentation { }, Node::ImplItem(impl_item) => { if let ImplItemKind::Fn(sig, body_id) = impl_item.kind - && !in_external_macro(cx.tcx.sess, impl_item.span) + && !impl_item.span.in_external_macro(cx.tcx.sess.source_map()) && !is_trait_impl_item(cx, impl_item.hir_id()) { let body = cx.tcx.hir().body(body_id); @@ -791,7 +790,7 @@ fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet, attrs: &[ let (fragments, _) = attrs_to_doc_fragments( attrs.iter().filter_map(|attr| { - if in_external_macro(cx.sess(), attr.span) { + if attr.span.in_external_macro(cx.sess().source_map()) { None } else { Some((attr, None)) diff --git a/src/tools/clippy/clippy_lints/src/else_if_without_else.rs b/src/tools/clippy/clippy_lints/src/else_if_without_else.rs index 5315f55ba388..a38e853172f7 100644 --- a/src/tools/clippy/clippy_lints/src/else_if_without_else.rs +++ b/src/tools/clippy/clippy_lints/src/else_if_without_else.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use rustc_ast::ast::{Expr, ExprKind}; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::declare_lint_pass; declare_clippy_lint! { @@ -50,7 +49,7 @@ impl EarlyLintPass for ElseIfWithoutElse { fn check_expr(&mut self, cx: &EarlyContext<'_>, item: &Expr) { if let ExprKind::If(_, _, Some(ref els)) = item.kind && let ExprKind::If(_, _, None) = els.kind - && !in_external_macro(cx.sess(), item.span) + && !item.span.in_external_macro(cx.sess().source_map()) { #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")] span_lint_and_then( diff --git a/src/tools/clippy/clippy_lints/src/endian_bytes.rs b/src/tools/clippy/clippy_lints/src/endian_bytes.rs index 209104c5385c..29deaaf3bc7a 100644 --- a/src/tools/clippy/clippy_lints/src/endian_bytes.rs +++ b/src/tools/clippy/clippy_lints/src/endian_bytes.rs @@ -3,7 +3,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_lint_allowed; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_middle::ty::Ty; use rustc_session::declare_lint_pass; use rustc_span::Symbol; @@ -119,7 +118,7 @@ impl LateLintPass<'_> for EndianBytes { }, _ => return, }; - if !in_external_macro(cx.sess(), expr.span) + if !expr.span.in_external_macro(cx.sess().source_map()) && let ty = cx.typeck_results().expr_ty(ty_expr) && ty.is_primitive_ty() { diff --git a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs index 7ca2c9536998..cd9ab2764ac4 100644 --- a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs +++ b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs @@ -4,7 +4,6 @@ use clippy_utils::ty::implements_trait; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, Pat, PatKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_middle::ty::Ty; use rustc_session::declare_lint_pass; @@ -72,7 +71,7 @@ impl<'tcx> LateLintPass<'tcx> for PatternEquality { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { if let ExprKind::Let(let_expr) = expr.kind && unary_pattern(let_expr.pat) - && !in_external_macro(cx.sess(), expr.span) + && !expr.span.in_external_macro(cx.sess().source_map()) { let exp_ty = cx.typeck_results().expr_ty(let_expr.init); let pat_ty = cx.typeck_results().pat_ty(let_expr.pat); diff --git a/src/tools/clippy/clippy_lints/src/excessive_nesting.rs b/src/tools/clippy/clippy_lints/src/excessive_nesting.rs index dfea40db182f..36567b3ded0b 100644 --- a/src/tools/clippy/clippy_lints/src/excessive_nesting.rs +++ b/src/tools/clippy/clippy_lints/src/excessive_nesting.rs @@ -5,7 +5,6 @@ use rustc_ast::node_id::NodeSet; use rustc_ast::visit::{Visitor, walk_block, walk_item}; use rustc_ast::{Block, Crate, Inline, Item, ItemKind, ModKind, NodeId}; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; use rustc_span::Span; @@ -125,7 +124,7 @@ struct NestingVisitor<'conf, 'cx> { impl NestingVisitor<'_, '_> { fn check_indent(&mut self, span: Span, id: NodeId) -> bool { - if self.nest_level > self.conf.excessive_nesting_threshold && !in_external_macro(self.cx.sess(), span) { + if self.nest_level > self.conf.excessive_nesting_threshold && !span.in_external_macro(self.cx.sess().source_map()) { self.conf.nodes.insert(id); return true; diff --git a/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs b/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs index cdbfe7af8f9d..5d93aceb33ff 100644 --- a/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs +++ b/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs @@ -10,7 +10,6 @@ use rustc_hir::{ }; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::hir::nested_filter; -use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; use rustc_span::Span; use rustc_span::def_id::{DefId, LocalDefId}; @@ -261,7 +260,7 @@ impl<'tcx> LateLintPass<'tcx> for ExtraUnusedTypeParameters { && !generics.params.is_empty() && !is_empty_body(cx, body_id) && (!self.avoid_breaking_exported_api || !cx.effective_visibilities.is_exported(item.owner_id.def_id)) - && !in_external_macro(cx.sess(), item.span) + && !item.span.in_external_macro(cx.sess().source_map()) && !is_from_proc_macro(cx, item) { let mut walker = TypeWalker::new(cx, generics); @@ -277,7 +276,7 @@ impl<'tcx> LateLintPass<'tcx> for ExtraUnusedTypeParameters { && trait_ref_of_method(cx, item.owner_id.def_id).is_none() && !is_empty_body(cx, body_id) && (!self.avoid_breaking_exported_api || !cx.effective_visibilities.is_exported(item.owner_id.def_id)) - && !in_external_macro(cx.sess(), item.span) + && !item.span.in_external_macro(cx.sess().source_map()) && !is_from_proc_macro(cx, item) { let mut walker = TypeWalker::new(cx, item.generics); diff --git a/src/tools/clippy/clippy_lints/src/formatting.rs b/src/tools/clippy/clippy_lints/src/formatting.rs index 34e93bdb9b9b..c8fe7ac73cb3 100644 --- a/src/tools/clippy/clippy_lints/src/formatting.rs +++ b/src/tools/clippy/clippy_lints/src/formatting.rs @@ -3,7 +3,6 @@ use clippy_utils::is_span_if; use clippy_utils::source::snippet_opt; use rustc_ast::ast::{BinOpKind, Block, Expr, ExprKind, StmtKind}; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::declare_lint_pass; use rustc_span::Span; @@ -202,7 +201,7 @@ fn check_else(cx: &EarlyContext<'_>, expr: &Expr) { if let ExprKind::If(_, then, Some(else_)) = &expr.kind && (is_block(else_) || is_if(else_)) && !then.span.from_expansion() && !else_.span.from_expansion() - && !in_external_macro(cx.sess(), expr.span) + && !expr.span.in_external_macro(cx.sess().source_map()) // workaround for rust-lang/rust#43081 && expr.span.lo().0 != 0 && expr.span.hi().0 != 0 diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs index 90d3db2700fa..e480805cac2f 100644 --- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs +++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs @@ -5,7 +5,6 @@ use rustc_hir::def_id::DefIdSet; use rustc_hir::{self as hir, Attribute, QPath}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, Ty}; use rustc_span::{Span, sym}; @@ -107,7 +106,7 @@ fn check_needless_must_use( attrs: &[Attribute], sig: &FnSig<'_>, ) { - if in_external_macro(cx.sess(), item_span) { + if item_span.in_external_macro(cx.sess().source_map()) { return; } if returns_unit(decl) { @@ -185,7 +184,7 @@ fn check_must_use_candidate<'tcx>( ) { if has_mutable_arg(cx, body) || mutates_static(cx, body) - || in_external_macro(cx.sess(), item_span) + || item_span.in_external_macro(cx.sess().source_map()) || returns_unit(decl) || !cx.effective_visibilities.is_exported(item_id.def_id) || is_must_use_ty(cx, return_ty(cx, item_id)) diff --git a/src/tools/clippy/clippy_lints/src/functions/result.rs b/src/tools/clippy/clippy_lints/src/functions/result.rs index 9c396986f62a..74d365a72556 100644 --- a/src/tools/clippy/clippy_lints/src/functions/result.rs +++ b/src/tools/clippy/clippy_lints/src/functions/result.rs @@ -2,7 +2,6 @@ use clippy_utils::msrvs::{self, Msrv}; use rustc_errors::Diag; use rustc_hir as hir; use rustc_lint::{LateContext, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, Ty}; use rustc_span::{Span, sym}; @@ -20,7 +19,7 @@ fn result_err_ty<'tcx>( id: hir::def_id::LocalDefId, item_span: Span, ) -> Option<(&'tcx hir::Ty<'tcx>, Ty<'tcx>)> { - if !in_external_macro(cx.sess(), item_span) + if !item_span.in_external_macro(cx.sess().source_map()) && let hir::FnRetTy::Return(hir_ty) = decl.output && let ty = cx .tcx diff --git a/src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs b/src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs index 0f5ce340c44d..4f90d9655b44 100644 --- a/src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs +++ b/src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs @@ -3,7 +3,6 @@ use clippy_utils::source::SpanRangeExt; use rustc_hir as hir; use rustc_hir::intravisit::FnKind; use rustc_lint::{LateContext, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_span::Span; use super::TOO_MANY_LINES; @@ -17,7 +16,7 @@ pub(super) fn check_fn( ) { // Closures must be contained in a parent body, which will be checked for `too_many_lines`. // Don't check closures for `too_many_lines` to avoid duplicated lints. - if matches!(kind, FnKind::Closure) || in_external_macro(cx.sess(), span) { + if matches!(kind, FnKind::Closure) || span.in_external_macro(cx.sess().source_map()) { return; } diff --git a/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs b/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs index 3fc0a6965224..51e2944e6f99 100644 --- a/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs +++ b/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs @@ -11,7 +11,6 @@ use rustc_errors::Applicability; use rustc_hir::LangItem::{OptionNone, OptionSome}; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; declare_clippy_lint! { @@ -79,7 +78,7 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone { && is_res_lang_ctor(cx, path_res(cx, peel_blocks(els)), OptionNone) && !is_else_clause(cx.tcx, expr) && !is_in_const_context(cx) - && !in_external_macro(cx.sess(), expr.span) + && !expr.span.in_external_macro(cx.sess().source_map()) && self.msrv.meets(msrvs::BOOL_THEN) && !contains_return(then_block.stmts) { diff --git a/src/tools/clippy/clippy_lints/src/implicit_return.rs b/src/tools/clippy/clippy_lints/src/implicit_return.rs index ba06567b9572..5f95464e4d49 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_return.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_return.rs @@ -7,7 +7,6 @@ use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, FnRetTy, HirId}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::declare_lint_pass; use rustc_span::def_id::LocalDefId; use rustc_span::{Span, SyntaxContext}; @@ -227,7 +226,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitReturn { ) { if (!matches!(kind, FnKind::Closure) && matches!(decl.output, FnRetTy::DefaultReturn(_))) || !span.eq_ctxt(body.value.span) - || in_external_macro(cx.sess(), span) + || span.in_external_macro(cx.sess().source_map()) { return; } diff --git a/src/tools/clippy/clippy_lints/src/items_after_statements.rs b/src/tools/clippy/clippy_lints/src/items_after_statements.rs index 4f066113aea3..f5ad79a00279 100644 --- a/src/tools/clippy/clippy_lints/src/items_after_statements.rs +++ b/src/tools/clippy/clippy_lints/src/items_after_statements.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint_hir; use rustc_hir::{Block, ItemKind, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::declare_lint_pass; declare_clippy_lint! { @@ -70,7 +69,7 @@ impl LateLintPass<'_> for ItemsAfterStatements { // Don't use `next` due to the complex filter chain. .for_each(|item| { // Only do the macro check once, but delay it until it's needed. - if !*in_external.get_or_insert_with(|| in_external_macro(cx.sess(), block.span)) { + if !*in_external.get_or_insert_with(|| block.span.in_external_macro(cx.sess().source_map())) { span_lint_hir( cx, ITEMS_AFTER_STATEMENTS, diff --git a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs index 906da81b1837..238f66d66755 100644 --- a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs +++ b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs @@ -6,7 +6,6 @@ use rustc_ast::Mutability; use rustc_errors::Applicability; use rustc_hir::{FnRetTy, ImplItemKind, ImplicitSelfKind, ItemKind, TyKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, Ty}; use rustc_session::declare_lint_pass; use rustc_span::sym; @@ -131,7 +130,7 @@ impl LateLintPass<'_> for IterWithoutIntoIter { && trait_ref .trait_def_id() .is_some_and(|did| cx.tcx.is_diagnostic_item(sym::IntoIterator, did)) - && !in_external_macro(cx.sess(), item.span) + && !item.span.in_external_macro(cx.sess().source_map()) && let &ty::Ref(_, ty, mtbl) = cx.tcx.type_of(item.owner_id).instantiate_identity().kind() && let expected_method_name = match mtbl { Mutability::Mut => sym::iter_mut, @@ -193,7 +192,7 @@ impl {self_ty_without_ref} {{ _ => return, }; - if !in_external_macro(cx.sess(), item.span) + if !item.span.in_external_macro(cx.sess().source_map()) && let ImplItemKind::Fn(sig, _) = item.kind && let FnRetTy::Return(ret) = sig.decl.output && is_nameable_in_impl_trait(ret) diff --git a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs index 923089c72232..d9953dbc261b 100644 --- a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs +++ b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs @@ -5,7 +5,6 @@ use clippy_utils::ty::{AdtVariantInfo, approx_ty_size, is_copy}; use rustc_errors::Applicability; use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, Ty}; use rustc_session::impl_lint_pass; use rustc_span::Span; @@ -78,7 +77,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant { && let ty = cx.tcx.type_of(item.owner_id).instantiate_identity() && let ty::Adt(adt, subst) = ty.kind() && adt.variants().len() > 1 - && !in_external_macro(cx.tcx.sess, item.span) + && !item.span.in_external_macro(cx.tcx.sess.source_map()) { let variants_size = AdtVariantInfo::new(cx, *adt, subst); diff --git a/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs b/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs index fb46bdcab6e1..6f2ce04e8f8e 100644 --- a/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs +++ b/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs @@ -7,7 +7,6 @@ use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::{ExprKind, Item, ItemKind, QPath, UseKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; use rustc_span::symbol::kw; use rustc_span::{Symbol, sym}; @@ -54,7 +53,7 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants { // so lint on the `use` statement directly. if let ItemKind::Use(path, kind @ (UseKind::Single | UseKind::Glob)) = item.kind && self.msrv.meets(msrvs::NUMERIC_ASSOCIATED_CONSTANTS) - && !in_external_macro(cx.sess(), item.span) + && !item.span.in_external_macro(cx.sess().source_map()) && let Some(def_id) = path.res[0].opt_def_id() { let module = if is_integer_module(cx, def_id) { @@ -139,7 +138,7 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants { }; if self.msrv.meets(msrvs::NUMERIC_ASSOCIATED_CONSTANTS) - && !in_external_macro(cx.sess(), expr.span) + && !expr.span.in_external_macro(cx.sess().source_map()) && !is_from_proc_macro(cx, expr) { span_lint_hir_and_then(cx, LEGACY_NUMERIC_CONSTANTS, expr.hir_id, span, msg, |diag| { diff --git a/src/tools/clippy/clippy_lints/src/let_underscore.rs b/src/tools/clippy/clippy_lints/src/let_underscore.rs index b522c22a44d7..bdbf5b37c5f0 100644 --- a/src/tools/clippy/clippy_lints/src/let_underscore.rs +++ b/src/tools/clippy/clippy_lints/src/let_underscore.rs @@ -3,7 +3,6 @@ use clippy_utils::ty::{implements_trait, is_must_use_ty, match_type}; use clippy_utils::{is_from_proc_macro, is_must_use_func_call, paths}; use rustc_hir::{LetStmt, LocalSource, PatKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{GenericArgKind, IsSuggestable}; use rustc_session::declare_lint_pass; use rustc_span::{BytePos, Span}; @@ -141,7 +140,7 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore { if matches!(local.source, LocalSource::Normal) && let PatKind::Wild = local.pat.kind && let Some(init) = local.init - && !in_external_macro(cx.tcx.sess, local.span) + && !local.span.in_external_macro(cx.tcx.sess.source_map()) { let init_ty = cx.typeck_results().expr_ty(init); let contains_sync_guard = init_ty.walk().any(|inner| match inner.unpack() { diff --git a/src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs b/src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs index 34ded6c65009..9c8488ff381b 100644 --- a/src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs +++ b/src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs @@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::is_from_proc_macro; use rustc_hir::{LetStmt, TyKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::lint::in_external_macro; use rustc_session::declare_lint_pass; declare_clippy_lint! { @@ -30,7 +29,7 @@ impl<'tcx> LateLintPass<'tcx> for UnderscoreTyped { if let Some(ty) = local.ty // Ensure that it has a type defined && let TyKind::Infer(()) = &ty.kind // that type is '_' && local.span.eq_ctxt(ty.span) - && !in_external_macro(cx.tcx.sess, local.span) + && !local.span.in_external_macro(cx.tcx.sess.source_map()) && !is_from_proc_macro(cx, ty) { span_lint_and_help( diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs index c9ab0beb5dfa..860c0584accf 100644 --- a/src/tools/clippy/clippy_lints/src/lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs @@ -21,7 +21,6 @@ use rustc_hir::{ use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::hir::map::Map; use rustc_middle::hir::nested_filter as middle_nested_filter; -use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; use rustc_span::Span; use rustc_span::def_id::LocalDefId; @@ -164,7 +163,7 @@ fn check_fn_inner<'tcx>( report_extra_lifetimes: bool, msrv: &Msrv, ) { - if in_external_macro(cx.sess(), span) || has_where_lifetimes(cx, generics) { + if span.in_external_macro(cx.sess().source_map()) || has_where_lifetimes(cx, generics) { return; } diff --git a/src/tools/clippy/clippy_lints/src/literal_representation.rs b/src/tools/clippy/clippy_lints/src/literal_representation.rs index a4cedf3bed35..805de23408bf 100644 --- a/src/tools/clippy/clippy_lints/src/literal_representation.rs +++ b/src/tools/clippy/clippy_lints/src/literal_representation.rs @@ -6,7 +6,6 @@ use rustc_ast::ast::{Expr, ExprKind, LitKind}; use rustc_ast::token; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, Lint, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; use rustc_span::Span; use std::iter; @@ -207,7 +206,7 @@ impl_lint_pass!(LiteralDigitGrouping => [ impl EarlyLintPass for LiteralDigitGrouping { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { if let ExprKind::Lit(lit) = expr.kind - && !in_external_macro(cx.sess(), expr.span) + && !expr.span.in_external_macro(cx.sess().source_map()) { self.check_lit(cx, lit, expr.span); } @@ -421,7 +420,7 @@ impl_lint_pass!(DecimalLiteralRepresentation => [DECIMAL_LITERAL_REPRESENTATION] impl EarlyLintPass for DecimalLiteralRepresentation { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { if let ExprKind::Lit(lit) = expr.kind - && !in_external_macro(cx.sess(), expr.span) + && !expr.span.in_external_macro(cx.sess().source_map()) { self.check_lit(cx, lit, expr.span); } diff --git a/src/tools/clippy/clippy_lints/src/loops/infinite_loop.rs b/src/tools/clippy/clippy_lints/src/loops/infinite_loop.rs index 6be30f3c957b..4d206850c998 100644 --- a/src/tools/clippy/clippy_lints/src/loops/infinite_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/infinite_loop.rs @@ -6,7 +6,6 @@ use rustc_ast::Label; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::{LateContext, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_span::sym; use super::INFINITE_LOOP; @@ -30,7 +29,7 @@ pub(super) fn check<'tcx>( return; } - if in_external_macro(cx.sess(), expr.span) || is_from_proc_macro(cx, expr) { + if expr.span.in_external_macro(cx.sess().source_map()) || is_from_proc_macro(cx, expr) { return; } diff --git a/src/tools/clippy/clippy_lints/src/manual_float_methods.rs b/src/tools/clippy/clippy_lints/src/manual_float_methods.rs index a1951b9da44a..052e6502da92 100644 --- a/src/tools/clippy/clippy_lints/src/manual_float_methods.rs +++ b/src/tools/clippy/clippy_lints/src/manual_float_methods.rs @@ -9,7 +9,6 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::{BinOpKind, Constness, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, Lint, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_middle::ty::TyCtxt; use rustc_session::impl_lint_pass; @@ -142,7 +141,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods { // 16 possible alignments of constants/operands. For now, let's use `partition`. && let mut exprs = [lhs_lhs, lhs_rhs, rhs_lhs, rhs_rhs] && exprs.iter_mut().partition_in_place(|i| path_to_local(i).is_some()) == 2 - && !in_external_macro(cx.sess(), expr.span) + && !expr.span.in_external_macro(cx.sess().source_map()) && ( is_not_const(cx.tcx, cx.tcx.hir().enclosing_body_owner(expr.hir_id).into()) || self.msrv.meets(msrvs::CONST_FLOAT_CLASSIFY) diff --git a/src/tools/clippy/clippy_lints/src/manual_let_else.rs b/src/tools/clippy/clippy_lints/src/manual_let_else.rs index 274785061b3f..3643b8c4425e 100644 --- a/src/tools/clippy/clippy_lints/src/manual_let_else.rs +++ b/src/tools/clippy/clippy_lints/src/manual_let_else.rs @@ -9,7 +9,6 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, MatchSource, Pat, PatExpr, PatExprKind, PatKind, QPath, Stmt, StmtKind}; use rustc_lint::{LateContext, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_span::Span; use rustc_span::symbol::{Symbol, sym}; @@ -55,7 +54,7 @@ impl<'tcx> QuestionMark { && init.span.eq_ctxt(stmt.span) && let Some(if_let_or_match) = IfLetOrMatch::parse(cx, init) && self.msrv.meets(msrvs::LET_ELSE) - && !in_external_macro(cx.sess(), stmt.span) + && !stmt.span.in_external_macro(cx.sess().source_map()) { match if_let_or_match { IfLetOrMatch::IfLet(if_let_expr, let_pat, if_then, if_else, ..) => { diff --git a/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs b/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs index 2e5a92915d9c..bf4f2bff3195 100644 --- a/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs +++ b/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs @@ -5,7 +5,6 @@ use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::{PatExpr, PatExprKind, PatKind, RangeEnd}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::declare_lint_pass; use rustc_span::{DUMMY_SP, Span}; @@ -80,7 +79,7 @@ impl LateLintPass<'_> for ManualRangePatterns { // like described https://github.com/rust-lang/rust-clippy/issues/11825) if let PatKind::Or(pats) = pat.kind && (pats.len() >= 3 || (pats.len() > 1 && pats.iter().any(|p| matches!(p.kind, PatKind::Range(..))))) - && !in_external_macro(cx.sess(), pat.span) + && !pat.span.in_external_macro(cx.sess().source_map()) { let mut min = Num::dummy(i128::MAX); let mut max = Num::dummy(i128::MIN); diff --git a/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs b/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs index 8aeec89f0bfa..469b4b7cf89f 100644 --- a/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs +++ b/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs @@ -7,7 +7,6 @@ use clippy_utils::{is_in_const_context, path_to_local}; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, Node, TyKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; declare_clippy_lint! { @@ -60,7 +59,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualRemEuclid { && rem_rhs.span.ctxt() == ctxt && add_lhs.span.ctxt() == ctxt && add_rhs.span.ctxt() == ctxt - && !in_external_macro(cx.sess(), expr.span) + && !expr.span.in_external_macro(cx.sess().source_map()) && self.msrv.meets(msrvs::REM_EUCLID) && (self.msrv.meets(msrvs::REM_EUCLID_CONST) || !is_in_const_context(cx)) && let Some(const1) = check_for_unsigned_int_constant(cx, rem_rhs) diff --git a/src/tools/clippy/clippy_lints/src/matches/mod.rs b/src/tools/clippy/clippy_lints/src/matches/mod.rs index a7fdd483c16c..9ca914af281b 100644 --- a/src/tools/clippy/clippy_lints/src/matches/mod.rs +++ b/src/tools/clippy/clippy_lints/src/matches/mod.rs @@ -33,7 +33,6 @@ use clippy_utils::{ }; use rustc_hir::{Arm, Expr, ExprKind, LetStmt, MatchSource, Pat, PatKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; use rustc_span::{SpanData, SyntaxContext}; @@ -1054,7 +1053,7 @@ impl_lint_pass!(Matches => [ impl<'tcx> LateLintPass<'tcx> for Matches { #[expect(clippy::too_many_lines)] fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if is_direct_expn_of(expr.span, "matches").is_none() && in_external_macro(cx.sess(), expr.span) { + if is_direct_expn_of(expr.span, "matches").is_none() && expr.span.in_external_macro(cx.sess().source_map()) { return; } let from_expansion = expr.span.from_expansion(); diff --git a/src/tools/clippy/clippy_lints/src/mem_replace.rs b/src/tools/clippy/clippy_lints/src/mem_replace.rs index 5597cd85abc9..41528c5dee3a 100644 --- a/src/tools/clippy/clippy_lints/src/mem_replace.rs +++ b/src/tools/clippy/clippy_lints/src/mem_replace.rs @@ -11,7 +11,6 @@ use rustc_errors::Applicability; use rustc_hir::LangItem::OptionNone; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; use rustc_span::Span; use rustc_span::symbol::sym; @@ -188,7 +187,7 @@ fn check_replace_with_default(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr< if is_non_aggregate_primitive_type(expr_type) { return; } - if is_default_equivalent(cx, src) && !in_external_macro(cx.tcx.sess, expr_span) { + if is_default_equivalent(cx, src) && !expr_span.in_external_macro(cx.tcx.sess.source_map()) { let Some(top_crate) = std_or_core(cx) else { return }; span_lint_and_then( cx, diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs index 129e69254289..d550c1454668 100644 --- a/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs +++ b/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs @@ -6,13 +6,12 @@ use clippy_utils::{is_from_proc_macro, is_trait_method, peel_blocks}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_middle::ty::Binder; use rustc_middle::ty::adjustment::Adjust; use rustc_span::{Span, sym}; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, arg: &Expr<'_>, call_span: Span) { - if !in_external_macro(cx.sess(), expr.span) + if !expr.span.in_external_macro(cx.sess().source_map()) && is_trait_method(cx, expr, sym::Iterator) && let ExprKind::Closure(closure) = arg.kind && let body = cx.tcx.hir().body(closure.body) diff --git a/src/tools/clippy/clippy_lints/src/methods/is_empty.rs b/src/tools/clippy/clippy_lints/src/methods/is_empty.rs index a0c21faaa4cc..92c81b3c49d8 100644 --- a/src/tools/clippy/clippy_lints/src/methods/is_empty.rs +++ b/src/tools/clippy/clippy_lints/src/methods/is_empty.rs @@ -4,7 +4,6 @@ use clippy_utils::macros::{is_assert_macro, root_macro_call}; use clippy_utils::{find_binding_init, get_parent_expr, is_inside_always_const_context, path_to_local}; use rustc_hir::{Expr, HirId}; use rustc_lint::{LateContext, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_span::sym; use super::CONST_IS_EMPTY; @@ -12,7 +11,7 @@ use super::CONST_IS_EMPTY; /// Expression whose initialization depend on a constant conditioned by a `#[cfg(…)]` directive will /// not trigger the lint. pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, receiver: &Expr<'_>) { - if in_external_macro(cx.sess(), expr.span) || !receiver.span.eq_ctxt(expr.span) { + if expr.span.in_external_macro(cx.sess().source_map()) || !receiver.span.eq_ctxt(expr.span) { return; } if let Some(parent) = get_parent_expr(cx, expr) { diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_try_fold.rs b/src/tools/clippy/clippy_lints/src/methods/manual_try_fold.rs index 4a48d4b547cc..a56378b5b73a 100644 --- a/src/tools/clippy/clippy_lints/src/methods/manual_try_fold.rs +++ b/src/tools/clippy/clippy_lints/src/methods/manual_try_fold.rs @@ -7,7 +7,6 @@ use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_span::{Span, sym}; use super::MANUAL_TRY_FOLD; @@ -20,7 +19,7 @@ pub(super) fn check<'tcx>( fold_span: Span, msrv: &Msrv, ) { - if !in_external_macro(cx.sess(), fold_span) + if !fold_span.in_external_macro(cx.sess().source_map()) && msrv.meets(msrvs::ITERATOR_TRY_FOLD) && is_trait_method(cx, expr, sym::Iterator) && let init_ty = cx.typeck_results().expr_ty(init) diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index 42418318fda8..2f447775fa5b 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -152,7 +152,6 @@ use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::{Expr, ExprKind, Node, Stmt, StmtKind, TraitItem, TraitItemKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, TraitRef, Ty}; use rustc_session::impl_lint_pass; use rustc_span::{Span, sym}; @@ -4625,7 +4624,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { #[allow(clippy::too_many_lines)] fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::ImplItem<'_>) { - if in_external_macro(cx.sess(), impl_item.span) { + if impl_item.span.in_external_macro(cx.sess().source_map()) { return; } let name = impl_item.ident.name.as_str(); @@ -4713,7 +4712,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { } fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) { - if in_external_macro(cx.tcx.sess, item.span) { + if item.span.in_external_macro(cx.tcx.sess.source_map()) { return; } diff --git a/src/tools/clippy/clippy_lints/src/min_ident_chars.rs b/src/tools/clippy/clippy_lints/src/min_ident_chars.rs index a99e21d938c6..4119b1d1051c 100644 --- a/src/tools/clippy/clippy_lints/src/min_ident_chars.rs +++ b/src/tools/clippy/clippy_lints/src/min_ident_chars.rs @@ -6,7 +6,6 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{Visitor, walk_item, walk_trait_item}; use rustc_hir::{GenericParamKind, HirId, Item, ItemKind, ItemLocalId, Node, Pat, PatKind, TraitItem, UsePath}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; use rustc_span::Span; use std::borrow::Cow; @@ -55,7 +54,7 @@ impl MinIdentChars { #[expect(clippy::cast_possible_truncation)] fn is_ident_too_short(&self, cx: &LateContext<'_>, str: &str, span: Span) -> bool { - !in_external_macro(cx.sess(), span) + !span.in_external_macro(cx.sess().source_map()) && str.len() <= self.min_ident_chars_threshold as usize && !str.starts_with('_') && !str.is_empty() diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs index b511b1e46b38..fa0eb9a94b73 100644 --- a/src/tools/clippy/clippy_lints/src/misc.rs +++ b/src/tools/clippy/clippy_lints/src/misc.rs @@ -13,7 +13,6 @@ use rustc_hir::{ BinOpKind, BindingMode, Body, ByRef, Expr, ExprKind, FnDecl, Mutability, PatKind, QPath, Stmt, StmtKind, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::declare_lint_pass; use rustc_span::Span; use rustc_span::def_id::LocalDefId; @@ -162,7 +161,7 @@ impl<'tcx> LateLintPass<'tcx> for LintPass { for arg in iter_input_pats(decl, body) { if let PatKind::Binding(BindingMode(ByRef::Yes(_), _), ..) = arg.pat.kind && is_lint_allowed(cx, REF_PATTERNS, arg.pat.hir_id) - && !in_external_macro(cx.tcx.sess, arg.span) + && !arg.span.in_external_macro(cx.tcx.sess.source_map()) { span_lint_hir( cx, @@ -183,7 +182,7 @@ impl<'tcx> LateLintPass<'tcx> for LintPass { && let Some(init) = local.init // Do not emit if clippy::ref_patterns is not allowed to avoid having two lints for the same issue. && is_lint_allowed(cx, REF_PATTERNS, local.pat.hir_id) - && !in_external_macro(cx.tcx.sess, stmt.span) + && !stmt.span.in_external_macro(cx.tcx.sess.source_map()) { let ctxt = local.span.ctxt(); let mut app = Applicability::MachineApplicable; @@ -239,7 +238,7 @@ impl<'tcx> LateLintPass<'tcx> for LintPass { } fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if in_external_macro(cx.sess(), expr.span) + if expr.span.in_external_macro(cx.sess().source_map()) || expr.span.desugaring_kind().is_some() || in_automatically_derived(cx.tcx, expr.hir_id) { diff --git a/src/tools/clippy/clippy_lints/src/misc_early/mod.rs b/src/tools/clippy/clippy_lints/src/misc_early/mod.rs index 637d6ed3ad2c..f880f1f329ff 100644 --- a/src/tools/clippy/clippy_lints/src/misc_early/mod.rs +++ b/src/tools/clippy/clippy_lints/src/misc_early/mod.rs @@ -14,7 +14,6 @@ use rustc_ast::token; use rustc_ast::visit::FnKind; use rustc_data_structures::fx::FxHashMap; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::declare_lint_pass; use rustc_span::Span; @@ -350,7 +349,7 @@ impl EarlyLintPass for MiscEarlyLints { } fn check_pat(&mut self, cx: &EarlyContext<'_>, pat: &Pat) { - if in_external_macro(cx.sess(), pat.span) { + if pat.span.in_external_macro(cx.sess().source_map()) { return; } @@ -387,7 +386,7 @@ impl EarlyLintPass for MiscEarlyLints { } fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { - if in_external_macro(cx.sess(), expr.span) { + if expr.span.in_external_macro(cx.sess().source_map()) { return; } diff --git a/src/tools/clippy/clippy_lints/src/misc_early/redundant_at_rest_pattern.rs b/src/tools/clippy/clippy_lints/src/misc_early/redundant_at_rest_pattern.rs index 0c81ee5eced8..f2cf93465c0d 100644 --- a/src/tools/clippy/clippy_lints/src/misc_early/redundant_at_rest_pattern.rs +++ b/src/tools/clippy/clippy_lints/src/misc_early/redundant_at_rest_pattern.rs @@ -2,12 +2,11 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use rustc_ast::{Pat, PatKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, LintContext}; -use rustc_middle::lint::in_external_macro; use super::REDUNDANT_AT_REST_PATTERN; pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) { - if !in_external_macro(cx.sess(), pat.span) + if !pat.span.in_external_macro(cx.sess().source_map()) && let PatKind::Slice(slice) = &pat.kind && let [one] = &**slice && let PatKind::Ident(annotation, ident, Some(rest)) = &one.kind diff --git a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs index 2572e186ce6c..962d85c6a9d3 100644 --- a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs +++ b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs @@ -8,7 +8,6 @@ use rustc_hir::def_id::CRATE_DEF_ID; use rustc_hir::intravisit::FnKind; use rustc_hir::{self as hir, Body, Constness, FnDecl, GenericParamKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::lint::in_external_macro; use rustc_middle::ty; use rustc_session::impl_lint_pass; use rustc_span::Span; @@ -106,7 +105,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn { return; } - if in_external_macro(cx.tcx.sess, span) || is_entrypoint_fn(cx, def_id.to_def_id()) { + if span.in_external_macro(cx.tcx.sess.source_map()) || is_entrypoint_fn(cx, def_id.to_def_id()) { return; } diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs index bba1b63be277..18385ac92692 100644 --- a/src/tools/clippy/clippy_lints/src/missing_inline.rs +++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs @@ -88,7 +88,7 @@ declare_lint_pass!(MissingInline => [MISSING_INLINE_IN_PUBLIC_ITEMS]); impl<'tcx> LateLintPass<'tcx> for MissingInline { fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::Item<'_>) { - if rustc_middle::lint::in_external_macro(cx.sess(), it.span) || is_executable_or_proc_macro(cx) { + if it.span.in_external_macro(cx.sess().source_map()) || is_executable_or_proc_macro(cx) { return; } @@ -139,7 +139,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { } fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::ImplItem<'_>) { - if rustc_middle::lint::in_external_macro(cx.sess(), impl_item.span) || is_executable_or_proc_macro(cx) { + if impl_item.span.in_external_macro(cx.sess().source_map()) || is_executable_or_proc_macro(cx) { return; } diff --git a/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs index aad6ae52a6db..302db2c914ca 100644 --- a/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs +++ b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs @@ -6,7 +6,6 @@ use hir::{BlockCheckMode, ExprKind, QPath, UnOp}; use rustc_ast::Mutability; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::lint::in_external_macro; use rustc_middle::ty; use rustc_session::declare_lint_pass; use rustc_span::{DesugaringKind, Span}; @@ -65,7 +64,7 @@ declare_lint_pass!(MultipleUnsafeOpsPerBlock => [MULTIPLE_UNSAFE_OPS_PER_BLOCK]) impl<'tcx> LateLintPass<'tcx> for MultipleUnsafeOpsPerBlock { fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) { if !matches!(block.rules, BlockCheckMode::UnsafeBlock(_)) - || in_external_macro(cx.tcx.sess, block.span) + || block.span.in_external_macro(cx.tcx.sess.source_map()) || block.span.is_desugaring(DesugaringKind::Await) { return; diff --git a/src/tools/clippy/clippy_lints/src/mut_mut.rs b/src/tools/clippy/clippy_lints/src/mut_mut.rs index 0ee851a4cf94..3c4ba5141dd9 100644 --- a/src/tools/clippy/clippy_lints/src/mut_mut.rs +++ b/src/tools/clippy/clippy_lints/src/mut_mut.rs @@ -2,7 +2,6 @@ use clippy_utils::diagnostics::{span_lint, span_lint_hir}; use clippy_utils::higher; use rustc_hir::{self as hir, AmbigArg, intravisit}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_middle::ty; use rustc_session::declare_lint_pass; @@ -38,7 +37,7 @@ impl<'tcx> LateLintPass<'tcx> for MutMut { && mty.mutbl == hir::Mutability::Mut && let hir::TyKind::Ref(_, mty) = mty.ty.kind && mty.mutbl == hir::Mutability::Mut - && !in_external_macro(cx.sess(), ty.span) + && !ty.span.in_external_macro(cx.sess().source_map()) { span_lint( cx, @@ -56,7 +55,7 @@ pub struct MutVisitor<'a, 'tcx> { impl<'tcx> intravisit::Visitor<'tcx> for MutVisitor<'_, 'tcx> { fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) { - if in_external_macro(self.cx.sess(), expr.span) { + if expr.span.in_external_macro(self.cx.sess().source_map()) { return; } diff --git a/src/tools/clippy/clippy_lints/src/needless_if.rs b/src/tools/clippy/clippy_lints/src/needless_if.rs index 8e14fbf2f806..7eefb016aca9 100644 --- a/src/tools/clippy/clippy_lints/src/needless_if.rs +++ b/src/tools/clippy/clippy_lints/src/needless_if.rs @@ -5,7 +5,6 @@ use clippy_utils::source::SpanRangeExt; use rustc_errors::Applicability; use rustc_hir::{ExprKind, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::declare_lint_pass; declare_clippy_lint! { @@ -47,7 +46,7 @@ impl LateLintPass<'_> for NeedlessIf { && let ExprKind::Block(block, ..) = then.kind && block.stmts.is_empty() && block.expr.is_none() - && !in_external_macro(cx.sess(), expr.span) + && !expr.span.in_external_macro(cx.sess().source_map()) && then.span.check_source_text(cx, |src| { // Ignore // - empty macro expansions diff --git a/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs index fa90ee606121..4f62ba2e58db 100644 --- a/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs +++ b/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs @@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint; use clippy_utils::ty::implements_trait; use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::declare_lint_pass; use rustc_span::sym; @@ -48,7 +47,7 @@ impl<'tcx> LateLintPass<'tcx> for NoNegCompOpForPartialOrd { if let ExprKind::Unary(UnOp::Not, inner) = expr.kind && let ExprKind::Binary(ref op, left, _) = inner.kind && let BinOpKind::Le | BinOpKind::Ge | BinOpKind::Lt | BinOpKind::Gt = op.node - && !in_external_macro(cx.sess(), expr.span) + && !expr.span.in_external_macro(cx.sess().source_map()) { let ty = cx.typeck_results().expr_ty(left); diff --git a/src/tools/clippy/clippy_lints/src/new_without_default.rs b/src/tools/clippy/clippy_lints/src/new_without_default.rs index 688374b5676c..cc56df3a23d7 100644 --- a/src/tools/clippy/clippy_lints/src/new_without_default.rs +++ b/src/tools/clippy/clippy_lints/src/new_without_default.rs @@ -6,7 +6,6 @@ use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::HirIdSet; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; use rustc_span::sym; @@ -69,7 +68,7 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault { for assoc_item in *items { if assoc_item.kind == (hir::AssocItemKind::Fn { has_self: false }) { let impl_item = cx.tcx.hir().impl_item(assoc_item.id); - if in_external_macro(cx.sess(), impl_item.span) { + if impl_item.span.in_external_macro(cx.sess().source_map()) { return; } if let hir::ImplItemKind::Fn(ref sig, _) = impl_item.kind { diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs index ccd507580445..4d3e6aa79d0a 100644 --- a/src/tools/clippy/clippy_lints/src/no_effect.rs +++ b/src/tools/clippy/clippy_lints/src/no_effect.rs @@ -12,7 +12,6 @@ use rustc_hir::{ }; use rustc_infer::infer::TyCtxtInferExt as _; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; use rustc_span::Span; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; @@ -268,7 +267,7 @@ fn has_no_effect(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { fn check_unnecessary_operation(cx: &LateContext<'_>, stmt: &Stmt<'_>) { if let StmtKind::Semi(expr) = stmt.kind - && !in_external_macro(cx.sess(), stmt.span) + && !stmt.span.in_external_macro(cx.sess().source_map()) && let ctxt = stmt.span.ctxt() && expr.span.ctxt() == ctxt && let Some(reduced) = reduce_expression(cx, expr) diff --git a/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs b/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs index 94855c465677..dad1e8a3d6a1 100644 --- a/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs +++ b/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs @@ -5,7 +5,6 @@ use rustc_errors::Applicability; use rustc_hir::def_id::LocalDefId; use rustc_hir::{Expr, ExprKind, ImplItem, ImplItemKind, LangItem, Node, UnOp}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_middle::ty::EarlyBinder; use rustc_session::declare_lint_pass; use rustc_span::sym; @@ -129,7 +128,7 @@ impl LateLintPass<'_> for NonCanonicalImpls { let ExprKind::Block(block, ..) = body.value.kind else { return; }; - if in_external_macro(cx.sess(), block.span) || is_from_proc_macro(cx, impl_item) { + if block.span.in_external_macro(cx.sess().source_map()) || is_from_proc_macro(cx, impl_item) { return; } diff --git a/src/tools/clippy/clippy_lints/src/non_expressive_names.rs b/src/tools/clippy/clippy_lints/src/non_expressive_names.rs index 56c4157d6fe0..1a3b43cbb10a 100644 --- a/src/tools/clippy/clippy_lints/src/non_expressive_names.rs +++ b/src/tools/clippy/clippy_lints/src/non_expressive_names.rs @@ -5,7 +5,6 @@ use rustc_ast::ast::{ }; use rustc_ast::visit::{Visitor, walk_block, walk_expr, walk_pat}; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; use rustc_span::symbol::{Ident, Symbol}; use rustc_span::{Span, sym}; @@ -381,7 +380,7 @@ impl<'tcx> Visitor<'tcx> for SimilarNamesLocalVisitor<'_, 'tcx> { impl EarlyLintPass for NonExpressiveNames { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - if in_external_macro(cx.sess(), item.span) { + if item.span.in_external_macro(cx.sess().source_map()) { return; } @@ -396,7 +395,7 @@ impl EarlyLintPass for NonExpressiveNames { } fn check_impl_item(&mut self, cx: &EarlyContext<'_>, item: &AssocItem) { - if in_external_macro(cx.sess(), item.span) { + if item.span.in_external_macro(cx.sess().source_map()) { return; } diff --git a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs index 793eb5d94560..9542fed38759 100644 --- a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs +++ b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs @@ -7,7 +7,6 @@ use rustc_ast::ImplPolarity; use rustc_hir::def_id::DefId; use rustc_hir::{FieldDef, Item, ItemKind, Node}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, GenericArgKind, Ty}; use rustc_session::impl_lint_pass; use rustc_span::sym; @@ -81,7 +80,7 @@ impl<'tcx> LateLintPass<'tcx> for NonSendFieldInSendTy { // We start from `Send` impl instead of `check_field_def()` because // single `AdtDef` may have multiple `Send` impls due to generic // parameters, and the lint is much easier to implement in this way. - if !in_external_macro(cx.tcx.sess, item.span) + if !item.span.in_external_macro(cx.tcx.sess.source_map()) && let Some(send_trait) = cx.tcx.get_diagnostic_item(sym::Send) && let ItemKind::Impl(hir_impl) = &item.kind && let Some(trait_ref) = &hir_impl.of_trait diff --git a/src/tools/clippy/clippy_lints/src/non_std_lazy_statics.rs b/src/tools/clippy/clippy_lints/src/non_std_lazy_statics.rs index 312610db0423..22116505a1c1 100644 --- a/src/tools/clippy/clippy_lints/src/non_std_lazy_statics.rs +++ b/src/tools/clippy/clippy_lints/src/non_std_lazy_statics.rs @@ -9,7 +9,6 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::{self as hir, BodyId, Expr, ExprKind, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; use rustc_span::Span; @@ -139,7 +138,7 @@ impl<'hir> LateLintPass<'hir> for NonStdLazyStatic { return; } - if in_external_macro(cx.sess(), item.span) { + if item.span.in_external_macro(cx.sess().source_map()) { return; } diff --git a/src/tools/clippy/clippy_lints/src/octal_escapes.rs b/src/tools/clippy/clippy_lints/src/octal_escapes.rs index 2eae9b23746d..6e7ee727965d 100644 --- a/src/tools/clippy/clippy_lints/src/octal_escapes.rs +++ b/src/tools/clippy/clippy_lints/src/octal_escapes.rs @@ -4,7 +4,6 @@ use rustc_ast::token::LitKind; use rustc_ast::{Expr, ExprKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::declare_lint_pass; use rustc_span::{BytePos, Pos, SpanData}; @@ -59,7 +58,7 @@ impl EarlyLintPass for OctalEscapes { LitKind::ByteStr | LitKind::CStr => 2, _ => return, }) - && !in_external_macro(cx.sess(), expr.span) + && !expr.span.in_external_macro(cx.sess().source_map()) { let s = lit.symbol.as_str(); let mut iter = s.as_bytes().iter(); diff --git a/src/tools/clippy/clippy_lints/src/panicking_overflow_checks.rs b/src/tools/clippy/clippy_lints/src/panicking_overflow_checks.rs index 7f100a746d5e..bc1821a48a34 100644 --- a/src/tools/clippy/clippy_lints/src/panicking_overflow_checks.rs +++ b/src/tools/clippy/clippy_lints/src/panicking_overflow_checks.rs @@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint; use clippy_utils::eq_expr_value; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::lint::in_external_macro; use rustc_middle::ty; use rustc_session::declare_lint_pass; @@ -72,7 +71,7 @@ impl<'tcx> LateLintPass<'tcx> for PanickingOverflowChecks { && matches!(ty.kind(), ty::Uint(_)) && ty == typeck.expr_ty(op_rhs) && ty == typeck.expr_ty(other) - && !in_external_macro(cx.tcx.sess, expr.span) + && !expr.span.in_external_macro(cx.tcx.sess.source_map()) && (eq_expr_value(cx, op_lhs, other) || (commutative && eq_expr_value(cx, op_rhs, other))) { span_lint( diff --git a/src/tools/clippy/clippy_lints/src/pathbuf_init_then_push.rs b/src/tools/clippy/clippy_lints/src/pathbuf_init_then_push.rs index 668f09bbfd58..b653b459b04c 100644 --- a/src/tools/clippy/clippy_lints/src/pathbuf_init_then_push.rs +++ b/src/tools/clippy/clippy_lints/src/pathbuf_init_then_push.rs @@ -7,7 +7,6 @@ use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::{BindingMode, Block, Expr, ExprKind, HirId, LetStmt, PatKind, QPath, Stmt, StmtKind, TyKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; use rustc_span::{Span, Symbol, sym}; @@ -136,7 +135,7 @@ impl<'tcx> LateLintPass<'tcx> for PathbufThenPush<'tcx> { fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx LetStmt<'tcx>) { if let Some(init_expr) = local.init && let PatKind::Binding(BindingMode::MUT, id, name, None) = local.pat.kind - && !in_external_macro(cx.sess(), local.span) + && !local.span.in_external_macro(cx.sess().source_map()) && let ty = cx.typeck_results().pat_ty(local.pat) && is_type_diagnostic_item(cx, ty, sym::PathBuf) { @@ -157,7 +156,7 @@ impl<'tcx> LateLintPass<'tcx> for PathbufThenPush<'tcx> { && let ExprKind::Path(QPath::Resolved(None, path)) = left.kind && let [name] = &path.segments && let Res::Local(id) = path.res - && !in_external_macro(cx.sess(), expr.span) + && !expr.span.in_external_macro(cx.sess().source_map()) && let ty = cx.typeck_results().expr_ty(left) && is_type_diagnostic_item(cx, ty, sym::PathBuf) { diff --git a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs index 42fbba8ef6dc..8f1a1ee76c6a 100644 --- a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs +++ b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs @@ -3,7 +3,6 @@ use rustc_hir::{ Body, Expr, ExprKind, FnDecl, LetExpr, LocalSource, Mutability, Pat, PatKind, Stmt, StmtKind, intravisit, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_middle::ty; use rustc_session::declare_lint_pass; use rustc_span::Span; @@ -84,7 +83,7 @@ declare_lint_pass!(PatternTypeMismatch => [PATTERN_TYPE_MISMATCH]); impl<'tcx> LateLintPass<'tcx> for PatternTypeMismatch { fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { if let StmtKind::Let(local) = stmt.kind { - if in_external_macro(cx.sess(), local.pat.span) { + if local.pat.span.in_external_macro(cx.sess().source_map()) { return; } let deref_possible = match local.source { @@ -171,7 +170,7 @@ fn find_first_mismatch(cx: &LateContext<'_>, pat: &Pat<'_>) -> Option<(Span, Mut if result.is_some() { return false; } - if in_external_macro(cx.sess(), p.span) { + if p.span.in_external_macro(cx.sess().source_map()) { return true; } let adjust_pat = match p.kind { diff --git a/src/tools/clippy/clippy_lints/src/raw_strings.rs b/src/tools/clippy/clippy_lints/src/raw_strings.rs index 23d0e768c2f1..c6e6e782f9d4 100644 --- a/src/tools/clippy/clippy_lints/src/raw_strings.rs +++ b/src/tools/clippy/clippy_lints/src/raw_strings.rs @@ -5,7 +5,6 @@ use rustc_ast::ast::{Expr, ExprKind}; use rustc_ast::token::LitKind; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; use rustc_span::{BytePos, Pos, Span}; use std::iter::once; @@ -72,7 +71,7 @@ impl RawStrings { impl EarlyLintPass for RawStrings { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { if let ExprKind::FormatArgs(format_args) = &expr.kind - && !in_external_macro(cx.sess(), format_args.span) + && !format_args.span.in_external_macro(cx.sess().source_map()) && format_args.span.check_source_text(cx, |src| src.starts_with('r')) && let Some(str) = snippet_opt(cx.sess(), format_args.span) && let count_hash = str.bytes().skip(1).take_while(|b| *b == b'#').count() @@ -95,7 +94,7 @@ impl EarlyLintPass for RawStrings { LitKind::CStrRaw(max) => ("cr", max), _ => return, } - && !in_external_macro(cx.sess(), expr.span) + && !expr.span.in_external_macro(cx.sess().source_map()) && expr.span.check_source_text(cx, |src| src.starts_with(prefix)) { self.check_raw_string(cx, lit.symbol.as_str(), expr.span, prefix, max, lit.kind.descr()); diff --git a/src/tools/clippy/clippy_lints/src/redundant_async_block.rs b/src/tools/clippy/clippy_lints/src/redundant_async_block.rs index 3ade6bcee84d..65fd312b3a09 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_async_block.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_async_block.rs @@ -10,7 +10,6 @@ use rustc_hir::{ Closure, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, MatchSource, }; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::lint::in_external_macro; use rustc_middle::ty::UpvarCapture; use rustc_session::declare_lint_pass; @@ -47,7 +46,7 @@ declare_lint_pass!(RedundantAsyncBlock => [REDUNDANT_ASYNC_BLOCK]); impl<'tcx> LateLintPass<'tcx> for RedundantAsyncBlock { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { let span = expr.span; - if !in_external_macro(cx.tcx.sess, span) && + if !span.in_external_macro(cx.tcx.sess.source_map()) && let Some(body_expr) = desugar_async_block(cx, expr) && let Some(expr) = desugar_await(peel_blocks(body_expr)) && // The await prefix must not come from a macro as its content could change in the future. diff --git a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs index b4dadef57a3c..91d023500ca6 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs @@ -10,7 +10,6 @@ use rustc_hir::{ }; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::hir::nested_filter; -use rustc_middle::lint::in_external_macro; use rustc_middle::ty; use rustc_session::declare_lint_pass; use rustc_span::ExpnKind; @@ -138,7 +137,7 @@ fn get_parent_call_exprs<'tcx>( impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { - if in_external_macro(cx.sess(), expr.span) { + if expr.span.in_external_macro(cx.sess().source_map()) { return; } diff --git a/src/tools/clippy/clippy_lints/src/redundant_else.rs b/src/tools/clippy/clippy_lints/src/redundant_else.rs index a27f9b631143..3476f56cf338 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_else.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_else.rs @@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_help; use rustc_ast::ast::{Block, Expr, ExprKind, Stmt, StmtKind}; use rustc_ast::visit::{Visitor, walk_expr}; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::declare_lint_pass; declare_clippy_lint! { @@ -46,7 +45,7 @@ declare_lint_pass!(RedundantElse => [REDUNDANT_ELSE]); impl EarlyLintPass for RedundantElse { fn check_stmt(&mut self, cx: &EarlyContext<'_>, stmt: &Stmt) { - if in_external_macro(cx.sess(), stmt.span) { + if stmt.span.in_external_macro(cx.sess().source_map()) { return; } // Only look at expressions that are a whole statement diff --git a/src/tools/clippy/clippy_lints/src/redundant_field_names.rs b/src/tools/clippy/clippy_lints/src/redundant_field_names.rs index 347540e7344f..707abc008a86 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_field_names.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_field_names.rs @@ -4,7 +4,6 @@ use clippy_utils::msrvs::{self, Msrv}; use rustc_ast::ast::{Expr, ExprKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; declare_clippy_lint! { @@ -56,7 +55,7 @@ impl EarlyLintPass for RedundantFieldNames { return; } - if in_external_macro(cx.sess(), expr.span) { + if expr.span.in_external_macro(cx.sess().source_map()) { return; } if let ExprKind::Struct(ref se) = expr.kind { diff --git a/src/tools/clippy/clippy_lints/src/redundant_locals.rs b/src/tools/clippy/clippy_lints/src/redundant_locals.rs index 658d93e634cf..ebe3e7c20196 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_locals.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_locals.rs @@ -6,7 +6,6 @@ use rustc_hir::def::Res; use rustc_hir::{BindingMode, ByRef, ExprKind, HirId, LetStmt, Node, Pat, PatKind, QPath}; use rustc_hir_typeck::expr_use_visitor::PlaceBase; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_middle::ty::UpvarCapture; use rustc_session::declare_lint_pass; use rustc_span::DesugaringKind; @@ -69,7 +68,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantLocals { // the local does not affect the code's drop behavior && !needs_ordered_drop(cx, cx.typeck_results().expr_ty(expr)) // the local is user-controlled - && !in_external_macro(cx.sess(), local.span) + && !local.span.in_external_macro(cx.sess().source_map()) && !is_from_proc_macro(cx, expr) && !is_by_value_closure_capture(cx, local.hir_id, binding_id) { diff --git a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs index 8d6b1c7274d9..6a17b83b3d01 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs @@ -4,7 +4,6 @@ use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::lint::in_external_macro; use rustc_middle::ty; use rustc_session::impl_lint_pass; use rustc_span::def_id::CRATE_DEF_ID; @@ -51,7 +50,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate { && !cx.effective_visibilities.is_exported(item.owner_id.def_id) && self.is_exported.last() == Some(&false) && is_not_macro_export(item) - && !in_external_macro(cx.sess(), item.span) + && !item.span.in_external_macro(cx.sess().source_map()) { let span = item.span.with_hi(item.ident.span.hi()); let descr = cx.tcx.def_kind(item.owner_id).descr(item.owner_id.to_def_id()); diff --git a/src/tools/clippy/clippy_lints/src/reserve_after_initialization.rs b/src/tools/clippy/clippy_lints/src/reserve_after_initialization.rs index 6157adad059c..152d7450f5ff 100644 --- a/src/tools/clippy/clippy_lints/src/reserve_after_initialization.rs +++ b/src/tools/clippy/clippy_lints/src/reserve_after_initialization.rs @@ -6,7 +6,6 @@ use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::{BindingMode, Block, Expr, ExprKind, HirId, LetStmt, PatKind, QPath, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; use rustc_span::Span; @@ -72,7 +71,7 @@ impl<'tcx> LateLintPass<'tcx> for ReserveAfterInitialization { fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx LetStmt<'tcx>) { if let Some(init_expr) = local.init && let PatKind::Binding(BindingMode::MUT, id, _, None) = local.pat.kind - && !in_external_macro(cx.sess(), local.span) + && !local.span.in_external_macro(cx.sess().source_map()) && let Some(init) = get_vec_init_kind(cx, init_expr) && !matches!( init, @@ -101,7 +100,7 @@ impl<'tcx> LateLintPass<'tcx> for ReserveAfterInitialization { && let ExprKind::Assign(left, right, _) = expr.kind && let ExprKind::Path(QPath::Resolved(None, path)) = left.kind && let Res::Local(id) = path.res - && !in_external_macro(cx.sess(), expr.span) + && !expr.span.in_external_macro(cx.sess().source_map()) && let Some(init) = get_vec_init_kind(cx, right) && !matches!( init, diff --git a/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs b/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs index 42d9cf2c88c1..5a25483c397c 100644 --- a/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs +++ b/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs @@ -5,7 +5,6 @@ use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::FnKind; use rustc_hir::{Body, FnDecl, OwnerId, TraitItem, TraitItemKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::declare_lint_pass; use rustc_span::{Span, sym}; @@ -69,7 +68,7 @@ declare_clippy_lint! { declare_lint_pass!(ReturnSelfNotMustUse => [RETURN_SELF_NOT_MUST_USE]); fn check_method(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_def: LocalDefId, span: Span, owner_id: OwnerId) { - if !in_external_macro(cx.sess(), span) + if !span.in_external_macro(cx.sess().source_map()) // If it comes from an external macro, better ignore it. && decl.implicit_self.has_implicit_self() // We only show this warning for public exported methods. diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs index 664e984fece3..a1cf16e6ce9f 100644 --- a/src/tools/clippy/clippy_lints/src/returns.rs +++ b/src/tools/clippy/clippy_lints/src/returns.rs @@ -17,7 +17,6 @@ use rustc_hir::{ StmtKind, }; use rustc_lint::{LateContext, LateLintPass, Level, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_middle::ty::adjustment::Adjust; use rustc_middle::ty::{self, GenericArgKind, Ty}; use rustc_session::declare_lint_pass; @@ -191,7 +190,7 @@ fn stmt_needs_never_type(cx: &LateContext<'_>, stmt_hir_id: HirId) -> bool { impl<'tcx> LateLintPass<'tcx> for Return { fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { - if !in_external_macro(cx.sess(), stmt.span) + if !stmt.span.in_external_macro(cx.sess().source_map()) && let StmtKind::Semi(expr) = stmt.kind && let ExprKind::Ret(Some(ret)) = expr.kind // return Err(...)? desugars to a match @@ -237,8 +236,8 @@ impl<'tcx> LateLintPass<'tcx> for Return { && let PatKind::Binding(_, local_id, _, _) = local.pat.kind && path_to_local_id(retexpr, local_id) && !last_statement_borrows(cx, initexpr) - && !in_external_macro(cx.sess(), initexpr.span) - && !in_external_macro(cx.sess(), retexpr.span) + && !initexpr.span.in_external_macro(cx.sess().source_map()) + && !retexpr.span.in_external_macro(cx.sess().source_map()) && !local.span.from_expansion() && !span_contains_cfg(cx, stmt.span.between(retexpr.span)) { diff --git a/src/tools/clippy/clippy_lints/src/single_call_fn.rs b/src/tools/clippy/clippy_lints/src/single_call_fn.rs index 0176077c70e0..fdbccbaa8a59 100644 --- a/src/tools/clippy/clippy_lints/src/single_call_fn.rs +++ b/src/tools/clippy/clippy_lints/src/single_call_fn.rs @@ -6,7 +6,6 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; use rustc_hir::{Expr, ExprKind, HirId, Node}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; use rustc_span::Span; @@ -88,7 +87,7 @@ impl SingleCallFn { fn_span: Span, ) -> bool { (self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(fn_def_id)) - || in_external_macro(cx.sess(), fn_span) + || fn_span.in_external_macro(cx.sess().source_map()) || cx .tcx .hir() diff --git a/src/tools/clippy/clippy_lints/src/single_char_lifetime_names.rs b/src/tools/clippy/clippy_lints/src/single_char_lifetime_names.rs index d92b890950a3..50a6ee316c8a 100644 --- a/src/tools/clippy/clippy_lints/src/single_char_lifetime_names.rs +++ b/src/tools/clippy/clippy_lints/src/single_char_lifetime_names.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use rustc_ast::ast::{GenericParam, GenericParamKind}; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::declare_lint_pass; declare_clippy_lint! { @@ -42,7 +41,7 @@ declare_lint_pass!(SingleCharLifetimeNames => [SINGLE_CHAR_LIFETIME_NAMES]); impl EarlyLintPass for SingleCharLifetimeNames { fn check_generic_param(&mut self, ctx: &EarlyContext<'_>, param: &GenericParam) { - if in_external_macro(ctx.sess(), param.ident.span) { + if param.ident.span.in_external_macro(ctx.sess().source_map()) { return; } diff --git a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs index 8ec7bfe9edd3..59c13a1e2c53 100644 --- a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs +++ b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs @@ -8,7 +8,6 @@ use rustc_hir::def::Res; use rustc_hir::def_id::DefId; use rustc_hir::{HirId, Path, PathSegment}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; use rustc_span::symbol::kw; use rustc_span::{Span, sym}; @@ -112,7 +111,7 @@ impl<'tcx> LateLintPass<'tcx> for StdReexports { if let Res::Def(_, def_id) = path.res && let Some(first_segment) = get_first_segment(path) && is_stable(cx, def_id, &self.msrv) - && !in_external_macro(cx.sess(), path.span) + && !path.span.in_external_macro(cx.sess().source_map()) && !is_from_proc_macro(cx, &first_segment.ident) { let (lint, used_mod, replace_with) = match first_segment.ident.name { diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs index 2925f355d0b6..6164a6191db0 100644 --- a/src/tools/clippy/clippy_lints/src/strings.rs +++ b/src/tools/clippy/clippy_lints/src/strings.rs @@ -9,7 +9,6 @@ use rustc_errors::Applicability; use rustc_hir::def_id::DefId; use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, LangItem, Node, QPath}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_middle::ty; use rustc_session::declare_lint_pass; use rustc_span::source_map::Spanned; @@ -147,7 +146,7 @@ declare_lint_pass!(StringAdd => [STRING_ADD, STRING_ADD_ASSIGN, STRING_SLICE]); impl<'tcx> LateLintPass<'tcx> for StringAdd { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { - if in_external_macro(cx.sess(), e.span) { + if e.span.in_external_macro(cx.sess().source_map()) { return; } match e.kind { @@ -284,7 +283,7 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes { ); } - if !in_external_macro(cx.sess(), e.span) + if !e.span.in_external_macro(cx.sess().source_map()) && let ExprKind::MethodCall(path, receiver, ..) = &e.kind && path.ident.name.as_str() == "as_bytes" && let ExprKind::Lit(lit) = &receiver.kind diff --git a/src/tools/clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs b/src/tools/clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs index d1d822a55326..e55d17818e4f 100644 --- a/src/tools/clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs +++ b/src/tools/clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs @@ -5,7 +5,6 @@ use rustc_ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::declare_lint_pass; declare_clippy_lint! { @@ -32,7 +31,7 @@ declare_lint_pass!(ConfusingXorAndPow => [SUSPICIOUS_XOR_USED_AS_POW]); impl LateLintPass<'_> for ConfusingXorAndPow { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { - if !in_external_macro(cx.sess(), expr.span) + if !expr.span.in_external_macro(cx.sess().source_map()) && let ExprKind::Binary(op, left, right) = &expr.kind && op.node == BinOpKind::BitXor && left.span.eq_ctxt(right.span) diff --git a/src/tools/clippy/clippy_lints/src/swap.rs b/src/tools/clippy/clippy_lints/src/swap.rs index 9b4c3d275ae7..7176d533b616 100644 --- a/src/tools/clippy/clippy_lints/src/swap.rs +++ b/src/tools/clippy/clippy_lints/src/swap.rs @@ -12,7 +12,6 @@ use rustc_hir::intravisit::{Visitor, walk_expr}; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Block, Expr, ExprKind, LetStmt, PatKind, QPath, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_middle::ty; use rustc_session::declare_lint_pass; use rustc_span::source_map::Spanned; @@ -212,7 +211,7 @@ fn check_suspicious_swap(cx: &LateContext<'_>, block: &Block<'_>) { if let Some((lhs0, rhs0)) = parse(first) && let Some((lhs1, rhs1)) = parse(second) && first.span.eq_ctxt(second.span) - && !in_external_macro(cx.sess(), first.span) + && !first.span.in_external_macro(cx.sess().source_map()) && is_same(cx, lhs0, rhs1) && is_same(cx, lhs1, rhs0) && !is_same(cx, lhs1, rhs1) // Ignore a = b; a = a (#10421) diff --git a/src/tools/clippy/clippy_lints/src/transmute/missing_transmute_annotations.rs b/src/tools/clippy/clippy_lints/src/transmute/missing_transmute_annotations.rs index bed4e60ba62d..4961dd6b280a 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/missing_transmute_annotations.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/missing_transmute_annotations.rs @@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use rustc_errors::Applicability; use rustc_hir::{GenericArg, HirId, LetStmt, Node, Path, TyKind}; use rustc_lint::LateContext; -use rustc_middle::lint::in_external_macro; use rustc_middle::ty::Ty; use crate::transmute::MISSING_TRANSMUTE_ANNOTATIONS; @@ -44,7 +43,7 @@ pub(super) fn check<'tcx>( expr_hir_id: HirId, ) -> bool { let last = path.segments.last().unwrap(); - if in_external_macro(cx.tcx.sess, last.ident.span) { + if last.ident.span.in_external_macro(cx.tcx.sess.source_map()) { // If it comes from a non-local macro, we ignore it. return false; } diff --git a/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs b/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs index 008e09dd8bd1..c7aefc65f707 100644 --- a/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs +++ b/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs @@ -7,7 +7,6 @@ use itertools::Itertools; use rustc_ast::LitKind; use rustc_hir::{Expr, ExprKind, Node, PatKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, Ty}; use rustc_session::impl_lint_pass; use std::iter::once; @@ -56,7 +55,7 @@ impl TupleArrayConversions { impl LateLintPass<'_> for TupleArrayConversions { fn check_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { - if in_external_macro(cx.sess(), expr.span) || !self.msrv.meets(msrvs::TUPLE_ARRAY_CONVERSIONS) { + if expr.span.in_external_macro(cx.sess().source_map()) || !self.msrv.meets(msrvs::TUPLE_ARRAY_CONVERSIONS) { return; } diff --git a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs index 45d730985bb1..5e5d6a9e333b 100644 --- a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -11,7 +11,6 @@ use rustc_hir as hir; use rustc_hir::{Block, BlockCheckMode, ItemKind, Node, UnsafeSource}; use rustc_lexer::{TokenKind, tokenize}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; use rustc_span::{BytePos, Pos, RelativeBytePos, Span, SyntaxContext}; @@ -111,7 +110,7 @@ impl_lint_pass!(UndocumentedUnsafeBlocks => [UNDOCUMENTED_UNSAFE_BLOCKS, UNNECES impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks { fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) { if block.rules == BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) - && !in_external_macro(cx.tcx.sess, block.span) + && !block.span.in_external_macro(cx.tcx.sess.source_map()) && !is_lint_allowed(cx, UNDOCUMENTED_UNSAFE_BLOCKS, block.hir_id) && !is_unsafe_from_proc_macro(cx, block.span) && !block_has_safety_comment(cx, block.span) @@ -143,7 +142,7 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks { if let Some(tail) = block.expr && !is_lint_allowed(cx, UNNECESSARY_SAFETY_COMMENT, tail.hir_id) - && !in_external_macro(cx.tcx.sess, tail.span) + && !tail.span.in_external_macro(cx.tcx.sess.source_map()) && let HasSafetyComment::Yes(pos) = stmt_has_safety_comment(cx, tail.span, tail.hir_id) && let Some(help_span) = expr_has_unnecessary_safety_comment(cx, tail, pos) { @@ -167,7 +166,7 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks { return; }; if !is_lint_allowed(cx, UNNECESSARY_SAFETY_COMMENT, stmt.hir_id) - && !in_external_macro(cx.tcx.sess, stmt.span) + && !stmt.span.in_external_macro(cx.tcx.sess.source_map()) && let HasSafetyComment::Yes(pos) = stmt_has_safety_comment(cx, stmt.span, stmt.hir_id) && let Some(help_span) = expr_has_unnecessary_safety_comment(cx, expr, pos) { @@ -184,7 +183,7 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks { } fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { - if in_external_macro(cx.tcx.sess, item.span) { + if item.span.in_external_macro(cx.tcx.sess.source_map()) { return; } diff --git a/src/tools/clippy/clippy_lints/src/uninhabited_references.rs b/src/tools/clippy/clippy_lints/src/uninhabited_references.rs index ee9ef0172538..b342f37f0c5f 100644 --- a/src/tools/clippy/clippy_lints/src/uninhabited_references.rs +++ b/src/tools/clippy/clippy_lints/src/uninhabited_references.rs @@ -3,7 +3,6 @@ use rustc_hir::intravisit::FnKind; use rustc_hir::{Body, Expr, ExprKind, FnDecl, FnRetTy, TyKind, UnOp}; use rustc_hir_analysis::lower_ty; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::lint::in_external_macro; use rustc_session::declare_lint_pass; use rustc_span::Span; use rustc_span::def_id::LocalDefId; @@ -40,7 +39,7 @@ declare_lint_pass!(UninhabitedReferences => [UNINHABITED_REFERENCES]); impl LateLintPass<'_> for UninhabitedReferences { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) { - if in_external_macro(cx.tcx.sess, expr.span) { + if expr.span.in_external_macro(cx.tcx.sess.source_map()) { return; } @@ -66,7 +65,7 @@ impl LateLintPass<'_> for UninhabitedReferences { span: Span, _: LocalDefId, ) { - if in_external_macro(cx.tcx.sess, span) || matches!(kind, FnKind::Closure) { + if span.in_external_macro(cx.tcx.sess.source_map()) || matches!(kind, FnKind::Closure) { return; } if let FnRetTy::Return(hir_ty) = fndecl.output diff --git a/src/tools/clippy/clippy_lints/src/uninit_vec.rs b/src/tools/clippy/clippy_lints/src/uninit_vec.rs index 93ed15777e01..7803d5115c97 100644 --- a/src/tools/clippy/clippy_lints/src/uninit_vec.rs +++ b/src/tools/clippy/clippy_lints/src/uninit_vec.rs @@ -4,7 +4,6 @@ use clippy_utils::ty::{is_type_diagnostic_item, is_uninit_value_valid_for_ty}; use clippy_utils::{SpanlessEq, is_integer_literal, is_lint_allowed, path_to_local_id, peel_hir_expr_while}; use rustc_hir::{Block, Expr, ExprKind, HirId, PatKind, PathSegment, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::lint::in_external_macro; use rustc_middle::ty; use rustc_session::declare_lint_pass; use rustc_span::{Span, sym}; @@ -64,7 +63,7 @@ declare_lint_pass!(UninitVec => [UNINIT_VEC]); // Threads: https://github.com/rust-lang/rust-clippy/pull/7682#discussion_r710998368 impl<'tcx> LateLintPass<'tcx> for UninitVec { fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'_>) { - if !in_external_macro(cx.tcx.sess, block.span) { + if !block.span.in_external_macro(cx.tcx.sess.source_map()) { for w in block.stmts.windows(2) { if let StmtKind::Expr(expr) | StmtKind::Semi(expr) = w[1].kind { handle_uninit_vec_pair(cx, &w[0], expr); diff --git a/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs b/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs index 660bdb9e2be2..00b80e827d8a 100644 --- a/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs +++ b/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs @@ -7,7 +7,6 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{Visitor, walk_body}; use rustc_hir::{Expr, ExprKind, HirId, HirIdSet, LetStmt, MatchSource, Node, PatKind, QPath, TyKind}; use rustc_lint::{LateContext, LintContext}; -use rustc_middle::lint::{in_external_macro, is_from_async_await}; use rustc_middle::ty; use super::LET_UNIT_VALUE; @@ -22,8 +21,8 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, local: &'tcx LetStmt<'_>) { if let Some(init) = local.init && !local.pat.span.from_expansion() - && !in_external_macro(cx.sess(), local.span) - && !is_from_async_await(local.span) + && !local.span.in_external_macro(cx.sess().source_map()) + && !local.span.is_from_async_await() && cx.typeck_results().pat_ty(local.pat).is_unit() { // skip `let awa = ()` diff --git a/src/tools/clippy/clippy_lints/src/unused_result_ok.rs b/src/tools/clippy/clippy_lints/src/unused_result_ok.rs index 0c0d10eac5b8..958f19d18335 100644 --- a/src/tools/clippy/clippy_lints/src/unused_result_ok.rs +++ b/src/tools/clippy/clippy_lints/src/unused_result_ok.rs @@ -4,7 +4,6 @@ use clippy_utils::ty::is_type_diagnostic_item; use rustc_errors::Applicability; use rustc_hir::{ExprKind, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::declare_lint_pass; use rustc_span::sym; @@ -39,7 +38,7 @@ impl LateLintPass<'_> for UnusedResultOk { && let ExprKind::MethodCall(ok_path, recv, [], ..) = expr.kind //check is expr.ok() has type Result.ok(, _) && ok_path.ident.as_str() == "ok" && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result) - && !in_external_macro(cx.sess(), stmt.span) + && !stmt.span.in_external_macro(cx.sess().source_map()) { let ctxt = expr.span.ctxt(); let mut applicability = Applicability::MaybeIncorrect; diff --git a/src/tools/clippy/clippy_lints/src/unused_trait_names.rs b/src/tools/clippy/clippy_lints/src/unused_trait_names.rs index 17ee5fc20ca2..f83415834351 100644 --- a/src/tools/clippy/clippy_lints/src/unused_trait_names.rs +++ b/src/tools/clippy/clippy_lints/src/unused_trait_names.rs @@ -7,7 +7,6 @@ use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{Item, ItemKind, UseKind}; use rustc_lint::{LateContext, LateLintPass, LintContext as _}; -use rustc_middle::lint::in_external_macro; use rustc_middle::ty::Visibility; use rustc_session::impl_lint_pass; use rustc_span::symbol::kw; @@ -63,7 +62,7 @@ impl_lint_pass!(UnusedTraitNames => [UNUSED_TRAIT_NAMES]); impl<'tcx> LateLintPass<'tcx> for UnusedTraitNames { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { if self.msrv.meets(msrvs::UNDERSCORE_IMPORTS) - && !in_external_macro(cx.sess(), item.span) + && !item.span.in_external_macro(cx.sess().source_map()) && let ItemKind::Use(path, UseKind::Single) = item.kind // Ignore imports that already use Underscore && item.ident.name != kw::Underscore diff --git a/src/tools/clippy/clippy_lints/src/unwrap.rs b/src/tools/clippy/clippy_lints/src/unwrap.rs index eaa119b045f1..6a952c0d97aa 100644 --- a/src/tools/clippy/clippy_lints/src/unwrap.rs +++ b/src/tools/clippy/clippy_lints/src/unwrap.rs @@ -8,7 +8,6 @@ use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, HirId, Node, PathSegmen use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceWithHirId}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; -use rustc_middle::lint::in_external_macro; use rustc_middle::mir::FakeReadCause; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_session::declare_lint_pass; @@ -292,7 +291,7 @@ impl<'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'_, 'tcx> { fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { // Shouldn't lint when `expr` is in macro. - if in_external_macro(self.cx.tcx.sess, expr.span) { + if expr.span.in_external_macro(self.cx.tcx.sess.source_map()) { return; } if let Some(higher::If { cond, then, r#else }) = higher::If::hir(expr) { diff --git a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs index c3843279ba2e..3449468ef480 100644 --- a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs +++ b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs @@ -4,7 +4,6 @@ use core::mem::replace; use rustc_errors::Applicability; use rustc_hir::{HirId, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; use rustc_span::symbol::Ident; @@ -126,7 +125,7 @@ fn check_ident(cx: &LateContext<'_>, ident: &Ident, hir_id: HirId, be_aggressive impl LateLintPass<'_> for UpperCaseAcronyms { fn check_item(&mut self, cx: &LateContext<'_>, it: &Item<'_>) { // do not lint public items or in macros - if in_external_macro(cx.sess(), it.span) + if it.span.in_external_macro(cx.sess().source_map()) || (self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(it.owner_id.def_id)) { return; diff --git a/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs b/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs index d87d554eb074..3c23662e9d16 100644 --- a/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs +++ b/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs @@ -8,7 +8,6 @@ use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::{BindingMode, Block, Expr, ExprKind, HirId, LetStmt, Mutability, PatKind, QPath, Stmt, StmtKind, UnOp}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; use rustc_span::{Span, Symbol}; @@ -158,7 +157,7 @@ impl<'tcx> LateLintPass<'tcx> for VecInitThenPush { fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx LetStmt<'tcx>) { if let Some(init_expr) = local.init && let PatKind::Binding(BindingMode::MUT, id, name, None) = local.pat.kind - && !in_external_macro(cx.sess(), local.span) + && !local.span.in_external_macro(cx.sess().source_map()) && let Some(init) = get_vec_init_kind(cx, init_expr) && !matches!(init, VecInitKind::WithExprCapacity(_)) { @@ -181,7 +180,7 @@ impl<'tcx> LateLintPass<'tcx> for VecInitThenPush { && let ExprKind::Path(QPath::Resolved(None, path)) = left.kind && let [name] = &path.segments && let Res::Local(id) = path.res - && !in_external_macro(cx.sess(), expr.span) + && !expr.span.in_external_macro(cx.sess().source_map()) && let Some(init) = get_vec_init_kind(cx, right) && !matches!(init, VecInitKind::WithExprCapacity(_)) { diff --git a/src/tools/clippy/clippy_lints/src/visibility.rs b/src/tools/clippy/clippy_lints/src/visibility.rs index 2e5fc5834e24..d17b3df99216 100644 --- a/src/tools/clippy/clippy_lints/src/visibility.rs +++ b/src/tools/clippy/clippy_lints/src/visibility.rs @@ -3,7 +3,6 @@ use clippy_utils::source::SpanRangeExt; use rustc_ast::ast::{Item, VisibilityKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; -use rustc_middle::lint::in_external_macro; use rustc_session::declare_lint_pass; use rustc_span::Span; use rustc_span::symbol::kw; @@ -79,7 +78,7 @@ declare_lint_pass!(Visibility => [NEEDLESS_PUB_SELF, PUB_WITH_SHORTHAND, PUB_WIT impl EarlyLintPass for Visibility { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - if !in_external_macro(cx.sess(), item.span) + if !item.span.in_external_macro(cx.sess().source_map()) && let VisibilityKind::Restricted { path, shorthand, .. } = &item.vis.kind { if **path == kw::SelfLower && !is_from_proc_macro(cx, item.vis.span) { From 44482a529016dd94b8346db23c3203ecd3679908 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sun, 2 Feb 2025 17:35:11 +1100 Subject: [PATCH 24/35] Remove unused `ToType` trait. --- compiler/rustc_middle/src/infer/unify_key.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs index 7f9211043d69..faaaa8e9cc66 100644 --- a/compiler/rustc_middle/src/infer/unify_key.rs +++ b/compiler/rustc_middle/src/infer/unify_key.rs @@ -5,11 +5,7 @@ use rustc_data_structures::unify::{NoError, UnifyKey, UnifyValue}; use rustc_span::Span; use rustc_span::def_id::DefId; -use crate::ty::{self, Ty, TyCtxt}; - -pub trait ToType { - fn to_type<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx>; -} +use crate::ty; #[derive(Copy, Clone, Debug)] pub enum RegionVariableValue<'tcx> { From 000f8c4e824d35fbcdd1b7d1ebce05eae6cb93b2 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sun, 2 Feb 2025 17:36:53 +1100 Subject: [PATCH 25/35] Move `unify_key` module. From `rustc_middle::infer` to `rustc_infer::infer`. Because everything in it is only used within `rustc_infer`, and no longer needs to be `pub`. Plus it's always good to make the huge `rustc_middle` crate smaller. --- compiler/rustc_infer/src/infer/mod.rs | 3 ++- .../src/infer/region_constraints/mod.rs | 2 +- .../rustc_infer/src/infer/relate/generalize.rs | 2 +- compiler/rustc_infer/src/infer/snapshot/fudge.rs | 2 +- .../rustc_infer/src/infer/snapshot/undo_log.rs | 2 +- .../src/infer/unify_key.rs | 16 ++++++++-------- compiler/rustc_middle/src/infer/mod.rs | 1 - 7 files changed, 14 insertions(+), 14 deletions(-) rename compiler/{rustc_middle => rustc_infer}/src/infer/unify_key.rs (94%) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 515c9c340985..c2513a1af198 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -26,7 +26,6 @@ use rustc_macros::extension; pub use rustc_macros::{TypeFoldable, TypeVisitable}; use rustc_middle::bug; use rustc_middle::infer::canonical::{CanonicalQueryInput, CanonicalVarValues}; -use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableValue, ConstVidKey}; use rustc_middle::mir::ConstraintCategory; use rustc_middle::traits::select; pub use rustc_middle::ty::IntVarValue; @@ -46,6 +45,7 @@ use tracing::{debug, instrument}; use type_variable::TypeVariableOrigin; use crate::infer::region_constraints::UndoLog; +use crate::infer::unify_key::{ConstVariableOrigin, ConstVariableValue, ConstVidKey}; use crate::traits::{ self, ObligationCause, ObligationInspector, PredicateObligations, TraitEngine, }; @@ -64,6 +64,7 @@ pub mod relate; pub mod resolve; pub(crate) mod snapshot; mod type_variable; +mod unify_key; /// `InferOk<'tcx, ()>` is used a lot. It may seem like a useless wrapper /// around `PredicateObligations<'tcx>`, but it has one important property: diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 6496f38269a5..57555db37abd 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -8,7 +8,6 @@ use rustc_data_structures::undo_log::UndoLogs; use rustc_data_structures::unify as ut; use rustc_index::IndexVec; use rustc_macros::{TypeFoldable, TypeVisitable}; -use rustc_middle::infer::unify_key::{RegionVariableValue, RegionVidKey}; use rustc_middle::ty::{self, ReBound, ReStatic, ReVar, Region, RegionVid, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use tracing::{debug, instrument}; @@ -17,6 +16,7 @@ use self::CombineMapType::*; use self::UndoLog::*; use super::{MiscVariable, RegionVariableOrigin, Rollback, SubregionOrigin}; use crate::infer::snapshot::undo_log::{InferCtxtUndoLogs, Snapshot}; +use crate::infer::unify_key::{RegionVariableValue, RegionVidKey}; mod leak_check; diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index 21c47967eada..ce2d07f4af99 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -4,7 +4,6 @@ use rustc_data_structures::sso::SsoHashMap; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::def_id::DefId; use rustc_middle::bug; -use rustc_middle::infer::unify_key::ConstVariableValue; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::visit::MaxUniverse; use rustc_middle::ty::{ @@ -18,6 +17,7 @@ use super::{ PredicateEmittingRelation, Relate, RelateResult, StructurallyRelateAliases, TypeRelation, }; use crate::infer::type_variable::TypeVariableValue; +use crate::infer::unify_key::ConstVariableValue; use crate::infer::{InferCtxt, RegionVariableOrigin, relate}; impl<'tcx> InferCtxt<'tcx> { diff --git a/compiler/rustc_infer/src/infer/snapshot/fudge.rs b/compiler/rustc_infer/src/infer/snapshot/fudge.rs index 394e07a81e7d..3a47b13665d4 100644 --- a/compiler/rustc_infer/src/infer/snapshot/fudge.rs +++ b/compiler/rustc_infer/src/infer/snapshot/fudge.rs @@ -1,7 +1,6 @@ use std::ops::Range; use rustc_data_structures::{snapshot_vec as sv, unify as ut}; -use rustc_middle::infer::unify_key::{ConstVariableValue, ConstVidKey}; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::{self, ConstVid, FloatVid, IntVid, RegionVid, Ty, TyCtxt, TyVid}; use rustc_type_ir::visit::TypeVisitableExt; @@ -10,6 +9,7 @@ use ut::UnifyKey; use super::VariableLengths; use crate::infer::type_variable::TypeVariableOrigin; +use crate::infer::unify_key::{ConstVariableValue, ConstVidKey}; use crate::infer::{ConstVariableOrigin, InferCtxt, RegionVariableOrigin, UnificationTable}; fn vars_since_snapshot<'tcx, T>( diff --git a/compiler/rustc_infer/src/infer/snapshot/undo_log.rs b/compiler/rustc_infer/src/infer/snapshot/undo_log.rs index 713389f46183..ba7d8f588e68 100644 --- a/compiler/rustc_infer/src/infer/snapshot/undo_log.rs +++ b/compiler/rustc_infer/src/infer/snapshot/undo_log.rs @@ -2,10 +2,10 @@ use std::marker::PhantomData; use rustc_data_structures::undo_log::{Rollback, UndoLogs}; use rustc_data_structures::{snapshot_vec as sv, unify as ut}; -use rustc_middle::infer::unify_key::{ConstVidKey, RegionVidKey}; use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey}; use tracing::debug; +use crate::infer::unify_key::{ConstVidKey, RegionVidKey}; use crate::infer::{InferCtxtInner, region_constraints, type_variable}; use crate::traits; diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_infer/src/infer/unify_key.rs similarity index 94% rename from compiler/rustc_middle/src/infer/unify_key.rs rename to compiler/rustc_infer/src/infer/unify_key.rs index faaaa8e9cc66..3ba8aea1d3a0 100644 --- a/compiler/rustc_middle/src/infer/unify_key.rs +++ b/compiler/rustc_infer/src/infer/unify_key.rs @@ -2,19 +2,18 @@ use std::cmp; use std::marker::PhantomData; use rustc_data_structures::unify::{NoError, UnifyKey, UnifyValue}; +use rustc_middle::{bug, ty}; use rustc_span::Span; use rustc_span::def_id::DefId; -use crate::ty; - #[derive(Copy, Clone, Debug)] -pub enum RegionVariableValue<'tcx> { +pub(crate) enum RegionVariableValue<'tcx> { Known { value: ty::Region<'tcx> }, Unknown { universe: ty::UniverseIndex }, } #[derive(PartialEq, Copy, Clone, Debug)] -pub struct RegionVidKey<'tcx> { +pub(crate) struct RegionVidKey<'tcx> { pub vid: ty::RegionVid, pub phantom: PhantomData>, } @@ -40,7 +39,8 @@ impl<'tcx> UnifyKey for RegionVidKey<'tcx> { } } -pub struct RegionUnificationError; +pub(crate) struct RegionUnificationError; + impl<'tcx> UnifyValue for RegionVariableValue<'tcx> { type Error = RegionUnificationError; @@ -96,7 +96,7 @@ pub struct ConstVariableOrigin { } #[derive(Copy, Clone, Debug)] -pub enum ConstVariableValue<'tcx> { +pub(crate) enum ConstVariableValue<'tcx> { Known { value: ty::Const<'tcx> }, Unknown { origin: ConstVariableOrigin, universe: ty::UniverseIndex }, } @@ -104,7 +104,7 @@ pub enum ConstVariableValue<'tcx> { impl<'tcx> ConstVariableValue<'tcx> { /// If this value is known, returns the const it is known to be. /// Otherwise, `None`. - pub fn known(&self) -> Option> { + pub(crate) fn known(&self) -> Option> { match *self { ConstVariableValue::Unknown { .. } => None, ConstVariableValue::Known { value } => Some(value), @@ -113,7 +113,7 @@ impl<'tcx> ConstVariableValue<'tcx> { } #[derive(PartialEq, Copy, Clone, Debug)] -pub struct ConstVidKey<'tcx> { +pub(crate) struct ConstVidKey<'tcx> { pub vid: ty::ConstVid, pub phantom: PhantomData>, } diff --git a/compiler/rustc_middle/src/infer/mod.rs b/compiler/rustc_middle/src/infer/mod.rs index 3dfcf90cb935..73e8971c3bde 100644 --- a/compiler/rustc_middle/src/infer/mod.rs +++ b/compiler/rustc_middle/src/infer/mod.rs @@ -1,2 +1 @@ pub mod canonical; -pub mod unify_key; From 3320e915757baea34d796feb513e6563c04ad3c3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 2 Feb 2025 12:33:40 +0100 Subject: [PATCH 26/35] rustc_allowed_through_unstable_modules: require deprecation message --- .../src/stability.rs | 15 +- .../src/attributes/stability.rs | 18 +- compiler/rustc_feature/src/builtin_attrs.rs | 2 +- compiler/rustc_passes/src/stability.rs | 154 +++++++++--------- library/core/src/intrinsics/mod.rs | 6 +- src/librustdoc/clean/types.rs | 12 +- .../fully-stable-path-is-better.rs | 4 +- tests/rustdoc/stability.rs | 2 +- tests/ui/error-codes/E0789.rs | 2 +- .../allowed-through-unstable.rs | 3 +- .../allowed-through-unstable.stderr | 8 +- .../allowed-through-unstable-core.rs | 6 +- 12 files changed, 107 insertions(+), 125 deletions(-) diff --git a/compiler/rustc_attr_data_structures/src/stability.rs b/compiler/rustc_attr_data_structures/src/stability.rs index dfda04387ec5..c2213fc9ed88 100644 --- a/compiler/rustc_attr_data_structures/src/stability.rs +++ b/compiler/rustc_attr_data_structures/src/stability.rs @@ -101,16 +101,6 @@ impl PartialConstStability { } } -#[derive(Encodable, Decodable, PartialEq, Copy, Clone, Debug, Eq, Hash)] -#[derive(HashStable_Generic)] -pub enum AllowedThroughUnstableModules { - /// This does not get a deprecation warning. We still generally would prefer people to use the - /// fully stable path, and a warning will likely be emitted in the future. - WithoutDeprecation, - /// Emit the given deprecation warning. - WithDeprecation(Symbol), -} - /// The available stability levels. #[derive(Encodable, Decodable, PartialEq, Copy, Clone, Debug, Eq, Hash)] #[derive(HashStable_Generic)] @@ -147,8 +137,9 @@ pub enum StabilityLevel { Stable { /// Rust release which stabilized this feature. since: StableSince, - /// This is `Some` if this item allowed to be referred to on stable via unstable modules. - allowed_through_unstable_modules: Option, + /// This is `Some` if this item allowed to be referred to on stable via unstable modules; + /// the `Symbol` is the deprecation message printed in that case. + allowed_through_unstable_modules: Option, }, } diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index bfbe51b27d88..454b8b5de82b 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -6,12 +6,12 @@ use rustc_ast::MetaItem; use rustc_ast::attr::AttributeExt; use rustc_ast_pretty::pprust; use rustc_attr_data_structures::{ - AllowedThroughUnstableModules, ConstStability, DefaultBodyStability, Stability, StabilityLevel, - StableSince, UnstableReason, VERSION_PLACEHOLDER, + ConstStability, DefaultBodyStability, Stability, StabilityLevel, StableSince, UnstableReason, + VERSION_PLACEHOLDER, }; use rustc_errors::ErrorGuaranteed; use rustc_session::Session; -use rustc_span::{Span, Symbol, sym}; +use rustc_span::{Span, Symbol, kw, sym}; use crate::attributes::util::UnsupportedLiteralReason; use crate::{parse_version, session_diagnostics}; @@ -29,10 +29,14 @@ pub fn find_stability( for attr in attrs { match attr.name_or_empty() { sym::rustc_allowed_through_unstable_modules => { - allowed_through_unstable_modules = Some(match attr.value_str() { - Some(msg) => AllowedThroughUnstableModules::WithDeprecation(msg), - None => AllowedThroughUnstableModules::WithoutDeprecation, - }) + // The value is mandatory, but avoid ICEs in case such code reaches this function. + allowed_through_unstable_modules = Some(attr.value_str().unwrap_or_else(|| { + sess.dcx().span_delayed_bug( + item_sp, + "`#[rustc_allowed_through_unstable_modules]` without deprecation message", + ); + kw::Empty + })) } sym::unstable => { if stab.is_some() { diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 684fc5e37e0b..e0543977e98d 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -616,7 +616,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ EncodeCrossCrate::No, "allow_internal_unsafe side-steps the unsafe_code lint", ), rustc_attr!( - rustc_allowed_through_unstable_modules, Normal, template!(Word, NameValueStr: "deprecation message"), + rustc_allowed_through_unstable_modules, Normal, template!(NameValueStr: "deprecation message"), WarnFollowing, EncodeCrossCrate::No, "rustc_allowed_through_unstable_modules special cases accidental stabilizations of stable items \ through unstable paths" diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index a52f080038d1..34f1ca55c787 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -5,8 +5,8 @@ use std::mem::replace; use std::num::NonZero; use rustc_attr_parsing::{ - self as attr, AllowedThroughUnstableModules, ConstStability, DeprecatedSince, Stability, - StabilityLevel, StableSince, UnstableReason, VERSION_PLACEHOLDER, + self as attr, ConstStability, DeprecatedSince, Stability, StabilityLevel, StableSince, + UnstableReason, VERSION_PLACEHOLDER, }; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::unord::{ExtendUnord, UnordMap, UnordSet}; @@ -880,7 +880,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { if item_is_allowed { // The item itself is allowed; check whether the path there is also allowed. - let is_allowed_through_unstable_modules: Option = + let is_allowed_through_unstable_modules: Option = self.tcx.lookup_stability(def_id).and_then(|stab| match stab.level { StabilityLevel::Stable { allowed_through_unstable_modules, .. } => { allowed_through_unstable_modules @@ -888,84 +888,80 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { _ => None, }); - if is_allowed_through_unstable_modules.is_none() { - // Check parent modules stability as well if the item the path refers to is itself - // stable. We only emit warnings for unstable path segments if the item is stable - // or allowed because stability is often inherited, so the most common case is that - // both the segments and the item are unstable behind the same feature flag. - // - // We check here rather than in `visit_path_segment` to prevent visiting the last - // path segment twice - // - // We include special cases via #[rustc_allowed_through_unstable_modules] for items - // that were accidentally stabilized through unstable paths before this check was - // added, such as `core::intrinsics::transmute` - let parents = path.segments.iter().rev().skip(1); - for path_segment in parents { - if let Some(def_id) = path_segment.res.opt_def_id() { - // use `None` for id to prevent deprecation check - self.tcx.check_stability_allow_unstable( - def_id, - None, - path.span, - None, - if is_unstable_reexport(self.tcx, id) { - AllowUnstable::Yes - } else { - AllowUnstable::No - }, - ); - } - } - } else if let Some(AllowedThroughUnstableModules::WithDeprecation(deprecation)) = - is_allowed_through_unstable_modules - { - // Similar to above, but we cannot use `check_stability_allow_unstable` as that would - // immediately show the stability error. We just want to know the result and disaplay - // our own kind of error. - let parents = path.segments.iter().rev().skip(1); - for path_segment in parents { - if let Some(def_id) = path_segment.res.opt_def_id() { - // use `None` for id to prevent deprecation check - let eval_result = self.tcx.eval_stability_allow_unstable( - def_id, - None, - path.span, - None, - if is_unstable_reexport(self.tcx, id) { - AllowUnstable::Yes - } else { - AllowUnstable::No - }, - ); - let is_allowed = matches!(eval_result, EvalResult::Allow); - if !is_allowed { - // Calculating message for lint involves calling `self.def_path_str`, - // which will by default invoke the expensive `visible_parent_map` query. - // Skip all that work if the lint is allowed anyway. - if self.tcx.lint_level_at_node(DEPRECATED, id).0 - == lint::Level::Allow - { - return; - } - // Show a deprecation message. - let def_path = - with_no_trimmed_paths!(self.tcx.def_path_str(def_id)); - let def_kind = self.tcx.def_descr(def_id); - let diag = Deprecated { - sub: None, - kind: def_kind.to_owned(), - path: def_path, - note: Some(deprecation), - since_kind: lint::DeprecatedSinceKind::InEffect, - }; - self.tcx.emit_node_span_lint( - DEPRECATED, - id, - method_span.unwrap_or(path.span), - diag, + // Check parent modules stability as well if the item the path refers to is itself + // stable. We only emit errors for unstable path segments if the item is stable + // or allowed because stability is often inherited, so the most common case is that + // both the segments and the item are unstable behind the same feature flag. + // + // We check here rather than in `visit_path_segment` to prevent visiting the last + // path segment twice + // + // We include special cases via #[rustc_allowed_through_unstable_modules] for items + // that were accidentally stabilized through unstable paths before this check was + // added, such as `core::intrinsics::transmute` + let parents = path.segments.iter().rev().skip(1); + for path_segment in parents { + if let Some(def_id) = path_segment.res.opt_def_id() { + match is_allowed_through_unstable_modules { + None => { + // Emit a hard stability error if this path is not stable. + + // use `None` for id to prevent deprecation check + self.tcx.check_stability_allow_unstable( + def_id, + None, + path.span, + None, + if is_unstable_reexport(self.tcx, id) { + AllowUnstable::Yes + } else { + AllowUnstable::No + }, ); } + Some(deprecation) => { + // Call the stability check directly so that we can control which + // diagnostic is emitted. + let eval_result = self.tcx.eval_stability_allow_unstable( + def_id, + None, + path.span, + None, + if is_unstable_reexport(self.tcx, id) { + AllowUnstable::Yes + } else { + AllowUnstable::No + }, + ); + let is_allowed = matches!(eval_result, EvalResult::Allow); + if !is_allowed { + // Calculating message for lint involves calling `self.def_path_str`, + // which will by default invoke the expensive `visible_parent_map` query. + // Skip all that work if the lint is allowed anyway. + if self.tcx.lint_level_at_node(DEPRECATED, id).0 + == lint::Level::Allow + { + return; + } + // Show a deprecation message. + let def_path = + with_no_trimmed_paths!(self.tcx.def_path_str(def_id)); + let def_kind = self.tcx.def_descr(def_id); + let diag = Deprecated { + sub: None, + kind: def_kind.to_owned(), + path: def_path, + note: Some(deprecation), + since_kind: lint::DeprecatedSinceKind::InEffect, + }; + self.tcx.emit_node_span_lint( + DEPRECATED, + id, + method_span.unwrap_or(path.span), + diag, + ); + } + } } } } diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index c0d435f99c0c..bf07632d9928 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -78,7 +78,11 @@ pub mod simd; use crate::sync::atomic::{self, AtomicBool, AtomicI32, AtomicIsize, AtomicU32, Ordering}; #[stable(feature = "drop_in_place", since = "1.8.0")] -#[rustc_allowed_through_unstable_modules] +#[cfg_attr(bootstrap, rustc_allowed_through_unstable_modules)] +#[cfg_attr( + not(bootstrap), + rustc_allowed_through_unstable_modules = "import this function via `std::ptr` instead" +)] #[deprecated(note = "no longer an intrinsic - use `ptr::drop_in_place` directly", since = "1.52.0")] #[inline] pub unsafe fn drop_in_place(to_drop: *mut T) { diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 6e817af0d6e0..a44d74e6df67 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -5,9 +5,7 @@ use std::{fmt, iter}; use arrayvec::ArrayVec; use rustc_abi::{ExternAbi, VariantIdx}; -use rustc_attr_parsing::{ - AllowedThroughUnstableModules, ConstStability, Deprecation, Stability, StableSince, -}; +use rustc_attr_parsing::{ConstStability, Deprecation, Stability, StableSince}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId}; @@ -411,15 +409,9 @@ impl Item { .. } = stab.level { - let note = match note { - AllowedThroughUnstableModules::WithDeprecation(note) => Some(note), - // FIXME: Would be better to say *something* here about the *path* being - // deprecated rather than the item. - AllowedThroughUnstableModules::WithoutDeprecation => None, - }; Some(Deprecation { since: rustc_attr_parsing::DeprecatedSince::Unspecified, - note, + note: Some(note), suggestion: None, }) } else { diff --git a/tests/rustdoc/inline_local/fully-stable-path-is-better.rs b/tests/rustdoc/inline_local/fully-stable-path-is-better.rs index 88b0b0d57b08..41bf42d2e7aa 100644 --- a/tests/rustdoc/inline_local/fully-stable-path-is-better.rs +++ b/tests/rustdoc/inline_local/fully-stable-path-is-better.rs @@ -16,10 +16,10 @@ pub mod stb1 { #[unstable(feature = "uns", issue = "135003")] pub mod uns { #[stable(since = "1.0", feature = "stb1")] - #[rustc_allowed_through_unstable_modules] + #[rustc_allowed_through_unstable_modules = "use stable path instead"] pub struct Inside1; #[stable(since = "1.0", feature = "stb2")] - #[rustc_allowed_through_unstable_modules] + #[rustc_allowed_through_unstable_modules = "use stable path instead"] pub struct Inside2; } diff --git a/tests/rustdoc/stability.rs b/tests/rustdoc/stability.rs index b74abb0e0ba4..22cd4b9cd595 100644 --- a/tests/rustdoc/stability.rs +++ b/tests/rustdoc/stability.rs @@ -85,7 +85,7 @@ pub mod stable_later { } #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_allowed_through_unstable_modules] +#[rustc_allowed_through_unstable_modules = "use stable path instead"] pub mod stable_earlier1 { //@ has stability/stable_earlier1/struct.StableInUnstable.html \ // '//div[@class="main-heading"]//span[@class="since"]' '1.0.0' diff --git a/tests/ui/error-codes/E0789.rs b/tests/ui/error-codes/E0789.rs index 3acc983edc4e..08471e1b3f3e 100644 --- a/tests/ui/error-codes/E0789.rs +++ b/tests/ui/error-codes/E0789.rs @@ -4,7 +4,7 @@ #![feature(staged_api)] #![unstable(feature = "foo_module", reason = "...", issue = "123")] -#[rustc_allowed_through_unstable_modules] +#[rustc_allowed_through_unstable_modules = "use stable path instead"] // #[stable(feature = "foo", since = "1.0")] struct Foo; //~^ ERROR `rustc_allowed_through_unstable_modules` attribute must be paired with a `stable` attribute diff --git a/tests/ui/stability-attribute/allowed-through-unstable.rs b/tests/ui/stability-attribute/allowed-through-unstable.rs index e03417a4dae8..5baa0fda9403 100644 --- a/tests/ui/stability-attribute/allowed-through-unstable.rs +++ b/tests/ui/stability-attribute/allowed-through-unstable.rs @@ -5,6 +5,5 @@ extern crate allowed_through_unstable_core; -use allowed_through_unstable_core::unstable_module::OldStableTraitAllowedThoughUnstable; -use allowed_through_unstable_core::unstable_module::OldStableTraitAllowedThoughUnstableWithDeprecation; //~WARN use of deprecated module `allowed_through_unstable_core::unstable_module`: use the new path instead +use allowed_through_unstable_core::unstable_module::OldStableTraitAllowedThoughUnstable; //~WARN use of deprecated module `allowed_through_unstable_core::unstable_module`: use the new path instead use allowed_through_unstable_core::unstable_module::NewStableTraitNotAllowedThroughUnstable; //~ ERROR use of unstable library feature `unstable_test_feature` diff --git a/tests/ui/stability-attribute/allowed-through-unstable.stderr b/tests/ui/stability-attribute/allowed-through-unstable.stderr index 8d07b0cf9e8f..bda68045002e 100644 --- a/tests/ui/stability-attribute/allowed-through-unstable.stderr +++ b/tests/ui/stability-attribute/allowed-through-unstable.stderr @@ -1,13 +1,13 @@ warning: use of deprecated module `allowed_through_unstable_core::unstable_module`: use the new path instead - --> $DIR/allowed-through-unstable.rs:9:53 + --> $DIR/allowed-through-unstable.rs:8:53 | -LL | use allowed_through_unstable_core::unstable_module::OldStableTraitAllowedThoughUnstableWithDeprecation; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | use allowed_through_unstable_core::unstable_module::OldStableTraitAllowedThoughUnstable; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(deprecated)]` on by default error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/allowed-through-unstable.rs:10:5 + --> $DIR/allowed-through-unstable.rs:9:5 | LL | use allowed_through_unstable_core::unstable_module::NewStableTraitNotAllowedThroughUnstable; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/stability-attribute/auxiliary/allowed-through-unstable-core.rs b/tests/ui/stability-attribute/auxiliary/allowed-through-unstable-core.rs index 9dfbb451d04b..23c722d6e8eb 100644 --- a/tests/ui/stability-attribute/auxiliary/allowed-through-unstable-core.rs +++ b/tests/ui/stability-attribute/auxiliary/allowed-through-unstable-core.rs @@ -5,13 +5,9 @@ #[unstable(feature = "unstable_test_feature", issue = "1")] pub mod unstable_module { - #[stable(feature = "stable_test_feature", since = "1.2.0")] - #[rustc_allowed_through_unstable_modules] - pub trait OldStableTraitAllowedThoughUnstable {} - #[stable(feature = "stable_test_feature", since = "1.2.0")] #[rustc_allowed_through_unstable_modules = "use the new path instead"] - pub trait OldStableTraitAllowedThoughUnstableWithDeprecation {} + pub trait OldStableTraitAllowedThoughUnstable {} #[stable(feature = "stable_test_feature", since = "1.2.0")] pub trait NewStableTraitNotAllowedThroughUnstable {} From d237378cd164e1bf2fd6f91271abd49c8573ded7 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 2 Feb 2025 15:17:29 +0000 Subject: [PATCH 27/35] Some cleanups around EarlyDiagCtxt All callers of EarlyDiagCtxt::early_error now emit a fatal error. --- compiler/rustc_driver_impl/src/args.rs | 19 +++++++++---------- compiler/rustc_driver_impl/src/lib.rs | 10 ++++------ compiler/rustc_session/src/config.rs | 5 +++-- compiler/rustc_session/src/session.rs | 15 ++++----------- src/librustdoc/lib.rs | 3 +-- src/tools/clippy/src/driver.rs | 5 ++--- src/tools/miri/src/bin/miri.rs | 8 +++----- tests/ui-fulldeps/obtain-borrowck.rs | 1 - 8 files changed, 26 insertions(+), 40 deletions(-) diff --git a/compiler/rustc_driver_impl/src/args.rs b/compiler/rustc_driver_impl/src/args.rs index 2fc767b37508..b0970144c421 100644 --- a/compiler/rustc_driver_impl/src/args.rs +++ b/compiler/rustc_driver_impl/src/args.rs @@ -1,7 +1,6 @@ use std::{env, error, fmt, fs, io}; use rustc_session::EarlyDiagCtxt; -use rustc_span::ErrorGuaranteed; /// Expands argfiles in command line arguments. #[derive(Default)] @@ -118,22 +117,22 @@ pub fn arg_expand_all(early_dcx: &EarlyDiagCtxt, at_args: &[String]) -> Vec Result, ErrorGuaranteed> { - let mut res = Ok(Vec::new()); +pub fn raw_args(early_dcx: &EarlyDiagCtxt) -> Vec { + let mut args = Vec::new(); + let mut guar = Ok(()); for (i, arg) in env::args_os().enumerate() { match arg.into_string() { - Ok(arg) => { - if let Ok(args) = &mut res { - args.push(arg); - } - } + Ok(arg) => args.push(arg), Err(arg) => { - res = + guar = Err(early_dcx.early_err(format!("argument {i} is not valid Unicode: {arg:?}"))) } } } - res + if let Err(guar) = guar { + guar.raise_fatal(); + } + args } #[derive(Debug)] diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index c9d38a0f9325..b6fd15f0e06e 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -1212,9 +1212,9 @@ pub fn catch_fatal_errors R, R>(f: F) -> Result { /// Variant of `catch_fatal_errors` for the `interface::Result` return type /// that also computes the exit code. -pub fn catch_with_exit_code(f: impl FnOnce() -> interface::Result<()>) -> i32 { +pub fn catch_with_exit_code(f: impl FnOnce()) -> i32 { match catch_fatal_errors(f) { - Ok(Ok(())) => EXIT_SUCCESS, + Ok(()) => EXIT_SUCCESS, _ => EXIT_FAILURE, } } @@ -1499,10 +1499,8 @@ pub fn main() -> ! { install_ice_hook(DEFAULT_BUG_REPORT_URL, |_| ()); install_ctrlc_handler(); - let exit_code = catch_with_exit_code(|| { - run_compiler(&args::raw_args(&early_dcx)?, &mut callbacks); - Ok(()) - }); + let exit_code = + catch_with_exit_code(|| run_compiler(&args::raw_args(&early_dcx), &mut callbacks)); if let Some(format) = callbacks.time_passes { let end_rss = get_resident_set_size(); diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index c8a811985d5b..67e314cc6850 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1819,7 +1819,7 @@ pub fn parse_error_format( ErrorOutputType::HumanReadable(HumanReadableErrorType::Unicode, color) } Some(arg) => { - early_dcx.abort_if_error_and_set_error_format(ErrorOutputType::HumanReadable( + early_dcx.set_error_format(ErrorOutputType::HumanReadable( HumanReadableErrorType::Default, color, )); @@ -2360,7 +2360,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M let error_format = parse_error_format(early_dcx, matches, color, json_color, json_rendered); - early_dcx.abort_if_error_and_set_error_format(error_format); + early_dcx.set_error_format(error_format); let diagnostic_width = matches.opt_get("diagnostic-width").unwrap_or_else(|_| { early_dcx.early_fatal("`--diagnostic-width` must be an positive integer"); @@ -2770,6 +2770,7 @@ pub mod nightly_options { "the option `{}` is only accepted on the nightly compiler", opt.name ); + // The non-zero nightly_options_on_stable will force an early_fatal eventually. let _ = early_dcx.early_err(msg); } OptionStability::Stable => {} diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index c0f5f0d4a9e9..2b79081a26e7 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1362,12 +1362,6 @@ pub struct EarlyDiagCtxt { dcx: DiagCtxt, } -impl Default for EarlyDiagCtxt { - fn default() -> Self { - Self::new(ErrorOutputType::default()) - } -} - impl EarlyDiagCtxt { pub fn new(output: ErrorOutputType) -> Self { let emitter = mk_emitter(output); @@ -1375,10 +1369,9 @@ impl EarlyDiagCtxt { } /// Swap out the underlying dcx once we acquire the user's preference on error emission - /// format. Any errors prior to that will cause an abort and all stashed diagnostics of the - /// previous dcx will be emitted. - pub fn abort_if_error_and_set_error_format(&mut self, output: ErrorOutputType) { - self.dcx.handle().abort_if_errors(); + /// format. If `early_err` was previously called this will panic. + pub fn set_error_format(&mut self, output: ErrorOutputType) { + assert!(self.dcx.handle().has_errors().is_none()); let emitter = mk_emitter(output); self.dcx = DiagCtxt::new(emitter); @@ -1398,7 +1391,7 @@ impl EarlyDiagCtxt { #[allow(rustc::untranslatable_diagnostic)] #[allow(rustc::diagnostic_outside_of_impl)] - #[must_use = "ErrorGuaranteed must be returned from `run_compiler` in order to exit with a non-zero status code"] + #[must_use = "raise_fatal must be called on the returned ErrorGuaranteed in order to exit with a non-zero status code"] pub fn early_err(&self, msg: impl Into) -> ErrorGuaranteed { self.dcx.handle().err(msg) } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 44adf92ff0ee..af225c9d68dd 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -177,9 +177,8 @@ pub fn main() { rustc_driver::init_logger(&early_dcx, rustc_log::LoggerConfig::from_env("RUSTDOC_LOG")); let exit_code = rustc_driver::catch_with_exit_code(|| { - let at_args = rustc_driver::args::raw_args(&early_dcx)?; + let at_args = rustc_driver::args::raw_args(&early_dcx); main_args(&mut early_dcx, &at_args); - Ok(()) }); process::exit(exit_code); } diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs index c548f262a92f..e4092bcd1056 100644 --- a/src/tools/clippy/src/driver.rs +++ b/src/tools/clippy/src/driver.rs @@ -197,7 +197,7 @@ pub fn main() { }); exit(rustc_driver::catch_with_exit_code(move || { - let mut orig_args = rustc_driver::args::raw_args(&early_dcx)?; + let mut orig_args = rustc_driver::args::raw_args(&early_dcx); let has_sysroot_arg = |args: &mut [String]| -> bool { if has_arg(args, "--sysroot") { @@ -239,7 +239,7 @@ pub fn main() { pass_sysroot_env_if_given(&mut args, sys_root_env); rustc_driver::run_compiler(&args, &mut DefaultCallbacks); - return Ok(()); + return; } if orig_args.iter().any(|a| a == "--version" || a == "-V") { @@ -301,7 +301,6 @@ pub fn main() { } else { rustc_driver::run_compiler(&args, &mut RustcCallbacks { clippy_args_var }); } - Ok(()) })) } diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index 988a0be63277..fa68f65ceb5f 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -379,10 +379,8 @@ fn run_compiler_and_exit( callbacks: &mut (dyn rustc_driver::Callbacks + Send), ) -> ! { // Invoke compiler, and handle return code. - let exit_code = rustc_driver::catch_with_exit_code(move || { - rustc_driver::run_compiler(args, callbacks); - Ok(()) - }); + let exit_code = + rustc_driver::catch_with_exit_code(move || rustc_driver::run_compiler(args, callbacks)); std::process::exit(exit_code) } @@ -461,7 +459,7 @@ fn main() { // (`install_ice_hook` might change `RUST_BACKTRACE`.) let env_snapshot = env::vars_os().collect::>(); - let args = rustc_driver::args::raw_args(&early_dcx) + let args = rustc_driver::catch_fatal_errors(|| rustc_driver::args::raw_args(&early_dcx)) .unwrap_or_else(|_| std::process::exit(rustc_driver::EXIT_FAILURE)); // Install the ctrlc handler that sets `rustc_const_eval::CTRL_C_RECEIVED`, even if diff --git a/tests/ui-fulldeps/obtain-borrowck.rs b/tests/ui-fulldeps/obtain-borrowck.rs index f8064c245a87..c6bec4f77a06 100644 --- a/tests/ui-fulldeps/obtain-borrowck.rs +++ b/tests/ui-fulldeps/obtain-borrowck.rs @@ -48,7 +48,6 @@ fn main() { let mut callbacks = CompilerCalls::default(); // Call the Rust compiler with our callbacks. rustc_driver::run_compiler(&rustc_args, &mut callbacks); - Ok(()) }); std::process::exit(exit_code); } From aa2b870bb59a1eb6af3ee35567291a0f8c8a2828 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 2 Feb 2025 15:12:33 +0000 Subject: [PATCH 28/35] Slightly simplify DiagCtxt::make_silent --- compiler/rustc_errors/src/emitter.rs | 12 +++---- compiler/rustc_errors/src/lib.rs | 43 ++++++++++---------------- compiler/rustc_session/src/parse.rs | 5 ++- src/tools/rustfmt/src/parse/session.rs | 2 +- 4 files changed, 25 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 991dfa1821a9..050088d95ba4 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -35,8 +35,8 @@ use crate::snippet::{ use crate::styled_buffer::StyledBuffer; use crate::translation::{Translate, to_fluent_args}; use crate::{ - CodeSuggestion, DiagCtxt, DiagInner, DiagMessage, ErrCode, FluentBundle, LazyFallbackBundle, - Level, MultiSpan, Subdiag, SubstitutionHighlight, SuggestionStyle, TerminalUrl, + CodeSuggestion, DiagInner, DiagMessage, ErrCode, FluentBundle, LazyFallbackBundle, Level, + MultiSpan, Subdiag, SubstitutionHighlight, SuggestionStyle, TerminalUrl, }; /// Default column width, used in tests and when terminal dimensions cannot be determined. @@ -537,11 +537,11 @@ impl Emitter for HumanEmitter { } /// An emitter that does nothing when emitting a non-fatal diagnostic. -/// Fatal diagnostics are forwarded to `fatal_dcx` to avoid silent +/// Fatal diagnostics are forwarded to `fatal_emitter` to avoid silent /// failures of rustc, as witnessed e.g. in issue #89358. pub struct SilentEmitter { pub fallback_bundle: LazyFallbackBundle, - pub fatal_dcx: DiagCtxt, + pub fatal_emitter: Box, pub fatal_note: Option, pub emit_fatal_diagnostic: bool, } @@ -563,12 +563,12 @@ impl Emitter for SilentEmitter { None } - fn emit_diagnostic(&mut self, mut diag: DiagInner, _registry: &Registry) { + fn emit_diagnostic(&mut self, mut diag: DiagInner, registry: &Registry) { if self.emit_fatal_diagnostic && diag.level == Level::Fatal { if let Some(fatal_note) = &self.fatal_note { diag.sub(Level::Note, fatal_note.clone(), MultiSpan::new()); } - self.fatal_dcx.handle().emit_diagnostic(diag); + self.fatal_emitter.emit_diagnostic(diag, registry); } } } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 549729548f53..41862330458d 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -59,7 +59,7 @@ use emitter::{DynEmitter, Emitter, is_case_difference, is_different}; use rustc_data_structures::AtomicRef; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::stable_hasher::{Hash128, StableHasher}; -use rustc_data_structures::sync::Lock; +use rustc_data_structures::sync::{DynSend, Lock}; pub use rustc_error_messages::{ DiagMessage, FluentBundle, LanguageIdentifier, LazyFallbackBundle, MultiSpan, SpanLabel, SubdiagMessage, fallback_fluent_bundle, fluent_bundle, @@ -682,51 +682,40 @@ impl DiagCtxt { fatal_note: Option, emit_fatal_diagnostic: bool, ) { - self.wrap_emitter(|old_dcx| { - Box::new(emitter::SilentEmitter { - fallback_bundle, - fatal_dcx: DiagCtxt { inner: Lock::new(old_dcx) }, - fatal_note, - emit_fatal_diagnostic, - }) - }); - } - - fn wrap_emitter(&self, f: F) - where - F: FnOnce(DiagCtxtInner) -> Box, - { - // A empty type that implements `Emitter` so that a `DiagCtxtInner` can be constructed - // to temporarily swap in place of the real one, which will be used in constructing - // its replacement. + // An empty type that implements `Emitter` to temporarily swap in place of the real one, + // which will be used in constructing its replacement. struct FalseEmitter; impl Emitter for FalseEmitter { fn emit_diagnostic(&mut self, _: DiagInner, _: &Registry) { - unimplemented!("false emitter must only used during `wrap_emitter`") + unimplemented!("false emitter must only used during `make_silent`") } fn source_map(&self) -> Option<&SourceMap> { - unimplemented!("false emitter must only used during `wrap_emitter`") + unimplemented!("false emitter must only used during `make_silent`") } } impl translation::Translate for FalseEmitter { fn fluent_bundle(&self) -> Option<&FluentBundle> { - unimplemented!("false emitter must only used during `wrap_emitter`") + unimplemented!("false emitter must only used during `make_silent`") } fn fallback_fluent_bundle(&self) -> &FluentBundle { - unimplemented!("false emitter must only used during `wrap_emitter`") + unimplemented!("false emitter must only used during `make_silent`") } } let mut inner = self.inner.borrow_mut(); - let mut prev_dcx = DiagCtxtInner::new(Box::new(FalseEmitter)); - std::mem::swap(&mut *inner, &mut prev_dcx); - let new_emitter = f(prev_dcx); - let mut new_dcx = DiagCtxtInner::new(new_emitter); - std::mem::swap(&mut *inner, &mut new_dcx); + let mut prev_emitter = Box::new(FalseEmitter) as Box; + std::mem::swap(&mut inner.emitter, &mut prev_emitter); + let new_emitter = Box::new(emitter::SilentEmitter { + fallback_bundle, + fatal_emitter: prev_emitter, + fatal_note, + emit_fatal_diagnostic, + }); + inner.emitter = new_emitter; } /// Translate `message` eagerly with `args` to `SubdiagMessage::Eager`. diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 90361efed844..0c8040944fb0 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -277,14 +277,13 @@ impl ParseSess { ) -> Self { let fallback_bundle = fallback_fluent_bundle(locale_resources, false); let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); - let emitter = Box::new(HumanEmitter::new( + let fatal_emitter = Box::new(HumanEmitter::new( stderr_destination(ColorConfig::Auto), Lrc::clone(&fallback_bundle), )); - let fatal_dcx = DiagCtxt::new(emitter); let dcx = DiagCtxt::new(Box::new(SilentEmitter { fallback_bundle, - fatal_dcx, + fatal_emitter, fatal_note: Some(fatal_note), emit_fatal_diagnostic, })) diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs index 63cc8794ceae..d1a2974a6177 100644 --- a/src/tools/rustfmt/src/parse/session.rs +++ b/src/tools/rustfmt/src/parse/session.rs @@ -121,7 +121,7 @@ fn default_dcx( let emitter: Box = if !show_parse_errors { Box::new(SilentEmitter { fallback_bundle, - fatal_dcx: DiagCtxt::new(emitter), + fatal_emitter: emitter, fatal_note: None, emit_fatal_diagnostic: false, }) From 6556147d15f077dfc88dae22f3983b3598bce465 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 2 Feb 2025 15:36:28 +0000 Subject: [PATCH 29/35] Use fallback fluent bundle from inner emitter in SilentEmitter --- compiler/rustc_errors/src/emitter.rs | 5 +---- compiler/rustc_errors/src/lib.rs | 8 +------- compiler/rustc_session/src/parse.rs | 7 ++----- src/tools/rustfmt/src/parse/session.rs | 14 ++------------ 4 files changed, 6 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 050088d95ba4..d0b4211c351c 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -540,7 +540,6 @@ impl Emitter for HumanEmitter { /// Fatal diagnostics are forwarded to `fatal_emitter` to avoid silent /// failures of rustc, as witnessed e.g. in issue #89358. pub struct SilentEmitter { - pub fallback_bundle: LazyFallbackBundle, pub fatal_emitter: Box, pub fatal_note: Option, pub emit_fatal_diagnostic: bool, @@ -552,9 +551,7 @@ impl Translate for SilentEmitter { } fn fallback_fluent_bundle(&self) -> &FluentBundle { - // Ideally this field wouldn't be necessary and the fallback bundle in `fatal_dcx` would be - // used but the lock prevents this. - &self.fallback_bundle + self.fatal_emitter.fallback_fluent_bundle() } } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 41862330458d..e64bb003ddea 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -676,12 +676,7 @@ impl DiagCtxt { Self { inner: Lock::new(DiagCtxtInner::new(emitter)) } } - pub fn make_silent( - &self, - fallback_bundle: LazyFallbackBundle, - fatal_note: Option, - emit_fatal_diagnostic: bool, - ) { + pub fn make_silent(&self, fatal_note: Option, emit_fatal_diagnostic: bool) { // An empty type that implements `Emitter` to temporarily swap in place of the real one, // which will be used in constructing its replacement. struct FalseEmitter; @@ -710,7 +705,6 @@ impl DiagCtxt { let mut prev_emitter = Box::new(FalseEmitter) as Box; std::mem::swap(&mut inner.emitter, &mut prev_emitter); let new_emitter = Box::new(emitter::SilentEmitter { - fallback_bundle, fatal_emitter: prev_emitter, fatal_note, emit_fatal_diagnostic, diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 0c8040944fb0..b6b13a715eca 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -277,12 +277,9 @@ impl ParseSess { ) -> Self { let fallback_bundle = fallback_fluent_bundle(locale_resources, false); let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); - let fatal_emitter = Box::new(HumanEmitter::new( - stderr_destination(ColorConfig::Auto), - Lrc::clone(&fallback_bundle), - )); + let fatal_emitter = + Box::new(HumanEmitter::new(stderr_destination(ColorConfig::Auto), fallback_bundle)); let dcx = DiagCtxt::new(Box::new(SilentEmitter { - fallback_bundle, fatal_emitter, fatal_note: Some(fatal_note), emit_fatal_diagnostic, diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs index d1a2974a6177..34077c5f8665 100644 --- a/src/tools/rustfmt/src/parse/session.rs +++ b/src/tools/rustfmt/src/parse/session.rs @@ -114,13 +114,12 @@ fn default_dcx( false, ); let emitter = Box::new( - HumanEmitter::new(stderr_destination(emit_color), fallback_bundle.clone()) + HumanEmitter::new(stderr_destination(emit_color), fallback_bundle) .sm(Some(source_map.clone())), ); let emitter: Box = if !show_parse_errors { Box::new(SilentEmitter { - fallback_bundle, fatal_emitter: emitter, fatal_note: None, emit_fatal_diagnostic: false, @@ -205,16 +204,7 @@ impl ParseSess { } pub(crate) fn set_silent_emitter(&mut self) { - // Ideally this invocation wouldn't be necessary and the fallback bundle in - // `self.parse_sess.dcx` could be used, but the lock in `DiagCtxt` prevents this. - // See `::fallback_fluent_bundle`. - let fallback_bundle = rustc_errors::fallback_fluent_bundle( - rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), - false, - ); - self.raw_psess - .dcx() - .make_silent(fallback_bundle, None, false); + self.raw_psess.dcx().make_silent(None, false); } pub(crate) fn span_to_filename(&self, span: Span) -> FileName { From 6a566ee092cacf6e4b327e7fdbbb1003a514b820 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 2 Feb 2025 16:06:16 +0000 Subject: [PATCH 30/35] Replace ParseSess::set_dcx with DiagCtxt::set_emitter Replacing the error emitter doesn't accidentally clear the error count. --- compiler/rustc_errors/src/lib.rs | 4 ++++ compiler/rustc_session/src/parse.rs | 4 ---- .../examples/rustc-interface-getting-diagnostics.rs | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index e64bb003ddea..f30b6921cfb4 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -712,6 +712,10 @@ impl DiagCtxt { inner.emitter = new_emitter; } + pub fn set_emitter(&self, emitter: Box) { + self.inner.borrow_mut().emitter = emitter; + } + /// Translate `message` eagerly with `args` to `SubdiagMessage::Eager`. pub fn eagerly_translate<'a>( &self, diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index b6b13a715eca..81ae06602cdb 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -337,8 +337,4 @@ impl ParseSess { pub fn dcx(&self) -> DiagCtxtHandle<'_> { self.dcx.handle() } - - pub fn set_dcx(&mut self, dcx: DiagCtxt) { - self.dcx = dcx; - } } diff --git a/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs b/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs index be37dd867b25..2355cb85ab3d 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs @@ -10,6 +10,8 @@ extern crate rustc_interface; extern crate rustc_session; extern crate rustc_span; +use std::sync::{Arc, Mutex}; + use rustc_errors::emitter::Emitter; use rustc_errors::registry::{self, Registry}; use rustc_errors::translation::Translate; @@ -17,8 +19,6 @@ use rustc_errors::{DiagCtxt, DiagInner, FluentBundle}; use rustc_session::config; use rustc_span::source_map::SourceMap; -use std::sync::{Arc, Mutex}; - struct DebugEmitter { source_map: Arc, diagnostics: Arc>>, @@ -67,10 +67,10 @@ fn main() { locale_resources: rustc_driver::DEFAULT_LOCALE_RESOURCES.to_owned(), lint_caps: rustc_hash::FxHashMap::default(), psess_created: Some(Box::new(|parse_sess| { - parse_sess.set_dcx(DiagCtxt::new(Box::new(DebugEmitter { + parse_sess.dcx().set_emitter(Box::new(DebugEmitter { source_map: parse_sess.clone_source_map(), diagnostics, - }))); + })); })), register_lints: None, override_queries: None, From 2f2b32b84e778669e06be5e37643f21ba98bedc8 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 27 Jan 2025 16:36:45 +0000 Subject: [PATCH 31/35] Test validity of pattern types --- .../src/interpret/validity.rs | 12 +++ tests/ui/type/pattern_types/validity.rs | 37 +++++++++ tests/ui/type/pattern_types/validity.stderr | 79 +++++++++++++++++++ 3 files changed, 128 insertions(+) create mode 100644 tests/ui/type/pattern_types/validity.rs create mode 100644 tests/ui/type/pattern_types/validity.stderr diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index d75df1ad4425..649a759bc8bf 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -4,6 +4,7 @@ //! That's useful because it means other passes (e.g. promotion) can rely on `const`s //! to be const-safe. +use std::assert_matches::assert_matches; use std::borrow::Cow; use std::fmt::Write; use std::hash::Hash; @@ -1240,6 +1241,17 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, self.visit_field(val, 0, &self.ecx.project_index(val, 0)?)?; } } + ty::Pat(_base, pat) => { + // When you extend this match, make sure to also add tests to + // tests/ui/type/pattern_types/validity.rs(( + match **pat { + // Range patterns are precisely reflected into `valid_range` and thus + // handled fully by `visit_scalar` (called below). + ty::PatternKind::Range { .. } => { + assert_matches!(val.layout.backend_repr, BackendRepr::Scalar(_)); + }, + } + } _ => { // default handler try_validation!( diff --git a/tests/ui/type/pattern_types/validity.rs b/tests/ui/type/pattern_types/validity.rs new file mode 100644 index 000000000000..77a4e72f6755 --- /dev/null +++ b/tests/ui/type/pattern_types/validity.rs @@ -0,0 +1,37 @@ +//! Check that pattern types have their validity checked + +#![feature(pattern_types)] +#![feature(pattern_type_macro)] + +use std::pat::pattern_type; + +const BAD: pattern_type!(u32 is 1..) = unsafe { std::mem::transmute(0) }; +//~^ ERROR: it is undefined behavior to use this value + +const BAD_UNINIT: pattern_type!(u32 is 1..) = + //~^ ERROR: evaluation of constant value failed + unsafe { std::mem::transmute(std::mem::MaybeUninit::::uninit()) }; + +const BAD_PTR: pattern_type!(usize is 1..) = unsafe { std::mem::transmute(&42) }; +//~^ ERROR: evaluation of constant value failed + +const BAD_AGGREGATE: (pattern_type!(u32 is 1..), u32) = (unsafe { std::mem::transmute(0) }, 0); +//~^ ERROR: it is undefined behavior to use this value + +struct Foo(Bar); +struct Bar(pattern_type!(u32 is 1..)); + +const BAD_FOO: Foo = Foo(Bar(unsafe { std::mem::transmute(0) })); +//~^ ERROR: it is undefined behavior to use this value + +const CHAR_UNINIT: pattern_type!(char is 'A'..'Z') = + //~^ ERROR: evaluation of constant value failed + unsafe { std::mem::transmute(std::mem::MaybeUninit::::uninit()) }; + +const CHAR_OOB_PAT: pattern_type!(char is 'A'..'Z') = unsafe { std::mem::transmute('a') }; +//~^ ERROR: it is undefined behavior to use this value + +const CHAR_OOB: pattern_type!(char is 'A'..'Z') = unsafe { std::mem::transmute(u32::MAX) }; +//~^ ERROR: it is undefined behavior to use this value + +fn main() {} diff --git a/tests/ui/type/pattern_types/validity.stderr b/tests/ui/type/pattern_types/validity.stderr new file mode 100644 index 000000000000..21b7792b83e8 --- /dev/null +++ b/tests/ui/type/pattern_types/validity.stderr @@ -0,0 +1,79 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/validity.rs:8:1 + | +LL | const BAD: pattern_type!(u32 is 1..) = unsafe { std::mem::transmute(0) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 + | + = 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) { + 00 00 00 00 │ .... + } + +error[E0080]: evaluation of constant value failed + --> $DIR/validity.rs:11:1 + | +LL | const BAD_UNINIT: pattern_type!(u32 is 1..) = + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + +error[E0080]: evaluation of constant value failed + --> $DIR/validity.rs:15:1 + | +LL | const BAD_PTR: pattern_type!(usize is 1..) = unsafe { std::mem::transmute(&42) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: it is undefined behavior to use this value + --> $DIR/validity.rs:18:1 + | +LL | const BAD_AGGREGATE: (pattern_type!(u32 is 1..), u32) = (unsafe { std::mem::transmute(0) }, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0, but expected something greater or equal to 1 + | + = 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: 4) { + 00 00 00 00 00 00 00 00 │ ........ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/validity.rs:24:1 + | +LL | const BAD_FOO: Foo = Foo(Bar(unsafe { std::mem::transmute(0) })); + | ^^^^^^^^^^^^^^^^^^ constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1 + | + = 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) { + 00 00 00 00 │ .... + } + +error[E0080]: evaluation of constant value failed + --> $DIR/validity.rs:27:1 + | +LL | const CHAR_UNINIT: pattern_type!(char is 'A'..'Z') = + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + +error[E0080]: it is undefined behavior to use this value + --> $DIR/validity.rs:31:1 + | +LL | const CHAR_OOB_PAT: pattern_type!(char is 'A'..'Z') = unsafe { std::mem::transmute('a') }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 97, but expected something in the range 65..=89 + | + = 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) { + 61 00 00 00 │ a... + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/validity.rs:34:1 + | +LL | const CHAR_OOB: pattern_type!(char is 'A'..'Z') = unsafe { std::mem::transmute(u32::MAX) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 4294967295, but expected something in the range 65..=89 + | + = 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) { + ff ff ff ff │ .... + } + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0080`. From ded0836c18a0b25f076ee776e1c9eeb989272f3b Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Sun, 2 Feb 2025 17:54:35 +0000 Subject: [PATCH 32/35] Check the base type of pattern types for validity first --- compiler/rustc_const_eval/src/interpret/validity.rs | 9 ++++----- tests/ui/type/pattern_types/validity.stderr | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 649a759bc8bf..8e5447987429 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -4,7 +4,6 @@ //! That's useful because it means other passes (e.g. promotion) can rely on `const`s //! to be const-safe. -use std::assert_matches::assert_matches; use std::borrow::Cow; use std::fmt::Write; use std::hash::Hash; @@ -1241,15 +1240,15 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, self.visit_field(val, 0, &self.ecx.project_index(val, 0)?)?; } } - ty::Pat(_base, pat) => { + ty::Pat(base, pat) => { + // First check that the base type is valid + self.visit_value(&val.transmute(self.ecx.layout_of(*base)?, self.ecx)?)?; // When you extend this match, make sure to also add tests to // tests/ui/type/pattern_types/validity.rs(( match **pat { // Range patterns are precisely reflected into `valid_range` and thus // handled fully by `visit_scalar` (called below). - ty::PatternKind::Range { .. } => { - assert_matches!(val.layout.backend_repr, BackendRepr::Scalar(_)); - }, + ty::PatternKind::Range { .. } => {}, } } _ => { diff --git a/tests/ui/type/pattern_types/validity.stderr b/tests/ui/type/pattern_types/validity.stderr index 21b7792b83e8..5bc18cfba3f7 100644 --- a/tests/ui/type/pattern_types/validity.stderr +++ b/tests/ui/type/pattern_types/validity.stderr @@ -67,7 +67,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/validity.rs:34:1 | LL | const CHAR_OOB: pattern_type!(char is 'A'..'Z') = unsafe { std::mem::transmute(u32::MAX) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 4294967295, but expected something in the range 65..=89 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`) | = 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) { From 7e4ccc2f12f29a5c12c5669afd25b7e0481baf52 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 28 Jan 2025 12:07:36 +0000 Subject: [PATCH 33/35] Maintain a list of types permitted per pattern --- compiler/rustc_hir_analysis/messages.ftl | 4 +- .../src/errors/pattern_types.rs | 12 ++++ .../src/hir_ty_lowering/mod.rs | 15 ++++- tests/ui/type/pattern_types/chars.rs | 12 ++++ tests/ui/type/pattern_types/nested.rs | 26 ++++++++ tests/ui/type/pattern_types/nested.stderr | 62 +++++++++++++++++++ .../pattern_types/pattern_type_mismatch.rs | 20 ++++++ .../pattern_type_mismatch.stderr | 31 ++++++++++ tests/ui/type/pattern_types/reverse_range.rs | 14 +++++ .../type/pattern_types/reverse_range.stderr | 17 +++++ 10 files changed, 211 insertions(+), 2 deletions(-) create mode 100644 tests/ui/type/pattern_types/chars.rs create mode 100644 tests/ui/type/pattern_types/nested.rs create mode 100644 tests/ui/type/pattern_types/nested.stderr create mode 100644 tests/ui/type/pattern_types/pattern_type_mismatch.rs create mode 100644 tests/ui/type/pattern_types/pattern_type_mismatch.stderr create mode 100644 tests/ui/type/pattern_types/reverse_range.rs create mode 100644 tests/ui/type/pattern_types/reverse_range.stderr diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index be4004f5904c..a4b5a87361ef 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -234,6 +234,9 @@ hir_analysis_inherent_ty_outside_relevant = cannot define inherent `impl` for a .help = consider moving this inherent impl into the crate defining the type if possible .span_help = alternatively add `#[rustc_allow_incoherent_impl]` to the relevant impl items +hir_analysis_invalid_base_type = `{$ty}` is not a valid base type for range patterns + .note = range patterns only support integers + hir_analysis_invalid_generic_receiver_ty = invalid generic `self` parameter type: `{$receiver_ty}` .note = type of `self` must not be a method generic parameter type @@ -438,7 +441,6 @@ hir_analysis_pattern_type_wild_pat = wildcard patterns are not permitted for pat .label = this type is the same as the inner type without a pattern hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind} .label = not allowed in type signatures - hir_analysis_precise_capture_self_alias = `Self` can't be captured in `use<...>` precise captures list, since it is an alias .label = `Self` is not a generic argument, but an alias to the type of the {$what} diff --git a/compiler/rustc_hir_analysis/src/errors/pattern_types.rs b/compiler/rustc_hir_analysis/src/errors/pattern_types.rs index bb771d6ea170..272edbe841b9 100644 --- a/compiler/rustc_hir_analysis/src/errors/pattern_types.rs +++ b/compiler/rustc_hir_analysis/src/errors/pattern_types.rs @@ -1,4 +1,5 @@ use rustc_macros::Diagnostic; +use rustc_middle::ty::Ty; use rustc_span::Span; #[derive(Diagnostic)] @@ -7,3 +8,14 @@ pub(crate) struct WildPatTy { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(hir_analysis_invalid_base_type)] +pub(crate) struct InvalidBaseType<'tcx> { + pub ty: Ty<'tcx>, + #[primary_span] + pub ty_span: Span, + pub pat: &'static str, + #[note] + pub pat_span: Span, +} diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index b4cab3330afa..5813fdeae764 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -53,7 +53,7 @@ use tracing::{debug, instrument}; use crate::bounds::Bounds; use crate::check::check_abi_fn_ptr; -use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation, WildPatTy}; +use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation, InvalidBaseType, WildPatTy}; use crate::hir_ty_lowering::errors::{GenericsArgsErrExtend, prohibit_assoc_item_constraint}; use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args}; use crate::middle::resolve_bound_vars as rbv; @@ -2432,6 +2432,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { self.ty_infer(None, hir_ty.span) } hir::TyKind::Pat(ty, pat) => { + let ty_span = ty.span; let ty = self.lower_ty(ty); let pat_ty = match pat.kind { hir::PatKind::Wild => { @@ -2439,6 +2440,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Ty::new_error(tcx, err) } hir::PatKind::Range(start, end, include_end) => { + let ty = match ty.kind() { + ty::Int(_) | ty::Uint(_) | ty::Char => ty, + _ => Ty::new_error( + tcx, + self.dcx().emit_err(InvalidBaseType { + ty, + pat: "range", + ty_span, + pat_span: pat.span, + }), + ), + }; let expr_to_const = |expr: &'tcx hir::PatExpr<'tcx>| -> ty::Const<'tcx> { let (c, c_ty) = match expr.kind { hir::PatExprKind::Lit { lit, negated } => { diff --git a/tests/ui/type/pattern_types/chars.rs b/tests/ui/type/pattern_types/chars.rs new file mode 100644 index 000000000000..9073998b387b --- /dev/null +++ b/tests/ui/type/pattern_types/chars.rs @@ -0,0 +1,12 @@ +//! Check that chars can be used in ranges + +//@ check-pass + +#![feature(pattern_types)] +#![feature(pattern_type_macro)] + +use std::pat::pattern_type; + +const LOWERCASE: pattern_type!(char is 'a'..='z') = unsafe { std::mem::transmute('b') }; + +fn main() {} diff --git a/tests/ui/type/pattern_types/nested.rs b/tests/ui/type/pattern_types/nested.rs new file mode 100644 index 000000000000..519fb3f05b48 --- /dev/null +++ b/tests/ui/type/pattern_types/nested.rs @@ -0,0 +1,26 @@ +//! Check that pattern types can only have specific base types + +#![feature(pattern_types)] +#![feature(pattern_type_macro)] + +use std::pat::pattern_type; + +// Undoing an inner pattern type's restrictions should either be forbidden, +// or still validate correctly. +const BAD_NESTING: pattern_type!(pattern_type!(u32 is 1..) is 0..) = todo!(); +//~^ ERROR: not a valid base type for range patterns + +// We want to get the most narrowest version that a pattern could be +const BAD_NESTING2: pattern_type!(pattern_type!(i32 is 1..) is ..=-1) = todo!(); +//~^ ERROR: not a valid base type for range patterns + +const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!(); +//~^ ERROR: not a valid base type for range patterns + +const BAD_NESTING4: pattern_type!(() is ..0) = todo!(); +//~^ ERROR: not a valid base type for range patterns + +const BAD_NESTING5: pattern_type!(f32 is 1.0 .. 2.0) = todo!(); +//~^ ERROR: not a valid base type for range patterns + +fn main() {} diff --git a/tests/ui/type/pattern_types/nested.stderr b/tests/ui/type/pattern_types/nested.stderr new file mode 100644 index 000000000000..99d3979e98c4 --- /dev/null +++ b/tests/ui/type/pattern_types/nested.stderr @@ -0,0 +1,62 @@ +error: `(u32) is 1..=` is not a valid base type for range patterns + --> $DIR/nested.rs:10:34 + | +LL | const BAD_NESTING: pattern_type!(pattern_type!(u32 is 1..) is 0..) = todo!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: range patterns only support integers + --> $DIR/nested.rs:10:63 + | +LL | const BAD_NESTING: pattern_type!(pattern_type!(u32 is 1..) is 0..) = todo!(); + | ^^^ + +error: `(i32) is 1..=` is not a valid base type for range patterns + --> $DIR/nested.rs:14:35 + | +LL | const BAD_NESTING2: pattern_type!(pattern_type!(i32 is 1..) is ..=-1) = todo!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: range patterns only support integers + --> $DIR/nested.rs:14:64 + | +LL | const BAD_NESTING2: pattern_type!(pattern_type!(i32 is 1..) is ..=-1) = todo!(); + | ^^^^^ + +error: `(i32) is 1..=` is not a valid base type for range patterns + --> $DIR/nested.rs:17:35 + | +LL | const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: range patterns only support integers + --> $DIR/nested.rs:17:64 + | +LL | const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!(); + | ^^^ + +error: `()` is not a valid base type for range patterns + --> $DIR/nested.rs:20:35 + | +LL | const BAD_NESTING4: pattern_type!(() is ..0) = todo!(); + | ^^ + | +note: range patterns only support integers + --> $DIR/nested.rs:20:41 + | +LL | const BAD_NESTING4: pattern_type!(() is ..0) = todo!(); + | ^^^ + +error: `f32` is not a valid base type for range patterns + --> $DIR/nested.rs:23:35 + | +LL | const BAD_NESTING5: pattern_type!(f32 is 1.0 .. 2.0) = todo!(); + | ^^^ + | +note: range patterns only support integers + --> $DIR/nested.rs:23:42 + | +LL | const BAD_NESTING5: pattern_type!(f32 is 1.0 .. 2.0) = todo!(); + | ^^^^^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/type/pattern_types/pattern_type_mismatch.rs b/tests/ui/type/pattern_types/pattern_type_mismatch.rs new file mode 100644 index 000000000000..8d375d7932bc --- /dev/null +++ b/tests/ui/type/pattern_types/pattern_type_mismatch.rs @@ -0,0 +1,20 @@ +//! Check that pattern types patterns must be of the type of the base type + +//@ known-bug: unknown +//@ failure-status: 101 +//@ normalize-stderr: "note: .*\n\n" -> "" +//@ normalize-stderr: "thread 'rustc' panicked.*\n" -> "" +//@ normalize-stderr: "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: " +//@ normalize-stderr: "(delayed at compiler/rustc_mir_transform/src/lib.rs:)\d+:\d+" -> "$1:LL:CC" +//@ rustc-env:RUST_BACKTRACE=0 + +#![feature(pattern_types)] +#![feature(pattern_type_macro)] + +use std::pat::pattern_type; + +const BAD_NESTING4: pattern_type!(u8 is 'a'..='a') = todo!(); + +const BAD_NESTING5: pattern_type!(char is 1..=1) = todo!(); + +fn main() {} diff --git a/tests/ui/type/pattern_types/pattern_type_mismatch.stderr b/tests/ui/type/pattern_types/pattern_type_mismatch.stderr new file mode 100644 index 000000000000..ee413133ab31 --- /dev/null +++ b/tests/ui/type/pattern_types/pattern_type_mismatch.stderr @@ -0,0 +1,31 @@ +error: internal compiler error: ty::ConstKind::Error constructed but no error reported + | + = error: internal compiler error: ty::ConstKind::Error constructed but no error reported + | + = note: delayed at compiler/rustc_mir_build/src/thir/constant.rs:72:21 - disabled backtrace + = error: internal compiler error: mir_const_qualif: MIR had errors + --> $DIR/pattern_type_mismatch.rs:16:1 + | +LL | const BAD_NESTING4: pattern_type!(u8 is 'a'..='a') = todo!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: delayed at compiler/rustc_mir_transform/src/lib.rs::LL:CC - disabled backtrace + --> $DIR/pattern_type_mismatch.rs:16:1 + | +LL | const BAD_NESTING4: pattern_type!(u8 is 'a'..='a') = todo!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: internal compiler error: mir_const_qualif: MIR had errors + --> $DIR/pattern_type_mismatch.rs:18:1 + | +LL | const BAD_NESTING5: pattern_type!(char is 1..=1) = todo!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: delayed at compiler/rustc_mir_transform/src/lib.rs::LL:CC - disabled backtrace + --> $DIR/pattern_type_mismatch.rs:18:1 + | +LL | const BAD_NESTING5: pattern_type!(char is 1..=1) = todo!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +query stack during panic: +end of query stack diff --git a/tests/ui/type/pattern_types/reverse_range.rs b/tests/ui/type/pattern_types/reverse_range.rs new file mode 100644 index 000000000000..6a245615f1ac --- /dev/null +++ b/tests/ui/type/pattern_types/reverse_range.rs @@ -0,0 +1,14 @@ +//! Check that the range start must be smaller than the range end +//@ known-bug: unknown +//@ failure-status: 101 +//@ normalize-stderr: "note: .*\n\n" -> "" +//@ normalize-stderr: "thread 'rustc' panicked.*\n" -> "" +//@ normalize-stderr: "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: " +//@ rustc-env:RUST_BACKTRACE=0 + +#![feature(pattern_types)] +#![feature(pattern_type_macro)] + +use std::pat::pattern_type; + +const NONE: pattern_type!(u8 is 1..0) = unsafe { std::mem::transmute(3_u8) }; diff --git a/tests/ui/type/pattern_types/reverse_range.stderr b/tests/ui/type/pattern_types/reverse_range.stderr new file mode 100644 index 000000000000..b714ca7d9ab9 --- /dev/null +++ b/tests/ui/type/pattern_types/reverse_range.stderr @@ -0,0 +1,17 @@ +error[E0601]: `main` function not found in crate `reverse_range` + --> $DIR/reverse_range.rs:14:78 + | +LL | const NONE: pattern_type!(u8 is 1..0) = unsafe { std::mem::transmute(3_u8) }; + | ^ consider adding a `main` function to `$DIR/reverse_range.rs` + + +assertion failed: end <= max_value +error: the compiler unexpectedly panicked. this is a bug. + +query stack during panic: +#0 [eval_to_allocation_raw] const-evaluating + checking `NONE` +#1 [eval_to_const_value_raw] simplifying constant for the type system `NONE` +... and 1 other queries... use `env RUST_BACKTRACE=1` to see the full query stack +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0601`. From 3c7c38ad9335b043315addc1fcabf3631bbe1125 Mon Sep 17 00:00:00 2001 From: real-eren Date: Sun, 2 Feb 2025 17:59:43 -0500 Subject: [PATCH 34/35] Simplify SSE2 implementation --- .../rustc_span/src/analyze_source_file.rs | 24 +++++-------------- 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_span/src/analyze_source_file.rs b/compiler/rustc_span/src/analyze_source_file.rs index fba205665803..87c8e3fce072 100644 --- a/compiler/rustc_span/src/analyze_source_file.rs +++ b/compiler/rustc_span/src/analyze_source_file.rs @@ -110,25 +110,19 @@ cfg_match! { if control_char_mask != 0 { // Check for newlines in the chunk let newlines_test = unsafe { _mm_cmpeq_epi8(chunk, _mm_set1_epi8(b'\n' as i8)) }; - let newlines_mask = unsafe { _mm_movemask_epi8(newlines_test) }; + let mut newlines_mask = unsafe { _mm_movemask_epi8(newlines_test) }; if control_char_mask == newlines_mask { // All control characters are newlines, record them - let mut newlines_mask = 0xFFFF0000 | newlines_mask as u32; let output_offset = RelativeBytePos::from_usize(chunk_index * CHUNK_SIZE + 1); - loop { + while newlines_mask != 0 { let index = newlines_mask.trailing_zeros(); - if index >= CHUNK_SIZE as u32 { - // We have arrived at the end of the chunk. - break; - } - lines.push(RelativeBytePos(index) + output_offset); // Clear the bit, so we can find the next one. - newlines_mask &= (!1) << index; + newlines_mask &= newlines_mask - 1; } // We are done for this chunk. All control characters were @@ -268,25 +262,19 @@ cfg_match! { if control_char_mask != 0 { // Check for newlines in the chunk let newlines_test = unsafe { _mm_cmpeq_epi8(chunk, _mm_set1_epi8(b'\n' as i8)) }; - let newlines_mask = unsafe { _mm_movemask_epi8(newlines_test) }; + let mut newlines_mask = unsafe { _mm_movemask_epi8(newlines_test) }; if control_char_mask == newlines_mask { // All control characters are newlines, record them - let mut newlines_mask = 0xFFFF0000 | newlines_mask as u32; let output_offset = RelativeBytePos::from_usize(chunk_index * CHUNK_SIZE + 1); - loop { + while newlines_mask != 0 { let index = newlines_mask.trailing_zeros(); - if index >= CHUNK_SIZE as u32 { - // We have arrived at the end of the chunk. - break; - } - lines.push(RelativeBytePos(index) + output_offset); // Clear the bit, so we can find the next one. - newlines_mask &= (!1) << index; + newlines_mask &= newlines_mask - 1; } // We are done for this chunk. All control characters were From d6ca7ad0d7a7e8acd14f6da3bad4e7b5a25c3d17 Mon Sep 17 00:00:00 2001 From: real-eren Date: Sun, 2 Feb 2025 19:39:07 -0500 Subject: [PATCH 35/35] Remove dead control char logic Only newlines and multibyte characters are actually relevant --- .../rustc_span/src/analyze_source_file.rs | 159 ++++++------------ 1 file changed, 47 insertions(+), 112 deletions(-) diff --git a/compiler/rustc_span/src/analyze_source_file.rs b/compiler/rustc_span/src/analyze_source_file.rs index 87c8e3fce072..47cc16b623d1 100644 --- a/compiler/rustc_span/src/analyze_source_file.rs +++ b/compiler/rustc_span/src/analyze_source_file.rs @@ -95,59 +95,32 @@ cfg_match! { if multibyte_mask == 0 { assert!(intra_chunk_offset == 0); - // Check if there are any control characters in the chunk. All - // control characters that we can encounter at this point have a - // byte value less than 32 or ... - let control_char_test0 = unsafe { _mm_cmplt_epi8(chunk, _mm_set1_epi8(32)) }; - let control_char_mask0 = unsafe { _mm_movemask_epi8(control_char_test0) }; + // Check for newlines in the chunk + let newlines_test = unsafe { _mm_cmpeq_epi8(chunk, _mm_set1_epi8(b'\n' as i8)) }; + let mut newlines_mask = unsafe { _mm_movemask_epi8(newlines_test) }; - // ... it's the ASCII 'DEL' character with a value of 127. - let control_char_test1 = unsafe { _mm_cmpeq_epi8(chunk, _mm_set1_epi8(127)) }; - let control_char_mask1 = unsafe { _mm_movemask_epi8(control_char_test1) }; + let output_offset = RelativeBytePos::from_usize(chunk_index * CHUNK_SIZE + 1); - let control_char_mask = control_char_mask0 | control_char_mask1; + while newlines_mask != 0 { + let index = newlines_mask.trailing_zeros(); - if control_char_mask != 0 { - // Check for newlines in the chunk - let newlines_test = unsafe { _mm_cmpeq_epi8(chunk, _mm_set1_epi8(b'\n' as i8)) }; - let mut newlines_mask = unsafe { _mm_movemask_epi8(newlines_test) }; + lines.push(RelativeBytePos(index) + output_offset); - if control_char_mask == newlines_mask { - // All control characters are newlines, record them - let output_offset = RelativeBytePos::from_usize(chunk_index * CHUNK_SIZE + 1); - - while newlines_mask != 0 { - let index = newlines_mask.trailing_zeros(); - - lines.push(RelativeBytePos(index) + output_offset); - - // Clear the bit, so we can find the next one. - newlines_mask &= newlines_mask - 1; - } - - // We are done for this chunk. All control characters were - // newlines and we took care of those. - continue; - } else { - // Some of the control characters are not newlines, - // fall through to the slow path below. - } - } else { - // No control characters, nothing to record for this chunk - continue; + // Clear the bit, so we can find the next one. + newlines_mask &= newlines_mask - 1; } + } else { + // The slow path. + // There are multibyte chars in here, fallback to generic decoding. + let scan_start = chunk_index * CHUNK_SIZE + intra_chunk_offset; + intra_chunk_offset = analyze_source_file_generic( + &src[scan_start..], + CHUNK_SIZE - intra_chunk_offset, + RelativeBytePos::from_usize(scan_start), + lines, + multi_byte_chars, + ); } - - // The slow path. - // There are control chars in here, fallback to generic decoding. - let scan_start = chunk_index * CHUNK_SIZE + intra_chunk_offset; - intra_chunk_offset = analyze_source_file_generic( - &src[scan_start..], - CHUNK_SIZE - intra_chunk_offset, - RelativeBytePos::from_usize(scan_start), - lines, - multi_byte_chars, - ); } // There might still be a tail left to analyze @@ -247,59 +220,32 @@ cfg_match! { if multibyte_mask == 0 { assert!(intra_chunk_offset == 0); - // Check if there are any control characters in the chunk. All - // control characters that we can encounter at this point have a - // byte value less than 32 or ... - let control_char_test0 = unsafe { _mm_cmplt_epi8(chunk, _mm_set1_epi8(32)) }; - let control_char_mask0 = unsafe { _mm_movemask_epi8(control_char_test0) }; + // Check for newlines in the chunk + let newlines_test = unsafe { _mm_cmpeq_epi8(chunk, _mm_set1_epi8(b'\n' as i8)) }; + let mut newlines_mask = unsafe { _mm_movemask_epi8(newlines_test) }; - // ... it's the ASCII 'DEL' character with a value of 127. - let control_char_test1 = unsafe { _mm_cmpeq_epi8(chunk, _mm_set1_epi8(127)) }; - let control_char_mask1 = unsafe { _mm_movemask_epi8(control_char_test1) }; + let output_offset = RelativeBytePos::from_usize(chunk_index * CHUNK_SIZE + 1); - let control_char_mask = control_char_mask0 | control_char_mask1; + while newlines_mask != 0 { + let index = newlines_mask.trailing_zeros(); - if control_char_mask != 0 { - // Check for newlines in the chunk - let newlines_test = unsafe { _mm_cmpeq_epi8(chunk, _mm_set1_epi8(b'\n' as i8)) }; - let mut newlines_mask = unsafe { _mm_movemask_epi8(newlines_test) }; + lines.push(RelativeBytePos(index) + output_offset); - if control_char_mask == newlines_mask { - // All control characters are newlines, record them - let output_offset = RelativeBytePos::from_usize(chunk_index * CHUNK_SIZE + 1); - - while newlines_mask != 0 { - let index = newlines_mask.trailing_zeros(); - - lines.push(RelativeBytePos(index) + output_offset); - - // Clear the bit, so we can find the next one. - newlines_mask &= newlines_mask - 1; - } - - // We are done for this chunk. All control characters were - // newlines and we took care of those. - continue; - } else { - // Some of the control characters are not newlines, - // fall through to the slow path below. - } - } else { - // No control characters, nothing to record for this chunk - continue; + // Clear the bit, so we can find the next one. + newlines_mask &= newlines_mask - 1; } + } else { + // The slow path. + // There are multibyte chars in here, fallback to generic decoding. + let scan_start = chunk_index * CHUNK_SIZE + intra_chunk_offset; + intra_chunk_offset = analyze_source_file_generic( + &src[scan_start..], + CHUNK_SIZE - intra_chunk_offset, + RelativeBytePos::from_usize(scan_start), + lines, + multi_byte_chars, + ); } - - // The slow path. - // There are control chars in here, fallback to generic decoding. - let scan_start = chunk_index * CHUNK_SIZE + intra_chunk_offset; - intra_chunk_offset = analyze_source_file_generic( - &src[scan_start..], - CHUNK_SIZE - intra_chunk_offset, - RelativeBytePos::from_usize(scan_start), - lines, - multi_byte_chars, - ); } // There might still be a tail left to analyze @@ -357,29 +303,18 @@ fn analyze_source_file_generic( // string. let mut char_len = 1; - if byte < 32 { - // This is an ASCII control character, it could be one of the cases - // that are interesting to us. - + if byte == b'\n' { let pos = RelativeBytePos::from_usize(i) + output_offset; - - if let b'\n' = byte { - lines.push(pos + RelativeBytePos(1)); - } - } else if byte >= 127 { - // The slow path: - // This is either ASCII control character "DEL" or the beginning of - // a multibyte char. Just decode to `char`. + lines.push(pos + RelativeBytePos(1)); + } else if byte >= 128 { + // This is the beginning of a multibyte char. Just decode to `char`. let c = src[i..].chars().next().unwrap(); char_len = c.len_utf8(); let pos = RelativeBytePos::from_usize(i) + output_offset; - - if char_len > 1 { - assert!((2..=4).contains(&char_len)); - let mbc = MultiByteChar { pos, bytes: char_len as u8 }; - multi_byte_chars.push(mbc); - } + assert!((2..=4).contains(&char_len)); + let mbc = MultiByteChar { pos, bytes: char_len as u8 }; + multi_byte_chars.push(mbc); } i += char_len;