Merge from rustc

This commit is contained in:
The Miri Conjob Bot 2023-07-30 05:43:01 +00:00
commit 16816aa859
652 changed files with 9124 additions and 8073 deletions

View file

@ -55,7 +55,7 @@ jobs:
- name: mingw-check-tidy
os: ubuntu-20.04-16core-64gb
env: {}
- name: x86_64-gnu-llvm-14
- name: x86_64-gnu-llvm-15
os: ubuntu-20.04-16core-64gb
env: {}
- name: x86_64-gnu-tools
@ -293,10 +293,6 @@ jobs:
env:
RUST_BACKTRACE: 1
os: ubuntu-20.04-8core-32gb
- name: x86_64-gnu-llvm-14
env:
RUST_BACKTRACE: 1
os: ubuntu-20.04-8core-32gb
- name: x86_64-gnu-nopt
os: ubuntu-20.04-4core-16gb
env: {}

View file

@ -220,7 +220,7 @@ dependencies = [
"proc-macro2",
"quote",
"serde",
"syn 2.0.8",
"syn 2.0.27",
]
[[package]]
@ -502,7 +502,7 @@ dependencies = [
"heck",
"proc-macro2",
"quote",
"syn 2.0.8",
"syn 2.0.27",
]
[[package]]
@ -527,7 +527,7 @@ dependencies = [
"regex",
"rustc_tools_util",
"serde",
"syn 2.0.8",
"syn 2.0.27",
"tempfile",
"termize",
"tester",
@ -842,7 +842,7 @@ version = "0.1.73"
dependencies = [
"itertools",
"quote",
"syn 2.0.8",
"syn 2.0.27",
]
[[package]]
@ -943,7 +943,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.8",
"syn 2.0.27",
]
[[package]]
@ -1309,7 +1309,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.8",
"syn 2.0.27",
]
[[package]]
@ -2456,7 +2456,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.8",
"syn 2.0.27",
]
[[package]]
@ -2643,7 +2643,7 @@ dependencies = [
"pest_meta",
"proc-macro2",
"quote",
"syn 2.0.8",
"syn 2.0.27",
]
[[package]]
@ -3586,7 +3586,7 @@ dependencies = [
"fluent-syntax",
"proc-macro2",
"quote",
"syn 2.0.8",
"syn 2.0.27",
"unic-langid",
]
@ -3734,7 +3734,6 @@ dependencies = [
name = "rustc_interface"
version = "0.0.0"
dependencies = [
"atty",
"libloading",
"rustc-rayon",
"rustc-rayon-core",
@ -3856,7 +3855,7 @@ version = "0.1.0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.8",
"syn 2.0.27",
"synstructure 0.13.0",
]
@ -4198,7 +4197,6 @@ dependencies = [
name = "rustc_session"
version = "0.0.0"
dependencies = [
"atty",
"bitflags 1.3.2",
"getopts",
"libc",
@ -4464,7 +4462,7 @@ dependencies = [
"proc-macro2",
"quote",
"serde",
"syn 2.0.8",
"syn 2.0.27",
]
[[package]]
@ -4631,7 +4629,7 @@ checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.8",
"syn 2.0.27",
]
[[package]]
@ -4912,9 +4910,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.8"
version = "2.0.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcc02725fd69ab9f26eab07fad303e2497fad6fb9eba4f96c4d1687bdf704ad9"
checksum = "b60f673f44a8255b9c8c657daf66a596d435f2da81a555b06dc644d080ba45e0"
dependencies = [
"proc-macro2",
"quote",
@ -4941,7 +4939,7 @@ checksum = "285ba80e733fac80aa4270fbcdf83772a79b80aa35c97075320abfee4a915b06"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.8",
"syn 2.0.27",
"unicode-xid",
]
@ -5091,7 +5089,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.8",
"syn 2.0.27",
]
[[package]]
@ -5312,7 +5310,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.8",
"syn 2.0.27",
]
[[package]]
@ -5742,7 +5740,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.8",
"syn 2.0.27",
"wasm-bindgen-shared",
]
@ -5776,7 +5774,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.8",
"syn 2.0.27",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]

View file

@ -2947,6 +2947,7 @@ pub struct StaticItem {
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct ConstItem {
pub defaultness: Defaultness,
pub generics: Generics,
pub ty: P<Ty>,
pub expr: Option<P<Expr>>,
}
@ -3058,6 +3059,7 @@ impl ItemKind {
match self {
Self::Fn(box Fn { generics, .. })
| Self::TyAlias(box TyAlias { generics, .. })
| Self::Const(box ConstItem { generics, .. })
| Self::Enum(_, generics)
| Self::Struct(_, generics)
| Self::Union(_, generics)

View file

@ -285,17 +285,17 @@ impl MetaItem {
self.kind.value_str()
}
fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<MetaItem>
fn from_tokens<'a, I>(tokens: &mut iter::Peekable<I>) -> Option<MetaItem>
where
I: Iterator<Item = TokenTree>,
I: Iterator<Item = &'a TokenTree>,
{
// FIXME: Share code with `parse_path`.
let path = match tokens.next().map(TokenTree::uninterpolate) {
Some(TokenTree::Token(
Token { kind: kind @ (token::Ident(..) | token::ModSep), span },
let path = match tokens.next().map(|tt| TokenTree::uninterpolate(tt)).as_deref() {
Some(&TokenTree::Token(
Token { kind: ref kind @ (token::Ident(..) | token::ModSep), span },
_,
)) => 'arm: {
let mut segments = if let token::Ident(name, _) = kind {
let mut segments = if let &token::Ident(name, _) = kind {
if let Some(TokenTree::Token(Token { kind: token::ModSep, .. }, _)) =
tokens.peek()
{
@ -308,8 +308,8 @@ impl MetaItem {
thin_vec![PathSegment::path_root(span)]
};
loop {
if let Some(TokenTree::Token(Token { kind: token::Ident(name, _), span }, _)) =
tokens.next().map(TokenTree::uninterpolate)
if let Some(&TokenTree::Token(Token { kind: token::Ident(name, _), span }, _)) =
tokens.next().map(|tt| TokenTree::uninterpolate(tt)).as_deref()
{
segments.push(PathSegment::from_ident(Ident::new(name, span)));
} else {
@ -326,7 +326,7 @@ impl MetaItem {
let span = span.with_hi(segments.last().unwrap().ident.span.hi());
Path { span, segments, tokens: None }
}
Some(TokenTree::Token(Token { kind: token::Interpolated(nt), .. }, _)) => match &*nt {
Some(TokenTree::Token(Token { kind: token::Interpolated(nt), .. }, _)) => match &**nt {
token::Nonterminal::NtMeta(item) => return item.meta(item.path.span),
token::Nonterminal::NtPath(path) => (**path).clone(),
_ => return None,
@ -354,7 +354,7 @@ impl MetaItemKind {
}
fn list_from_tokens(tokens: TokenStream) -> Option<ThinVec<NestedMetaItem>> {
let mut tokens = tokens.into_trees().peekable();
let mut tokens = tokens.trees().peekable();
let mut result = ThinVec::new();
while tokens.peek().is_some() {
let item = NestedMetaItem::from_tokens(&mut tokens)?;
@ -367,12 +367,12 @@ impl MetaItemKind {
Some(result)
}
fn name_value_from_tokens(
tokens: &mut impl Iterator<Item = TokenTree>,
fn name_value_from_tokens<'a>(
tokens: &mut impl Iterator<Item = &'a TokenTree>,
) -> Option<MetaItemKind> {
match tokens.next() {
Some(TokenTree::Delimited(_, Delimiter::Invisible, inner_tokens)) => {
MetaItemKind::name_value_from_tokens(&mut inner_tokens.into_trees())
MetaItemKind::name_value_from_tokens(&mut inner_tokens.trees())
}
Some(TokenTree::Token(token, _)) => {
MetaItemLit::from_token(&token).map(MetaItemKind::NameValue)
@ -381,8 +381,8 @@ impl MetaItemKind {
}
}
fn from_tokens(
tokens: &mut iter::Peekable<impl Iterator<Item = TokenTree>>,
fn from_tokens<'a>(
tokens: &mut iter::Peekable<impl Iterator<Item = &'a TokenTree>>,
) -> Option<MetaItemKind> {
match tokens.peek() {
Some(TokenTree::Delimited(_, Delimiter::Parenthesis, inner_tokens)) => {
@ -501,9 +501,9 @@ impl NestedMetaItem {
self.meta_item().is_some()
}
fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<NestedMetaItem>
fn from_tokens<'a, I>(tokens: &mut iter::Peekable<I>) -> Option<NestedMetaItem>
where
I: Iterator<Item = TokenTree>,
I: Iterator<Item = &'a TokenTree>,
{
match tokens.peek() {
Some(TokenTree::Token(token, _))
@ -513,9 +513,8 @@ impl NestedMetaItem {
return Some(NestedMetaItem::Lit(lit));
}
Some(TokenTree::Delimited(_, Delimiter::Invisible, inner_tokens)) => {
let inner_tokens = inner_tokens.clone();
tokens.next();
return NestedMetaItem::from_tokens(&mut inner_tokens.into_trees().peekable());
return NestedMetaItem::from_tokens(&mut inner_tokens.trees().peekable());
}
_ => {}
}

View file

@ -1149,10 +1149,11 @@ pub fn noop_flat_map_assoc_item<T: MutVisitor>(
}
fn visit_const_item<T: MutVisitor>(
ConstItem { defaultness, ty, expr }: &mut ConstItem,
ConstItem { defaultness, generics, ty, expr }: &mut ConstItem,
visitor: &mut T,
) {
visit_defaultness(defaultness, visitor);
visitor.visit_generics(generics);
visitor.visit_ty(ty);
visit_opt(expr, |expr| visitor.visit_expr(expr));
}

View file

@ -226,7 +226,9 @@ fn ident_can_begin_type(name: Symbol, span: Span, is_raw: bool) -> bool {
.contains(&name)
}
#[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
// SAFETY: due to the `Clone` impl below, all fields of all variants other than
// `Interpolated` must impl `Copy`.
#[derive(PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum TokenKind {
/* Expression-operator symbols. */
Eq,
@ -299,6 +301,19 @@ pub enum TokenKind {
Eof,
}
impl Clone for TokenKind {
fn clone(&self) -> Self {
// `TokenKind` would impl `Copy` if it weren't for `Interpolated`. So
// for all other variants, this implementation of `clone` is just like
// a copy. This is faster than the `derive(Clone)` version which has a
// separate path for every variant.
match self {
Interpolated(nt) => Interpolated(nt.clone()),
_ => unsafe { std::ptr::read(self) },
}
}
}
#[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct Token {
pub kind: TokenKind,

View file

@ -25,6 +25,7 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use rustc_span::{Span, DUMMY_SP};
use smallvec::{smallvec, SmallVec};
use std::borrow::Cow;
use std::{fmt, iter, mem};
/// When the main Rust parser encounters a syntax-extension invocation, it
@ -98,12 +99,13 @@ impl TokenTree {
TokenTree::Token(Token::new(kind, span), Spacing::Joint)
}
pub fn uninterpolate(self) -> TokenTree {
pub fn uninterpolate(&self) -> Cow<'_, TokenTree> {
match self {
TokenTree::Token(token, spacing) => {
TokenTree::Token(token.uninterpolate().into_owned(), spacing)
}
tt => tt,
TokenTree::Token(token, spacing) => match token.uninterpolate() {
Cow::Owned(token) => Cow::Owned(TokenTree::Token(token, *spacing)),
Cow::Borrowed(_) => Cow::Borrowed(self),
},
_ => Cow::Borrowed(self),
}
}
}
@ -595,26 +597,21 @@ impl<'t> Iterator for RefTokenTreeCursor<'t> {
}
}
/// Owning by-value iterator over a [`TokenStream`], that produces `TokenTree`
/// Owning by-value iterator over a [`TokenStream`], that produces `&TokenTree`
/// items.
// FIXME: Many uses of this can be replaced with by-reference iterator to avoid clones.
///
/// Doesn't impl `Iterator` because Rust doesn't permit an owning iterator to
/// return `&T` from `next`; the need for an explicit lifetime in the `Item`
/// associated type gets in the way. Instead, use `next_ref` (which doesn't
/// involve associated types) for getting individual elements, or
/// `RefTokenTreeCursor` if you really want an `Iterator`, e.g. in a `for`
/// loop.
#[derive(Clone)]
pub struct TokenTreeCursor {
pub stream: TokenStream,
index: usize,
}
impl Iterator for TokenTreeCursor {
type Item = TokenTree;
fn next(&mut self) -> Option<TokenTree> {
self.stream.0.get(self.index).map(|tree| {
self.index += 1;
tree.clone()
})
}
}
impl TokenTreeCursor {
fn new(stream: TokenStream) -> Self {
TokenTreeCursor { stream, index: 0 }

View file

@ -308,8 +308,12 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
match &item.kind {
ItemKind::ExternCrate(_) => {}
ItemKind::Use(use_tree) => visitor.visit_use_tree(use_tree, item.id, false),
ItemKind::Static(box StaticItem { ty, mutability: _, expr })
| ItemKind::Const(box ConstItem { ty, expr, .. }) => {
ItemKind::Static(box StaticItem { ty, mutability: _, expr }) => {
visitor.visit_ty(ty);
walk_list!(visitor, visit_expr, expr);
}
ItemKind::Const(box ConstItem { defaultness: _, generics, ty, expr }) => {
visitor.visit_generics(generics);
visitor.visit_ty(ty);
walk_list!(visitor, visit_expr, expr);
}
@ -677,7 +681,8 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem,
visitor.visit_ident(ident);
walk_list!(visitor, visit_attribute, attrs);
match kind {
AssocItemKind::Const(box ConstItem { ty, expr, .. }) => {
AssocItemKind::Const(box ConstItem { defaultness: _, generics, ty, expr }) => {
visitor.visit_generics(generics);
visitor.visit_ty(ty);
walk_list!(visitor, visit_expr, expr);
}

View file

@ -231,9 +231,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
let (ty, body_id) = self.lower_const_item(t, span, e.as_deref());
hir::ItemKind::Static(ty, *m, body_id)
}
ItemKind::Const(box ast::ConstItem { ty, expr, .. }) => {
let (ty, body_id) = self.lower_const_item(ty, span, expr.as_deref());
hir::ItemKind::Const(ty, body_id)
ItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => {
let (generics, (ty, body_id)) = self.lower_generics(
generics,
Const::No,
id,
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| this.lower_const_item(ty, span, expr.as_deref()),
);
hir::ItemKind::Const(ty, generics, body_id)
}
ItemKind::Fn(box Fn {
sig: FnSig { decl, header, span: fn_sig_span },
@ -715,11 +721,23 @@ impl<'hir> LoweringContext<'_, 'hir> {
let trait_item_def_id = hir_id.expect_owner();
let (generics, kind, has_default) = match &i.kind {
AssocItemKind::Const(box ConstItem { ty, expr, .. }) => {
let ty =
self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
let body = expr.as_ref().map(|x| self.lower_const_body(i.span, Some(x)));
(hir::Generics::empty(), hir::TraitItemKind::Const(ty, body), body.is_some())
AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => {
let (generics, kind) = self.lower_generics(
&generics,
Const::No,
i.id,
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| {
let ty = this.lower_ty(
ty,
&ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy),
);
let body = expr.as_ref().map(|x| this.lower_const_body(i.span, Some(x)));
hir::TraitItemKind::Const(ty, body)
},
);
(generics, kind, expr.is_some())
}
AssocItemKind::Fn(box Fn { sig, generics, body: None, .. }) => {
let asyncness = sig.header.asyncness;
@ -817,14 +835,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.lower_attrs(hir_id, &i.attrs);
let (generics, kind) = match &i.kind {
AssocItemKind::Const(box ConstItem { ty, expr, .. }) => {
let ty =
self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
(
hir::Generics::empty(),
hir::ImplItemKind::Const(ty, self.lower_const_body(i.span, expr.as_deref())),
)
}
AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => self.lower_generics(
&generics,
Const::No,
i.id,
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| {
let ty = this
.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
let body = this.lower_const_body(i.span, expr.as_deref());
hir::ImplItemKind::Const(ty, body)
},
),
AssocItemKind::Fn(box Fn { sig, generics, body, .. }) => {
self.current_item = Some(i.span);
let asyncness = sig.header.asyncness;

View file

@ -218,6 +218,19 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}
}
}
if !attr.is_doc_comment()
&& attr.get_normal_item().path.segments.len() == 2
&& attr.get_normal_item().path.segments[0].ident.name == sym::diagnostic
&& !self.features.diagnostic_namespace
{
let msg = "`#[diagnostic]` attribute name space is experimental";
gate_feature_post!(
self,
diagnostic_namespace,
attr.get_normal_item().path.segments[0].ident.span,
msg
);
}
// Emit errors for non-staged-api crates.
if !self.features.staged_api {
@ -556,6 +569,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
gate_all!(const_closures, "const closures are experimental");
gate_all!(builtin_syntax, "`builtin #` syntax is unstable");
gate_all!(explicit_tail_calls, "`become` expression is experimental");
gate_all!(generic_const_items, "generic const items are experimental");
if !visitor.features.negative_bounds {
for &span in spans.get(&sym::negative_bounds).iter().copied().flatten() {

View file

@ -30,10 +30,15 @@ impl<'a> State<'a> {
ast::ForeignItemKind::Fn(box ast::Fn { defaultness, sig, generics, body }) => {
self.print_fn_full(sig, ident, generics, vis, *defaultness, body.as_deref(), attrs);
}
ast::ForeignItemKind::Static(ty, mutbl, body) => {
let def = ast::Defaultness::Final;
self.print_item_const(ident, Some(*mutbl), ty, body.as_deref(), vis, def);
}
ast::ForeignItemKind::Static(ty, mutbl, body) => self.print_item_const(
ident,
Some(*mutbl),
&ast::Generics::default(),
ty,
body.as_deref(),
vis,
ast::Defaultness::Final,
),
ast::ForeignItemKind::TyAlias(box ast::TyAlias {
defaultness,
generics,
@ -67,6 +72,7 @@ impl<'a> State<'a> {
&mut self,
ident: Ident,
mutbl: Option<ast::Mutability>,
generics: &ast::Generics,
ty: &ast::Ty,
body: Option<&ast::Expr>,
vis: &ast::Visibility,
@ -82,6 +88,7 @@ impl<'a> State<'a> {
};
self.word_space(leading);
self.print_ident(ident);
self.print_generic_params(&generics.params);
self.word_space(":");
self.print_type(ty);
if body.is_some() {
@ -92,6 +99,7 @@ impl<'a> State<'a> {
self.word_space("=");
self.print_expr(body);
}
self.print_where_clause(&generics.where_clause);
self.word(";");
self.end(); // end the outer cbox
}
@ -158,20 +166,21 @@ impl<'a> State<'a> {
self.word(";");
}
ast::ItemKind::Static(box StaticItem { ty, mutability: mutbl, expr: body }) => {
let def = ast::Defaultness::Final;
self.print_item_const(
item.ident,
Some(*mutbl),
&ast::Generics::default(),
ty,
body.as_deref(),
&item.vis,
def,
ast::Defaultness::Final,
);
}
ast::ItemKind::Const(box ast::ConstItem { defaultness, ty, expr }) => {
ast::ItemKind::Const(box ast::ConstItem { defaultness, generics, ty, expr }) => {
self.print_item_const(
item.ident,
None,
generics,
ty,
expr.as_deref(),
&item.vis,
@ -515,8 +524,16 @@ impl<'a> State<'a> {
ast::AssocItemKind::Fn(box ast::Fn { defaultness, sig, generics, body }) => {
self.print_fn_full(sig, ident, generics, vis, *defaultness, body.as_deref(), attrs);
}
ast::AssocItemKind::Const(box ast::ConstItem { defaultness, ty, expr }) => {
self.print_item_const(ident, None, ty, expr.as_deref(), vis, *defaultness);
ast::AssocItemKind::Const(box ast::ConstItem { defaultness, generics, ty, expr }) => {
self.print_item_const(
ident,
None,
generics,
ty,
expr.as_deref(),
vis,
*defaultness,
);
}
ast::AssocItemKind::Type(box ast::TyAlias {
defaultness,

View file

@ -37,8 +37,8 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
desc,
);
err.span_label(borrow_span, format!("{} is borrowed here", borrow_desc));
err.span_label(span, format!("use of borrowed {}", borrow_desc));
err.span_label(borrow_span, format!("{borrow_desc} is borrowed here"));
err.span_label(span, format!("use of borrowed {borrow_desc}"));
err
}
@ -51,8 +51,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
old_opt_via: &str,
old_load_end_span: Option<Span>,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
let via =
|msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {})", msg) };
let via = |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {msg})") };
let mut err = struct_span_err!(
self,
new_loan_span,
@ -143,9 +142,9 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
);
err.span_label(
new_loan_span,
format!("{} construction occurs here{}", container_name, opt_via),
format!("{container_name} construction occurs here{opt_via}"),
);
err.span_label(old_loan_span, format!("borrow occurs here{}", old_opt_via));
err.span_label(old_loan_span, format!("borrow occurs here{old_opt_via}"));
if let Some(previous_end_span) = previous_end_span {
err.span_label(previous_end_span, "borrow ends here");
}
@ -173,13 +172,10 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
opt_via,
kind_new,
);
err.span_label(
new_loan_span,
format!("{}borrow occurs here{}", second_borrow_desc, opt_via),
);
err.span_label(new_loan_span, format!("{second_borrow_desc}borrow occurs here{opt_via}"));
err.span_label(
old_loan_span,
format!("{} construction occurs here{}", container_name, old_opt_via),
format!("{container_name} construction occurs here{old_opt_via}"),
);
if let Some(previous_end_span) = previous_end_span {
err.span_label(previous_end_span, "borrow from closure ends here");
@ -199,8 +195,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
msg_old: &str,
old_load_end_span: Option<Span>,
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
let via =
|msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {})", msg) };
let via = |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {msg})") };
let mut err = struct_span_err!(
self,
span,
@ -216,22 +211,21 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
if msg_new == "" {
// If `msg_new` is empty, then this isn't a borrow of a union field.
err.span_label(span, format!("{} borrow occurs here", kind_new));
err.span_label(old_span, format!("{} borrow occurs here", kind_old));
err.span_label(span, format!("{kind_new} borrow occurs here"));
err.span_label(old_span, format!("{kind_old} borrow occurs here"));
} else {
// If `msg_new` isn't empty, then this a borrow of a union field.
err.span_label(
span,
format!(
"{} borrow of {} -- which overlaps with {} -- occurs here",
kind_new, msg_new, msg_old,
"{kind_new} borrow of {msg_new} -- which overlaps with {msg_old} -- occurs here",
),
);
err.span_label(old_span, format!("{} borrow occurs here{}", kind_old, via(msg_old)));
}
if let Some(old_load_end_span) = old_load_end_span {
err.span_label(old_load_end_span, format!("{} borrow ends here", kind_old));
err.span_label(old_load_end_span, format!("{kind_old} borrow ends here"));
}
err
}
@ -250,8 +244,8 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
desc,
);
err.span_label(borrow_span, format!("{} is borrowed here", desc));
err.span_label(span, format!("{} is assigned to here but it was already borrowed", desc));
err.span_label(borrow_span, format!("{desc} is borrowed here"));
err.span_label(span, format!("{desc} is assigned to here but it was already borrowed"));
err
}
@ -330,7 +324,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
optional_adverb_for_moved: &str,
moved_path: Option<String>,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
let moved_path = moved_path.map(|mp| format!(": `{}`", mp)).unwrap_or_default();
let moved_path = moved_path.map(|mp| format!(": `{mp}`")).unwrap_or_default();
struct_span_err!(
self,
@ -369,8 +363,8 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
immutable_place,
immutable_section,
);
err.span_label(mutate_span, format!("cannot {}", action));
err.span_label(immutable_span, format!("value is immutable in {}", immutable_section));
err.span_label(mutate_span, format!("cannot {action}"));
err.span_label(immutable_span, format!("value is immutable in {immutable_section}"));
err
}
@ -428,7 +422,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
err.span_label(
span,
format!("{}s a {} data owned by the current function", return_kind, reference_desc),
format!("{return_kind}s a {reference_desc} data owned by the current function"),
);
err
@ -449,8 +443,8 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
"{closure_kind} may outlive the current {scope}, but it borrows {borrowed_path}, \
which is owned by the current {scope}",
);
err.span_label(capture_span, format!("{} is borrowed here", borrowed_path))
.span_label(closure_span, format!("may outlive borrowed value {}", borrowed_path));
err.span_label(capture_span, format!("{borrowed_path} is borrowed here"))
.span_label(closure_span, format!("may outlive borrowed value {borrowed_path}"));
err
}

View file

@ -360,7 +360,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
return;
}
let index = self.borrow_set.get_index_of(&location).unwrap_or_else(|| {
panic!("could not find BorrowIndex for location {:?}", location);
panic!("could not find BorrowIndex for location {location:?}");
});
trans.gen(index);

View file

@ -653,7 +653,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
err.span_suggestion_verbose(
sugg_span.shrink_to_hi(),
"consider assigning a value",
format!(" = {}", assign_value),
format!(" = {assign_value}"),
Applicability::MaybeIncorrect,
);
}
@ -738,7 +738,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// Try to find predicates on *generic params* that would allow copying `ty`
let suggestion =
if let Some(symbol) = tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
format!(": {}.clone()", symbol)
format!(": {symbol}.clone()")
} else {
".clone()".to_owned()
};
@ -1162,8 +1162,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if union_type_name != "" {
err.note(format!(
"{} is a field of the union `{}`, so it overlaps the field {}",
msg_place, union_type_name, msg_borrow,
"{msg_place} is a field of the union `{union_type_name}`, so it overlaps the field {msg_borrow}",
));
}
@ -1353,8 +1352,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let Some(trait_did) = tcx.trait_of_item(def_id) &&
tcx.is_diagnostic_item(sym::Iterator, trait_did) {
err.note(format!(
"a for loop advances the iterator for you, the result is stored in `{}`.",
loop_bind
"a for loop advances the iterator for you, the result is stored in `{loop_bind}`."
));
err.help("if you want to call `next` on a iterator within the loop, consider using `while let`.");
}
@ -1825,7 +1823,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
},
ConstraintCategory::CallArgument(None),
var_or_use_span,
&format!("`{}`", name),
&format!("`{name}`"),
"block",
),
(
@ -1847,7 +1845,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
region_name,
category,
span,
&format!("`{}`", name),
&format!("`{name}`"),
"function",
),
(
@ -1921,14 +1919,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
}
let mut err = self.path_does_not_live_long_enough(borrow_span, &format!("`{}`", name));
let mut err = self.path_does_not_live_long_enough(borrow_span, &format!("`{name}`"));
if let Some(annotation) = self.annotate_argument_and_return_for_borrow(borrow) {
let region_name = annotation.emit(self, &mut err);
err.span_label(
borrow_span,
format!("`{}` would have to be valid for `{}`...", name, region_name),
format!("`{name}` would have to be valid for `{region_name}`..."),
);
err.span_label(
@ -1939,7 +1937,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
self.infcx
.tcx
.opt_item_name(self.mir_def_id().to_def_id())
.map(|name| format!("function `{}`", name))
.map(|name| format!("function `{name}`"))
.unwrap_or_else(|| {
match &self.infcx.tcx.def_kind(self.mir_def_id()) {
DefKind::Closure => "enclosing closure",
@ -1974,7 +1972,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
} else {
err.span_label(borrow_span, "borrowed value does not live long enough");
err.span_label(drop_span, format!("`{}` dropped here while still borrowed", name));
err.span_label(drop_span, format!("`{name}` dropped here while still borrowed"));
borrow_spans.args_subdiag(&mut err, |args_span| {
crate::session_diagnostics::CaptureArgLabel::Capture {
@ -2018,22 +2016,17 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let mut err = self.cannot_borrow_across_destructor(borrow_span);
let what_was_dropped = match self.describe_place(place.as_ref()) {
Some(name) => format!("`{}`", name),
Some(name) => format!("`{name}`"),
None => String::from("temporary value"),
};
let label = match self.describe_place(borrow.borrowed_place.as_ref()) {
Some(borrowed) => format!(
"here, drop of {D} needs exclusive access to `{B}`, \
because the type `{T}` implements the `Drop` trait",
D = what_was_dropped,
T = dropped_ty,
B = borrowed
"here, drop of {what_was_dropped} needs exclusive access to `{borrowed}`, \
because the type `{dropped_ty}` implements the `Drop` trait"
),
None => format!(
"here is drop of {D}; whose type `{T}` implements the `Drop` trait",
D = what_was_dropped,
T = dropped_ty
"here is drop of {what_was_dropped}; whose type `{dropped_ty}` implements the `Drop` trait"
),
};
err.span_label(drop_span, label);
@ -2245,10 +2238,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
} else {
"local data "
};
(
format!("{}`{}`", local_kind, place_desc),
format!("`{}` is borrowed here", place_desc),
)
(format!("{local_kind}`{place_desc}`"), format!("`{place_desc}` is borrowed here"))
} else {
let root_place =
self.prefixes(borrow.borrowed_place.as_ref(), PrefixSet::All).last().unwrap();
@ -2350,9 +2340,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
err.span_suggestion_verbose(
sugg_span,
format!(
"to force the {} to take ownership of {} (and any \
other referenced variables), use the `move` keyword",
kind, captured_var
"to force the {kind} to take ownership of {captured_var} (and any \
other referenced variables), use the `move` keyword"
),
suggestion,
Applicability::MachineApplicable,
@ -2360,7 +2349,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
match category {
ConstraintCategory::Return(_) | ConstraintCategory::OpaqueType => {
let msg = format!("{} is returned here", kind);
let msg = format!("{kind} is returned here");
err.span_note(constraint_span, msg);
}
ConstraintCategory::CallArgument(_) => {
@ -2402,21 +2391,18 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
err.span_label(
upvar_span,
format!("`{}` declared here, outside of the {} body", upvar_name, escapes_from),
format!("`{upvar_name}` declared here, outside of the {escapes_from} body"),
);
err.span_label(borrow_span, format!("borrow is only valid in the {} body", escapes_from));
err.span_label(borrow_span, format!("borrow is only valid in the {escapes_from} body"));
if let Some(name) = name {
err.span_label(
escape_span,
format!("reference to `{}` escapes the {} body here", name, escapes_from),
format!("reference to `{name}` escapes the {escapes_from} body here"),
);
} else {
err.span_label(
escape_span,
format!("reference escapes the {} body here", escapes_from),
);
err.span_label(escape_span, format!("reference escapes the {escapes_from} body here"));
}
err
@ -2697,10 +2683,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
});
if let Some(Ok(instance)) = deref_target {
let deref_target_ty = instance.ty(tcx, self.param_env);
err.note(format!(
"borrow occurs due to deref coercion to `{}`",
deref_target_ty
));
err.note(format!("borrow occurs due to deref coercion to `{deref_target_ty}`"));
err.span_note(tcx.def_span(instance.def_id()), "deref defined here");
}
}
@ -2756,7 +2739,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
"cannot assign twice to immutable variable"
};
if span != assigned_span && !from_arg {
err.span_label(assigned_span, format!("first assignment to {}", place_description));
err.span_label(assigned_span, format!("first assignment to {place_description}"));
}
if let Some(decl) = local_decl
&& let Some(name) = local_name
@ -2765,7 +2748,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
err.span_suggestion(
decl.source_info.span,
"consider making this binding mutable",
format!("mut {}", name),
format!("mut {name}"),
Applicability::MachineApplicable,
);
}
@ -3226,7 +3209,7 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> {
return_span,
} => {
let argument_ty_name = cx.get_name_for_ty(argument_ty, 0);
diag.span_label(argument_span, format!("has type `{}`", argument_ty_name));
diag.span_label(argument_span, format!("has type `{argument_ty_name}`"));
let return_ty_name = cx.get_name_for_ty(return_ty, 0);
let types_equal = return_ty_name == argument_ty_name;
@ -3253,15 +3236,14 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> {
// Region of return type and arguments checked to be the same earlier.
let region_name = cx.get_region_name_for_ty(*return_ty, 0);
for (_, argument_span) in arguments {
diag.span_label(*argument_span, format!("has lifetime `{}`", region_name));
diag.span_label(*argument_span, format!("has lifetime `{region_name}`"));
}
diag.span_label(*return_span, format!("also has lifetime `{}`", region_name,));
diag.span_label(*return_span, format!("also has lifetime `{region_name}`",));
diag.help(format!(
"use data from the highlighted arguments which match the `{}` lifetime of \
"use data from the highlighted arguments which match the `{region_name}` lifetime of \
the return type",
region_name,
));
region_name

View file

@ -202,7 +202,7 @@ trait FactCell {
impl<A: Debug> FactCell for A {
default fn to_string(&self, _location_table: &LocationTable) -> String {
format!("{:?}", self)
format!("{self:?}")
}
}

View file

@ -1817,8 +1817,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
ProjectionElem::Subslice { .. } => {
panic!("we don't allow assignments to subslices, location: {:?}",
location);
panic!("we don't allow assignments to subslices, location: {location:?}");
}
ProjectionElem::Field(..) => {
@ -2017,8 +2016,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
self.infcx.tcx.sess.delay_span_bug(
span,
format!(
"Accessing `{:?}` with the kind `{:?}` shouldn't be possible",
place, kind,
"Accessing `{place:?}` with the kind `{kind:?}` shouldn't be possible",
),
);
}

View file

@ -347,7 +347,7 @@ pub(super) fn dump_mir_results<'tcx>(
for_each_region_constraint(
infcx.tcx,
closure_region_requirements,
&mut |msg| writeln!(out, "| {}", msg),
&mut |msg| writeln!(out, "| {msg}"),
)?;
writeln!(out, "|")?;
}
@ -426,7 +426,7 @@ pub(super) fn dump_annotation<'tcx>(
};
if !opaque_type_values.is_empty() {
err.note(format!("Inferred opaque type values:\n{:#?}", opaque_type_values));
err.note(format!("Inferred opaque type values:\n{opaque_type_values:#?}"));
}
errors.buffer_non_error_diag(err);
@ -439,7 +439,7 @@ fn for_each_region_constraint<'tcx>(
) -> io::Result<()> {
for req in &closure_region_requirements.outlives_requirements {
let subject = match req.subject {
ClosureOutlivesSubject::Region(subject) => format!("{:?}", subject),
ClosureOutlivesSubject::Region(subject) => format!("{subject:?}"),
ClosureOutlivesSubject::Ty(ty) => {
format!("{:?}", ty.instantiate(tcx, |vid| ty::Region::new_var(tcx, vid)))
}

View file

@ -52,7 +52,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
writeln!(out, "|")?;
writeln!(out, "| Inference Constraints")?;
self.for_each_constraint(tcx, &mut |msg| writeln!(out, "| {}", msg))?;
self.for_each_constraint(tcx, &mut |msg| writeln!(out, "| {msg}"))?;
Ok(())
}
@ -69,7 +69,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
for region in self.definitions.indices() {
let value = self.liveness_constraints.region_value_str(region);
if value != "{}" {
with_msg(&format!("{:?} live at {}", region, value))?;
with_msg(&format!("{region:?} live at {value}"))?;
}
}
@ -81,12 +81,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
Locations::All(span) => {
("All", tcx.sess.source_map().span_to_embeddable_string(*span))
}
Locations::Single(loc) => ("Single", format!("{:?}", loc)),
Locations::Single(loc) => ("Single", format!("{loc:?}")),
};
with_msg(&format!(
"{:?}: {:?} due to {:?} at {}({}) ({:?}",
sup, sub, category, name, arg, span
))?;
with_msg(&format!("{sup:?}: {sub:?} due to {category:?} at {name}({arg}) ({span:?}"))?;
}
Ok(())

View file

@ -49,7 +49,7 @@ impl<'a, 'this, 'tcx> dot::Labeller<'this> for RawConstraints<'a, 'tcx> {
Some(dot::LabelText::LabelStr(Cow::Borrowed("box")))
}
fn node_label(&'this self, n: &RegionVid) -> dot::LabelText<'this> {
dot::LabelText::LabelStr(format!("{:?}", n).into())
dot::LabelText::LabelStr(format!("{n:?}").into())
}
fn edge_label(&'this self, e: &OutlivesConstraint<'tcx>) -> dot::LabelText<'this> {
dot::LabelText::LabelStr(format!("{:?}", e.locations).into())
@ -100,7 +100,7 @@ impl<'a, 'this, 'tcx> dot::Labeller<'this> for SccConstraints<'a, 'tcx> {
}
fn node_label(&'this self, n: &ConstraintSccIndex) -> dot::LabelText<'this> {
let nodes = &self.nodes_per_scc[*n];
dot::LabelText::LabelStr(format!("{:?} = {:?}", n, nodes).into())
dot::LabelText::LabelStr(format!("{n:?} = {nodes:?}").into())
}
}

View file

@ -259,7 +259,7 @@ fn sccs_info<'cx, 'tcx>(
let mut reg_vars_to_origins_str = "region variables to origins:\n".to_string();
for (reg_var, origin) in var_to_origin_sorted.into_iter() {
reg_vars_to_origins_str.push_str(&format!("{:?}: {:?}\n", reg_var, origin));
reg_vars_to_origins_str.push_str(&format!("{reg_var:?}: {origin:?}\n"));
}
debug!("{}", reg_vars_to_origins_str);

View file

@ -419,7 +419,7 @@ fn check_opaque_type_parameter_valid(
return Err(tcx
.sess
.struct_span_err(span, "non-defining opaque type use in defining scope")
.span_note(spans, format!("{} used multiple times", descr))
.span_note(spans, format!("{descr} used multiple times"))
.emit());
}
}

View file

@ -470,7 +470,7 @@ fn region_value_str(elements: impl IntoIterator<Item = RegionElement>) -> String
}
push_sep(&mut result);
result.push_str(&format!("{:?}", fr));
result.push_str(&format!("{fr:?}"));
}
RegionElement::PlaceholderRegion(placeholder) => {
@ -481,7 +481,7 @@ fn region_value_str(elements: impl IntoIterator<Item = RegionElement>) -> String
}
push_sep(&mut result);
result.push_str(&format!("{:?}", placeholder));
result.push_str(&format!("{placeholder:?}"));
}
}
}
@ -497,7 +497,7 @@ fn region_value_str(elements: impl IntoIterator<Item = RegionElement>) -> String
fn push_location_range(str: &mut String, location1: Location, location2: Location) {
if location1 == location2 {
str.push_str(&format!("{:?}", location1));
str.push_str(&format!("{location1:?}"));
} else {
assert_eq!(location1.block, location2.block);
str.push_str(&format!(

View file

@ -409,18 +409,12 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
}
if let ty::FnDef(def_id, args) = *constant.literal.ty().kind() {
// const_trait_impl: use a non-const param env when checking that a FnDef type is well formed.
// this is because the well-formedness of the function does not need to be proved to have `const`
// impls for trait bounds.
let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, args);
let prev = self.cx.param_env;
self.cx.param_env = prev.without_const();
self.cx.normalize_and_prove_instantiated_predicates(
def_id,
instantiated_predicates,
locations,
);
self.cx.param_env = prev;
}
}
}

View file

@ -255,6 +255,7 @@ pub fn expand_test_or_bench(
ast::ItemKind::Const(
ast::ConstItem {
defaultness: ast::Defaultness::Final,
generics: ast::Generics::default(),
ty: cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))),
// test::TestDescAndFn {
expr: Some(

View file

@ -363,50 +363,44 @@ pub fn from_fn_attrs<'ll, 'tcx>(
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::ALLOCATOR)
|| codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::ALLOCATOR_ZEROED)
{
if llvm_util::get_version() >= (15, 0, 0) {
to_add.push(create_alloc_family_attr(cx.llcx));
// apply to argument place instead of function
let alloc_align = AttributeKind::AllocAlign.create_attr(cx.llcx);
attributes::apply_to_llfn(llfn, AttributePlace::Argument(1), &[alloc_align]);
to_add.push(llvm::CreateAllocSizeAttr(cx.llcx, 0));
let mut flags = AllocKindFlags::Alloc | AllocKindFlags::Aligned;
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::ALLOCATOR) {
flags |= AllocKindFlags::Uninitialized;
} else {
flags |= AllocKindFlags::Zeroed;
}
to_add.push(llvm::CreateAllocKindAttr(cx.llcx, flags));
to_add.push(create_alloc_family_attr(cx.llcx));
// apply to argument place instead of function
let alloc_align = AttributeKind::AllocAlign.create_attr(cx.llcx);
attributes::apply_to_llfn(llfn, AttributePlace::Argument(1), &[alloc_align]);
to_add.push(llvm::CreateAllocSizeAttr(cx.llcx, 0));
let mut flags = AllocKindFlags::Alloc | AllocKindFlags::Aligned;
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::ALLOCATOR) {
flags |= AllocKindFlags::Uninitialized;
} else {
flags |= AllocKindFlags::Zeroed;
}
to_add.push(llvm::CreateAllocKindAttr(cx.llcx, flags));
// apply to return place instead of function (unlike all other attributes applied in this function)
let no_alias = AttributeKind::NoAlias.create_attr(cx.llcx);
attributes::apply_to_llfn(llfn, AttributePlace::ReturnValue, &[no_alias]);
}
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::REALLOCATOR) {
if llvm_util::get_version() >= (15, 0, 0) {
to_add.push(create_alloc_family_attr(cx.llcx));
to_add.push(llvm::CreateAllocKindAttr(
cx.llcx,
AllocKindFlags::Realloc | AllocKindFlags::Aligned,
));
// applies to argument place instead of function place
let allocated_pointer = AttributeKind::AllocatedPointer.create_attr(cx.llcx);
attributes::apply_to_llfn(llfn, AttributePlace::Argument(0), &[allocated_pointer]);
// apply to argument place instead of function
let alloc_align = AttributeKind::AllocAlign.create_attr(cx.llcx);
attributes::apply_to_llfn(llfn, AttributePlace::Argument(2), &[alloc_align]);
to_add.push(llvm::CreateAllocSizeAttr(cx.llcx, 3));
}
to_add.push(create_alloc_family_attr(cx.llcx));
to_add.push(llvm::CreateAllocKindAttr(
cx.llcx,
AllocKindFlags::Realloc | AllocKindFlags::Aligned,
));
// applies to argument place instead of function place
let allocated_pointer = AttributeKind::AllocatedPointer.create_attr(cx.llcx);
attributes::apply_to_llfn(llfn, AttributePlace::Argument(0), &[allocated_pointer]);
// apply to argument place instead of function
let alloc_align = AttributeKind::AllocAlign.create_attr(cx.llcx);
attributes::apply_to_llfn(llfn, AttributePlace::Argument(2), &[alloc_align]);
to_add.push(llvm::CreateAllocSizeAttr(cx.llcx, 3));
let no_alias = AttributeKind::NoAlias.create_attr(cx.llcx);
attributes::apply_to_llfn(llfn, AttributePlace::ReturnValue, &[no_alias]);
}
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::DEALLOCATOR) {
if llvm_util::get_version() >= (15, 0, 0) {
to_add.push(create_alloc_family_attr(cx.llcx));
to_add.push(llvm::CreateAllocKindAttr(cx.llcx, AllocKindFlags::Free));
// applies to argument place instead of function place
let allocated_pointer = AttributeKind::AllocatedPointer.create_attr(cx.llcx);
attributes::apply_to_llfn(llfn, AttributePlace::Argument(0), &[allocated_pointer]);
}
to_add.push(create_alloc_family_attr(cx.llcx));
to_add.push(llvm::CreateAllocKindAttr(cx.llcx, AllocKindFlags::Free));
// applies to argument place instead of function place
let allocated_pointer = AttributeKind::AllocatedPointer.create_attr(cx.llcx);
attributes::apply_to_llfn(llfn, AttributePlace::Argument(0), &[allocated_pointer]);
}
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY) {
to_add.push(llvm::CreateAttrString(cx.llcx, "cmse_nonsecure_entry"));

View file

@ -2074,6 +2074,53 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
simd_neg: Int => neg, Float => fneg;
}
// Unary integer intrinsics
if matches!(name, sym::simd_bswap | sym::simd_bitreverse | sym::simd_ctlz | sym::simd_cttz) {
let vec_ty = bx.cx.type_vector(
match *in_elem.kind() {
ty::Int(i) => bx.cx.type_int_from_ty(i),
ty::Uint(i) => bx.cx.type_uint_from_ty(i),
_ => return_error!(InvalidMonomorphization::UnsupportedOperation {
span,
name,
in_ty,
in_elem
}),
},
in_len as u64,
);
let intrinsic_name = match name {
sym::simd_bswap => "bswap",
sym::simd_bitreverse => "bitreverse",
sym::simd_ctlz => "ctlz",
sym::simd_cttz => "cttz",
_ => unreachable!(),
};
let llvm_intrinsic = &format!(
"llvm.{}.v{}i{}",
intrinsic_name,
in_len,
in_elem.int_size_and_signed(bx.tcx()).0.bits(),
);
return Ok(if matches!(name, sym::simd_ctlz | sym::simd_cttz) {
let fn_ty = bx.type_func(&[vec_ty, bx.type_i1()], vec_ty);
let f = bx.declare_cfn(llvm_intrinsic, llvm::UnnamedAddr::No, fn_ty);
bx.call(
fn_ty,
None,
None,
f,
&[args[0].immediate(), bx.const_int(bx.type_i1(), 0)],
None,
)
} else {
let fn_ty = bx.type_func(&[vec_ty], vec_ty);
let f = bx.declare_cfn(llvm_intrinsic, llvm::UnnamedAddr::No, fn_ty);
bx.call(fn_ty, None, None, f, &[args[0].immediate()], None)
});
}
if name == sym::simd_arith_offset {
// This also checks that the first operand is a ptr type.
let pointee = in_elem.builtin_deref(true).unwrap_or_else(|| {

View file

@ -507,8 +507,6 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
.features
.split(',')
.filter(|v| !v.is_empty() && backend_feature_name(v).is_some())
// Drop +atomics-32 feature introduced in LLVM 15.
.filter(|v| *v != "+atomics-32" || get_version() >= (15, 0, 0))
.map(String::from),
);

View file

@ -38,6 +38,7 @@ use rustc_span::symbol::sym;
use rustc_span::Symbol;
use rustc_target::abi::{Align, FIRST_VARIANT};
use std::cmp;
use std::collections::BTreeSet;
use std::time::{Duration, Instant};
@ -682,10 +683,10 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
// are large size variations, this can reduce memory usage significantly.
let codegen_units: Vec<_> = {
let mut sorted_cgus = codegen_units.iter().collect::<Vec<_>>();
sorted_cgus.sort_by_cached_key(|cgu| cgu.size_estimate());
sorted_cgus.sort_by_key(|cgu| cmp::Reverse(cgu.size_estimate()));
let (first_half, second_half) = sorted_cgus.split_at(sorted_cgus.len() / 2);
second_half.iter().rev().interleave(first_half).copied().collect()
first_half.iter().interleave(second_half.iter().rev()).copied().collect()
};
// Calculate the CGU reuse

View file

@ -138,7 +138,10 @@ where
err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => {
ErrorHandled::TooGeneric
}
err_inval!(AlreadyReported(error_reported)) => ErrorHandled::Reported(error_reported),
err_inval!(AlreadyReported(guar)) => ErrorHandled::Reported(guar),
err_inval!(Layout(LayoutError::ReferencesError(guar))) => {
ErrorHandled::Reported(guar.into())
}
err_inval!(Layout(layout_error @ LayoutError::SizeOverflow(_))) => {
// We must *always* hard error on these, even if the caller wants just a lint.
// The `message` makes little sense here, this is a more serious error than the

View file

@ -52,7 +52,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
trace!(
"eval_body_using_ecx: pushing stack frame for global: {}{}",
with_no_trimmed_paths!(ecx.tcx.def_path_str(cid.instance.def_id())),
cid.promoted.map_or_else(String::new, |p| format!("::promoted[{:?}]", p))
cid.promoted.map_or_else(String::new, |p| format!("::promoted[{p:?}]"))
);
ecx.push_stack_frame(
@ -228,7 +228,6 @@ pub fn eval_to_const_value_raw_provider<'tcx>(
tcx: TyCtxt<'tcx>,
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> {
assert!(key.param_env.is_const());
// see comment in eval_to_allocation_raw_provider for what we're doing here
if key.param_env.reveal() == Reveal::All {
let mut key = key;
@ -269,7 +268,6 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
tcx: TyCtxt<'tcx>,
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
) -> ::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> {
assert!(key.param_env.is_const());
// Because the constant is computed twice (once per value of `Reveal`), we are at risk of
// reporting the same error twice here. To resolve this, we check whether we can evaluate the
// constant in the more restrictive `Reveal::UserFacing`, which most likely already was

View file

@ -28,15 +28,18 @@ pub fn is_parent_const_impl_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
&& tcx.constness(parent_id) == hir::Constness::Const
}
/// Checks whether an item is considered to be `const`. If it is a constructor, it is const. If
/// it is a trait impl/function, return if it has a `const` modifier. If it is an intrinsic,
/// report whether said intrinsic has a `rustc_const_{un,}stable` attribute. Otherwise, return
/// `Constness::NotConst`.
/// Checks whether an item is considered to be `const`. If it is a constructor, anonymous const,
/// const block, const item or associated const, it is const. If it is a trait impl/function,
/// return if it has a `const` modifier. If it is an intrinsic, report whether said intrinsic
/// has a `rustc_const_{un,}stable` attribute. Otherwise, return `Constness::NotConst`.
fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {
let node = tcx.hir().get_by_def_id(def_id);
match node {
hir::Node::Ctor(_) => hir::Constness::Const,
hir::Node::Ctor(_)
| hir::Node::AnonConst(_)
| hir::Node::ConstBlock(_)
| hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) => hir::Constness::Const,
hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) => impl_.constness,
hir::Node::ForeignItem(hir::ForeignItem { kind: hir::ForeignItemKind::Fn(..), .. }) => {
// Intrinsics use `rustc_const_{un,}stable` attributes to indicate constness. All other

View file

@ -55,7 +55,7 @@ fn slice_branches<'tcx>(
place: &MPlaceTy<'tcx>,
num_nodes: &mut usize,
) -> ValTreeCreationResult<'tcx> {
let n = place.len(ecx).unwrap_or_else(|_| panic!("expected to use len of place {:?}", place));
let n = place.len(ecx).unwrap_or_else(|_| panic!("expected to use len of place {place:?}"));
let mut elems = Vec::with_capacity(n as usize);
for i in 0..n {

View file

@ -958,7 +958,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
} else {
self.param_env
};
let param_env = param_env.with_const();
let val = self.ctfe_query(span, |tcx| tcx.eval_to_allocation_raw(param_env.and(gid)))?;
self.raw_const_to_mplace(val)
}
@ -1016,7 +1015,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> std::fmt::Debug
match self.place {
Place::Local { frame, local, offset } => {
let mut allocs = Vec::new();
write!(fmt, "{:?}", local)?;
write!(fmt, "{local:?}")?;
if let Some(offset) = offset {
write!(fmt, "+{:#x}", offset.bytes())?;
}
@ -1035,7 +1034,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> std::fmt::Debug
fmt,
" by {} ref {:?}:",
match mplace.meta {
MemPlaceMeta::Meta(meta) => format!(" meta({:?})", meta),
MemPlaceMeta::Meta(meta) => format!(" meta({meta:?})"),
MemPlaceMeta::None => String::new(),
},
mplace.ptr,
@ -1043,13 +1042,13 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> std::fmt::Debug
allocs.extend(mplace.ptr.provenance.map(Provenance::get_alloc_id));
}
LocalValue::Live(Operand::Immediate(Immediate::Scalar(val))) => {
write!(fmt, " {:?}", val)?;
write!(fmt, " {val:?}")?;
if let Scalar::Ptr(ptr, _size) = val {
allocs.push(ptr.provenance.get_alloc_id());
}
}
LocalValue::Live(Operand::Immediate(Immediate::ScalarPair(val1, val2))) => {
write!(fmt, " ({:?}, {:?})", val1, val2)?;
write!(fmt, " ({val1:?}, {val2:?})")?;
if let Scalar::Ptr(ptr, _size) = val1 {
allocs.push(ptr.provenance.get_alloc_id());
}
@ -1065,7 +1064,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> std::fmt::Debug
Some(alloc_id) => {
write!(fmt, "by ref {:?}: {:?}", mplace.ptr, self.ecx.dump_alloc(alloc_id))
}
ptr => write!(fmt, " integral by ref: {:?}", ptr),
ptr => write!(fmt, " integral by ref: {ptr:?}"),
},
}
}

View file

@ -394,17 +394,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// For *all* intrinsics we first check `is_uninhabited` to give a more specific
// error message.
_ if layout.abi.is_uninhabited() => format!(
"aborted execution: attempted to instantiate uninhabited type `{}`",
ty
"aborted execution: attempted to instantiate uninhabited type `{ty}`"
),
ValidityRequirement::Inhabited => bug!("handled earlier"),
ValidityRequirement::Zero => format!(
"aborted execution: attempted to zero-initialize type `{}`, which is invalid",
ty
"aborted execution: attempted to zero-initialize type `{ty}`, which is invalid"
),
ValidityRequirement::UninitMitigated0x01Fill => format!(
"aborted execution: attempted to leave type `{}` uninitialized, which is invalid",
ty
"aborted execution: attempted to leave type `{ty}` uninitialized, which is invalid"
),
ValidityRequirement::Uninit => bug!("assert_uninit_valid doesn't exist"),
};
@ -420,9 +417,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
assert_eq!(input_len, dest_len, "Return vector length must match input length");
assert!(
index < dest_len,
"Index `{}` must be in bounds of vector with length {}",
index,
dest_len
"Index `{index}` must be in bounds of vector with length {dest_len}"
);
for i in 0..dest_len {
@ -440,9 +435,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let (input, input_len) = self.operand_to_simd(&args[0])?;
assert!(
index < input_len,
"index `{}` must be in bounds of vector with length {}",
index,
input_len
"index `{index}` must be in bounds of vector with length {input_len}"
);
self.copy_op(
&self.project_index(&input, index)?,

View file

@ -53,7 +53,7 @@ impl<T: fmt::Display> fmt::Display for MemoryKind<T> {
match self {
MemoryKind::Stack => write!(f, "stack variable"),
MemoryKind::CallerLocation => write!(f, "caller location"),
MemoryKind::Machine(m) => write!(f, "{}", m),
MemoryKind::Machine(m) => write!(f, "{m}"),
}
}
}
@ -907,7 +907,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a,
match self.ecx.memory.alloc_map.get(id) {
Some((kind, alloc)) => {
// normal alloc
write!(fmt, " ({}, ", kind)?;
write!(fmt, " ({kind}, ")?;
write_allocation_track_relocs(
&mut *fmt,
*self.ecx.tcx,

View file

@ -698,10 +698,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
ty::ConstKind::Unevaluated(uv) => {
let instance = self.resolve(uv.def, uv.args)?;
let cid = GlobalId { instance, promoted: None };
self.ctfe_query(span, |tcx| {
tcx.eval_to_valtree(self.param_env.with_const().and(cid))
})?
.unwrap_or_else(|| bug!("unable to create ValTree for {uv:?}"))
self.ctfe_query(span, |tcx| tcx.eval_to_valtree(self.param_env.and(cid)))?
.unwrap_or_else(|| bug!("unable to create ValTree for {uv:?}"))
}
ty::ConstKind::Bound(..) | ty::ConstKind::Infer(..) => {
span_bug!(self.cur_span(), "unexpected ConstKind in ctfe: {val:?}")

View file

@ -24,8 +24,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
debug_assert_eq!(
Ty::new_tup(self.tcx.tcx, &[ty, self.tcx.types.bool]),
dest.layout.ty,
"type mismatch for result of {:?}",
op,
"type mismatch for result of {op:?}",
);
// Write the result to `dest`.
if let Abi::ScalarPair(..) = dest.layout.abi {
@ -56,7 +55,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
dest: &PlaceTy<'tcx, M::Provenance>,
) -> InterpResult<'tcx> {
let (val, _overflowed, ty) = self.overflowing_binary_op(op, left, right)?;
assert_eq!(ty, dest.layout.ty, "type mismatch for result of {:?}", op);
assert_eq!(ty, dest.layout.ty, "type mismatch for result of {op:?}");
self.write_scalar(val, dest)
}
}

View file

@ -178,7 +178,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// The operand always has the same type as the result.
let val = self.read_immediate(&self.eval_operand(operand, Some(dest.layout))?)?;
let val = self.unary_op(un_op, &val)?;
assert_eq!(val.layout, dest.layout, "layout mismatch for result of {:?}", un_op);
assert_eq!(val.layout, dest.layout, "layout mismatch for result of {un_op:?}");
self.write_immediate(*val, &dest)?;
}

View file

@ -164,14 +164,14 @@ fn write_path(out: &mut String, path: &[PathElem]) {
for elem in path.iter() {
match elem {
Field(name) => write!(out, ".{}", name),
Field(name) => write!(out, ".{name}"),
EnumTag => write!(out, ".<enum-tag>"),
Variant(name) => write!(out, ".<enum-variant({})>", name),
Variant(name) => write!(out, ".<enum-variant({name})>"),
GeneratorTag => write!(out, ".<generator-tag>"),
GeneratorState(idx) => write!(out, ".<generator-state({})>", idx.index()),
CapturedVar(name) => write!(out, ".<captured-var({})>", name),
TupleElem(idx) => write!(out, ".{}", idx),
ArrayElem(idx) => write!(out, "[{}]", idx),
CapturedVar(name) => write!(out, ".<captured-var({name})>"),
TupleElem(idx) => write!(out, ".{idx}"),
ArrayElem(idx) => write!(out, "[{idx}]"),
// `.<deref>` does not match Rust syntax, but it is more readable for long paths -- and
// some of the other items here also are not Rust syntax. Actually we can't
// even use the usual syntax because we are just showing the projections,

View file

@ -21,7 +21,7 @@ use std::mem;
use std::ops::Deref;
use super::ops::{self, NonConstOp, Status};
use super::qualifs::{self, CustomEq, HasMutInterior, NeedsDrop, NeedsNonConstDrop};
use super::qualifs::{self, CustomEq, HasMutInterior, NeedsDrop};
use super::resolver::FlowSensitiveAnalysis;
use super::{ConstCx, Qualif};
use crate::const_eval::is_unstable_const_fn;
@ -34,7 +34,7 @@ type QualifResults<'mir, 'tcx, Q> =
pub struct Qualifs<'mir, 'tcx> {
has_mut_interior: Option<QualifResults<'mir, 'tcx, HasMutInterior>>,
needs_drop: Option<QualifResults<'mir, 'tcx, NeedsDrop>>,
needs_non_const_drop: Option<QualifResults<'mir, 'tcx, NeedsNonConstDrop>>,
// needs_non_const_drop: Option<QualifResults<'mir, 'tcx, NeedsNonConstDrop>>,
}
impl<'mir, 'tcx> Qualifs<'mir, 'tcx> {
@ -77,15 +77,17 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> {
local: Local,
location: Location,
) -> bool {
// FIXME(effects) replace with `NeedsNonconstDrop` after const traits work again
/*
let ty = ccx.body.local_decls[local].ty;
if !NeedsNonConstDrop::in_any_value_of_ty(ccx, ty) {
if !NeedsDrop::in_any_value_of_ty(ccx, ty) {
return false;
}
let needs_non_const_drop = self.needs_non_const_drop.get_or_insert_with(|| {
let ConstCx { tcx, body, .. } = *ccx;
FlowSensitiveAnalysis::new(NeedsNonConstDrop, ccx)
FlowSensitiveAnalysis::new(NeedsDrop, ccx)
.into_engine(tcx, &body)
.iterate_to_fixpoint()
.into_results_cursor(&body)
@ -93,6 +95,9 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> {
needs_non_const_drop.seek_before_primary_effect(location);
needs_non_const_drop.get().contains(local)
*/
self.needs_drop(ccx, local, location)
}
/// Returns `true` if `local` is `HasMutInterior` at the given `Location`.
@ -798,16 +803,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
}
Ok(Some(ImplSource::UserDefined(data))) => {
let callee_name = tcx.item_name(callee);
if let Some(&did) = tcx
.associated_item_def_ids(data.impl_def_id)
.iter()
.find(|did| tcx.item_name(**did) == callee_name)
{
// using internal args is ok here, since this is only
// used for the `resolve` call below
fn_args = GenericArgs::identity_for_item(tcx, did);
callee = did;
}
if let hir::Constness::NotConst = tcx.constness(data.impl_def_id) {
self.check_op(ops::FnCallNonConst {
@ -820,6 +815,17 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
});
return;
}
if let Some(&did) = tcx
.associated_item_def_ids(data.impl_def_id)
.iter()
.find(|did| tcx.item_name(**did) == callee_name)
{
// using internal args is ok here, since this is only
// used for the `resolve` call below
fn_args = GenericArgs::identity_for_item(tcx, did);
callee = did;
}
}
_ if !tcx.is_const_fn_raw(callee) => {
// At this point, it is only legal when the caller is in a trait
@ -996,8 +1002,9 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
let mut err_span = self.span;
let ty_of_dropped_place = dropped_place.ty(self.body, self.tcx).ty;
// FIXME(effects) replace with `NeedsNonConstDrop` once we fix const traits
let ty_needs_non_const_drop =
qualifs::NeedsNonConstDrop::in_any_value_of_ty(self.ccx, ty_of_dropped_place);
qualifs::NeedsDrop::in_any_value_of_ty(self.ccx, ty_of_dropped_place);
debug!(?ty_of_dropped_place, ?ty_needs_non_const_drop);

View file

@ -310,8 +310,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
if let Some(feature) = feature && ccx.tcx.sess.is_nightly_build() {
err.help(format!(
"add `#![feature({})]` to the crate attributes to enable",
feature,
"add `#![feature({feature})]` to the crate attributes to enable",
));
}
@ -346,10 +345,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallUnstable {
err.help("const-stable functions can only call other const-stable functions");
} else if ccx.tcx.sess.is_nightly_build() {
if let Some(feature) = feature {
err.help(format!(
"add `#![feature({})]` to the crate attributes to enable",
feature
));
err.help(format!("add `#![feature({feature})]` to the crate attributes to enable"));
}
}

View file

@ -5,7 +5,7 @@ use rustc_span::{symbol::sym, Span};
use super::check::Qualifs;
use super::ops::{self, NonConstOp};
use super::qualifs::{NeedsNonConstDrop, Qualif};
use super::qualifs::{NeedsDrop, Qualif};
use super::ConstCx;
/// Returns `true` if we should use the more precise live drop checker that runs after drop
@ -82,7 +82,9 @@ impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> {
match &terminator.kind {
mir::TerminatorKind::Drop { place: dropped_place, .. } => {
let dropped_ty = dropped_place.ty(self.body, self.tcx).ty;
if !NeedsNonConstDrop::in_any_value_of_ty(self.ccx, dropped_ty) {
// FIXME(effects) use `NeedsNonConstDrop`
if !NeedsDrop::in_any_value_of_ty(self.ccx, dropped_ty) {
// Instead of throwing a bug, we just return here. This is because we have to
// run custom `const Drop` impls.
return;

View file

@ -23,7 +23,8 @@ pub fn in_any_value_of_ty<'tcx>(
ConstQualifs {
has_mut_interior: HasMutInterior::in_any_value_of_ty(cx, ty),
needs_drop: NeedsDrop::in_any_value_of_ty(cx, ty),
needs_non_const_drop: NeedsNonConstDrop::in_any_value_of_ty(cx, ty),
// FIXME(effects)
needs_non_const_drop: NeedsDrop::in_any_value_of_ty(cx, ty),
custom_eq: CustomEq::in_any_value_of_ty(cx, ty),
tainted_by_errors,
}

View file

@ -149,7 +149,7 @@ impl<'a, 'tcx> CfgChecker<'a, 'tcx> {
}
}
} else {
self.fail(location, format!("encountered jump to invalid basic block {:?}", bb))
self.fail(location, format!("encountered jump to invalid basic block {bb:?}"))
}
}
@ -222,8 +222,7 @@ impl<'a, 'tcx> CfgChecker<'a, 'tcx> {
self.fail(
Location { block: bb, statement_index: 0 },
format!(
"Cleanup control flow violation: Cycle involving edge {:?} -> {:?}",
bb, parent,
"Cleanup control flow violation: Cycle involving edge {bb:?} -> {parent:?}",
),
);
break;
@ -257,7 +256,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
if self.body.local_decls.get(local).is_none() {
self.fail(
location,
format!("local {:?} has no corresponding declaration in `body.local_decls`", local),
format!("local {local:?} has no corresponding declaration in `body.local_decls`"),
);
}
@ -272,7 +271,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
self.storage_liveness.seek_after_primary_effect(location);
let locals_with_storage = self.storage_liveness.get();
if !locals_with_storage.contains(local) {
self.fail(location, format!("use of local {:?}, which has no storage here", local));
self.fail(location, format!("use of local {local:?}, which has no storage here"));
}
}
}
@ -323,7 +322,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
// DropsLowered`. However, this causes ICEs with generation of drop shims, which
// seem to fail to set their `MirPhase` correctly.
if matches!(kind, RetagKind::Raw | RetagKind::TwoPhase) {
self.fail(location, format!("explicit `{:?}` is forbidden", kind));
self.fail(location, format!("explicit `{kind:?}` is forbidden"));
}
}
StatementKind::StorageLive(local) => {
@ -556,7 +555,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
let ty = place.ty(&self.body.local_decls, self.tcx).ty;
if !ty.is_copy_modulo_regions(self.tcx, self.param_env) {
self.fail(location, format!("`Operand::Copy` with non-`Copy` type {}", ty));
self.fail(location, format!("`Operand::Copy` with non-`Copy` type {ty}"));
}
}
}
@ -575,7 +574,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
ProjectionElem::Index(index) => {
let index_ty = self.body.local_decls[index].ty;
if index_ty != self.tcx.types.usize {
self.fail(location, format!("bad index ({:?} != usize)", index_ty))
self.fail(location, format!("bad index ({index_ty:?} != usize)"))
}
}
ProjectionElem::Deref
@ -586,22 +585,21 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
if base_ty.is_box() {
self.fail(
location,
format!("{:?} dereferenced after ElaborateBoxDerefs", base_ty),
format!("{base_ty:?} dereferenced after ElaborateBoxDerefs"),
)
}
}
ProjectionElem::Field(f, ty) => {
let parent_ty = place_ref.ty(&self.body.local_decls, self.tcx);
let fail_out_of_bounds = |this: &mut Self, location| {
this.fail(location, format!("Out of bounds field {:?} for {:?}", f, parent_ty));
this.fail(location, format!("Out of bounds field {f:?} for {parent_ty:?}"));
};
let check_equal = |this: &mut Self, location, f_ty| {
if !this.mir_assign_valid_types(ty, f_ty) {
this.fail(
location,
format!(
"Field projection `{:?}.{:?}` specified type `{:?}`, but actual type is `{:?}`",
place_ref, f, ty, f_ty
"Field projection `{place_ref:?}.{f:?}` specified type `{ty:?}`, but actual type is `{f_ty:?}`"
)
)
}
@ -649,7 +647,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
let Some(layout) = gen_body.generator_layout() else {
self.fail(
location,
format!("No generator layout for {:?}", parent_ty),
format!("No generator layout for {parent_ty:?}"),
);
return;
};
@ -662,7 +660,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
let Some(f_ty) = layout.field_tys.get(local) else {
self.fail(
location,
format!("Out of bounds local {:?} for {:?}", local, parent_ty),
format!("Out of bounds local {local:?} for {parent_ty:?}"),
);
return;
};
@ -705,7 +703,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
if debuginfo.references != 0 && place.projection.last() == Some(&PlaceElem::Deref) {
self.fail(
START_BLOCK.start_location(),
format!("debuginfo {:?}, has both ref and deref", debuginfo),
format!("debuginfo {debuginfo:?}, has both ref and deref"),
);
}
}
@ -715,7 +713,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
if ty.is_union() || ty.is_enum() {
self.fail(
START_BLOCK.start_location(),
format!("invalid type {:?} for composite debuginfo", ty),
format!("invalid type {ty:?} for composite debuginfo"),
);
}
if f.projection.iter().any(|p| !matches!(p, PlaceElem::Field(..))) {
@ -742,7 +740,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
&& cntxt != PlaceContext::NonUse(NonUseContext::VarDebugInfo)
&& place.projection[1..].contains(&ProjectionElem::Deref)
{
self.fail(location, format!("{:?}, has deref at the wrong place", place));
self.fail(location, format!("{place:?}, has deref at the wrong place"));
}
self.super_place(place, cntxt, location);
@ -802,7 +800,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
Offset => {
check_kinds!(a, "Cannot offset non-pointer type {:?}", ty::RawPtr(..));
if b != self.tcx.types.isize && b != self.tcx.types.usize {
self.fail(location, format!("Cannot offset by non-isize type {:?}", b));
self.fail(location, format!("Cannot offset by non-isize type {b:?}"));
}
}
Eq | Lt | Le | Ne | Ge | Gt => {
@ -867,13 +865,12 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
self.fail(
location,
format!(
"Cannot perform checked arithmetic on unequal types {:?} and {:?}",
a, b
"Cannot perform checked arithmetic on unequal types {a:?} and {b:?}"
),
);
}
}
_ => self.fail(location, format!("There is no checked version of {:?}", op)),
_ => self.fail(location, format!("There is no checked version of {op:?}")),
}
}
Rvalue::UnaryOp(op, operand) => {
@ -1078,7 +1075,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
if !ty.is_bool() {
self.fail(
location,
format!("`assume` argument must be `bool`, but got: `{}`", ty),
format!("`assume` argument must be `bool`, but got: `{ty}`"),
);
}
}
@ -1091,7 +1088,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
} else {
self.fail(
location,
format!("Expected src to be ptr in copy_nonoverlapping, got: {}", src_ty),
format!("Expected src to be ptr in copy_nonoverlapping, got: {src_ty}"),
);
return;
};
@ -1101,19 +1098,19 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
} else {
self.fail(
location,
format!("Expected dst to be ptr in copy_nonoverlapping, got: {}", dst_ty),
format!("Expected dst to be ptr in copy_nonoverlapping, got: {dst_ty}"),
);
return;
};
// since CopyNonOverlapping is parametrized by 1 type,
// we only need to check that they are equal and not keep an extra parameter.
if !self.mir_assign_valid_types(op_src_ty, op_dst_ty) {
self.fail(location, format!("bad arg ({:?} != {:?})", op_src_ty, op_dst_ty));
self.fail(location, format!("bad arg ({op_src_ty:?} != {op_dst_ty:?})"));
}
let op_cnt_ty = count.ty(&self.body.local_decls, self.tcx);
if op_cnt_ty != self.tcx.types.usize {
self.fail(location, format!("bad arg ({:?} != usize)", op_cnt_ty))
self.fail(location, format!("bad arg ({op_cnt_ty:?} != usize)"))
}
}
StatementKind::SetDiscriminant { place, .. } => {
@ -1125,8 +1122,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
self.fail(
location,
format!(
"`SetDiscriminant` is only allowed on ADTs and generators, not {:?}",
pty
"`SetDiscriminant` is only allowed on ADTs and generators, not {pty:?}"
),
);
}
@ -1141,7 +1137,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
// DropsLowered`. However, this causes ICEs with generation of drop shims, which
// seem to fail to set their `MirPhase` correctly.
if matches!(kind, RetagKind::Raw | RetagKind::TwoPhase) {
self.fail(location, format!("explicit `{:?}` is forbidden", kind));
self.fail(location, format!("explicit `{kind:?}` is forbidden"));
}
}
StatementKind::StorageLive(_)
@ -1174,7 +1170,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
if Scalar::<()>::try_from_uint(value, size).is_none() {
self.fail(
location,
format!("the value {:#x} is not a proper {:?}", value, switch_ty),
format!("the value {value:#x} is not a proper {switch_ty:?}"),
)
}
}
@ -1185,7 +1181,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
ty::FnPtr(..) | ty::FnDef(..) => {}
_ => self.fail(
location,
format!("encountered non-callable type {} in `Call` terminator", func_ty),
format!("encountered non-callable type {func_ty} in `Call` terminator"),
),
}
}
@ -1195,8 +1191,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
self.fail(
location,
format!(
"encountered non-boolean condition of type {} in `Assert` terminator",
cond_ty
"encountered non-boolean condition of type {cond_ty} in `Assert` terminator"
),
);
}

View file

@ -57,12 +57,15 @@ pub fn is_subtype<'tcx>(
// we would get unification errors because we're unable to look into opaque types,
// even if they're constrained in our current function.
for (key, ty) in infcx.take_opaque_types() {
span_bug!(
ty.hidden_type.span,
"{}, {}",
tcx.type_of(key.def_id).instantiate(tcx, key.args),
ty.hidden_type.ty
);
let hidden_ty = tcx.type_of(key.def_id).instantiate(tcx, key.args);
if hidden_ty != ty.hidden_type.ty {
span_bug!(
ty.hidden_type.span,
"{}, {}",
tcx.type_of(key.def_id).instantiate(tcx, key.args),
ty.hidden_type.ty
);
}
}
errors.is_empty()
}

View file

@ -1,3 +1,25 @@
errors_delayed_at_with_newline =
delayed at {$emitted_at}
{$note}
errors_delayed_at_without_newline =
delayed at {$emitted_at} - {$note}
errors_expected_lifetime_parameter =
expected lifetime {$count ->
[1] parameter
*[other] parameters
}
errors_indicate_anonymous_lifetime =
indicate the anonymous {$count ->
[1] lifetime
*[other] lifetimes
}
errors_invalid_flushed_delayed_diagnostic_level =
`flushed_delayed` got diagnostic with level {$level}, instead of the expected `DelayedBug`
errors_target_inconsistent_architecture =
inconsistent target specification: "data-layout" claims architecture is {$dl}-endian, while "target-endian" is `{$target}`

View file

@ -1,3 +1,4 @@
use crate::diagnostic::DiagnosticLocation;
use crate::{fluent_generated as fluent, AddToDiagnostic};
use crate::{DiagnosticArgValue, DiagnosticBuilder, Handler, IntoDiagnostic, IntoDiagnosticArg};
use rustc_ast as ast;
@ -10,6 +11,7 @@ use rustc_span::Span;
use rustc_target::abi::TargetDataLayoutErrors;
use rustc_target::spec::{PanicStrategy, SplitDebuginfo, StackProtector, TargetTriple};
use rustc_type_ir as type_ir;
use std::backtrace::Backtrace;
use std::borrow::Cow;
use std::fmt;
use std::num::ParseIntError;
@ -317,3 +319,62 @@ pub enum LabelKind {
Label,
Help,
}
#[derive(Subdiagnostic)]
#[label(errors_expected_lifetime_parameter)]
pub struct ExpectedLifetimeParameter {
#[primary_span]
pub span: Span,
pub count: usize,
}
#[derive(Subdiagnostic)]
#[note(errors_delayed_at_with_newline)]
pub struct DelayedAtWithNewline {
#[primary_span]
pub span: Span,
pub emitted_at: DiagnosticLocation,
pub note: Backtrace,
}
#[derive(Subdiagnostic)]
#[note(errors_delayed_at_without_newline)]
pub struct DelayedAtWithoutNewline {
#[primary_span]
pub span: Span,
pub emitted_at: DiagnosticLocation,
pub note: Backtrace,
}
impl IntoDiagnosticArg for DiagnosticLocation {
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
DiagnosticArgValue::Str(Cow::from(self.to_string()))
}
}
impl IntoDiagnosticArg for Backtrace {
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
DiagnosticArgValue::Str(Cow::from(self.to_string()))
}
}
#[derive(Subdiagnostic)]
#[note(errors_invalid_flushed_delayed_diagnostic_level)]
pub struct InvalidFlushedDelayedDiagnosticLevel {
#[primary_span]
pub span: Span,
pub level: rustc_errors::Level,
}
impl IntoDiagnosticArg for rustc_errors::Level {
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
DiagnosticArgValue::Str(Cow::from(self.to_string()))
}
}
#[derive(Subdiagnostic)]
#[suggestion(errors_indicate_anonymous_lifetime, code = "{suggestion}", style = "verbose")]
pub struct IndicateAnonymousLifetime {
#[primary_span]
pub span: Span,
pub count: usize,
pub suggestion: String,
}

View file

@ -22,6 +22,8 @@ extern crate rustc_macros;
#[macro_use]
extern crate tracing;
extern crate self as rustc_errors;
pub use emitter::ColorConfig;
use rustc_lint_defs::LintExpectationId;
@ -377,13 +379,16 @@ pub struct ExplicitBug;
/// rather than a failed assertion, etc.
pub struct DelayedBugPanic;
use crate::diagnostic_impls::{DelayedAtWithNewline, DelayedAtWithoutNewline};
pub use diagnostic::{
AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgValue, DiagnosticId,
DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic,
};
pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee, Noted};
pub use diagnostic_impls::{
DiagnosticArgFromDisplay, DiagnosticSymbolList, LabelKind, SingleLabelManySpans,
DiagnosticArgFromDisplay, DiagnosticSymbolList, ExpectedLifetimeParameter,
IndicateAnonymousLifetime, InvalidFlushedDelayedDiagnosticLevel, LabelKind,
SingleLabelManySpans,
};
use std::backtrace::{Backtrace, BacktraceStatus};
@ -1650,11 +1655,11 @@ impl HandlerInner {
let backtrace = std::env::var_os("RUST_BACKTRACE").map_or(true, |x| &x != "0");
for bug in bugs {
if let Some(file) = self.ice_file.as_ref()
&& let Ok(mut out) = std::fs::File::options().append(true).open(file)
&& let Ok(mut out) = std::fs::File::options().create(true).append(true).open(file)
{
let _ = write!(
&mut out,
"\n\ndelayed span bug: {}\n{}",
"delayed span bug: {}\n{}\n",
bug.inner.styled_message().iter().filter_map(|(msg, _)| msg.as_str()).collect::<String>(),
&bug.note
);
@ -1673,11 +1678,10 @@ impl HandlerInner {
if bug.level != Level::DelayedBug {
// NOTE(eddyb) not panicking here because we're already producing
// an ICE, and the more information the merrier.
bug.note(format!(
"`flushed_delayed` got diagnostic with level {:?}, \
instead of the expected `DelayedBug`",
bug.level,
));
bug.subdiagnostic(InvalidFlushedDelayedDiagnosticLevel {
span: bug.span.primary_span().unwrap(),
level: bug.level,
});
}
bug.level = Level::Bug;
@ -1744,12 +1748,22 @@ impl DelayedDiagnostic {
fn decorate(mut self) -> Diagnostic {
match self.note.status() {
BacktraceStatus::Captured => {
self.inner.note(format!("delayed at {}\n{}", self.inner.emitted_at, self.note));
let inner = &self.inner;
self.inner.subdiagnostic(DelayedAtWithNewline {
span: inner.span.primary_span().unwrap(),
emitted_at: inner.emitted_at.clone(),
note: self.note,
});
}
// Avoid the needless newline when no backtrace has been captured,
// the display impl should just be a single line.
_ => {
self.inner.note(format!("delayed at {} - {}", self.inner.emitted_at, self.note));
let inner = &self.inner;
self.inner.subdiagnostic(DelayedAtWithoutNewline {
span: inner.span.primary_span().unwrap(),
emitted_at: inner.emitted_at.clone(),
note: self.note,
});
}
}
@ -1841,7 +1855,7 @@ pub fn add_elided_lifetime_in_path_suggestion(
incl_angl_brckt: bool,
insertion_span: Span,
) {
diag.span_label(path_span, format!("expected lifetime parameter{}", pluralize!(n)));
diag.subdiagnostic(ExpectedLifetimeParameter { span: path_span, count: n });
if !source_map.is_span_accessible(insertion_span) {
// Do not try to suggest anything if generated by a proc-macro.
return;
@ -1849,12 +1863,28 @@ pub fn add_elided_lifetime_in_path_suggestion(
let anon_lts = vec!["'_"; n].join(", ");
let suggestion =
if incl_angl_brckt { format!("<{}>", anon_lts) } else { format!("{}, ", anon_lts) };
diag.span_suggestion_verbose(
insertion_span.shrink_to_hi(),
format!("indicate the anonymous lifetime{}", pluralize!(n)),
diag.subdiagnostic(IndicateAnonymousLifetime {
span: insertion_span.shrink_to_hi(),
count: n,
suggestion,
Applicability::MachineApplicable,
);
});
}
pub fn report_ambiguity_error<'a, G: EmissionGuarantee>(
db: &mut DiagnosticBuilder<'a, G>,
ambiguity: rustc_lint_defs::AmbiguityErrorDiag,
) {
db.span_label(ambiguity.label_span, ambiguity.label_msg);
db.note(ambiguity.note_msg);
db.span_note(ambiguity.b1_span, ambiguity.b1_note_msg);
for help_msg in ambiguity.b1_help_msgs {
db.help(help_msg);
}
db.span_note(ambiguity.b2_span, ambiguity.b2_note_msg);
for help_msg in ambiguity.b2_help_msgs {
db.help(help_msg);
}
}
#[derive(Clone, Copy, PartialEq, Hash, Debug)]

View file

@ -63,7 +63,7 @@ fn test_wrapping_write() {
#[test]
fn test_output() {
// Capture `--bless` when run via ./x
let bless = std::env::var("RUSTC_BLESS").unwrap_or_default() == "1";
let bless = std::env::var_os("RUSTC_BLESS").is_some_and(|v| v != "0");
let ast = MdStream::parse_str(INPUT);
let bufwtr = BufferWriter::stderr(ColorChoice::Always);
let mut buffer = bufwtr.buffer();

View file

@ -643,7 +643,16 @@ impl<'a> ExtCtxt<'a> {
span,
name,
AttrVec::new(),
ast::ItemKind::Const(ast::ConstItem { defaultness, ty, expr: Some(expr) }.into()),
ast::ItemKind::Const(
ast::ConstItem {
defaultness,
// FIXME(generic_const_items): Pass the generics as a parameter.
generics: ast::Generics::default(),
ty,
expr: Some(expr),
}
.into(),
),
)
}

View file

@ -365,9 +365,9 @@ impl<'a> StripUnconfigured<'a> {
// Use the `#` in `#[cfg_attr(pred, attr)]` as the `#` token
// for `attr` when we expand it to `#[attr]`
let mut orig_trees = orig_tokens.into_trees();
let mut orig_trees = orig_tokens.trees();
let TokenTree::Token(pound_token @ Token { kind: TokenKind::Pound, .. }, _) =
orig_trees.next().unwrap()
orig_trees.next().unwrap().clone()
else {
panic!("Bad tokens for attribute {:?}", attr);
};
@ -377,7 +377,7 @@ impl<'a> StripUnconfigured<'a> {
if attr.style == AttrStyle::Inner {
// For inner attributes, we do the same thing for the `!` in `#![some_attr]`
let TokenTree::Token(bang_token @ Token { kind: TokenKind::Not, .. }, _) =
orig_trees.next().unwrap()
orig_trees.next().unwrap().clone()
else {
panic!("Bad tokens for attribute {:?}", attr);
};

View file

@ -500,7 +500,7 @@ pub fn compile_declarative_macro(
.map(|m| {
if let MatchedTokenTree(tt) = m {
let tt = mbe::quoted::parse(
TokenStream::new(vec![tt.clone()]),
&TokenStream::new(vec![tt.clone()]),
true,
&sess.parse_sess,
def.id,
@ -524,7 +524,7 @@ pub fn compile_declarative_macro(
.map(|m| {
if let MatchedTokenTree(tt) = m {
return mbe::quoted::parse(
TokenStream::new(vec![tt.clone()]),
&TokenStream::new(vec![tt.clone()]),
false,
&sess.parse_sess,
def.id,

View file

@ -36,7 +36,7 @@ const VALID_FRAGMENT_NAMES_MSG: &str = "valid fragment specifiers are \
///
/// A collection of `self::TokenTree`. There may also be some errors emitted to `sess`.
pub(super) fn parse(
input: tokenstream::TokenStream,
input: &tokenstream::TokenStream,
parsing_patterns: bool,
sess: &ParseSess,
node_id: NodeId,
@ -48,7 +48,7 @@ pub(super) fn parse(
// For each token tree in `input`, parse the token into a `self::TokenTree`, consuming
// additional trees if need be.
let mut trees = input.into_trees();
let mut trees = input.trees();
while let Some(tree) = trees.next() {
// Given the parsed tree, if there is a metavar and we are expecting matchers, actually
// parse out the matcher (i.e., in `$id:ident` this would parse the `:` and `ident`).
@ -56,7 +56,7 @@ pub(super) fn parse(
match tree {
TokenTree::MetaVar(start_sp, ident) if parsing_patterns => {
let span = match trees.next() {
Some(tokenstream::TokenTree::Token(Token { kind: token::Colon, span }, _)) => {
Some(&tokenstream::TokenTree::Token(Token { kind: token::Colon, span }, _)) => {
match trees.next() {
Some(tokenstream::TokenTree::Token(token, _)) => match token.ident() {
Some((frag, _)) => {
@ -96,10 +96,10 @@ pub(super) fn parse(
}
_ => token.span,
},
tree => tree.as_ref().map_or(span, tokenstream::TokenTree::span),
tree => tree.map_or(span, tokenstream::TokenTree::span),
}
}
tree => tree.as_ref().map_or(start_sp, tokenstream::TokenTree::span),
tree => tree.map_or(start_sp, tokenstream::TokenTree::span),
};
result.push(TokenTree::MetaVarDecl(span, ident, None));
@ -134,9 +134,9 @@ fn maybe_emit_macro_metavar_expr_feature(features: &Features, sess: &ParseSess,
/// - `parsing_patterns`: same as [parse].
/// - `sess`: the parsing session. Any errors will be emitted to this session.
/// - `features`: language features so we can do feature gating.
fn parse_tree(
tree: tokenstream::TokenTree,
outer_trees: &mut impl Iterator<Item = tokenstream::TokenTree>,
fn parse_tree<'a>(
tree: &'a tokenstream::TokenTree,
outer_trees: &mut impl Iterator<Item = &'a tokenstream::TokenTree>,
parsing_patterns: bool,
sess: &ParseSess,
node_id: NodeId,
@ -146,13 +146,13 @@ fn parse_tree(
// Depending on what `tree` is, we could be parsing different parts of a macro
match tree {
// `tree` is a `$` token. Look at the next token in `trees`
tokenstream::TokenTree::Token(Token { kind: token::Dollar, span }, _) => {
&tokenstream::TokenTree::Token(Token { kind: token::Dollar, span }, _) => {
// FIXME: Handle `Invisible`-delimited groups in a more systematic way
// during parsing.
let mut next = outer_trees.next();
let mut trees: Box<dyn Iterator<Item = tokenstream::TokenTree>>;
let mut trees: Box<dyn Iterator<Item = &tokenstream::TokenTree>>;
if let Some(tokenstream::TokenTree::Delimited(_, Delimiter::Invisible, tts)) = next {
trees = Box::new(tts.into_trees());
trees = Box::new(tts.trees());
next = trees.next();
} else {
trees = Box::new(outer_trees);
@ -160,7 +160,7 @@ fn parse_tree(
match next {
// `tree` is followed by a delimited set of token trees.
Some(tokenstream::TokenTree::Delimited(delim_span, delim, tts)) => {
Some(&tokenstream::TokenTree::Delimited(delim_span, delim, ref tts)) => {
if parsing_patterns {
if delim != Delimiter::Parenthesis {
span_dollar_dollar_or_metavar_in_the_lhs_err(
@ -228,7 +228,7 @@ fn parse_tree(
}
// `tree` is followed by another `$`. This is an escaped `$`.
Some(tokenstream::TokenTree::Token(Token { kind: token::Dollar, span }, _)) => {
Some(&tokenstream::TokenTree::Token(Token { kind: token::Dollar, span }, _)) => {
if parsing_patterns {
span_dollar_dollar_or_metavar_in_the_lhs_err(
sess,
@ -256,11 +256,11 @@ fn parse_tree(
}
// `tree` is an arbitrary token. Keep it.
tokenstream::TokenTree::Token(token, _) => TokenTree::Token(token),
tokenstream::TokenTree::Token(token, _) => TokenTree::Token(token.clone()),
// `tree` is the beginning of a delimited set of tokens (e.g., `(` or `{`). We need to
// descend into the delimited set and further parse it.
tokenstream::TokenTree::Delimited(span, delim, tts) => TokenTree::Delimited(
&tokenstream::TokenTree::Delimited(span, delim, ref tts) => TokenTree::Delimited(
span,
Delimited {
delim,
@ -286,16 +286,16 @@ fn kleene_op(token: &Token) -> Option<KleeneOp> {
/// - Ok(Ok((op, span))) if the next token tree is a KleeneOp
/// - Ok(Err(tok, span)) if the next token tree is a token but not a KleeneOp
/// - Err(span) if the next token tree is not a token
fn parse_kleene_op(
input: &mut impl Iterator<Item = tokenstream::TokenTree>,
fn parse_kleene_op<'a>(
input: &mut impl Iterator<Item = &'a tokenstream::TokenTree>,
span: Span,
) -> Result<Result<(KleeneOp, Span), Token>, Span> {
match input.next() {
Some(tokenstream::TokenTree::Token(token, _)) => match kleene_op(&token) {
Some(op) => Ok(Ok((op, token.span))),
None => Ok(Err(token)),
None => Ok(Err(token.clone())),
},
tree => Err(tree.as_ref().map_or(span, tokenstream::TokenTree::span)),
tree => Err(tree.map_or(span, tokenstream::TokenTree::span)),
}
}
@ -311,8 +311,8 @@ fn parse_kleene_op(
/// session `sess`. If the next one (or possibly two) tokens in `input` correspond to a Kleene
/// operator and separator, then a tuple with `(separator, KleeneOp)` is returned. Otherwise, an
/// error with the appropriate span is emitted to `sess` and a dummy value is returned.
fn parse_sep_and_kleene_op(
input: &mut impl Iterator<Item = tokenstream::TokenTree>,
fn parse_sep_and_kleene_op<'a>(
input: &mut impl Iterator<Item = &'a tokenstream::TokenTree>,
span: Span,
sess: &ParseSess,
) -> (Option<Token>, KleeneToken) {

View file

@ -69,9 +69,8 @@ fn bad_path_expr_1() {
#[test]
fn string_to_tts_macro() {
create_default_session_globals_then(|| {
let tts: Vec<_> =
string_to_stream("macro_rules! zip (($a)=>($a))".to_string()).into_trees().collect();
let tts: &[TokenTree] = &tts[..];
let stream = string_to_stream("macro_rules! zip (($a)=>($a))".to_string());
let tts = &stream.trees().collect::<Vec<_>>()[..];
match tts {
[
@ -300,9 +299,7 @@ fn ttdelim_span() {
.unwrap();
let ast::ExprKind::MacCall(mac) = &expr.kind else { panic!("not a macro") };
let tts: Vec<_> = mac.args.tokens.clone().into_trees().collect();
let span = tts.iter().rev().next().unwrap().span();
let span = mac.args.tokens.trees().last().unwrap().span();
match sess.source_map().span_to_snippet(span) {
Ok(s) => assert_eq!(&s[..], "{ body }"),

View file

@ -94,10 +94,10 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStre
// Estimate the capacity as `stream.len()` rounded up to the next power
// of two to limit the number of required reallocations.
let mut trees = Vec::with_capacity(stream.len().next_power_of_two());
let mut cursor = stream.into_trees();
let mut cursor = stream.trees();
while let Some(tree) = cursor.next() {
let (Token { kind, span }, joint) = match tree {
let (Token { kind, span }, joint) = match tree.clone() {
tokenstream::TokenTree::Delimited(span, delim, tts) => {
let delimiter = pm::Delimiter::from_internal(delim);
trees.push(TokenTree::Group(Group {

View file

@ -379,6 +379,8 @@ declare_features! (
(active, deprecated_safe, "1.61.0", Some(94978), None),
/// Allows having using `suggestion` in the `#[deprecated]` attribute.
(active, deprecated_suggestion, "1.61.0", Some(94785), None),
/// Allows using the `#[diagnostic]` attribute tool namespace
(active, diagnostic_namespace, "CURRENT_RUSTC_VERSION", Some(94785), None),
/// Controls errors in trait implementations.
(active, do_not_recommend, "1.67.0", Some(51992), None),
/// Tells rustdoc to automatically generate `#[doc(cfg(...))]`.
@ -422,6 +424,8 @@ declare_features! (
(incomplete, generic_associated_types_extended, "1.61.0", Some(95451), None),
/// Allows non-trivial generic constants which have to have wfness manually propagated to callers
(incomplete, generic_const_exprs, "1.56.0", Some(76560), None),
/// Allows generic parameters and where-clauses on free & associated const items.
(incomplete, generic_const_items, "CURRENT_RUSTC_VERSION", Some(113521), None),
/// Allows using `..=X` as a patterns in slices.
(active, half_open_range_patterns_in_slices, "1.66.0", Some(67264), None),
/// Allows `if let` guard in match arms.

View file

@ -3130,9 +3130,9 @@ impl<'hir> Item<'hir> {
}
/// Expect an [`ItemKind::Const`] or panic.
#[track_caller]
pub fn expect_const(&self) -> (&'hir Ty<'hir>, BodyId) {
let ItemKind::Const(ty, body) = self.kind else { self.expect_failed("a constant") };
(ty, body)
pub fn expect_const(&self) -> (&'hir Ty<'hir>, &'hir Generics<'hir>, BodyId) {
let ItemKind::Const(ty, gen, body) = self.kind else { self.expect_failed("a constant") };
(ty, gen, body)
}
/// Expect an [`ItemKind::Fn`] or panic.
#[track_caller]
@ -3319,7 +3319,7 @@ pub enum ItemKind<'hir> {
/// A `static` item.
Static(&'hir Ty<'hir>, Mutability, BodyId),
/// A `const` item.
Const(&'hir Ty<'hir>, BodyId),
Const(&'hir Ty<'hir>, &'hir Generics<'hir>, BodyId),
/// A function declaration.
Fn(FnSig<'hir>, &'hir Generics<'hir>, BodyId),
/// A MBE macro definition (`macro_rules!` or `macro`).
@ -3372,6 +3372,7 @@ impl ItemKind<'_> {
Some(match *self {
ItemKind::Fn(_, ref generics, _)
| ItemKind::TyAlias(_, ref generics)
| ItemKind::Const(_, ref generics, _)
| ItemKind::OpaqueTy(OpaqueTy { ref generics, .. })
| ItemKind::Enum(_, ref generics)
| ItemKind::Struct(_, ref generics)
@ -3567,7 +3568,9 @@ impl<'hir> OwnerNode<'hir> {
match self {
OwnerNode::Item(Item {
kind:
ItemKind::Static(_, _, body) | ItemKind::Const(_, body) | ItemKind::Fn(_, _, body),
ItemKind::Static(_, _, body)
| ItemKind::Const(_, _, body)
| ItemKind::Fn(_, _, body),
..
})
| OwnerNode::TraitItem(TraitItem {
@ -3770,9 +3773,9 @@ impl<'hir> Node<'hir> {
pub fn ty(self) -> Option<&'hir Ty<'hir>> {
match self {
Node::Item(it) => match it.kind {
ItemKind::TyAlias(ty, _) | ItemKind::Static(ty, _, _) | ItemKind::Const(ty, _) => {
Some(ty)
}
ItemKind::TyAlias(ty, _)
| ItemKind::Static(ty, _, _)
| ItemKind::Const(ty, _, _) => Some(ty),
_ => None,
},
Node::TraitItem(it) => match it.kind {
@ -3800,7 +3803,9 @@ impl<'hir> Node<'hir> {
match self {
Node::Item(Item {
kind:
ItemKind::Static(_, _, body) | ItemKind::Const(_, body) | ItemKind::Fn(_, _, body),
ItemKind::Static(_, _, body)
| ItemKind::Const(_, _, body)
| ItemKind::Fn(_, _, body),
..
})
| Node::TraitItem(TraitItem {

View file

@ -467,11 +467,17 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
ItemKind::Use(ref path, _) => {
visitor.visit_use(path, item.hir_id());
}
ItemKind::Static(ref typ, _, body) | ItemKind::Const(ref typ, body) => {
ItemKind::Static(ref typ, _, body) => {
visitor.visit_id(item.hir_id());
visitor.visit_ty(typ);
visitor.visit_nested_body(body);
}
ItemKind::Const(ref typ, ref generics, body) => {
visitor.visit_id(item.hir_id());
visitor.visit_ty(typ);
visitor.visit_generics(generics);
visitor.visit_nested_body(body);
}
ItemKind::Fn(ref sig, ref generics, body_id) => {
visitor.visit_id(item.hir_id());
visitor.visit_fn(

View file

@ -197,7 +197,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
}
err.span_label(span, format!("associated type `{}` not found", assoc_name));
err.span_label(span, format!("associated type `{assoc_name}` not found"));
err.emit()
}
@ -393,7 +393,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.into_iter()
.map(|error| error.root_obligation.predicate)
.filter_map(format_pred)
.map(|(p, _)| format!("`{}`", p))
.map(|(p, _)| format!("`{p}`"))
.collect();
bounds.sort();
bounds.dedup();
@ -652,7 +652,7 @@ pub(crate) fn fn_trait_to_string(
}
.map(|s| {
// `s.empty()` checks to see if the type is the unit tuple, if so we don't want a comma
if parenthesized || s.is_empty() { format!("({})", s) } else { format!("({},)", s) }
if parenthesized || s.is_empty() { format!("({s})") } else { format!("({s},)") }
})
.ok(),
_ => None,

View file

@ -81,7 +81,7 @@ fn generic_arg_mismatch_err(
err.span_suggestion(
tcx.def_span(src_def_id),
"consider changing this type parameter to a const parameter",
format!("const {}: {}", param_name, param_type),
format!("const {param_name}: {param_type}"),
Applicability::MaybeIncorrect,
);
};
@ -102,7 +102,7 @@ fn generic_arg_mismatch_err(
err.span_suggestion(
arg.span(),
"array type provided where a `usize` was expected, try",
format!("{{ {} }}", snippet),
format!("{{ {snippet} }}"),
Applicability::MaybeIncorrect,
);
}
@ -130,7 +130,7 @@ fn generic_arg_mismatch_err(
} else {
(arg.descr(), param.kind.descr())
};
err.note(format!("{} arguments must be provided before {} arguments", first, last));
err.note(format!("{first} arguments must be provided before {last} arguments"));
if let Some(help) = help {
err.help(help);
}
@ -304,7 +304,7 @@ pub fn create_args_for_parent_generic_args<'tcx, 'a>(
"reorder the arguments: {}: `<{}>`",
param_types_present
.into_iter()
.map(|ord| format!("{}s", ord))
.map(|ord| format!("{ord}s"))
.collect::<Vec<String>>()
.join(", then "),
ordered_params

View file

@ -34,9 +34,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let param_name = generics.params.next_type_param_name(None);
let add_generic_sugg = if let Some(span) = generics.span_for_param_suggestion() {
(span, format!(", {}: {}", param_name, impl_trait_name))
(span, format!(", {param_name}: {impl_trait_name}"))
} else {
(generics.span, format!("<{}: {}>", param_name, impl_trait_name))
(generics.span, format!("<{param_name}: {impl_trait_name}>"))
};
diag.multipart_suggestion(
format!("alternatively use a blanket \

View file

@ -1128,7 +1128,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
ty_param_name
)
};
err.span_label(span, format!("ambiguous associated type `{}`", assoc_name));
err.span_label(span, format!("ambiguous associated type `{assoc_name}`"));
let mut where_bounds = vec![];
for bound in bounds {
@ -1407,7 +1407,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
_ => {
let reported = if variant_resolution.is_some() {
// Variant in type position
let msg = format!("expected type, found variant `{}`", assoc_ident);
let msg = format!("expected type, found variant `{assoc_ident}`");
tcx.sess.span_err(span, msg)
} else if qself_ty.is_enum() {
let mut err = struct_span_err!(
@ -1438,12 +1438,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
} else {
err.span_label(
assoc_ident.span,
format!("variant not found in `{}`", qself_ty),
format!("variant not found in `{qself_ty}`"),
);
}
if let Some(sp) = tcx.hir().span_if_local(adt_def.did()) {
err.span_label(sp, format!("variant `{}` not found here", assoc_ident));
err.span_label(sp, format!("variant `{assoc_ident}` not found here"));
}
err.emit()
@ -2750,7 +2750,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon(..) | ty::BrEnv => {
"an anonymous lifetime".to_string()
}
ty::BrNamed(_, name) => format!("lifetime `{}`", name),
ty::BrNamed(_, name) => format!("lifetime `{name}`"),
};
let mut err = generate_err(&br_name);

View file

@ -345,7 +345,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
err.span_suggestion(
span,
"consider spelling out the type instead",
name.unwrap_or_else(|| format!("{:?}", ty)),
name.unwrap_or_else(|| format!("{ty:?}")),
Applicability::MaybeIncorrect,
);
}
@ -797,7 +797,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
"replace the {} parameters with concrete {}{}",
kinds,
kinds_pl,
egs.map(|egs| format!(" like `{}`", egs)).unwrap_or_default(),
egs.map(|egs| format!(" like `{egs}`")).unwrap_or_default(),
),
)
.emit();
@ -882,7 +882,7 @@ pub(super) fn check_specialization_validity<'tcx>(
} else {
tcx.sess.delay_span_bug(
DUMMY_SP,
format!("parent item: {:?} not marked as default", parent_impl),
format!("parent item: {parent_impl:?} not marked as default"),
);
}
}

View file

@ -76,7 +76,7 @@ fn check_method_is_structurally_compatible<'tcx>(
Ok(())
}
/// This function is best explained by example. Consider a trait with it's implementation:
/// This function is best explained by example. Consider a trait with its implementation:
///
/// ```rust
/// trait Trait<'t, T> {
@ -120,7 +120,7 @@ fn check_method_is_structurally_compatible<'tcx>(
/// types:
///
/// ```rust,ignore (pseudo-Rust)
/// <'b> fn(t: &'i0 U0, m: &'b) -> Foo
/// <'b> fn(t: &'i0 U0, m: &'b N0) -> Foo
/// ```
///
/// We now want to extract and substitute the type of the *trait*
@ -137,7 +137,7 @@ fn check_method_is_structurally_compatible<'tcx>(
/// Applying this to the trait method type yields:
///
/// ```rust,ignore (pseudo-Rust)
/// <'a> fn(t: &'i0 U0, m: &'a) -> Foo
/// <'a> fn(t: &'i0 U0, m: &'a N0) -> Foo
/// ```
///
/// This type is also the same but the name of the bound region (`'a`
@ -219,11 +219,7 @@ fn compare_method_predicate_entailment<'tcx>(
// The key step here is to update the caller_bounds's predicates to be
// the new hybrid bounds we computed.
let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_def_id);
let param_env = ty::ParamEnv::new(
tcx.mk_clauses(&hybrid_preds.predicates),
Reveal::UserFacing,
hir::Constness::NotConst,
);
let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds.predicates), Reveal::UserFacing);
let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
let infcx = &tcx.infer_ctxt().build();
@ -262,8 +258,6 @@ fn compare_method_predicate_entailment<'tcx>(
// type.
// Compute placeholder form of impl and trait method tys.
let tcx = infcx.tcx;
let mut wf_tys = FxIndexSet::default();
let unnormalized_impl_sig = infcx.instantiate_binder_with_fresh_vars(
@ -760,7 +754,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
);
ocx.resolve_regions_and_report_errors(impl_m_def_id, &outlives_env)?;
let mut collected_tys = FxHashMap::default();
let mut remapped_types = FxHashMap::default();
for (def_id, (ty, args)) in collected_types {
match infcx.fully_resolve((ty, args)) {
Ok((ty, args)) => {
@ -810,19 +804,37 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
Ok(ty) => ty,
Err(guar) => Ty::new_error(tcx, guar),
};
collected_tys.insert(def_id, ty::EarlyBinder::bind(ty));
remapped_types.insert(def_id, ty::EarlyBinder::bind(ty));
}
Err(err) => {
let reported = tcx.sess.delay_span_bug(
return_span,
format!("could not fully resolve: {ty} => {err:?}"),
);
collected_tys.insert(def_id, ty::EarlyBinder::bind(Ty::new_error(tcx, reported)));
remapped_types.insert(def_id, ty::EarlyBinder::bind(Ty::new_error(tcx, reported)));
}
}
}
Ok(&*tcx.arena.alloc(collected_tys))
// We may not collect all RPITITs that we see in the HIR for a trait signature
// because an RPITIT was located within a missing item. Like if we have a sig
// returning `-> Missing<impl Sized>`, that gets converted to `-> [type error]`,
// and when walking through the signature we end up never collecting the def id
// of the `impl Sized`. Insert that here, so we don't ICE later.
for assoc_item in tcx.associated_types_for_impl_traits_in_associated_fn(trait_m.def_id) {
if !remapped_types.contains_key(assoc_item) {
remapped_types.insert(
*assoc_item,
ty::EarlyBinder::bind(Ty::new_error_with_message(
tcx,
return_span,
"missing synthetic item for RPITIT",
)),
);
}
}
Ok(&*tcx.arena.alloc(remapped_types))
}
struct ImplTraitInTraitCollector<'a, 'tcx> {
@ -1672,19 +1684,19 @@ fn compare_synthetic_generics<'tcx>(
/// ```rust,ignore (pseudo-Rust)
/// trait Foo {
/// fn foo<const N: u8>();
/// type bar<const N: u8>;
/// type Bar<const N: u8>;
/// fn baz<const N: u32>();
/// type blah<T>;
/// type Blah<T>;
/// }
///
/// impl Foo for () {
/// fn foo<const N: u64>() {}
/// //~^ error
/// type bar<const N: u64> {}
/// type Bar<const N: u64> = ();
/// //~^ error
/// fn baz<T>() {}
/// //~^ error
/// type blah<const N: i64> = u32;
/// type Blah<const N: i64> = u32;
/// //~^ error
/// }
/// ```
@ -1744,7 +1756,7 @@ fn compare_generic_param_kinds<'tcx>(
tcx.type_of(param.def_id).instantiate_identity()
)
}
Type { .. } => format!("{} type parameter", prefix),
Type { .. } => format!("{prefix} type parameter"),
Lifetime { .. } => unreachable!(),
};
@ -1773,36 +1785,82 @@ pub(super) fn compare_impl_const_raw(
let trait_const_item = tcx.associated_item(trait_const_item_def);
let impl_trait_ref =
tcx.impl_trait_ref(impl_const_item.container_id(tcx)).unwrap().instantiate_identity();
debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref);
let impl_c_span = tcx.def_span(impl_const_item_def.to_def_id());
debug!("compare_impl_const(impl_trait_ref={:?})", impl_trait_ref);
let infcx = tcx.infer_ctxt().build();
let param_env = tcx.param_env(impl_const_item_def.to_def_id());
let ocx = ObligationCtxt::new(&infcx);
compare_number_of_generics(tcx, impl_const_item, trait_const_item, false)?;
compare_generic_param_kinds(tcx, impl_const_item, trait_const_item, false)?;
compare_const_predicate_entailment(tcx, impl_const_item, trait_const_item, impl_trait_ref)
}
/// The equivalent of [compare_method_predicate_entailment], but for associated constants
/// instead of associated functions.
// FIXME(generic_const_items): If possible extract the common parts of `compare_{type,const}_predicate_entailment`.
fn compare_const_predicate_entailment<'tcx>(
tcx: TyCtxt<'tcx>,
impl_ct: ty::AssocItem,
trait_ct: ty::AssocItem,
impl_trait_ref: ty::TraitRef<'tcx>,
) -> Result<(), ErrorGuaranteed> {
let impl_ct_def_id = impl_ct.def_id.expect_local();
let impl_ct_span = tcx.def_span(impl_ct_def_id);
// The below is for the most part highly similar to the procedure
// for methods above. It is simpler in many respects, especially
// because we shouldn't really have to deal with lifetimes or
// predicates. In fact some of this should probably be put into
// shared functions because of DRY violations...
let trait_to_impl_args = impl_trait_ref.args;
let impl_args = GenericArgs::identity_for_item(tcx, impl_ct.def_id);
let trait_to_impl_args =
impl_args.rebase_onto(tcx, impl_ct.container_id(tcx), impl_trait_ref.args);
// Create a parameter environment that represents the implementation's
// method.
// Compute placeholder form of impl and trait const tys.
let impl_ty = tcx.type_of(impl_const_item_def.to_def_id()).instantiate_identity();
let trait_ty = tcx.type_of(trait_const_item_def).instantiate(tcx, trait_to_impl_args);
let mut cause = ObligationCause::new(
impl_c_span,
impl_const_item_def,
ObligationCauseCode::CompareImplItemObligation {
impl_item_def_id: impl_const_item_def,
trait_item_def_id: trait_const_item_def,
kind: impl_const_item.kind,
},
let impl_ty = tcx.type_of(impl_ct_def_id).instantiate_identity();
let trait_ty = tcx.type_of(trait_ct.def_id).instantiate(tcx, trait_to_impl_args);
let code = ObligationCauseCode::CompareImplItemObligation {
impl_item_def_id: impl_ct_def_id,
trait_item_def_id: trait_ct.def_id,
kind: impl_ct.kind,
};
let mut cause = ObligationCause::new(impl_ct_span, impl_ct_def_id, code.clone());
let impl_ct_predicates = tcx.predicates_of(impl_ct.def_id);
let trait_ct_predicates = tcx.predicates_of(trait_ct.def_id);
check_region_bounds_on_impl_item(tcx, impl_ct, trait_ct, false)?;
// The predicates declared by the impl definition, the trait and the
// associated const in the trait are assumed.
let impl_predicates = tcx.predicates_of(impl_ct_predicates.parent.unwrap());
let mut hybrid_preds = impl_predicates.instantiate_identity(tcx);
hybrid_preds.predicates.extend(
trait_ct_predicates
.instantiate_own(tcx, trait_to_impl_args)
.map(|(predicate, _)| predicate),
);
let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds.predicates), Reveal::UserFacing);
let param_env = traits::normalize_param_env_or_error(
tcx,
param_env,
ObligationCause::misc(impl_ct_span, impl_ct_def_id),
);
let infcx = tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(&infcx);
let impl_ct_own_bounds = impl_ct_predicates.instantiate_own(tcx, impl_args);
for (predicate, span) in impl_ct_own_bounds {
let cause = ObligationCause::misc(span, impl_ct_def_id);
let predicate = ocx.normalize(&cause, param_env, predicate);
let cause = ObligationCause::new(span, impl_ct_def_id, code.clone());
ocx.register_obligation(traits::Obligation::new(tcx, cause, param_env, predicate));
}
// There is no "body" here, so just pass dummy id.
let impl_ty = ocx.normalize(&cause, param_env, impl_ty);
@ -1821,7 +1879,7 @@ pub(super) fn compare_impl_const_raw(
);
// Locate the Span containing just the type of the offending impl
let (ty, _) = tcx.hir().expect_impl_item(impl_const_item_def).expect_const();
let (ty, _) = tcx.hir().expect_impl_item(impl_ct_def_id).expect_const();
cause.span = ty.span;
let mut diag = struct_span_err!(
@ -1829,12 +1887,12 @@ pub(super) fn compare_impl_const_raw(
cause.span,
E0326,
"implemented const `{}` has an incompatible type for trait",
trait_const_item.name
trait_ct.name
);
let trait_c_span = trait_const_item_def.as_local().map(|trait_c_def_id| {
let trait_c_span = trait_ct.def_id.as_local().map(|trait_ct_def_id| {
// Add a label to the Span containing just the type of the const
let (ty, _) = tcx.hir().expect_trait_item(trait_c_def_id).expect_const();
let (ty, _) = tcx.hir().expect_trait_item(trait_ct_def_id).expect_const();
ty.span
});
@ -1861,7 +1919,7 @@ pub(super) fn compare_impl_const_raw(
}
let outlives_env = OutlivesEnvironment::new(param_env);
ocx.resolve_regions_and_report_errors(impl_const_item_def, &outlives_env)
ocx.resolve_regions_and_report_errors(impl_ct_def_id, &outlives_env)
}
pub(super) fn compare_impl_ty<'tcx>(
@ -1903,7 +1961,7 @@ fn compare_type_predicate_entailment<'tcx>(
return Ok(());
}
// This `HirId` should be used for the `body_id` field on each
// This `DefId` should be used for the `body_id` field on each
// `ObligationCause` (and the `FnCtxt`). This is what
// `regionck_item` expects.
let impl_ty_def_id = impl_ty.def_id.expect_local();
@ -1922,12 +1980,8 @@ fn compare_type_predicate_entailment<'tcx>(
debug!("compare_type_predicate_entailment: bounds={:?}", hybrid_preds);
let impl_ty_span = tcx.def_span(impl_ty_def_id);
let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_def_id);
let param_env = ty::ParamEnv::new(
tcx.mk_clauses(&hybrid_preds.predicates),
Reveal::UserFacing,
hir::Constness::NotConst,
);
let normalize_cause = ObligationCause::misc(impl_ty_span, impl_ty_def_id);
let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds.predicates), Reveal::UserFacing);
let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
let infcx = tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(&infcx);
@ -1971,7 +2025,7 @@ fn compare_type_predicate_entailment<'tcx>(
///
/// trait X { type Y: Copy } impl X for T { type Y = S; }
///
/// We are able to normalize `<T as X>::U` to `S`, and so when we check the
/// We are able to normalize `<T as X>::Y` to `S`, and so when we check the
/// impl is well-formed we have to prove `S: Copy`.
///
/// For default associated types the normalization is not possible (the value
@ -2102,7 +2156,7 @@ pub(super) fn check_type_bounds<'tcx>(
.to_predicate(tcx),
),
};
ty::ParamEnv::new(tcx.mk_clauses(&predicates), Reveal::UserFacing, param_env.constness())
ty::ParamEnv::new(tcx.mk_clauses(&predicates), Reveal::UserFacing)
};
debug!(?normalize_param_env);

View file

@ -129,9 +129,8 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
// We don't need to normalize this param-env or anything, since we're only
// substituting it with free params, so no additional param-env normalization
// can occur on top of what has been done in the param_env query itself.
let param_env = ty::EarlyBinder::bind(tcx.param_env(adt_def_id))
.instantiate(tcx, adt_to_impl_args)
.with_constness(tcx.constness(drop_impl_def_id));
let param_env =
ty::EarlyBinder::bind(tcx.param_env(adt_def_id)).instantiate(tcx, adt_to_impl_args);
for (pred, span) in tcx.predicates_of(drop_impl_def_id).instantiate_identity(tcx) {
let normalize_cause = traits::ObligationCause::misc(span, adt_def_id);

View file

@ -134,7 +134,7 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: DefId) -> hir
/// Remember to add all intrinsics here, in `compiler/rustc_codegen_llvm/src/intrinsic.rs`,
/// and in `library/core/src/intrinsics.rs`.
pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
let param = |n| Ty::new_param(tcx, n, Symbol::intern(&format!("P{}", n)));
let param = |n| Ty::new_param(tcx, n, Symbol::intern(&format!("P{n}")));
let intrinsic_id = it.owner_id.to_def_id();
let intrinsic_name = tcx.item_name(intrinsic_id);
let name_str = intrinsic_name.as_str();
@ -494,7 +494,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
/// Type-check `extern "platform-intrinsic" { ... }` functions.
pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
let param = |n| {
let name = Symbol::intern(&format!("P{}", n));
let name = Symbol::intern(&format!("P{n}"));
Ty::new_param(tcx, n, name)
};
@ -521,6 +521,10 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
| sym::simd_saturating_sub => (1, vec![param(0), param(0)], param(0)),
sym::simd_arith_offset => (2, vec![param(0), param(1)], param(0)),
sym::simd_neg
| sym::simd_bswap
| sym::simd_bitreverse
| sym::simd_ctlz
| sym::simd_cttz
| sym::simd_fsqrt
| sym::simd_fsin
| sym::simd_fcos

View file

@ -211,7 +211,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
// register class is usable at all.
if let Some(feature) = feature {
if !target_features.contains(feature) {
let msg = format!("`{}` target feature is not enabled", feature);
let msg = format!("`{feature}` target feature is not enabled");
let mut err = self.tcx.sess.struct_span_err(expr.span, msg);
err.note(format!(
"this is required to use type `{}` with register class `{}`",

View file

@ -214,7 +214,7 @@ fn missing_items_err(
trait_item,
tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity(),
);
let code = format!("{}{}\n{}", padding, snippet, padding);
let code = format!("{padding}{snippet}\n{padding}");
if let Some(span) = tcx.hir().span_if_local(trait_item.def_id) {
missing_trait_item_label
.push(errors::MissingTraitItemLabel { span, item: trait_item.name });

View file

@ -75,12 +75,10 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
self.body_def_id,
ObligationCauseCode::WellFormed(loc),
);
// for a type to be WF, we do not need to check if const trait predicates satisfy.
let param_env = self.param_env.without_const();
self.ocx.register_obligation(traits::Obligation::new(
self.tcx(),
cause,
param_env,
self.param_env,
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg))),
));
}
@ -286,6 +284,17 @@ fn check_trait_item(tcx: TyCtxt<'_>, trait_item: &hir::TraitItem<'_>) {
};
check_object_unsafe_self_trait_by_name(tcx, trait_item);
check_associated_item(tcx, def_id, span, method_sig);
if matches!(trait_item.kind, hir::TraitItemKind::Fn(..)) {
for &assoc_ty_def_id in tcx.associated_types_for_impl_traits_in_associated_fn(def_id) {
check_associated_item(
tcx,
assoc_ty_def_id.expect_local(),
tcx.def_span(assoc_ty_def_id),
None,
);
}
}
}
/// Require that the user writes where clauses on GATs for the implicit
@ -472,8 +481,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
let bound =
if unsatisfied_bounds.len() > 1 { "these bounds are" } else { "this bound is" };
err.note(format!(
"{} currently required to ensure that impls have maximum flexibility",
bound
"{bound} currently required to ensure that impls have maximum flexibility"
));
err.note(
"we are soliciting feedback, see issue #87479 \
@ -505,7 +513,7 @@ fn augment_param_env<'tcx>(
);
// FIXME(compiler-errors): Perhaps there is a case where we need to normalize this
// i.e. traits::normalize_param_env_or_error
ty::ParamEnv::new(bounds, param_env.reveal(), param_env.constness())
ty::ParamEnv::new(bounds, param_env.reveal())
}
/// We use the following trait as an example throughout this function.
@ -989,7 +997,7 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b
let ty = tcx.erase_regions(ty);
if ty.has_infer() {
tcx.sess
.delay_span_bug(item.span, format!("inference variables in {:?}", ty));
.delay_span_bug(item.span, format!("inference variables in {ty:?}"));
// Just treat unresolved type expression as if it needs drop.
true
} else {
@ -1416,7 +1424,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
let wf_obligations = predicates.into_iter().flat_map(|(p, sp)| {
traits::wf::predicate_obligations(
infcx,
wfcx.param_env.without_const(),
wfcx.param_env,
wfcx.body_def_id,
p.as_predicate(),
sp,
@ -1469,13 +1477,6 @@ fn check_fn_or_method<'tcx>(
check_where_clauses(wfcx, span, def_id);
check_return_position_impl_trait_in_trait_bounds(
wfcx,
def_id,
sig.output(),
hir_decl.output.span(),
);
if sig.abi == Abi::RustCall {
let span = tcx.def_span(def_id);
let has_implicit_self = hir_decl.implicit_self != hir::ImplicitSelfKind::None;
@ -1510,87 +1511,6 @@ fn check_fn_or_method<'tcx>(
}
}
/// Basically `check_associated_type_bounds`, but separated for now and should be
/// deduplicated when RPITITs get lowered into real associated items.
#[tracing::instrument(level = "trace", skip(wfcx))]
fn check_return_position_impl_trait_in_trait_bounds<'tcx>(
wfcx: &WfCheckingCtxt<'_, 'tcx>,
fn_def_id: LocalDefId,
fn_output: Ty<'tcx>,
span: Span,
) {
let tcx = wfcx.tcx();
let Some(assoc_item) = tcx.opt_associated_item(fn_def_id.to_def_id()) else {
return;
};
if assoc_item.container != ty::AssocItemContainer::TraitContainer {
return;
}
fn_output.visit_with(&mut ImplTraitInTraitFinder {
wfcx,
fn_def_id,
depth: ty::INNERMOST,
seen: FxHashSet::default(),
});
}
// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): Even with the new lowering
// strategy, we can't just call `check_associated_item` on the new RPITITs,
// because tests like `tests/ui/async-await/in-trait/implied-bounds.rs` will fail.
// That's because we need to check that the bounds of the RPITIT hold using
// the special args that we create during opaque type lowering, otherwise we're
// getting a bunch of early bound and free regions mixed up... Haven't looked too
// deep into this, though.
struct ImplTraitInTraitFinder<'a, 'tcx> {
wfcx: &'a WfCheckingCtxt<'a, 'tcx>,
fn_def_id: LocalDefId,
depth: ty::DebruijnIndex,
seen: FxHashSet<DefId>,
}
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
type BreakTy = !;
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<!> {
let tcx = self.wfcx.tcx();
if let ty::Alias(ty::Opaque, unshifted_opaque_ty) = *ty.kind()
&& self.seen.insert(unshifted_opaque_ty.def_id)
&& let Some(opaque_def_id) = unshifted_opaque_ty.def_id.as_local()
&& let origin = tcx.opaque_type_origin(opaque_def_id)
&& let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = origin
&& source == self.fn_def_id
{
let opaque_ty = tcx.fold_regions(unshifted_opaque_ty, |re, _depth| {
match re.kind() {
ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReError(_) | ty::ReStatic => re,
r => bug!("unexpected region: {r:?}"),
}
});
for (bound, bound_span) in tcx
.explicit_item_bounds(opaque_ty.def_id)
.iter_instantiated_copied(tcx, opaque_ty.args)
{
let bound = self.wfcx.normalize(bound_span, None, bound);
self.wfcx.register_obligations(traits::wf::predicate_obligations(
self.wfcx.infcx,
self.wfcx.param_env,
self.wfcx.body_def_id,
bound.as_predicate(),
bound_span,
));
// Set the debruijn index back to innermost here, since we already eagerly
// shifted the args that we use to generate these bounds. This is unfortunately
// subtly different behavior than the `ImplTraitInTraitFinder` we use in `param_env`,
// but that function doesn't actually need to normalize the bound it's visiting
// (whereas we have to do so here)...
let old_depth = std::mem::replace(&mut self.depth, ty::INNERMOST);
bound.visit_with(self);
self.depth = old_depth;
}
}
ty.super_visit_with(self)
}
}
const HELP_FOR_SELF_TYPE: &str = "consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, \
`self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one \
of the previous types except `Self`)";
@ -1863,8 +1783,7 @@ fn report_bivariance(
if matches!(param.kind, hir::GenericParamKind::Type { .. }) && !has_explicit_bounds {
err.help(format!(
"if you intended `{0}` to be a const parameter, use `const {0}: usize` instead",
param_name
"if you intended `{param_name}` to be a const parameter, use `const {param_name}: usize` instead"
));
}
err.emit()

View file

@ -36,7 +36,7 @@ fn check_unused_traits(tcx: TyCtxt<'_>, (): ()) {
}
let (path, _) = item.expect_use();
let msg = if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(path.span) {
format!("unused import: `{}`", snippet)
format!("unused import: `{snippet}`")
} else {
"unused import".to_owned()
};

View file

@ -171,8 +171,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
create_err(&format!(
"the trait `DispatchFromDyn` may only be implemented \
for a coercion between structures with the same \
definition; expected `{}`, found `{}`",
source_path, target_path,
definition; expected `{source_path}`, found `{target_path}`",
))
.emit();

View file

@ -148,8 +148,7 @@ impl<'tcx> InherentCollect<'tcx> {
if let ty::Ref(_, subty, _) = ty.kind() {
err.note(format!(
"you could also try moving the reference to \
uses of `{}` (such as `self`) within the implementation",
subty
uses of `{subty}` (such as `self`) within the implementation"
));
}
err.emit();

View file

@ -77,8 +77,8 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
"duplicate definitions with name `{}`",
ident,
);
err.span_label(span, format!("duplicate definitions for `{}`", ident));
err.span_label(*former, format!("other definition for `{}`", ident));
err.span_label(span, format!("duplicate definitions for `{ident}`"));
err.span_label(*former, format!("other definition for `{ident}`"));
err.emit();
}
@ -114,11 +114,11 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
);
err.span_label(
self.tcx.def_span(item1.def_id),
format!("duplicate definitions for `{}`", name),
format!("duplicate definitions for `{name}`"),
);
err.span_label(
self.tcx.def_span(item2.def_id),
format!("other definition for `{}`", name),
format!("other definition for `{name}`"),
);
for cause in &overlap.intercrate_ambiguity_causes {

View file

@ -412,9 +412,8 @@ fn emit_orphan_check_error<'tcx>(
.span_label(
sp,
format!(
"type parameter `{}` must be covered by another type \
when it appears before the first local type (`{}`)",
param_ty, local_type
"type parameter `{param_ty}` must be covered by another type \
when it appears before the first local type (`{local_type}`)"
),
)
.note(
@ -441,9 +440,8 @@ fn emit_orphan_check_error<'tcx>(
.span_label(
sp,
format!(
"type parameter `{}` must be used as the type parameter for some \
"type parameter `{param_ty}` must be used as the type parameter for some \
local type",
param_ty,
),
)
.note(
@ -541,17 +539,16 @@ fn lint_auto_trait_impl<'tcx>(
let self_descr = tcx.def_descr(self_type_did);
match arg {
ty::util::NotUniqueParam::DuplicateParam(arg) => {
lint.note(format!("`{}` is mentioned multiple times", arg));
lint.note(format!("`{arg}` is mentioned multiple times"));
}
ty::util::NotUniqueParam::NotParam(arg) => {
lint.note(format!("`{}` is not a generic parameter", arg));
lint.note(format!("`{arg}` is not a generic parameter"));
}
}
lint.span_note(
item_span,
format!(
"try using the same sequence of generic parameters as the {} definition",
self_descr,
"try using the same sequence of generic parameters as the {self_descr} definition",
),
)
},

View file

@ -195,9 +195,9 @@ pub(crate) fn placeholder_type_error_diag<'tcx>(
sugg.push((arg.span, (*type_name).to_string()));
} else if let Some(span) = generics.span_for_param_suggestion() {
// Account for bounds, we want `fn foo<T: E, K>(_: K)` not `fn foo<T, K: E>(_: K)`.
sugg.push((span, format!(", {}", type_name)));
sugg.push((span, format!(", {type_name}")));
} else {
sugg.push((generics.span, format!("<{}>", type_name)));
sugg.push((generics.span, format!("<{type_name}>")));
}
}
@ -329,7 +329,7 @@ fn bad_placeholder<'tcx>(
mut spans: Vec<Span>,
kind: &'static str,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
let kind = if kind.ends_with('s') { format!("{}es", kind) } else { format!("{}s", kind) };
let kind = if kind.ends_with('s') { format!("{kind}es") } else { format!("{kind}s") };
spans.sort();
tcx.sess.create_err(errors::PlaceholderNotAllowedItemSignatures { spans, kind })
@ -425,10 +425,8 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
| hir::ItemKind::Union(_, generics) => {
let lt_name = get_new_lifetime_name(self.tcx, poly_trait_ref, generics);
let (lt_sp, sugg) = match generics.params {
[] => (generics.span, format!("<{}>", lt_name)),
[bound, ..] => {
(bound.span.shrink_to_lo(), format!("{}, ", lt_name))
}
[] => (generics.span, format!("<{lt_name}>")),
[bound, ..] => (bound.span.shrink_to_lo(), format!("{lt_name}, ")),
};
mpart_sugg = Some(errors::AssociatedTypeTraitUninferredGenericParamsMultipartSuggestion {
fspan: lt_sp,
@ -1027,7 +1025,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
} else {
tcx.sess.span_err(
meta.span(),
format!("unknown meta item passed to `rustc_deny_explicit_impl` {:?}", meta),
format!("unknown meta item passed to `rustc_deny_explicit_impl` {meta:?}"),
);
}
}
@ -1505,7 +1503,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
.sess
.source_map()
.span_to_snippet(ast_ty.span)
.map_or_else(|_| String::new(), |s| format!(" `{}`", s));
.map_or_else(|_| String::new(), |s| format!(" `{s}`"));
tcx.sess.emit_err(errors::SIMDFFIHighlyExperimental { span: ast_ty.span, snip });
}
};

View file

@ -209,6 +209,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
| ItemKind::Struct(..)
| ItemKind::OpaqueTy(..)
| ItemKind::Union(..) => (None, Defaults::Allowed),
ItemKind::Const(..) => (None, Defaults::Deny),
_ => (None, Defaults::FutureCompatDisallowed),
}
}

View file

@ -156,6 +156,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
}
ItemKind::Fn(.., generics, _)
| ItemKind::TyAlias(_, generics)
| ItemKind::Const(_, generics, _)
| ItemKind::Enum(_, generics)
| ItemKind::Struct(_, generics)
| ItemKind::Union(_, generics) => generics,
@ -762,6 +763,7 @@ pub(super) fn type_param_predicates(
ItemKind::Fn(.., generics, _)
| ItemKind::Impl(&hir::Impl { generics, .. })
| ItemKind::TyAlias(_, generics)
| ItemKind::Const(_, generics, _)
| ItemKind::OpaqueTy(&OpaqueTy {
generics,
origin: hir::OpaqueTyOrigin::TyAlias { .. },

View file

@ -518,7 +518,6 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
| hir::ItemKind::Mod(..)
| hir::ItemKind::ForeignMod { .. }
| hir::ItemKind::Static(..)
| hir::ItemKind::Const(..)
| hir::ItemKind::GlobalAsm(..) => {
// These sorts of items have no lifetime parameters at all.
intravisit::walk_item(self, item);
@ -583,6 +582,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
})
}
hir::ItemKind::TyAlias(_, generics)
| hir::ItemKind::Const(_, generics, _)
| hir::ItemKind::Enum(_, generics)
| hir::ItemKind::Struct(_, generics)
| hir::ItemKind::Union(_, generics)
@ -590,21 +590,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
| hir::ItemKind::TraitAlias(generics, ..)
| hir::ItemKind::Impl(&hir::Impl { generics, .. }) => {
// These kinds of items have only early-bound lifetime parameters.
let bound_vars = generics.params.iter().map(ResolvedArg::early).collect();
self.record_late_bound_vars(item.hir_id(), vec![]);
let scope = Scope::Binder {
hir_id: item.hir_id(),
bound_vars,
scope_type: BinderScopeType::Normal,
s: self.scope,
where_bound_origin: None,
};
self.with(scope, |this| {
let scope = Scope::TraitRefBoundary { s: this.scope };
this.with(scope, |this| {
intravisit::walk_item(this, item);
});
});
self.visit_early(item.hir_id(), generics, |this| intravisit::walk_item(this, item));
}
}
}
@ -777,39 +763,24 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
use self::hir::TraitItemKind::*;
match trait_item.kind {
Fn(_, _) => {
self.visit_early_late(trait_item.hir_id(), &trait_item.generics, |this| {
self.visit_early_late(trait_item.hir_id(), trait_item.generics, |this| {
intravisit::walk_trait_item(this, trait_item)
});
}
Type(bounds, ty) => {
let generics = &trait_item.generics;
let bound_vars = generics.params.iter().map(ResolvedArg::early).collect();
self.record_late_bound_vars(trait_item.hir_id(), vec![]);
let scope = Scope::Binder {
hir_id: trait_item.hir_id(),
bound_vars,
s: self.scope,
scope_type: BinderScopeType::Normal,
where_bound_origin: None,
};
self.with(scope, |this| {
let scope = Scope::TraitRefBoundary { s: this.scope };
this.with(scope, |this| {
this.visit_generics(generics);
for bound in bounds {
this.visit_param_bound(bound);
}
if let Some(ty) = ty {
this.visit_ty(ty);
}
})
});
}
Const(_, _) => {
// Only methods and types support generics.
assert!(trait_item.generics.params.is_empty());
intravisit::walk_trait_item(self, trait_item);
self.visit_early(trait_item.hir_id(), trait_item.generics, |this| {
this.visit_generics(&trait_item.generics);
for bound in bounds {
this.visit_param_bound(bound);
}
if let Some(ty) = ty {
this.visit_ty(ty);
}
})
}
Const(_, _) => self.visit_early(trait_item.hir_id(), trait_item.generics, |this| {
intravisit::walk_trait_item(this, trait_item)
}),
}
}
@ -817,34 +788,16 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
use self::hir::ImplItemKind::*;
match impl_item.kind {
Fn(..) => self.visit_early_late(impl_item.hir_id(), &impl_item.generics, |this| {
Fn(..) => self.visit_early_late(impl_item.hir_id(), impl_item.generics, |this| {
intravisit::walk_impl_item(this, impl_item)
}),
Type(ty) => self.visit_early(impl_item.hir_id(), impl_item.generics, |this| {
this.visit_generics(impl_item.generics);
this.visit_ty(ty);
}),
Const(_, _) => self.visit_early(impl_item.hir_id(), impl_item.generics, |this| {
intravisit::walk_impl_item(this, impl_item)
}),
Type(ty) => {
let generics = &impl_item.generics;
let bound_vars: FxIndexMap<LocalDefId, ResolvedArg> =
generics.params.iter().map(ResolvedArg::early).collect();
self.record_late_bound_vars(impl_item.hir_id(), vec![]);
let scope = Scope::Binder {
hir_id: impl_item.hir_id(),
bound_vars,
s: self.scope,
scope_type: BinderScopeType::Normal,
where_bound_origin: None,
};
self.with(scope, |this| {
let scope = Scope::TraitRefBoundary { s: this.scope };
this.with(scope, |this| {
this.visit_generics(generics);
this.visit_ty(ty);
})
});
}
Const(_, _) => {
// Only methods and types support generics.
assert!(impl_item.generics.params.is_empty());
intravisit::walk_impl_item(self, impl_item);
}
}
}
@ -1180,6 +1133,25 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
self.with(scope, walk);
}
fn visit_early<F>(&mut self, hir_id: hir::HirId, generics: &'tcx hir::Generics<'tcx>, walk: F)
where
F: for<'b, 'c> FnOnce(&'b mut BoundVarContext<'c, 'tcx>),
{
let bound_vars = generics.params.iter().map(ResolvedArg::early).collect();
self.record_late_bound_vars(hir_id, vec![]);
let scope = Scope::Binder {
hir_id,
bound_vars,
s: self.scope,
scope_type: BinderScopeType::Normal,
where_bound_origin: None,
};
self.with(scope, |this| {
let scope = Scope::TraitRefBoundary { s: this.scope };
this.with(scope, walk)
});
}
#[instrument(level = "debug", skip(self))]
fn resolve_lifetime_ref(
&mut self,
@ -2040,8 +2012,7 @@ fn is_late_bound_map(
tcx.sess.delay_span_bug(
*span,
format!(
"Incorrect generic arg count for alias {:?}",
alias_def
"Incorrect generic arg count for alias {alias_def:?}"
),
);
None

View file

@ -156,7 +156,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
let Some(type_dependent_def) = tables.type_dependent_def_id(parent_node_id) else {
return Ty::new_error_with_message(tcx,
tcx.def_span(def_id),
format!("unable to find type-dependent def for {:?}", parent_node_id),
format!("unable to find type-dependent def for {parent_node_id:?}"),
);
};
let idx = segment
@ -197,14 +197,14 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
} else {
return Ty::new_error_with_message(tcx,
tcx.def_span(def_id),
format!("unable to find const parent for {} in pat {:?}", hir_id, pat),
format!("unable to find const parent for {hir_id} in pat {pat:?}"),
);
}
}
_ => {
return Ty::new_error_with_message(tcx,
tcx.def_span(def_id),
format!("unexpected const parent path {:?}", parent_node),
format!("unexpected const parent path {parent_node:?}"),
);
}
};
@ -404,7 +404,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
icx.to_ty(ty)
}
}
ItemKind::Const(ty, body_id) => {
ItemKind::Const(ty, _, body_id) => {
if is_suggestable_infer_ty(ty) {
infer_placeholder_type(
tcx, def_id, body_id, ty.span, item.ident, "constant",
@ -544,7 +544,7 @@ fn infer_placeholder_type<'a>(
if let Some(ty) = ty.make_suggestable(tcx, false) {
err.span_suggestion(
span,
format!("provide a type for the {item}", item = kind),
format!("provide a type for the {kind}"),
format!("{colon} {ty}"),
Applicability::MachineApplicable,
);

View file

@ -216,7 +216,7 @@ impl<'a> IntoDiagnostic<'a> for MissingTypeParams {
"parameters",
self.missing_type_params
.iter()
.map(|n| format!("`{}`", n))
.map(|n| format!("`{n}`"))
.collect::<Vec<_>>()
.join(", "),
);

View file

@ -130,7 +130,7 @@ fn diagnostic_hir_wf_check<'tcx>(
hir::Node::Item(item) => match item.kind {
hir::ItemKind::TyAlias(ty, _)
| hir::ItemKind::Static(ty, _, _)
| hir::ItemKind::Const(ty, _) => vec![ty],
| hir::ItemKind::Const(ty, _, _) => vec![ty],
hir::ItemKind::Impl(impl_) => match &impl_.of_trait {
Some(t) => t
.path

View file

@ -77,8 +77,7 @@ fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId)
tcx.sess.delay_span_bug(
tcx.def_span(impl_def_id),
format!(
"potentially unconstrained type parameters weren't evaluated: {:?}",
impl_self_ty,
"potentially unconstrained type parameters weren't evaluated: {impl_self_ty:?}",
),
);
return;
@ -180,7 +179,7 @@ fn report_unused_parameter(tcx: TyCtxt<'_>, span: Span, kind: &str, name: Symbol
kind,
name
);
err.span_label(span, format!("unconstrained {} parameter", kind));
err.span_label(span, format!("unconstrained {kind} parameter"));
if kind == "const" {
err.note(
"expressions using a const parameter must map each value to a distinct output value",

View file

@ -294,7 +294,7 @@ fn check_duplicate_params<'tcx>(
if let (_, [duplicate, ..]) = base_params.partition_dedup() {
let param = impl1_args[duplicate.0 as usize];
tcx.sess
.struct_span_err(span, format!("specializing impl repeats parameter `{}`", param))
.struct_span_err(span, format!("specializing impl repeats parameter `{param}`"))
.emit();
}
}
@ -523,7 +523,7 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
}
_ => {
tcx.sess
.struct_span_err(span, format!("cannot specialize on predicate `{}`", predicate))
.struct_span_err(span, format!("cannot specialize on predicate `{predicate}`"))
.emit();
}
}

View file

@ -474,7 +474,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
verb
)
} else {
format!("missing generics for {} `{}`", def_kind, def_path)
format!("missing generics for {def_kind} `{def_path}`")
}
}
@ -599,7 +599,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
let span = self.path_segment.ident.span;
// insert a suggestion of the form "Y<'a, 'b>"
let sugg = format!("<{}>", suggested_args);
let sugg = format!("<{suggested_args}>");
debug!("sugg: {:?}", sugg);
err.span_suggestion_verbose(
@ -624,7 +624,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
let sugg_suffix =
if is_first && (has_non_lt_args || has_bindings) { ", " } else { "" };
let sugg = format!("{}{}{}", sugg_prefix, suggested_args, sugg_suffix);
let sugg = format!("{sugg_prefix}{suggested_args}{sugg_suffix}");
debug!("sugg: {:?}", sugg);
err.span_suggestion_verbose(sugg_span, msg, sugg, Applicability::HasPlaceholders);
@ -649,7 +649,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
let span = self.path_segment.ident.span;
// insert a suggestion of the form "Y<T, U>"
let sugg = format!("<{}>", suggested_args);
let sugg = format!("<{suggested_args}>");
debug!("sugg: {:?}", sugg);
err.span_suggestion_verbose(
@ -682,7 +682,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
let sugg_suffix =
if is_first && !self.gen_args.bindings.is_empty() { ", " } else { "" };
let sugg = format!("{}{}{}", sugg_prefix, suggested_args, sugg_suffix);
let sugg = format!("{sugg_prefix}{suggested_args}{sugg_suffix}");
debug!("sugg: {:?}", sugg);
err.span_suggestion_verbose(sugg_span, msg, sugg, Applicability::HasPlaceholders);
@ -1024,7 +1024,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
.collect::<Vec<_>>()
.join(", ");
format!(": {}", params)
format!(": {params}")
};
format!(

View file

@ -32,8 +32,8 @@ pub enum VarianceTerm<'a> {
impl<'a> fmt::Debug for VarianceTerm<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
ConstantTerm(c1) => write!(f, "{:?}", c1),
TransformTerm(v1, v2) => write!(f, "({:?} \u{00D7} {:?})", v1, v2),
ConstantTerm(c1) => write!(f, "{c1:?}"),
TransformTerm(v1, v2) => write!(f, "({v1:?} \u{00D7} {v2:?})"),
InferredTerm(id) => write!(f, "[{}]", {
let InferredIndex(i) = id;
i

View file

@ -420,12 +420,13 @@ impl<'a> State<'a> {
fn print_associated_const(
&mut self,
ident: Ident,
generics: &hir::Generics<'_>,
ty: &hir::Ty<'_>,
default: Option<hir::BodyId>,
) {
self.head("");
self.word_space("const");
self.print_ident(ident);
self.print_generic_params(generics.params);
self.word_space(":");
self.print_type(ty);
if let Some(expr) = default {
@ -433,6 +434,7 @@ impl<'a> State<'a> {
self.word_space("=");
self.ann.nested(self, Nested::Body(expr));
}
self.print_where_clause(generics);
self.word(";")
}
@ -532,9 +534,10 @@ impl<'a> State<'a> {
self.word(";");
self.end(); // end the outer cbox
}
hir::ItemKind::Const(ty, expr) => {
hir::ItemKind::Const(ty, generics, expr) => {
self.head("const");
self.print_ident(item.ident);
self.print_generic_params(generics.params);
self.word_space(":");
self.print_type(ty);
self.space();
@ -542,6 +545,7 @@ impl<'a> State<'a> {
self.word_space("=");
self.ann.nested(self, Nested::Body(expr));
self.print_where_clause(generics);
self.word(";");
self.end(); // end the outer cbox
}
@ -836,7 +840,7 @@ impl<'a> State<'a> {
self.print_outer_attributes(self.attrs(ti.hir_id()));
match ti.kind {
hir::TraitItemKind::Const(ty, default) => {
self.print_associated_const(ti.ident, ty, default);
self.print_associated_const(ti.ident, ti.generics, ty, default);
}
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(arg_names)) => {
self.print_method_sig(ti.ident, sig, ti.generics, arg_names, None);
@ -865,7 +869,7 @@ impl<'a> State<'a> {
match ii.kind {
hir::ImplItemKind::Const(ty, expr) => {
self.print_associated_const(ii.ident, ty, Some(expr));
self.print_associated_const(ii.ident, ii.generics, ty, Some(expr));
}
hir::ImplItemKind::Fn(ref sig, body) => {
self.head("");

View file

@ -77,6 +77,10 @@ hir_typeck_note_edition_guide = for more on editions, read https://doc.rust-lang
hir_typeck_op_trait_generic_params = `{$method_name}` must not have any generic parameters
hir_typeck_option_result_asref = use `{$def_path}::as_ref` to convert `{$expected_ty}` to `{$expr_ty}`
hir_typeck_option_result_cloned = use `{$def_path}::cloned` to clone the value inside the `{$def_path}`
hir_typeck_option_result_copied = use `{$def_path}::copied` to copy the value inside the `{$def_path}`
hir_typeck_return_stmt_outside_of_fn_body =
{$statement_kind} statement outside of function body
.encl_body_label = the {$statement_kind} is part of this body...

View file

@ -402,7 +402,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.sess
.struct_span_err(
callee_expr.span,
format!("evaluate({:?}) = {:?}", predicate, result),
format!("evaluate({predicate:?}) = {result:?}"),
)
.span_label(predicate_span, "predicate")
.emit();
@ -531,8 +531,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return;
}
let up_to_rcvr_span = segment.ident.span.until(callee_expr.span);
let rest_span = callee_expr.span.shrink_to_hi().to(call_expr.span.shrink_to_hi());
let Some(callee_expr_span) = callee_expr.span.find_ancestor_inside(call_expr.span)
else {
return;
};
let up_to_rcvr_span = segment.ident.span.until(callee_expr_span);
let rest_span = callee_expr_span.shrink_to_hi().to(call_expr.span.shrink_to_hi());
let rest_snippet = if let Some(first) = rest.first() {
self.tcx
.sess

View file

@ -144,7 +144,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let reported = self
.tcx
.sess
.delay_span_bug(span, format!("`{:?}` should be sized but is not?", t));
.delay_span_bug(span, format!("`{t:?}` should be sized but is not?"));
return Err(reported);
}
})
@ -644,12 +644,12 @@ impl<'a, 'tcx> CastCheck<'tcx> {
err.span_suggestion(
self.cast_span,
"try casting to a reference instead",
format!("&{}{}", mtstr, s),
format!("&{mtstr}{s}"),
Applicability::MachineApplicable,
);
}
Err(_) => {
let msg = format!("did you mean `&{}{}`?", mtstr, tstr);
let msg = format!("did you mean `&{mtstr}{tstr}`?");
err.span_help(self.cast_span, msg);
}
}

View file

@ -81,7 +81,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
debug!(?bound_sig, ?liberated_sig);
let mut fcx = FnCtxt::new(self, self.param_env.without_const(), closure.def_id);
let mut fcx = FnCtxt::new(self, self.param_env, closure.def_id);
let generator_types = check_fn(
&mut fcx,
liberated_sig,

View file

@ -1797,8 +1797,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
err.span_note(
sp,
format!(
"return type inferred to be `{}` here",
expected
"return type inferred to be `{expected}` here"
),
);
}

View file

@ -252,6 +252,45 @@ impl HelpUseLatestEdition {
}
}
#[derive(Subdiagnostic)]
pub enum OptionResultRefMismatch<'tcx> {
#[suggestion(
hir_typeck_option_result_copied,
code = ".copied()",
style = "verbose",
applicability = "machine-applicable"
)]
Copied {
#[primary_span]
span: Span,
def_path: String,
},
#[suggestion(
hir_typeck_option_result_cloned,
code = ".cloned()",
style = "verbose",
applicability = "machine-applicable"
)]
Cloned {
#[primary_span]
span: Span,
def_path: String,
},
#[suggestion(
hir_typeck_option_result_asref,
code = ".as_ref()",
style = "verbose",
applicability = "machine-applicable"
)]
AsRef {
#[primary_span]
span: Span,
def_path: String,
expected_ty: Ty<'tcx>,
expr_ty: Ty<'tcx>,
},
}
#[derive(Diagnostic)]
#[diag(hir_typeck_const_select_must_be_const)]
#[help]

View file

@ -1334,7 +1334,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
t_cast,
t.span,
expr.span,
self.param_env.constness(),
hir::Constness::NotConst,
) {
Ok(cast_check) => {
debug!(
@ -1394,7 +1394,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let Some((
_,
hir::Node::Local(hir::Local { ty: Some(ty), .. })
| hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(ty, _), .. }),
| hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(ty, _, _), .. }),
)) = parent_node
else {
return;
@ -1428,7 +1428,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Create a new function context.
let def_id = block.def_id;
let fcx = FnCtxt::new(self, self.param_env.with_const(), def_id);
let fcx = FnCtxt::new(self, self.param_env, def_id);
crate::GatherLocalsVisitor::new(&fcx).visit_body(body);
let ty = fcx.check_expr_with_expectation(&body.value, expected);
@ -1890,7 +1890,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut truncated_fields_error = String::new();
let remaining_fields_names = match &displayable_field_names[..] {
[field1] => format!("`{}`", field1),
[field1] => format!("`{field1}`"),
[field1, field2] => format!("`{field1}` and `{field2}`"),
[field1, field2, field3] => format!("`{field1}`, `{field2}` and `{field3}`"),
_ => {
@ -2117,16 +2117,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}
_ => {
err.span_label(variant_ident_span, format!("`{adt}` defined here", adt = ty));
err.span_label(variant_ident_span, format!("`{ty}` defined here"));
err.span_label(field.ident.span, "field does not exist");
err.span_suggestion_verbose(
expr_span,
format!(
"`{adt}` is a tuple {kind_name}, use the appropriate syntax",
adt = ty,
kind_name = kind_name,
),
format!("{adt}(/* fields */)", adt = ty),
format!("`{ty}` is a tuple {kind_name}, use the appropriate syntax",),
format!("{ty}(/* fields */)"),
Applicability::HasPlaceholders,
);
}
@ -2243,7 +2239,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// dynamic limit, to never omit just one field
let limit = if names.len() == 6 { 6 } else { 5 };
let mut display =
names.iter().take(limit).map(|n| format!("`{}`", n)).collect::<Vec<_>>().join(", ");
names.iter().take(limit).map(|n| format!("`{n}`")).collect::<Vec<_>>().join(", ");
if names.len() > limit {
display = format!("{} ... and {} others", display, names.len() - limit);
}

View file

@ -61,7 +61,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
debug!("warn_if_unreachable: id={:?} span={:?} kind={}", id, span, kind);
let msg = format!("unreachable {}", kind);
let msg = format!("unreachable {kind}");
self.tcx().struct_span_lint_hir(
lint::builtin::UNREACHABLE_CODE,
id,
@ -134,7 +134,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
pub fn tag(&self) -> String {
format!("{:p}", self)
format!("{self:p}")
}
pub fn local_ty(&self, span: Span, nid: hir::HirId) -> Ty<'tcx> {
@ -1412,9 +1412,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.tcx.sess.delay_span_bug(
span,
format!(
"instantiate_value_path: (UFCS) {:?} was a subtype of {:?} but now is not?",
self_ty,
impl_ty,
"instantiate_value_path: (UFCS) {self_ty:?} was a subtype of {impl_ty:?} but now is not?",
),
);
}

View file

@ -45,12 +45,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
debug!("FnCtxt::check_casts: {} deferred checks", deferred_cast_checks.len());
for cast in deferred_cast_checks.drain(..) {
let prev_env = self.param_env;
self.param_env = self.param_env.with_constness(cast.constness);
cast.check(self);
self.param_env = prev_env;
}
*self.deferred_cast_checks.borrow_mut() = deferred_cast_checks;
@ -689,7 +684,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
err.span_label(
full_call_span,
format!("arguments to this {} are incorrect", call_name),
format!("arguments to this {call_name} are incorrect"),
);
} else {
err = tcx.sess.struct_span_err_with_code(
@ -796,10 +791,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
None,
None,
);
err.span_label(
full_call_span,
format!("arguments to this {} are incorrect", call_name),
);
err.span_label(full_call_span, format!("arguments to this {call_name} are incorrect"));
if let hir::ExprKind::MethodCall(_, rcvr, _, _) = call_expr.kind
&& provided_idx.as_usize() == expected_idx.as_usize()
@ -874,7 +866,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if ty.is_unit() {
"()".to_string()
} else if ty.is_suggestable(tcx, false) {
format!("/* {} */", ty)
format!("/* {ty} */")
} else if let Some(fn_def_id) = fn_def_id
&& self.tcx.def_kind(fn_def_id).is_fn_like()
&& let self_implicit =
@ -931,12 +923,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let (provided_ty, provided_span) = provided_arg_tys[arg_idx];
let provided_ty_name = if !has_error_or_infer([provided_ty]) {
// FIXME: not suggestable, use something else
format!(" of type `{}`", provided_ty)
format!(" of type `{provided_ty}`")
} else {
"".to_string()
};
labels
.push((provided_span, format!("unexpected argument{}", provided_ty_name)));
labels.push((provided_span, format!("unexpected argument{provided_ty_name}")));
let mut span = provided_span;
if span.can_be_used_for_suggestions() {
if arg_idx.index() > 0
@ -1009,11 +1000,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
args_span
};
let rendered = if !has_error_or_infer([input_ty]) {
format!(" of type `{}`", input_ty)
format!(" of type `{input_ty}`")
} else {
"".to_string()
};
labels.push((span, format!("an argument{} is missing", rendered)));
labels.push((span, format!("an argument{rendered} is missing")));
suggestion_text = match suggestion_text {
SuggestionText::None => SuggestionText::Provide(false),
SuggestionText::Provide(_) => SuggestionText::Provide(true),
@ -1034,13 +1025,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let rendered =
if !has_error_or_infer([first_expected_ty, second_expected_ty]) {
format!(
" of type `{}` and `{}`",
first_expected_ty, second_expected_ty
" of type `{first_expected_ty}` and `{second_expected_ty}`"
)
} else {
"".to_string()
};
labels.push((span, format!("two arguments{} are missing", rendered)));
labels.push((span, format!("two arguments{rendered} are missing")));
suggestion_text = match suggestion_text {
SuggestionText::None | SuggestionText::Provide(_) => {
SuggestionText::Provide(true)
@ -1066,13 +1056,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
third_expected_ty,
]) {
format!(
" of type `{}`, `{}`, and `{}`",
first_expected_ty, second_expected_ty, third_expected_ty
" of type `{first_expected_ty}`, `{second_expected_ty}`, and `{third_expected_ty}`"
)
} else {
"".to_string()
};
labels.push((span, format!("three arguments{} are missing", rendered)));
labels.push((span, format!("three arguments{rendered} are missing")));
suggestion_text = match suggestion_text {
SuggestionText::None | SuggestionText::Provide(_) => {
SuggestionText::Provide(true)
@ -1113,25 +1102,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let (first_provided_ty, first_span) = provided_arg_tys[first_provided_idx];
let (_, first_expected_ty) = formal_and_expected_inputs[first_expected_idx];
let first_provided_ty_name = if !has_error_or_infer([first_provided_ty]) {
format!(", found `{}`", first_provided_ty)
format!(", found `{first_provided_ty}`")
} else {
String::new()
};
labels.push((
first_span,
format!("expected `{}`{}", first_expected_ty, first_provided_ty_name),
format!("expected `{first_expected_ty}`{first_provided_ty_name}"),
));
let (second_provided_ty, second_span) = provided_arg_tys[second_provided_idx];
let (_, second_expected_ty) = formal_and_expected_inputs[second_expected_idx];
let second_provided_ty_name = if !has_error_or_infer([second_provided_ty]) {
format!(", found `{}`", second_provided_ty)
format!(", found `{second_provided_ty}`")
} else {
String::new()
};
labels.push((
second_span,
format!("expected `{}`{}", second_expected_ty, second_provided_ty_name),
format!("expected `{second_expected_ty}`{second_provided_ty_name}"),
));
suggestion_text = match suggestion_text {
@ -1144,13 +1133,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let (_, expected_ty) = formal_and_expected_inputs[dst_arg];
let (provided_ty, provided_span) = provided_arg_tys[dest_input];
let provided_ty_name = if !has_error_or_infer([provided_ty]) {
format!(", found `{}`", provided_ty)
format!(", found `{provided_ty}`")
} else {
String::new()
};
labels.push((
provided_span,
format!("expected `{}`{}", expected_ty, provided_ty_name),
format!("expected `{expected_ty}`{provided_ty_name}"),
));
}
@ -2031,7 +2020,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else {
("closure", self.tcx.def_span(def_id))
};
err.span_note(span, format!("{} defined here", kind));
err.span_note(span, format!("{kind} defined here"));
} else {
err.span_note(
self.tcx.def_span(def_id),

View file

@ -1,8 +1,6 @@
use super::FnCtxt;
use crate::errors::{
AddReturnTypeSuggestion, ExpectedReturnTypeLabel, SuggestBoxing, SuggestConvertViaMethod,
};
use crate::errors;
use crate::fluent_generated as fluent;
use crate::method::probe::{IsSuggestion, Mode, ProbeScope};
use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX};
@ -397,7 +395,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let struct_pat_shorthand_field =
self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr);
if let Some(name) = struct_pat_shorthand_field {
sugg.insert(0, (expr.span.shrink_to_lo(), format!("{}: ", name)));
sugg.insert(0, (expr.span.shrink_to_lo(), format!("{name}: ")));
}
Some(sugg)
})
@ -434,7 +432,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// FIXME: This could/should be extended to suggest `as_mut` and `as_deref_mut`,
// but those checks need to be a bit more delicate and the benefit is diminishing.
if self.can_eq(self.param_env, found_ty_inner, peeled) && error_tys_equate_as_ref {
err.subdiagnostic(SuggestConvertViaMethod {
err.subdiagnostic(errors::SuggestConvertViaMethod {
span: expr.span.shrink_to_hi(),
sugg: ".as_ref()",
expected,
@ -447,7 +445,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&& self.can_eq(self.param_env, deref_ty, peeled)
&& error_tys_equate_as_ref
{
err.subdiagnostic(SuggestConvertViaMethod {
err.subdiagnostic(errors::SuggestConvertViaMethod {
span: expr.span.shrink_to_hi(),
sugg: ".as_deref()",
expected,
@ -521,7 +519,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if self.can_coerce(Ty::new_box(self.tcx, found), expected) {
let suggest_boxing = match found.kind() {
ty::Tuple(tuple) if tuple.is_empty() => {
SuggestBoxing::Unit { start: span.shrink_to_lo(), end: span }
errors::SuggestBoxing::Unit { start: span.shrink_to_lo(), end: span }
}
ty::Generator(def_id, ..)
if matches!(
@ -529,9 +527,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Some(GeneratorKind::Async(AsyncGeneratorKind::Closure))
) =>
{
SuggestBoxing::AsyncBody
errors::SuggestBoxing::AsyncBody
}
_ => SuggestBoxing::Other { start: span.shrink_to_lo(), end: span.shrink_to_hi() },
_ => errors::SuggestBoxing::Other {
start: span.shrink_to_lo(),
end: span.shrink_to_hi(),
},
};
err.subdiagnostic(suggest_boxing);
@ -558,7 +559,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.take(4)
.map(|(var_hir_id, upvar)| {
let var_name = self.tcx.hir().name(*var_hir_id).to_string();
let msg = format!("`{}` captured here", var_name);
let msg = format!("`{var_name}` captured here");
(upvar.span, msg)
})
.collect::<Vec<_>>();
@ -756,23 +757,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
match &fn_decl.output {
&hir::FnRetTy::DefaultReturn(span) if expected.is_unit() && !can_suggest => {
// `fn main()` must return `()`, do not suggest changing return type
err.subdiagnostic(ExpectedReturnTypeLabel::Unit { span });
err.subdiagnostic(errors::ExpectedReturnTypeLabel::Unit { span });
return true;
}
&hir::FnRetTy::DefaultReturn(span) if expected.is_unit() => {
if let Some(found) = found.make_suggestable(self.tcx, false) {
err.subdiagnostic(AddReturnTypeSuggestion::Add { span, found: found.to_string() });
err.subdiagnostic(errors::AddReturnTypeSuggestion::Add { span, found: found.to_string() });
return true;
} else if let ty::Closure(_, args) = found.kind()
// FIXME(compiler-errors): Get better at printing binders...
&& let closure = args.as_closure()
&& closure.sig().is_suggestable(self.tcx, false)
{
err.subdiagnostic(AddReturnTypeSuggestion::Add { span, found: closure.print_as_impl_trait().to_string() });
err.subdiagnostic(errors::AddReturnTypeSuggestion::Add { span, found: closure.print_as_impl_trait().to_string() });
return true;
} else {
// FIXME: if `found` could be `impl Iterator` we should suggest that.
err.subdiagnostic(AddReturnTypeSuggestion::MissingHere { span });
err.subdiagnostic(errors::AddReturnTypeSuggestion::MissingHere { span });
return true
}
}
@ -794,10 +795,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
debug!(?found);
if found.is_suggestable(self.tcx, false) {
if term.span.is_empty() {
err.subdiagnostic(AddReturnTypeSuggestion::Add { span, found: found.to_string() });
err.subdiagnostic(errors::AddReturnTypeSuggestion::Add { span, found: found.to_string() });
return true;
} else {
err.subdiagnostic(ExpectedReturnTypeLabel::Other { span, expected });
err.subdiagnostic(errors::ExpectedReturnTypeLabel::Other { span, expected });
}
}
}
@ -813,7 +814,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let ty = self.normalize(span, ty);
let ty = self.tcx.erase_late_bound_regions(ty);
if self.can_coerce(expected, ty) {
err.subdiagnostic(ExpectedReturnTypeLabel::Other { span, expected });
err.subdiagnostic(errors::ExpectedReturnTypeLabel::Other { span, expected });
self.try_suggest_return_impl_trait(err, expected, ty, fn_id);
return true;
}
@ -931,7 +932,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.span_suggestion(
fn_return.span(),
"consider using an impl return type",
format!("impl {}", all_bounds_str),
format!("impl {all_bounds_str}"),
Applicability::MaybeIncorrect,
);
}
@ -1070,7 +1071,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.must_apply_modulo_regions()
{
let suggestion = match self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
Some(ident) => format!(": {}.clone()", ident),
Some(ident) => format!(": {ident}.clone()"),
None => ".clone()".to_string()
};
@ -1103,65 +1104,46 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return false;
}
let mut suggest_copied_cloned_or_as_ref = || {
if Some(adt_def.did()) == self.tcx.get_diagnostic_item(sym::Result)
&& self.can_eq(self.param_env, args.type_at(1), expected_args.type_at(1))
|| Some(adt_def.did()) == self.tcx.get_diagnostic_item(sym::Option)
{
let expr_inner_ty = args.type_at(0);
let expected_inner_ty = expected_args.type_at(0);
if let &ty::Ref(_, ty, hir::Mutability::Not) = expr_inner_ty.kind()
&& self.can_eq(self.param_env, ty, expected_inner_ty)
{
let def_path = self.tcx.def_path_str(adt_def.did());
if self.type_is_copy_modulo_regions(self.param_env, ty) {
diag.span_suggestion_verbose(
expr.span.shrink_to_hi(),
format!(
"use `{def_path}::copied` to copy the value inside the `{def_path}`"
),
".copied()",
Applicability::MachineApplicable,
);
return true;
} else if let Some(expected_ty_expr) = expected_ty_expr {
diag.span_suggestion_verbose(
expected_ty_expr.span.shrink_to_hi(),
format!(
"use `{def_path}::as_ref()` to convert `{expected_ty}` to `{expr_ty}`"
),
".as_ref()",
Applicability::MachineApplicable,
);
return true;
} else if let Some(clone_did) = self.tcx.lang_items().clone_trait()
&& rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions(
self,
self.param_env,
ty,
clone_did,
)
if let &ty::Ref(_, ty, mutability) = expr_inner_ty.kind()
&& self.can_eq(self.param_env, ty, expected_inner_ty)
{
diag.span_suggestion_verbose(
expr.span.shrink_to_hi(),
format!(
"use `{def_path}::cloned` to clone the value inside the `{def_path}`"
),
".cloned()",
Applicability::MachineApplicable,
);
let def_path = self.tcx.def_path_str(adt_def.did());
let span = expr.span.shrink_to_hi();
let subdiag = if self.type_is_copy_modulo_regions(self.param_env, ty) {
errors::OptionResultRefMismatch::Copied {
span, def_path
}
} else if let Some(expected_ty_expr) = expected_ty_expr
// FIXME: suggest changes to both expressions to convert both to
// Option/Result<&T>
&& mutability.is_not()
{
errors::OptionResultRefMismatch::AsRef {
span: expected_ty_expr.span.shrink_to_hi(), expected_ty, expr_ty, def_path
}
} else if let Some(clone_did) = self.tcx.lang_items().clone_trait()
&& rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions(
self,
self.param_env,
ty,
clone_did,
)
{
errors::OptionResultRefMismatch::Cloned {
span, def_path
}
} else {
return false;
};
diag.subdiagnostic(subdiag);
return true;
}
}
false
};
if let Some(result_did) = self.tcx.get_diagnostic_item(sym::Result)
&& adt_def.did() == result_did
// Check that the error types are equal
&& self.can_eq(self.param_env, args.type_at(1), expected_args.type_at(1))
{
return suggest_copied_cloned_or_as_ref();
} else if let Some(option_did) = self.tcx.get_diagnostic_item(sym::Option)
&& adt_def.did() == option_did
{
return suggest_copied_cloned_or_as_ref();
}
false
@ -1259,7 +1241,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
let suggestion = match self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
Some(ident) => format!(": {}.is_some()", ident),
Some(ident) => format!(": {ident}.is_some()"),
None => ".is_some()".to_string(),
};

View file

@ -125,8 +125,8 @@ impl Debug for TrackedValue {
write!(f, "{}", tcx.hir().node_to_string(self.hir_id()))
} else {
match self {
Self::Variable(hir_id) => write!(f, "Variable({:?})", hir_id),
Self::Temporary(hir_id) => write!(f, "Temporary({:?})", hir_id),
Self::Variable(hir_id) => write!(f, "Variable({hir_id:?})"),
Self::Temporary(hir_id) => write!(f, "Temporary({hir_id:?})"),
}
}
})

View file

@ -112,7 +112,7 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
self.fcx
.tcx
.sess
.delay_span_bug(span, format!("Encountered var {:?}", unresolved_term));
.delay_span_bug(span, format!("Encountered var {unresolved_term:?}"));
} else {
let note = format!(
"the type is part of the {} because of this {}",

View file

@ -85,7 +85,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Ok(SizeSkeleton::Pointer { tail, .. }) => format!("pointer to `{tail}`"),
Ok(SizeSkeleton::Known(size)) => {
if let Some(v) = u128::from(size.bytes()).checked_mul(8) {
format!("{} bits", v)
format!("{v} bits")
} else {
// `u128` should definitely be able to hold the size of different architectures
// larger sizes should be reported as error `are too big for the current architecture`
@ -122,14 +122,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else {
err.note(format!("source type: `{}` ({})", from, skeleton_string(from, sk_from)))
.note(format!("target type: `{}` ({})", to, skeleton_string(to, sk_to)));
let mut should_delay_as_bug = false;
if let Err(LayoutError::Unknown(bad_from)) = sk_from && bad_from.references_error() {
should_delay_as_bug = true;
}
if let Err(LayoutError::Unknown(bad_to)) = sk_to && bad_to.references_error() {
should_delay_as_bug = true;
}
if should_delay_as_bug {
if let Err(LayoutError::ReferencesError(_)) = sk_from {
err.delay_as_bug();
} else if let Err(LayoutError::ReferencesError(_)) = sk_to {
err.delay_as_bug();
}
}

View file

@ -71,7 +71,7 @@ use rustc_middle::traits;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_session::config;
use rustc_span::def_id::{DefId, LocalDefId};
use rustc_span::{sym, Span};
use rustc_span::Span;
fluent_messages! { "../messages.ftl" }
@ -101,7 +101,7 @@ fn primary_body_of(
) -> Option<(hir::BodyId, Option<&hir::Ty<'_>>, Option<&hir::FnSig<'_>>)> {
match node {
Node::Item(item) => match item.kind {
hir::ItemKind::Const(ty, body) | hir::ItemKind::Static(ty, _, body) => {
hir::ItemKind::Const(ty, _, body) | hir::ItemKind::Static(ty, _, body) => {
Some((body, Some(ty), None))
}
hir::ItemKind::Fn(ref sig, .., body) => Some((body, None, Some(sig))),
@ -182,11 +182,7 @@ fn typeck_with_fallback<'tcx>(
let body = tcx.hir().body(body_id);
let param_env = tcx.param_env(def_id);
let param_env = if tcx.has_attr(def_id, sym::rustc_do_not_const_check) {
param_env.without_const()
} else {
param_env
};
let inh = Inherited::new(tcx, def_id);
let mut fcx = FnCtxt::new(&inh, param_env, def_id);
@ -263,11 +259,7 @@ fn typeck_with_fallback<'tcx>(
// Closure and generator analysis may run after fallback
// because they don't constrain other type variables.
// Closure analysis only runs on closures. Therefore they only need to fulfill non-const predicates (as of now)
let prev_constness = fcx.param_env.constness();
fcx.param_env = fcx.param_env.without_const();
fcx.closure_analyze(body);
fcx.param_env = fcx.param_env.with_constness(prev_constness);
assert!(fcx.deferred_call_resolutions.borrow().is_empty());
// Before the generator analysis, temporary scopes shall be marked to provide more
// precise information on types to be captured.

Some files were not shown because too many files have changed in this diff Show more