Auto merge of #2996 - rust-lang:rustup-2023-07-30, r=oli-obk
Automatic sync from rustc
This commit is contained in:
commit
2183cdac19
653 changed files with 9125 additions and 8074 deletions
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
|
|
@ -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: {}
|
||||
|
|
|
|||
40
Cargo.lock
40
Cargo.lock
|
|
@ -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",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:?}")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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!(
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
|
|
|
|||
|
|
@ -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(|| {
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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:?}"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)?,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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:?}")
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)?;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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}`
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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 }"),
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 `{}`",
|
||||
|
|
|
|||
|
|
@ -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 });
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
),
|
||||
)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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 });
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 { .. },
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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(", "),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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!(
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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("");
|
||||
|
|
|
|||
|
|
@ -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...
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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?",
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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:?})"),
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -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 {}",
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue