Merge from rustc
This commit is contained in:
commit
1194ad9af9
321 changed files with 4745 additions and 2109 deletions
|
|
@ -4064,6 +4064,7 @@ name = "rustc_lexer"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"expect-test",
|
||||
"memchr",
|
||||
"unicode-properties",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
//! - [`UnOp`], [`BinOp`], and [`BinOpKind`]: Unary and binary operators.
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::sync::Arc;
|
||||
use std::{cmp, fmt};
|
||||
|
||||
pub use GenericArgs::*;
|
||||
|
|
@ -27,7 +28,6 @@ pub use rustc_ast_ir::{Movability, Mutability, Pinnedness};
|
|||
use rustc_data_structures::packed::Pu128;
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_data_structures::tagged_ptr::Tag;
|
||||
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
|
||||
pub use rustc_span::AttrId;
|
||||
|
|
@ -1611,7 +1611,7 @@ pub enum ExprKind {
|
|||
/// Added for optimization purposes to avoid the need to escape
|
||||
/// large binary blobs - should always behave like [`ExprKind::Lit`]
|
||||
/// with a `ByteStr` literal.
|
||||
IncludedBytes(Lrc<[u8]>),
|
||||
IncludedBytes(Arc<[u8]>),
|
||||
|
||||
/// A `format_args!()` expression.
|
||||
FormatArgs(P<FormatArgs>),
|
||||
|
|
@ -1904,9 +1904,9 @@ pub enum LitKind {
|
|||
Str(Symbol, StrStyle),
|
||||
/// A byte string (`b"foo"`). Not stored as a symbol because it might be
|
||||
/// non-utf8, and symbols only allow utf8 strings.
|
||||
ByteStr(Lrc<[u8]>, StrStyle),
|
||||
ByteStr(Arc<[u8]>, StrStyle),
|
||||
/// A C String (`c"foo"`). Guaranteed to only have `\0` at the end.
|
||||
CStr(Lrc<[u8]>, StrStyle),
|
||||
CStr(Arc<[u8]>, StrStyle),
|
||||
/// A byte char (`b'f'`).
|
||||
Byte(u8),
|
||||
/// A character literal (`'a'`).
|
||||
|
|
|
|||
|
|
@ -9,10 +9,10 @@
|
|||
|
||||
use std::ops::DerefMut;
|
||||
use std::panic;
|
||||
use std::sync::Arc;
|
||||
|
||||
use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::{Ident, Span};
|
||||
use smallvec::{Array, SmallVec, smallvec};
|
||||
|
|
@ -793,14 +793,14 @@ fn visit_tt<T: MutVisitor>(vis: &mut T, tt: &mut TokenTree) {
|
|||
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
|
||||
fn visit_tts<T: MutVisitor>(vis: &mut T, TokenStream(tts): &mut TokenStream) {
|
||||
if T::VISIT_TOKENS && !tts.is_empty() {
|
||||
let tts = Lrc::make_mut(tts);
|
||||
let tts = Arc::make_mut(tts);
|
||||
visit_vec(tts, |tree| visit_tt(vis, tree));
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_attr_tts<T: MutVisitor>(vis: &mut T, AttrTokenStream(tts): &mut AttrTokenStream) {
|
||||
if T::VISIT_TOKENS && !tts.is_empty() {
|
||||
let tts = Lrc::make_mut(tts);
|
||||
let tts = Arc::make_mut(tts);
|
||||
visit_vec(tts, |tree| visit_attr_tt(vis, tree));
|
||||
}
|
||||
}
|
||||
|
|
@ -840,7 +840,7 @@ pub fn visit_token<T: MutVisitor>(vis: &mut T, t: &mut Token) {
|
|||
vis.visit_ident(ident);
|
||||
}
|
||||
token::Interpolated(nt) => {
|
||||
let nt = Lrc::make_mut(nt);
|
||||
let nt = Arc::make_mut(nt);
|
||||
visit_nonterminal(vis, nt);
|
||||
}
|
||||
_ => {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use std::borrow::Cow;
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub use BinOpToken::*;
|
||||
pub use LitKind::*;
|
||||
|
|
@ -8,7 +9,6 @@ pub use NtExprKind::*;
|
|||
pub use NtPatKind::*;
|
||||
pub use TokenKind::*;
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, kw, sym};
|
||||
|
|
@ -451,7 +451,7 @@ pub enum TokenKind {
|
|||
/// The span in the surrounding `Token` is that of the metavariable in the
|
||||
/// macro's RHS. The span within the Nonterminal is that of the fragment
|
||||
/// passed to the macro at the call site.
|
||||
Interpolated(Lrc<Nonterminal>),
|
||||
Interpolated(Arc<Nonterminal>),
|
||||
|
||||
/// A doc comment token.
|
||||
/// `Symbol` is the doc comment's data excluding its "quotes" (`///`, `/**`, etc)
|
||||
|
|
@ -469,7 +469,7 @@ impl Clone for TokenKind {
|
|||
// a copy. This is faster than the `derive(Clone)` version which has a
|
||||
// separate path for every variant.
|
||||
match self {
|
||||
Interpolated(nt) => Interpolated(Lrc::clone(nt)),
|
||||
Interpolated(nt) => Interpolated(Arc::clone(nt)),
|
||||
_ => unsafe { std::ptr::read(self) },
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,10 +14,11 @@
|
|||
//! ownership of the original.
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::sync::Arc;
|
||||
use std::{cmp, fmt, iter};
|
||||
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_data_structures::sync::{self, Lrc};
|
||||
use rustc_data_structures::sync;
|
||||
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
|
||||
use rustc_serialize::{Decodable, Encodable};
|
||||
use rustc_span::{DUMMY_SP, Span, SpanDecoder, SpanEncoder, Symbol, sym};
|
||||
|
|
@ -119,11 +120,11 @@ impl ToAttrTokenStream for AttrTokenStream {
|
|||
/// of an actual `TokenStream` until it is needed.
|
||||
/// `Box` is here only to reduce the structure size.
|
||||
#[derive(Clone)]
|
||||
pub struct LazyAttrTokenStream(Lrc<Box<dyn ToAttrTokenStream>>);
|
||||
pub struct LazyAttrTokenStream(Arc<Box<dyn ToAttrTokenStream>>);
|
||||
|
||||
impl LazyAttrTokenStream {
|
||||
pub fn new(inner: impl ToAttrTokenStream + 'static) -> LazyAttrTokenStream {
|
||||
LazyAttrTokenStream(Lrc::new(Box::new(inner)))
|
||||
LazyAttrTokenStream(Arc::new(Box::new(inner)))
|
||||
}
|
||||
|
||||
pub fn to_attr_token_stream(&self) -> AttrTokenStream {
|
||||
|
|
@ -160,7 +161,7 @@ impl<CTX> HashStable<CTX> for LazyAttrTokenStream {
|
|||
/// during expansion to perform early cfg-expansion, and to process attributes
|
||||
/// during proc-macro invocations.
|
||||
#[derive(Clone, Debug, Default, Encodable, Decodable)]
|
||||
pub struct AttrTokenStream(pub Lrc<Vec<AttrTokenTree>>);
|
||||
pub struct AttrTokenStream(pub Arc<Vec<AttrTokenTree>>);
|
||||
|
||||
/// Like `TokenTree`, but for `AttrTokenStream`.
|
||||
#[derive(Clone, Debug, Encodable, Decodable)]
|
||||
|
|
@ -175,7 +176,7 @@ pub enum AttrTokenTree {
|
|||
|
||||
impl AttrTokenStream {
|
||||
pub fn new(tokens: Vec<AttrTokenTree>) -> AttrTokenStream {
|
||||
AttrTokenStream(Lrc::new(tokens))
|
||||
AttrTokenStream(Arc::new(tokens))
|
||||
}
|
||||
|
||||
/// Converts this `AttrTokenStream` to a plain `Vec<TokenTree>`. During
|
||||
|
|
@ -293,7 +294,7 @@ pub struct AttrsTarget {
|
|||
/// Today's `TokenTree`s can still contain AST via `token::Interpolated` for
|
||||
/// backwards compatibility.
|
||||
#[derive(Clone, Debug, Default, Encodable, Decodable)]
|
||||
pub struct TokenStream(pub(crate) Lrc<Vec<TokenTree>>);
|
||||
pub struct TokenStream(pub(crate) Arc<Vec<TokenTree>>);
|
||||
|
||||
/// Indicates whether a token can join with the following token to form a
|
||||
/// compound token. Used for conversions to `proc_macro::Spacing`. Also used to
|
||||
|
|
@ -412,7 +413,7 @@ impl PartialEq<TokenStream> for TokenStream {
|
|||
|
||||
impl TokenStream {
|
||||
pub fn new(tts: Vec<TokenTree>) -> TokenStream {
|
||||
TokenStream(Lrc::new(tts))
|
||||
TokenStream(Arc::new(tts))
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
|
|
@ -544,7 +545,7 @@ impl TokenStream {
|
|||
/// Push `tt` onto the end of the stream, possibly gluing it to the last
|
||||
/// token. Uses `make_mut` to maximize efficiency.
|
||||
pub fn push_tree(&mut self, tt: TokenTree) {
|
||||
let vec_mut = Lrc::make_mut(&mut self.0);
|
||||
let vec_mut = Arc::make_mut(&mut self.0);
|
||||
|
||||
if Self::try_glue_to_last(vec_mut, &tt) {
|
||||
// nothing else to do
|
||||
|
|
@ -557,7 +558,7 @@ impl TokenStream {
|
|||
/// token tree to the last token. (No other token trees will be glued.)
|
||||
/// Uses `make_mut` to maximize efficiency.
|
||||
pub fn push_stream(&mut self, stream: TokenStream) {
|
||||
let vec_mut = Lrc::make_mut(&mut self.0);
|
||||
let vec_mut = Arc::make_mut(&mut self.0);
|
||||
|
||||
let stream_iter = stream.0.iter().cloned();
|
||||
|
||||
|
|
@ -577,7 +578,7 @@ impl TokenStream {
|
|||
}
|
||||
|
||||
/// Desugar doc comments like `/// foo` in the stream into `#[doc =
|
||||
/// r"foo"]`. Modifies the `TokenStream` via `Lrc::make_mut`, but as little
|
||||
/// r"foo"]`. Modifies the `TokenStream` via `Arc::make_mut`, but as little
|
||||
/// as possible.
|
||||
pub fn desugar_doc_comments(&mut self) {
|
||||
if let Some(desugared_stream) = desugar_inner(self.clone()) {
|
||||
|
|
@ -596,7 +597,7 @@ impl TokenStream {
|
|||
) => {
|
||||
let desugared = desugared_tts(attr_style, data, span);
|
||||
let desugared_len = desugared.len();
|
||||
Lrc::make_mut(&mut stream.0).splice(i..i + 1, desugared);
|
||||
Arc::make_mut(&mut stream.0).splice(i..i + 1, desugared);
|
||||
modified = true;
|
||||
i += desugared_len;
|
||||
}
|
||||
|
|
@ -607,7 +608,7 @@ impl TokenStream {
|
|||
if let Some(desugared_delim_stream) = desugar_inner(delim_stream.clone()) {
|
||||
let new_tt =
|
||||
TokenTree::Delimited(sp, spacing, delim, desugared_delim_stream);
|
||||
Lrc::make_mut(&mut stream.0)[i] = new_tt;
|
||||
Arc::make_mut(&mut stream.0)[i] = new_tt;
|
||||
modified = true;
|
||||
}
|
||||
i += 1;
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ impl LitKind {
|
|||
}
|
||||
token::ByteStrRaw(n) => {
|
||||
// Raw strings have no escapes so we can convert the symbol
|
||||
// directly to a `Lrc<u8>`.
|
||||
// directly to a `Arc<u8>`.
|
||||
let buf = symbol.as_str().to_owned().into_bytes();
|
||||
LitKind::ByteStr(buf.into(), StrStyle::Raw(n))
|
||||
}
|
||||
|
|
@ -142,7 +142,7 @@ impl LitKind {
|
|||
}
|
||||
token::CStrRaw(n) => {
|
||||
// Raw strings have no escapes so we can convert the symbol
|
||||
// directly to a `Lrc<u8>` after appending the terminating NUL
|
||||
// directly to a `Arc<u8>` after appending the terminating NUL
|
||||
// char.
|
||||
let mut buf = symbol.as_str().to_owned().into_bytes();
|
||||
buf.push(0);
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
use std::assert_matches::assert_matches;
|
||||
use std::ops::ControlFlow;
|
||||
use std::sync::Arc;
|
||||
|
||||
use rustc_ast::ptr::P as AstP;
|
||||
use rustc_ast::*;
|
||||
use rustc_ast_pretty::pprust::expr_to_string;
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::HirId;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
|
|
@ -147,7 +147,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
ExprKind::IncludedBytes(bytes) => {
|
||||
let lit = self.arena.alloc(respan(
|
||||
self.lower_span(e.span),
|
||||
LitKind::ByteStr(Lrc::clone(bytes), StrStyle::Cooked),
|
||||
LitKind::ByteStr(Arc::clone(bytes), StrStyle::Cooked),
|
||||
));
|
||||
hir::ExprKind::Lit(lit)
|
||||
}
|
||||
|
|
@ -625,7 +625,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
this.mark_span_with_reason(
|
||||
DesugaringKind::TryBlock,
|
||||
expr.span,
|
||||
Some(Lrc::clone(&this.allow_try_trait)),
|
||||
Some(Arc::clone(&this.allow_try_trait)),
|
||||
),
|
||||
expr,
|
||||
)
|
||||
|
|
@ -633,7 +633,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let try_span = this.mark_span_with_reason(
|
||||
DesugaringKind::TryBlock,
|
||||
this.tcx.sess.source_map().end_point(body.span),
|
||||
Some(Lrc::clone(&this.allow_try_trait)),
|
||||
Some(Arc::clone(&this.allow_try_trait)),
|
||||
);
|
||||
|
||||
(try_span, this.expr_unit(try_span))
|
||||
|
|
@ -742,7 +742,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let unstable_span = self.mark_span_with_reason(
|
||||
DesugaringKind::Async,
|
||||
self.lower_span(span),
|
||||
Some(Lrc::clone(&self.allow_gen_future)),
|
||||
Some(Arc::clone(&self.allow_gen_future)),
|
||||
);
|
||||
let resume_ty =
|
||||
self.make_lang_item_qpath(hir::LangItem::ResumeTy, unstable_span, None);
|
||||
|
|
@ -826,7 +826,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let unstable_span = self.mark_span_with_reason(
|
||||
DesugaringKind::Async,
|
||||
span,
|
||||
Some(Lrc::clone(&self.allow_gen_future)),
|
||||
Some(Arc::clone(&self.allow_gen_future)),
|
||||
);
|
||||
self.lower_attrs(inner_hir_id, &[Attribute {
|
||||
kind: AttrKind::Normal(ptr::P(NormalAttr::from_ident(Ident::new(
|
||||
|
|
@ -902,13 +902,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
|
||||
let features = match await_kind {
|
||||
FutureKind::Future => None,
|
||||
FutureKind::AsyncIterator => Some(Lrc::clone(&self.allow_for_await)),
|
||||
FutureKind::AsyncIterator => Some(Arc::clone(&self.allow_for_await)),
|
||||
};
|
||||
let span = self.mark_span_with_reason(DesugaringKind::Await, await_kw_span, features);
|
||||
let gen_future_span = self.mark_span_with_reason(
|
||||
DesugaringKind::Await,
|
||||
full_span,
|
||||
Some(Lrc::clone(&self.allow_gen_future)),
|
||||
Some(Arc::clone(&self.allow_gen_future)),
|
||||
);
|
||||
let expr_hir_id = expr.hir_id;
|
||||
|
||||
|
|
@ -1952,13 +1952,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let unstable_span = self.mark_span_with_reason(
|
||||
DesugaringKind::QuestionMark,
|
||||
span,
|
||||
Some(Lrc::clone(&self.allow_try_trait)),
|
||||
Some(Arc::clone(&self.allow_try_trait)),
|
||||
);
|
||||
let try_span = self.tcx.sess.source_map().end_point(span);
|
||||
let try_span = self.mark_span_with_reason(
|
||||
DesugaringKind::QuestionMark,
|
||||
try_span,
|
||||
Some(Lrc::clone(&self.allow_try_trait)),
|
||||
Some(Arc::clone(&self.allow_try_trait)),
|
||||
);
|
||||
|
||||
// `Try::branch(<expr>)`
|
||||
|
|
@ -2053,7 +2053,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let unstable_span = self.mark_span_with_reason(
|
||||
DesugaringKind::YeetExpr,
|
||||
span,
|
||||
Some(Lrc::clone(&self.allow_try_trait)),
|
||||
Some(Arc::clone(&self.allow_try_trait)),
|
||||
);
|
||||
|
||||
let from_yeet_expr = self.wrap_in_try_constructor(
|
||||
|
|
|
|||
|
|
@ -41,13 +41,14 @@
|
|||
#![warn(unreachable_pub)]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use rustc_ast::node_id::NodeMap;
|
||||
use rustc_ast::{self as ast, *};
|
||||
use rustc_data_structures::captures::Captures;
|
||||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
use rustc_data_structures::sorted_map::SortedMap;
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_data_structures::tagged_ptr::TaggedRef;
|
||||
use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, StashKey};
|
||||
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
|
||||
|
|
@ -144,11 +145,11 @@ struct LoweringContext<'a, 'hir> {
|
|||
#[cfg(debug_assertions)]
|
||||
node_id_to_local_id: NodeMap<hir::ItemLocalId>,
|
||||
|
||||
allow_try_trait: Lrc<[Symbol]>,
|
||||
allow_gen_future: Lrc<[Symbol]>,
|
||||
allow_async_iterator: Lrc<[Symbol]>,
|
||||
allow_for_await: Lrc<[Symbol]>,
|
||||
allow_async_fn_traits: Lrc<[Symbol]>,
|
||||
allow_try_trait: Arc<[Symbol]>,
|
||||
allow_gen_future: Arc<[Symbol]>,
|
||||
allow_async_iterator: Arc<[Symbol]>,
|
||||
allow_for_await: Arc<[Symbol]>,
|
||||
allow_async_fn_traits: Arc<[Symbol]>,
|
||||
}
|
||||
|
||||
impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
|
|
@ -738,7 +739,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
&self,
|
||||
reason: DesugaringKind,
|
||||
span: Span,
|
||||
allow_internal_unstable: Option<Lrc<[Symbol]>>,
|
||||
allow_internal_unstable: Option<Arc<[Symbol]>>,
|
||||
) -> Span {
|
||||
self.tcx.with_stable_hashing_context(|hcx| {
|
||||
span.mark_with_reason(allow_internal_unstable, reason, span.edition(), hcx)
|
||||
|
|
@ -1686,7 +1687,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
CoroutineKind::Async { return_impl_trait_id, .. } => (return_impl_trait_id, None),
|
||||
CoroutineKind::Gen { return_impl_trait_id, .. } => (return_impl_trait_id, None),
|
||||
CoroutineKind::AsyncGen { return_impl_trait_id, .. } => {
|
||||
(return_impl_trait_id, Some(Lrc::clone(&self.allow_async_iterator)))
|
||||
(return_impl_trait_id, Some(Arc::clone(&self.allow_async_iterator)))
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use rustc_ast::{self as ast, *};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::GenericArg;
|
||||
use rustc_hir::def::{DefKind, PartialRes, Res};
|
||||
|
|
@ -72,7 +73,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
let bound_modifier_allowed_features = if let Res::Def(DefKind::Trait, async_def_id) = res
|
||||
&& self.tcx.async_fn_trait_kind_from_def_id(async_def_id).is_some()
|
||||
{
|
||||
Some(Lrc::clone(&self.allow_async_fn_traits))
|
||||
Some(Arc::clone(&self.allow_async_fn_traits))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
|
@ -257,7 +258,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
// Additional features ungated with a bound modifier like `async`.
|
||||
// This is passed down to the implicit associated type binding in
|
||||
// parenthesized bounds.
|
||||
bound_modifier_allowed_features: Option<Lrc<[Symbol]>>,
|
||||
bound_modifier_allowed_features: Option<Arc<[Symbol]>>,
|
||||
) -> hir::PathSegment<'hir> {
|
||||
debug!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span, segment);
|
||||
let (mut generic_args, infer_args) = if let Some(generic_args) = segment.args.as_deref() {
|
||||
|
|
@ -490,7 +491,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
&mut self,
|
||||
data: &ParenthesizedArgs,
|
||||
itctx: ImplTraitContext,
|
||||
bound_modifier_allowed_features: Option<Lrc<[Symbol]>>,
|
||||
bound_modifier_allowed_features: Option<Arc<[Symbol]>>,
|
||||
) -> (GenericArgsCtor<'hir>, bool) {
|
||||
// Switch to `PassThrough` mode for anonymous lifetimes; this
|
||||
// means that we permit things like `&Ref<T>`, where `Ref` has
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ mod fixup;
|
|||
mod item;
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::sync::Arc;
|
||||
|
||||
use rustc_ast::attr::AttrIdGenerator;
|
||||
use rustc_ast::ptr::P;
|
||||
|
|
@ -21,7 +22,6 @@ use rustc_ast::{
|
|||
InlineAsmOperand, InlineAsmOptions, InlineAsmRegOrRegClass, InlineAsmTemplatePiece, PatKind,
|
||||
RangeEnd, RangeSyntax, Safety, SelfKind, Term, attr,
|
||||
};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::source_map::{SourceMap, Spanned};
|
||||
use rustc_span::symbol::IdentPrinter;
|
||||
|
|
@ -106,7 +106,7 @@ fn split_block_comment_into_lines(text: &str, col: CharPos) -> Vec<String> {
|
|||
fn gather_comments(sm: &SourceMap, path: FileName, src: String) -> Vec<Comment> {
|
||||
let sm = SourceMap::new(sm.path_mapping().clone());
|
||||
let source_file = sm.new_source_file(path, src);
|
||||
let text = Lrc::clone(&(*source_file.src.as_ref().unwrap()));
|
||||
let text = Arc::clone(&(*source_file.src.as_ref().unwrap()));
|
||||
|
||||
let text: &str = text.as_str();
|
||||
let start_bpos = source_file.start_pos;
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
use std::path::{Path, PathBuf};
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token;
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_expand::base::{
|
||||
DummyResult, ExpandResult, ExtCtxt, MacEager, MacResult, MacroExpanderResult, resolve_path,
|
||||
};
|
||||
|
|
@ -249,7 +249,7 @@ fn load_binary_file(
|
|||
original_path: &Path,
|
||||
macro_span: Span,
|
||||
path_span: Span,
|
||||
) -> Result<(Lrc<[u8]>, Span), Box<dyn MacResult>> {
|
||||
) -> Result<(Arc<[u8]>, Span), Box<dyn MacResult>> {
|
||||
let resolved_path = match resolve_path(&cx.sess, original_path, macro_span) {
|
||||
Ok(path) => path,
|
||||
Err(err) => {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
use std::ops::Range;
|
||||
use std::sync::Arc;
|
||||
|
||||
use gccjit::{Location, RValue};
|
||||
use rustc_abi::Size;
|
||||
use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind};
|
||||
use rustc_codegen_ssa::traits::{DebugInfoBuilderMethods, DebugInfoCodegenMethods};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_index::bit_set::DenseBitSet;
|
||||
use rustc_index::{Idx, IndexVec};
|
||||
use rustc_middle::mir::{self, Body, SourceScope};
|
||||
|
|
@ -172,7 +172,7 @@ fn make_mir_scope<'gcc, 'tcx>(
|
|||
// `lookup_char_pos` return the right information instead.
|
||||
pub struct DebugLoc {
|
||||
/// Information about the original source file.
|
||||
pub file: Lrc<SourceFile>,
|
||||
pub file: Arc<SourceFile>,
|
||||
/// The (1-based) line number.
|
||||
pub line: u32,
|
||||
/// The (1-based) column number.
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use std::cell::{OnceCell, RefCell};
|
||||
use std::ops::Range;
|
||||
use std::sync::Arc;
|
||||
use std::{iter, ptr};
|
||||
|
||||
use libc::c_uint;
|
||||
|
|
@ -10,7 +11,6 @@ use rustc_codegen_ssa::debuginfo::type_names;
|
|||
use rustc_codegen_ssa::mir::debuginfo::VariableKind::*;
|
||||
use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind};
|
||||
use rustc_codegen_ssa::traits::*;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_data_structures::unord::UnordMap;
|
||||
use rustc_hir::def_id::{DefId, DefIdMap};
|
||||
use rustc_index::IndexVec;
|
||||
|
|
@ -244,7 +244,7 @@ impl<'ll> DebugInfoBuilderMethods for Builder<'_, 'll, '_> {
|
|||
// `lookup_char_pos` return the right information instead.
|
||||
struct DebugLoc {
|
||||
/// Information about the original source file.
|
||||
file: Lrc<SourceFile>,
|
||||
file: Arc<SourceFile>,
|
||||
/// The (1-based) line number.
|
||||
line: u32,
|
||||
/// The (1-based) column number.
|
||||
|
|
|
|||
|
|
@ -71,14 +71,9 @@ mod debuginfo;
|
|||
mod declare;
|
||||
mod errors;
|
||||
mod intrinsic;
|
||||
|
||||
// The following is a workaround that replaces `pub mod llvm;` and that fixes issue 53912.
|
||||
#[path = "llvm/mod.rs"]
|
||||
mod llvm_;
|
||||
pub mod llvm {
|
||||
pub use super::llvm_::*;
|
||||
}
|
||||
|
||||
// FIXME(Zalathar): Fix all the unreachable-pub warnings that would occur if
|
||||
// this isn't pub, then make it not pub.
|
||||
pub mod llvm;
|
||||
mod llvm_util;
|
||||
mod mono_item;
|
||||
mod type_;
|
||||
|
|
|
|||
|
|
@ -10,13 +10,9 @@ use libc::c_uint;
|
|||
use rustc_abi::{Align, Size, WrappingRange};
|
||||
use rustc_llvm::RustString;
|
||||
|
||||
pub use self::AtomicRmwBinOp::*;
|
||||
pub use self::CallConv::*;
|
||||
pub use self::CodeGenOptSize::*;
|
||||
pub use self::IntPredicate::*;
|
||||
pub use self::Linkage::*;
|
||||
pub use self::MetadataType::*;
|
||||
pub use self::RealPredicate::*;
|
||||
pub use self::ffi::*;
|
||||
use crate::common::AsCCharPtr;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use std::cmp;
|
||||
use std::collections::BTreeSet;
|
||||
use std::sync::Arc;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use itertools::Itertools;
|
||||
|
|
@ -7,7 +8,7 @@ use rustc_abi::FIRST_VARIANT;
|
|||
use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, AllocatorKind, global_fn_name};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
|
||||
use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
|
||||
use rustc_data_structures::sync::{Lrc, par_map};
|
||||
use rustc_data_structures::sync::par_map;
|
||||
use rustc_data_structures::unord::UnordMap;
|
||||
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
|
|
@ -932,7 +933,7 @@ impl CrateInfo {
|
|||
crate_name: UnordMap::with_capacity(n_crates),
|
||||
used_crates,
|
||||
used_crate_source: UnordMap::with_capacity(n_crates),
|
||||
dependency_formats: Lrc::clone(tcx.dependency_formats(())),
|
||||
dependency_formats: Arc::clone(tcx.dependency_formats(())),
|
||||
windows_subsystem,
|
||||
natvis_debugger_visualizers: Default::default(),
|
||||
lint_levels: CodegenLintLevels::from_tcx(tcx),
|
||||
|
|
@ -946,7 +947,7 @@ impl CrateInfo {
|
|||
info.crate_name.insert(cnum, tcx.crate_name(cnum));
|
||||
|
||||
let used_crate_source = tcx.used_crate_source(cnum);
|
||||
info.used_crate_source.insert(cnum, Lrc::clone(used_crate_source));
|
||||
info.used_crate_source.insert(cnum, Arc::clone(used_crate_source));
|
||||
if tcx.is_profiler_runtime(cnum) {
|
||||
info.profiler_runtime = Some(cnum);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,10 +24,10 @@
|
|||
use std::collections::BTreeSet;
|
||||
use std::io;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
|
||||
use rustc_ast as ast;
|
||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_data_structures::unord::UnordMap;
|
||||
use rustc_hir::CRATE_HIR_ID;
|
||||
use rustc_hir::def_id::CrateNum;
|
||||
|
|
@ -200,9 +200,9 @@ pub struct CrateInfo {
|
|||
pub native_libraries: FxIndexMap<CrateNum, Vec<NativeLib>>,
|
||||
pub crate_name: UnordMap<CrateNum, Symbol>,
|
||||
pub used_libraries: Vec<NativeLib>,
|
||||
pub used_crate_source: UnordMap<CrateNum, Lrc<CrateSource>>,
|
||||
pub used_crate_source: UnordMap<CrateNum, Arc<CrateSource>>,
|
||||
pub used_crates: Vec<CrateNum>,
|
||||
pub dependency_formats: Lrc<Dependencies>,
|
||||
pub dependency_formats: Arc<Dependencies>,
|
||||
pub windows_subsystem: Option<String>,
|
||||
pub natvis_debugger_visualizers: BTreeSet<DebuggerVisualizerFile>,
|
||||
pub lint_levels: CodegenLintLevels,
|
||||
|
|
|
|||
|
|
@ -51,6 +51,8 @@ pub fn provide(providers: &mut Providers) {
|
|||
providers.check_validity_requirement = |tcx, (init_kind, param_env_and_ty)| {
|
||||
util::check_validity_requirement(tcx, init_kind, param_env_and_ty)
|
||||
};
|
||||
providers.hooks.validate_scalar_in_layout =
|
||||
|tcx, scalar, layout| util::validate_scalar_in_layout(tcx, scalar, layout);
|
||||
}
|
||||
|
||||
/// `rustc_driver::main` installs a handler that will set this to `true` if
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
use rustc_abi::{BackendRepr, FieldsShape, Scalar, Variants};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::layout::{
|
||||
HasTyCtxt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, ValidityRequirement,
|
||||
};
|
||||
use rustc_middle::ty::{PseudoCanonicalInput, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{PseudoCanonicalInput, ScalarInt, Ty, TyCtxt};
|
||||
use rustc_middle::{bug, ty};
|
||||
use rustc_span::DUMMY_SP;
|
||||
|
||||
use crate::const_eval::{CanAccessMutGlobal, CheckAlignment, CompileTimeMachine};
|
||||
use crate::interpret::{InterpCx, MemoryKind};
|
||||
|
|
@ -34,7 +35,7 @@ pub fn check_validity_requirement<'tcx>(
|
|||
|
||||
let layout_cx = LayoutCx::new(tcx, input.typing_env);
|
||||
if kind == ValidityRequirement::Uninit || tcx.sess.opts.unstable_opts.strict_init_checks {
|
||||
check_validity_requirement_strict(layout, &layout_cx, kind)
|
||||
Ok(check_validity_requirement_strict(layout, &layout_cx, kind))
|
||||
} else {
|
||||
check_validity_requirement_lax(layout, &layout_cx, kind)
|
||||
}
|
||||
|
|
@ -46,10 +47,10 @@ fn check_validity_requirement_strict<'tcx>(
|
|||
ty: TyAndLayout<'tcx>,
|
||||
cx: &LayoutCx<'tcx>,
|
||||
kind: ValidityRequirement,
|
||||
) -> Result<bool, &'tcx LayoutError<'tcx>> {
|
||||
) -> bool {
|
||||
let machine = CompileTimeMachine::new(CanAccessMutGlobal::No, CheckAlignment::Error);
|
||||
|
||||
let mut cx = InterpCx::new(cx.tcx(), rustc_span::DUMMY_SP, cx.typing_env, machine);
|
||||
let mut cx = InterpCx::new(cx.tcx(), DUMMY_SP, cx.typing_env, machine);
|
||||
|
||||
let allocated = cx
|
||||
.allocate(ty, MemoryKind::Machine(crate::const_eval::MemoryKind::Heap))
|
||||
|
|
@ -69,14 +70,13 @@ fn check_validity_requirement_strict<'tcx>(
|
|||
// due to this.
|
||||
// The value we are validating is temporary and discarded at the end of this function, so
|
||||
// there is no point in reseting provenance and padding.
|
||||
Ok(cx
|
||||
.validate_operand(
|
||||
&allocated.into(),
|
||||
/*recursive*/ false,
|
||||
/*reset_provenance_and_padding*/ false,
|
||||
)
|
||||
.discard_err()
|
||||
.is_some())
|
||||
cx.validate_operand(
|
||||
&allocated.into(),
|
||||
/*recursive*/ false,
|
||||
/*reset_provenance_and_padding*/ false,
|
||||
)
|
||||
.discard_err()
|
||||
.is_some()
|
||||
}
|
||||
|
||||
/// Implements the 'lax' (default) version of the [`check_validity_requirement`] checks; see that
|
||||
|
|
@ -168,3 +168,31 @@ fn check_validity_requirement_lax<'tcx>(
|
|||
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
pub(crate) fn validate_scalar_in_layout<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
scalar: ScalarInt,
|
||||
ty: Ty<'tcx>,
|
||||
) -> bool {
|
||||
let machine = CompileTimeMachine::new(CanAccessMutGlobal::No, CheckAlignment::Error);
|
||||
|
||||
let typing_env = ty::TypingEnv::fully_monomorphized();
|
||||
let mut cx = InterpCx::new(tcx, DUMMY_SP, typing_env, machine);
|
||||
|
||||
let Ok(layout) = cx.layout_of(ty) else {
|
||||
bug!("could not compute layout of {scalar:?}:{ty:?}")
|
||||
};
|
||||
let allocated = cx
|
||||
.allocate(layout, MemoryKind::Machine(crate::const_eval::MemoryKind::Heap))
|
||||
.expect("OOM: failed to allocate for uninit check");
|
||||
|
||||
cx.write_scalar(scalar, &allocated).unwrap();
|
||||
|
||||
cx.validate_operand(
|
||||
&allocated.into(),
|
||||
/*recursive*/ false,
|
||||
/*reset_provenance_and_padding*/ false,
|
||||
)
|
||||
.discard_err()
|
||||
.is_some()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ mod type_name;
|
|||
|
||||
pub use self::alignment::{is_disaligned, is_within_packed};
|
||||
pub use self::check_validity_requirement::check_validity_requirement;
|
||||
pub(crate) use self::check_validity_requirement::validate_scalar_in_layout;
|
||||
pub use self::compare_types::{relate_types, sub_types};
|
||||
pub use self::type_name::type_name;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,13 +3,13 @@ use std::io;
|
|||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
/// A trivial wrapper for [`memmap2::Mmap`] (or `Vec<u8>` on WASM).
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[cfg(not(any(miri, target_arch = "wasm32")))]
|
||||
pub struct Mmap(memmap2::Mmap);
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[cfg(any(miri, target_arch = "wasm32"))]
|
||||
pub struct Mmap(Vec<u8>);
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[cfg(not(any(miri, target_arch = "wasm32")))]
|
||||
impl Mmap {
|
||||
/// # Safety
|
||||
///
|
||||
|
|
@ -29,7 +29,7 @@ impl Mmap {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[cfg(any(miri, target_arch = "wasm32"))]
|
||||
impl Mmap {
|
||||
#[inline]
|
||||
pub unsafe fn map(mut file: File) -> io::Result<Self> {
|
||||
|
|
@ -56,13 +56,13 @@ impl AsRef<[u8]> for Mmap {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[cfg(not(any(miri, target_arch = "wasm32")))]
|
||||
pub struct MmapMut(memmap2::MmapMut);
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[cfg(any(miri, target_arch = "wasm32"))]
|
||||
pub struct MmapMut(Vec<u8>);
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[cfg(not(any(miri, target_arch = "wasm32")))]
|
||||
impl MmapMut {
|
||||
#[inline]
|
||||
pub fn map_anon(len: usize) -> io::Result<Self> {
|
||||
|
|
@ -82,7 +82,7 @@ impl MmapMut {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[cfg(any(miri, target_arch = "wasm32"))]
|
||||
impl MmapMut {
|
||||
#[inline]
|
||||
pub fn map_anon(len: usize) -> io::Result<Self> {
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
use std::borrow::Borrow;
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
|
||||
// Use our fake Send/Sync traits when on not parallel compiler,
|
||||
// so that `OwnedSlice` only implements/requires Send/Sync
|
||||
// for parallel compiler builds.
|
||||
use crate::sync;
|
||||
use crate::sync::Lrc;
|
||||
|
||||
/// An owned slice.
|
||||
///
|
||||
/// This is similar to `Lrc<[u8]>` but allows slicing and using anything as the
|
||||
/// This is similar to `Arc<[u8]>` but allows slicing and using anything as the
|
||||
/// backing buffer.
|
||||
///
|
||||
/// See [`slice_owned`] for `OwnedSlice` construction and examples.
|
||||
|
|
@ -34,7 +34,7 @@ pub struct OwnedSlice {
|
|||
// \/
|
||||
// ⊂(´・◡・⊂ )∘˚˳° (I am the phantom remnant of #97770)
|
||||
#[expect(dead_code)]
|
||||
owner: Lrc<dyn sync::Send + sync::Sync>,
|
||||
owner: Arc<dyn sync::Send + sync::Sync>,
|
||||
}
|
||||
|
||||
/// Makes an [`OwnedSlice`] out of an `owner` and a `slicer` function.
|
||||
|
|
@ -86,7 +86,7 @@ where
|
|||
// N.B. the HRTB on the `slicer` is important — without it the caller could provide
|
||||
// a short lived slice, unrelated to the owner.
|
||||
|
||||
let owner = Lrc::new(owner);
|
||||
let owner = Arc::new(owner);
|
||||
let bytes = slicer(&*owner)?;
|
||||
|
||||
Ok(OwnedSlice { bytes, owner })
|
||||
|
|
|
|||
|
|
@ -17,6 +17,18 @@ const STACK_PER_RECURSION: usize = 16 * 1024 * 1024; // 16MB
|
|||
///
|
||||
/// Should not be sprinkled around carelessly, as it causes a little bit of overhead.
|
||||
#[inline]
|
||||
#[cfg(not(miri))]
|
||||
pub fn ensure_sufficient_stack<R>(f: impl FnOnce() -> R) -> R {
|
||||
stacker::maybe_grow(RED_ZONE, STACK_PER_RECURSION, f)
|
||||
}
|
||||
|
||||
/// Grows the stack on demand to prevent stack overflow. Call this in strategic locations
|
||||
/// to "break up" recursive calls. E.g. almost any call to `visit_expr` or equivalent can benefit
|
||||
/// from this.
|
||||
///
|
||||
/// Should not be sprinkled around carelessly, as it causes a little bit of overhead.
|
||||
#[cfg(miri)]
|
||||
#[inline]
|
||||
pub fn ensure_sufficient_stack<R>(f: impl FnOnce() -> R) -> R {
|
||||
f()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@
|
|||
//!
|
||||
//! | Type | Serial version | Parallel version |
|
||||
//! | ----------------------- | ------------------- | ------------------------------- |
|
||||
//! | `Lrc<T>` | `rc::Rc<T>` | `sync::Arc<T>` |
|
||||
//! |` Weak<T>` | `rc::Weak<T>` | `sync::Weak<T>` |
|
||||
//! | `LRef<'a, T>` [^2] | `&'a mut T` | `&'a T` |
|
||||
//! | | | |
|
||||
|
|
@ -109,7 +108,7 @@ pub use std::marker::{Send, Sync};
|
|||
#[cfg(target_has_atomic = "64")]
|
||||
pub use std::sync::atomic::AtomicU64;
|
||||
pub use std::sync::atomic::{AtomicBool, AtomicU32, AtomicUsize};
|
||||
pub use std::sync::{Arc as Lrc, OnceLock, Weak};
|
||||
pub use std::sync::{OnceLock, Weak};
|
||||
|
||||
pub use mode::{is_dyn_thread_safe, set_dyn_thread_safe_mode};
|
||||
pub use parking_lot::{
|
||||
|
|
|
|||
|
|
@ -89,10 +89,10 @@ pub mod pretty;
|
|||
#[macro_use]
|
||||
mod print;
|
||||
mod session_diagnostics;
|
||||
#[cfg(all(unix, any(target_env = "gnu", target_os = "macos")))]
|
||||
#[cfg(all(not(miri), unix, any(target_env = "gnu", target_os = "macos")))]
|
||||
mod signal_handler;
|
||||
|
||||
#[cfg(not(all(unix, any(target_env = "gnu", target_os = "macos"))))]
|
||||
#[cfg(not(all(not(miri), unix, any(target_env = "gnu", target_os = "macos"))))]
|
||||
mod signal_handler {
|
||||
/// On platforms which don't support our signal handler's requirements,
|
||||
/// simply use the default signal handler provided by std.
|
||||
|
|
@ -1024,7 +1024,7 @@ pub fn describe_flag_categories(early_dcx: &EarlyDiagCtxt, matches: &Matches) ->
|
|||
let wall = matches.opt_strs("W");
|
||||
if wall.iter().any(|x| *x == "all") {
|
||||
print_wall_help();
|
||||
rustc_errors::FatalError.raise();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Don't handle -W help here, because we might first load additional lints.
|
||||
|
|
@ -1474,7 +1474,7 @@ pub fn init_logger(early_dcx: &EarlyDiagCtxt, cfg: rustc_log::LoggerConfig) {
|
|||
/// Install our usual `ctrlc` handler, which sets [`rustc_const_eval::CTRL_C_RECEIVED`].
|
||||
/// Making this handler optional lets tools can install a different handler, if they wish.
|
||||
pub fn install_ctrlc_handler() {
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
#[cfg(all(not(miri), not(target_family = "wasm")))]
|
||||
ctrlc::set_handler(move || {
|
||||
// Indicate that we have been signaled to stop, then give the rest of the compiler a bit of
|
||||
// time to check CTRL_C_RECEIVED and run its own shutdown logic, but after a short amount
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
use std::borrow::Cow;
|
||||
use std::error::Error;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::LazyLock;
|
||||
use std::sync::{Arc, LazyLock};
|
||||
use std::{fmt, fs, io};
|
||||
|
||||
use fluent_bundle::FluentResource;
|
||||
|
|
@ -19,7 +19,7 @@ pub use fluent_bundle::{self, FluentArgs, FluentError, FluentValue};
|
|||
use fluent_syntax::parser::ParserError;
|
||||
use icu_provider_adapters::fallback::{LocaleFallbackProvider, LocaleFallbacker};
|
||||
use intl_memoizer::concurrent::IntlLangMemoizer;
|
||||
use rustc_data_structures::sync::{IntoDynSyncSend, Lrc};
|
||||
use rustc_data_structures::sync::IntoDynSyncSend;
|
||||
use rustc_macros::{Decodable, Encodable};
|
||||
use rustc_span::Span;
|
||||
use tracing::{instrument, trace};
|
||||
|
|
@ -112,7 +112,7 @@ pub fn fluent_bundle(
|
|||
requested_locale: Option<LanguageIdentifier>,
|
||||
additional_ftl_path: Option<&Path>,
|
||||
with_directionality_markers: bool,
|
||||
) -> Result<Option<Lrc<FluentBundle>>, TranslationBundleError> {
|
||||
) -> Result<Option<Arc<FluentBundle>>, TranslationBundleError> {
|
||||
if requested_locale.is_none() && additional_ftl_path.is_none() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
|
@ -190,7 +190,7 @@ pub fn fluent_bundle(
|
|||
bundle.add_resource_overriding(resource);
|
||||
}
|
||||
|
||||
let bundle = Lrc::new(bundle);
|
||||
let bundle = Arc::new(bundle);
|
||||
Ok(Some(bundle))
|
||||
}
|
||||
|
||||
|
|
@ -205,7 +205,7 @@ fn register_functions(bundle: &mut FluentBundle) {
|
|||
|
||||
/// Type alias for the result of `fallback_fluent_bundle` - a reference-counted pointer to a lazily
|
||||
/// evaluated fluent bundle.
|
||||
pub type LazyFallbackBundle = Lrc<LazyLock<FluentBundle, impl FnOnce() -> FluentBundle>>;
|
||||
pub type LazyFallbackBundle = Arc<LazyLock<FluentBundle, impl FnOnce() -> FluentBundle>>;
|
||||
|
||||
/// Return the default `FluentBundle` with standard "en-US" diagnostic messages.
|
||||
#[instrument(level = "trace", skip(resources))]
|
||||
|
|
@ -213,7 +213,7 @@ pub fn fallback_fluent_bundle(
|
|||
resources: Vec<&'static str>,
|
||||
with_directionality_markers: bool,
|
||||
) -> LazyFallbackBundle {
|
||||
Lrc::new(LazyLock::new(move || {
|
||||
Arc::new(LazyLock::new(move || {
|
||||
let mut fallback_bundle = new_bundle(vec![langid!("en-US")]);
|
||||
|
||||
register_functions(&mut fallback_bundle);
|
||||
|
|
|
|||
|
|
@ -5,8 +5,9 @@
|
|||
//!
|
||||
//! [annotate_snippets]: https://docs.rs/crate/annotate-snippets/
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use annotate_snippets::{Renderer, Snippet};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_error_messages::FluentArgs;
|
||||
use rustc_span::SourceFile;
|
||||
use rustc_span::source_map::SourceMap;
|
||||
|
|
@ -22,8 +23,8 @@ use crate::{
|
|||
|
||||
/// Generates diagnostics using annotate-snippet
|
||||
pub struct AnnotateSnippetEmitter {
|
||||
source_map: Option<Lrc<SourceMap>>,
|
||||
fluent_bundle: Option<Lrc<FluentBundle>>,
|
||||
source_map: Option<Arc<SourceMap>>,
|
||||
fluent_bundle: Option<Arc<FluentBundle>>,
|
||||
fallback_bundle: LazyFallbackBundle,
|
||||
|
||||
/// If true, hides the longer explanation text
|
||||
|
|
@ -80,7 +81,7 @@ impl Emitter for AnnotateSnippetEmitter {
|
|||
}
|
||||
|
||||
/// Provides the source string for the given `line` of `file`
|
||||
fn source_string(file: Lrc<SourceFile>, line: &Line) -> String {
|
||||
fn source_string(file: Arc<SourceFile>, line: &Line) -> String {
|
||||
file.get_line(line.line_index - 1).map(|a| a.to_string()).unwrap_or_default()
|
||||
}
|
||||
|
||||
|
|
@ -102,8 +103,8 @@ fn annotation_level_for_level(level: Level) -> annotate_snippets::Level {
|
|||
|
||||
impl AnnotateSnippetEmitter {
|
||||
pub fn new(
|
||||
source_map: Option<Lrc<SourceMap>>,
|
||||
fluent_bundle: Option<Lrc<FluentBundle>>,
|
||||
source_map: Option<Arc<SourceMap>>,
|
||||
fluent_bundle: Option<Arc<FluentBundle>>,
|
||||
fallback_bundle: LazyFallbackBundle,
|
||||
short_message: bool,
|
||||
macro_backtrace: bool,
|
||||
|
|
@ -174,7 +175,7 @@ impl AnnotateSnippetEmitter {
|
|||
source_map.ensure_source_file_source_present(&file);
|
||||
(
|
||||
format!("{}", source_map.filename_for_diagnostics(&file.name)),
|
||||
source_string(Lrc::clone(&file), &line),
|
||||
source_string(Arc::clone(&file), &line),
|
||||
line.line_index,
|
||||
line.annotations,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -14,10 +14,11 @@ use std::io::prelude::*;
|
|||
use std::io::{self, IsTerminal};
|
||||
use std::iter;
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
|
||||
use derive_setters::Setters;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
|
||||
use rustc_data_structures::sync::{DynSend, IntoDynSyncSend, Lrc};
|
||||
use rustc_data_structures::sync::{DynSend, IntoDynSyncSend};
|
||||
use rustc_error_messages::{FluentArgs, SpanLabel};
|
||||
use rustc_lexer;
|
||||
use rustc_lint_defs::pluralize;
|
||||
|
|
@ -610,8 +611,8 @@ pub enum OutputTheme {
|
|||
pub struct HumanEmitter {
|
||||
#[setters(skip)]
|
||||
dst: IntoDynSyncSend<Destination>,
|
||||
sm: Option<Lrc<SourceMap>>,
|
||||
fluent_bundle: Option<Lrc<FluentBundle>>,
|
||||
sm: Option<Arc<SourceMap>>,
|
||||
fluent_bundle: Option<Arc<FluentBundle>>,
|
||||
#[setters(skip)]
|
||||
fallback_bundle: LazyFallbackBundle,
|
||||
short_message: bool,
|
||||
|
|
@ -628,7 +629,7 @@ pub struct HumanEmitter {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct FileWithAnnotatedLines {
|
||||
pub(crate) file: Lrc<SourceFile>,
|
||||
pub(crate) file: Arc<SourceFile>,
|
||||
pub(crate) lines: Vec<Line>,
|
||||
multiline_depth: usize,
|
||||
}
|
||||
|
|
@ -712,7 +713,7 @@ impl HumanEmitter {
|
|||
fn render_source_line(
|
||||
&self,
|
||||
buffer: &mut StyledBuffer,
|
||||
file: Lrc<SourceFile>,
|
||||
file: Arc<SourceFile>,
|
||||
line: &Line,
|
||||
width_offset: usize,
|
||||
code_offset: usize,
|
||||
|
|
@ -1691,7 +1692,7 @@ impl HumanEmitter {
|
|||
// Get the left-side margin to remove it
|
||||
let mut whitespace_margin = usize::MAX;
|
||||
for line_idx in 0..annotated_file.lines.len() {
|
||||
let file = Lrc::clone(&annotated_file.file);
|
||||
let file = Arc::clone(&annotated_file.file);
|
||||
let line = &annotated_file.lines[line_idx];
|
||||
if let Some(source_string) =
|
||||
line.line_index.checked_sub(1).and_then(|l| file.get_line(l))
|
||||
|
|
@ -1764,7 +1765,7 @@ impl HumanEmitter {
|
|||
|
||||
let column_width = if let Some(width) = self.diagnostic_width {
|
||||
width.saturating_sub(code_offset)
|
||||
} else if self.ui_testing {
|
||||
} else if self.ui_testing || cfg!(miri) {
|
||||
DEFAULT_COLUMN_WIDTH
|
||||
} else {
|
||||
termize::dimensions()
|
||||
|
|
@ -1787,7 +1788,7 @@ impl HumanEmitter {
|
|||
|
||||
let depths = self.render_source_line(
|
||||
&mut buffer,
|
||||
Lrc::clone(&annotated_file.file),
|
||||
Arc::clone(&annotated_file.file),
|
||||
&annotated_file.lines[line_idx],
|
||||
width_offset,
|
||||
code_offset,
|
||||
|
|
@ -2976,7 +2977,7 @@ impl FileWithAnnotatedLines {
|
|||
) -> Vec<FileWithAnnotatedLines> {
|
||||
fn add_annotation_to_file(
|
||||
file_vec: &mut Vec<FileWithAnnotatedLines>,
|
||||
file: Lrc<SourceFile>,
|
||||
file: Arc<SourceFile>,
|
||||
line_index: usize,
|
||||
ann: Annotation,
|
||||
) {
|
||||
|
|
@ -3113,7 +3114,7 @@ impl FileWithAnnotatedLines {
|
|||
// | baz
|
||||
add_annotation_to_file(
|
||||
&mut output,
|
||||
Lrc::clone(&file),
|
||||
Arc::clone(&file),
|
||||
ann.line_start,
|
||||
ann.as_start(),
|
||||
);
|
||||
|
|
@ -3140,12 +3141,12 @@ impl FileWithAnnotatedLines {
|
|||
.unwrap_or(ann.line_start);
|
||||
for line in ann.line_start + 1..until {
|
||||
// Every `|` that joins the beginning of the span (`___^`) to the end (`|__^`).
|
||||
add_annotation_to_file(&mut output, Lrc::clone(&file), line, ann.as_line());
|
||||
add_annotation_to_file(&mut output, Arc::clone(&file), line, ann.as_line());
|
||||
}
|
||||
let line_end = ann.line_end - 1;
|
||||
let end_is_empty = file.get_line(line_end - 1).is_some_and(|s| !filter(&s));
|
||||
if middle < line_end && !end_is_empty {
|
||||
add_annotation_to_file(&mut output, Lrc::clone(&file), line_end, ann.as_line());
|
||||
add_annotation_to_file(&mut output, Arc::clone(&file), line_end, ann.as_line());
|
||||
}
|
||||
} else {
|
||||
end_ann.annotation_type = AnnotationType::Singleline;
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ use std::sync::{Arc, Mutex};
|
|||
use std::vec;
|
||||
|
||||
use derive_setters::Setters;
|
||||
use rustc_data_structures::sync::{IntoDynSyncSend, Lrc};
|
||||
use rustc_data_structures::sync::IntoDynSyncSend;
|
||||
use rustc_error_messages::FluentArgs;
|
||||
use rustc_lint_defs::Applicability;
|
||||
use rustc_span::Span;
|
||||
|
|
@ -45,8 +45,8 @@ pub struct JsonEmitter {
|
|||
#[setters(skip)]
|
||||
dst: IntoDynSyncSend<Box<dyn Write + Send>>,
|
||||
#[setters(skip)]
|
||||
sm: Option<Lrc<SourceMap>>,
|
||||
fluent_bundle: Option<Lrc<FluentBundle>>,
|
||||
sm: Option<Arc<SourceMap>>,
|
||||
fluent_bundle: Option<Arc<FluentBundle>>,
|
||||
#[setters(skip)]
|
||||
fallback_bundle: LazyFallbackBundle,
|
||||
#[setters(skip)]
|
||||
|
|
@ -65,7 +65,7 @@ pub struct JsonEmitter {
|
|||
impl JsonEmitter {
|
||||
pub fn new(
|
||||
dst: Box<dyn Write + Send>,
|
||||
sm: Option<Lrc<SourceMap>>,
|
||||
sm: Option<Arc<SourceMap>>,
|
||||
fallback_bundle: LazyFallbackBundle,
|
||||
pretty: bool,
|
||||
json_rendered: HumanReadableErrorType,
|
||||
|
|
@ -369,7 +369,7 @@ impl Diagnostic {
|
|||
ColorConfig::Always | ColorConfig::Auto => dst = Box::new(termcolor::Ansi::new(dst)),
|
||||
ColorConfig::Never => {}
|
||||
}
|
||||
HumanEmitter::new(dst, Lrc::clone(&je.fallback_bundle))
|
||||
HumanEmitter::new(dst, Arc::clone(&je.fallback_bundle))
|
||||
.short_message(short)
|
||||
.sm(je.sm.clone())
|
||||
.fluent_bundle(je.fluent_bundle.clone())
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ impl<T: Write> Write for Shared<T> {
|
|||
/// Test the span yields correct positions in JSON.
|
||||
fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) {
|
||||
rustc_span::create_default_session_globals_then(|| {
|
||||
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
||||
let sm = Arc::new(SourceMap::new(FilePathMapping::empty()));
|
||||
sm.new_source_file(Path::new("test.rs").to_owned().into(), code.to_owned());
|
||||
let fallback_bundle =
|
||||
crate::fallback_fluent_bundle(vec![crate::DEFAULT_LOCALE_RESOURCE], false);
|
||||
|
|
|
|||
|
|
@ -1048,8 +1048,8 @@ impl<'a> DiagCtxtHandle<'a> {
|
|||
/// bad results, such as spurious/uninteresting additional errors -- when
|
||||
/// returning an error `Result` is difficult.
|
||||
pub fn abort_if_errors(&self) {
|
||||
if self.has_errors().is_some() {
|
||||
FatalError.raise();
|
||||
if let Some(guar) = self.has_errors() {
|
||||
guar.raise_fatal();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use std::iter;
|
|||
use std::path::Component::Prefix;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
use rustc_ast::attr::{AttributeExt, MarkedAttrs};
|
||||
use rustc_ast::ptr::P;
|
||||
|
|
@ -12,7 +13,7 @@ use rustc_ast::visit::{AssocCtxt, Visitor};
|
|||
use rustc_ast::{self as ast, AttrVec, Attribute, HasAttrs, Item, NodeId, PatKind};
|
||||
use rustc_attr_parsing::{self as attr, Deprecation, Stability};
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_data_structures::sync::{self, Lrc};
|
||||
use rustc_data_structures::sync;
|
||||
use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed, PResult};
|
||||
use rustc_feature::Features;
|
||||
use rustc_lint_defs::{BufferedEarlyLint, RegisteredTools};
|
||||
|
|
@ -727,7 +728,7 @@ pub struct SyntaxExtension {
|
|||
/// Span of the macro definition.
|
||||
pub span: Span,
|
||||
/// List of unstable features that are treated as stable inside this macro.
|
||||
pub allow_internal_unstable: Option<Lrc<[Symbol]>>,
|
||||
pub allow_internal_unstable: Option<Arc<[Symbol]>>,
|
||||
/// The macro's stability info.
|
||||
pub stability: Option<Stability>,
|
||||
/// The macro's deprecation info.
|
||||
|
|
@ -986,7 +987,7 @@ pub struct Indeterminate;
|
|||
pub struct DeriveResolution {
|
||||
pub path: ast::Path,
|
||||
pub item: Annotatable,
|
||||
pub exts: Option<Lrc<SyntaxExtension>>,
|
||||
pub exts: Option<Arc<SyntaxExtension>>,
|
||||
pub is_const: bool,
|
||||
}
|
||||
|
||||
|
|
@ -1017,7 +1018,7 @@ pub trait ResolverExpand {
|
|||
invoc: &Invocation,
|
||||
eager_expansion_root: LocalExpnId,
|
||||
force: bool,
|
||||
) -> Result<Lrc<SyntaxExtension>, Indeterminate>;
|
||||
) -> Result<Arc<SyntaxExtension>, Indeterminate>;
|
||||
|
||||
fn record_macro_rule_usage(&mut self, mac_id: NodeId, rule_index: usize);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use std::ops::Deref;
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use std::{iter, mem};
|
||||
|
||||
use rustc_ast as ast;
|
||||
|
|
@ -16,7 +17,6 @@ use rustc_ast::{
|
|||
};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::PResult;
|
||||
use rustc_feature::Features;
|
||||
use rustc_parse::parser::{
|
||||
|
|
@ -579,7 +579,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
&mut self,
|
||||
mut fragment: AstFragment,
|
||||
extra_placeholders: &[NodeId],
|
||||
) -> (AstFragment, Vec<(Invocation, Option<Lrc<SyntaxExtension>>)>) {
|
||||
) -> (AstFragment, Vec<(Invocation, Option<Arc<SyntaxExtension>>)>) {
|
||||
// Resolve `$crate`s in the fragment for pretty-printing.
|
||||
self.cx.resolver.resolve_dollar_crates();
|
||||
|
||||
|
|
@ -1774,7 +1774,7 @@ fn build_single_delegations<'a, Node: InvocationCollectorNode>(
|
|||
|
||||
struct InvocationCollector<'a, 'b> {
|
||||
cx: &'a mut ExtCtxt<'b>,
|
||||
invocations: Vec<(Invocation, Option<Lrc<SyntaxExtension>>)>,
|
||||
invocations: Vec<(Invocation, Option<Arc<SyntaxExtension>>)>,
|
||||
monotonic: bool,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
use std::mem;
|
||||
use std::sync::Arc;
|
||||
|
||||
use rustc_ast::ExprKind;
|
||||
use rustc_ast::mut_visit::{self, MutVisitor};
|
||||
use rustc_ast::token::{self, Delimiter, IdentIsRaw, Lit, LitKind, Nonterminal, Token, TokenKind};
|
||||
use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::{Diag, DiagCtxtHandle, PResult, pluralize};
|
||||
use rustc_parse::lexer::nfc_normalize;
|
||||
use rustc_parse::parser::ParseNtResult;
|
||||
|
|
@ -299,7 +299,7 @@ pub(super) fn transcribe<'a>(
|
|||
marker.visit_span(&mut sp);
|
||||
let use_span = nt.use_span();
|
||||
with_metavar_spans(|mspans| mspans.insert(use_span, sp));
|
||||
TokenTree::token_alone(token::Interpolated(Lrc::clone(nt)), sp)
|
||||
TokenTree::token_alone(token::Interpolated(Arc::clone(nt)), sp)
|
||||
}
|
||||
MatchedSeq(..) => {
|
||||
// We were unable to descend far enough. This is an error.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use std::ops::{Bound, Range};
|
||||
use std::sync::Arc;
|
||||
|
||||
use ast::token::IdentIsRaw;
|
||||
use pm::bridge::{
|
||||
|
|
@ -11,7 +12,6 @@ use rustc_ast::tokenstream::{self, DelimSpacing, Spacing, TokenStream};
|
|||
use rustc_ast::util::literal::escape_byte_str_symbol;
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::{Diag, ErrorGuaranteed, MultiSpan, PResult};
|
||||
use rustc_parse::lexer::nfc_normalize;
|
||||
use rustc_parse::parser::Parser;
|
||||
|
|
@ -446,7 +446,7 @@ impl<'a, 'b> Rustc<'a, 'b> {
|
|||
impl server::Types for Rustc<'_, '_> {
|
||||
type FreeFunctions = FreeFunctions;
|
||||
type TokenStream = TokenStream;
|
||||
type SourceFile = Lrc<SourceFile>;
|
||||
type SourceFile = Arc<SourceFile>;
|
||||
type Span = Span;
|
||||
type Symbol = Symbol;
|
||||
}
|
||||
|
|
@ -657,7 +657,7 @@ impl server::TokenStream for Rustc<'_, '_> {
|
|||
|
||||
impl server::SourceFile for Rustc<'_, '_> {
|
||||
fn eq(&mut self, file1: &Self::SourceFile, file2: &Self::SourceFile) -> bool {
|
||||
Lrc::ptr_eq(file1, file2)
|
||||
Arc::ptr_eq(file1, file2)
|
||||
}
|
||||
|
||||
fn path(&mut self, file: &Self::SourceFile) -> String {
|
||||
|
|
|
|||
|
|
@ -206,7 +206,7 @@ pub type UsePath<'hir> = Path<'hir, SmallVec<[Res; 3]>>;
|
|||
|
||||
impl Path<'_> {
|
||||
pub fn is_global(&self) -> bool {
|
||||
!self.segments.is_empty() && self.segments[0].ident.name == kw::PathRoot
|
||||
self.segments.first().is_some_and(|segment| segment.ident.name == kw::PathRoot)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1061,10 +1061,7 @@ impl Attribute {
|
|||
|
||||
pub fn value_lit(&self) -> Option<&MetaItemLit> {
|
||||
match &self.kind {
|
||||
AttrKind::Normal(n) => match n.as_ref() {
|
||||
AttrItem { args: AttrArgs::Eq { expr, .. }, .. } => Some(expr),
|
||||
_ => None,
|
||||
},
|
||||
AttrKind::Normal(box AttrItem { args: AttrArgs::Eq { expr, .. }, .. }) => Some(expr),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -1077,12 +1074,9 @@ impl AttributeExt for Attribute {
|
|||
|
||||
fn meta_item_list(&self) -> Option<ThinVec<ast::MetaItemInner>> {
|
||||
match &self.kind {
|
||||
AttrKind::Normal(n) => match n.as_ref() {
|
||||
AttrItem { args: AttrArgs::Delimited(d), .. } => {
|
||||
ast::MetaItemKind::list_from_tokens(d.tokens.clone())
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
AttrKind::Normal(box AttrItem { args: AttrArgs::Delimited(d), .. }) => {
|
||||
ast::MetaItemKind::list_from_tokens(d.tokens.clone())
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -1098,23 +1092,16 @@ impl AttributeExt for Attribute {
|
|||
/// For a single-segment attribute, returns its name; otherwise, returns `None`.
|
||||
fn ident(&self) -> Option<Ident> {
|
||||
match &self.kind {
|
||||
AttrKind::Normal(n) => {
|
||||
if let [ident] = n.path.segments.as_ref() {
|
||||
Some(*ident)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
AttrKind::DocComment(..) => None,
|
||||
AttrKind::Normal(box AttrItem {
|
||||
path: AttrPath { segments: box [ident], .. }, ..
|
||||
}) => Some(*ident),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn path_matches(&self, name: &[Symbol]) -> bool {
|
||||
match &self.kind {
|
||||
AttrKind::Normal(n) => {
|
||||
n.path.segments.len() == name.len()
|
||||
&& n.path.segments.iter().zip(name).all(|(s, n)| s.name == *n)
|
||||
}
|
||||
AttrKind::Normal(n) => n.path.segments.iter().map(|segment| &segment.name).eq(name),
|
||||
AttrKind::DocComment(..) => false,
|
||||
}
|
||||
}
|
||||
|
|
@ -1128,12 +1115,7 @@ impl AttributeExt for Attribute {
|
|||
}
|
||||
|
||||
fn is_word(&self) -> bool {
|
||||
match &self.kind {
|
||||
AttrKind::Normal(n) => {
|
||||
matches!(n.args, AttrArgs::Empty)
|
||||
}
|
||||
AttrKind::DocComment(..) => false,
|
||||
}
|
||||
matches!(self.kind, AttrKind::Normal(box AttrItem { args: AttrArgs::Empty, .. }))
|
||||
}
|
||||
|
||||
fn ident_path(&self) -> Option<SmallVec<[Ident; 1]>> {
|
||||
|
|
@ -1990,7 +1972,7 @@ impl fmt::Display for ConstContext {
|
|||
}
|
||||
|
||||
// NOTE: `IntoDiagArg` impl for `ConstContext` lives in `rustc_errors`
|
||||
// due to a cyclical dependency between hir that crate.
|
||||
// due to a cyclical dependency between hir and that crate.
|
||||
|
||||
/// A literal.
|
||||
pub type Lit = Spanned<LitKind>;
|
||||
|
|
@ -3604,10 +3586,10 @@ impl<'hir> FnRetTy<'hir> {
|
|||
}
|
||||
|
||||
pub fn is_suggestable_infer_ty(&self) -> Option<&'hir Ty<'hir>> {
|
||||
if let Self::Return(ty) = self {
|
||||
if ty.is_suggestable_infer_ty() {
|
||||
return Some(*ty);
|
||||
}
|
||||
if let Self::Return(ty) = self
|
||||
&& ty.is_suggestable_infer_ty()
|
||||
{
|
||||
return Some(*ty);
|
||||
}
|
||||
None
|
||||
}
|
||||
|
|
@ -3976,11 +3958,11 @@ pub struct FnHeader {
|
|||
|
||||
impl FnHeader {
|
||||
pub fn is_async(&self) -> bool {
|
||||
matches!(&self.asyncness, IsAsync::Async(_))
|
||||
matches!(self.asyncness, IsAsync::Async(_))
|
||||
}
|
||||
|
||||
pub fn is_const(&self) -> bool {
|
||||
matches!(&self.constness, Constness::Const)
|
||||
matches!(self.constness, Constness::Const)
|
||||
}
|
||||
|
||||
pub fn is_unsafe(&self) -> bool {
|
||||
|
|
@ -4076,16 +4058,16 @@ pub struct Impl<'hir> {
|
|||
|
||||
impl ItemKind<'_> {
|
||||
pub fn generics(&self) -> Option<&Generics<'_>> {
|
||||
Some(match *self {
|
||||
ItemKind::Fn { ref generics, .. }
|
||||
| ItemKind::TyAlias(_, ref generics)
|
||||
| ItemKind::Const(_, ref generics, _)
|
||||
| ItemKind::Enum(_, ref generics)
|
||||
| ItemKind::Struct(_, ref generics)
|
||||
| ItemKind::Union(_, ref generics)
|
||||
| ItemKind::Trait(_, _, ref generics, _, _)
|
||||
| ItemKind::TraitAlias(ref generics, _)
|
||||
| ItemKind::Impl(Impl { ref generics, .. }) => generics,
|
||||
Some(match self {
|
||||
ItemKind::Fn { generics, .. }
|
||||
| ItemKind::TyAlias(_, generics)
|
||||
| ItemKind::Const(_, generics, _)
|
||||
| ItemKind::Enum(_, generics)
|
||||
| ItemKind::Struct(_, generics)
|
||||
| ItemKind::Union(_, generics)
|
||||
| ItemKind::Trait(_, _, generics, _, _)
|
||||
| ItemKind::TraitAlias(generics, _)
|
||||
| ItemKind::Impl(Impl { generics, .. }) => generics,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
|
@ -4484,16 +4466,14 @@ impl<'hir> Node<'hir> {
|
|||
|
||||
/// Get a `hir::Impl` if the node is an impl block for the given `trait_def_id`.
|
||||
pub fn impl_block_of_trait(self, trait_def_id: DefId) -> Option<&'hir Impl<'hir>> {
|
||||
match self {
|
||||
Node::Item(Item { kind: ItemKind::Impl(impl_block), .. })
|
||||
if impl_block
|
||||
.of_trait
|
||||
.and_then(|trait_ref| trait_ref.trait_def_id())
|
||||
.is_some_and(|trait_id| trait_id == trait_def_id) =>
|
||||
{
|
||||
Some(impl_block)
|
||||
}
|
||||
_ => None,
|
||||
if let Node::Item(Item { kind: ItemKind::Impl(impl_block), .. }) = self
|
||||
&& let Some(trait_ref) = impl_block.of_trait
|
||||
&& let Some(trait_id) = trait_ref.trait_def_id()
|
||||
&& trait_id == trait_def_id
|
||||
{
|
||||
Some(impl_block)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -345,6 +345,9 @@ pub trait Visitor<'v>: Sized {
|
|||
fn visit_pat_expr(&mut self, expr: &'v PatExpr<'v>) -> Self::Result {
|
||||
walk_pat_expr(self, expr)
|
||||
}
|
||||
fn visit_lit(&mut self, _hir_id: HirId, _lit: &'v Lit, _negated: bool) -> Self::Result {
|
||||
Self::Result::output()
|
||||
}
|
||||
fn visit_anon_const(&mut self, c: &'v AnonConst) -> Self::Result {
|
||||
walk_anon_const(self, c)
|
||||
}
|
||||
|
|
@ -764,7 +767,7 @@ pub fn walk_pat_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v PatField<'
|
|||
pub fn walk_pat_expr<'v, V: Visitor<'v>>(visitor: &mut V, expr: &'v PatExpr<'v>) -> V::Result {
|
||||
try_visit!(visitor.visit_id(expr.hir_id));
|
||||
match &expr.kind {
|
||||
PatExprKind::Lit { .. } => V::Result::output(),
|
||||
PatExprKind::Lit { lit, negated } => visitor.visit_lit(expr.hir_id, lit, *negated),
|
||||
PatExprKind::ConstBlock(c) => visitor.visit_inline_const(c),
|
||||
PatExprKind::Path(qpath) => visitor.visit_qpath(qpath, expr.hir_id, expr.span),
|
||||
}
|
||||
|
|
@ -912,7 +915,8 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
|
|||
try_visit!(visitor.visit_expr(expr));
|
||||
visit_opt!(visitor, visit_ty_unambig, ty);
|
||||
}
|
||||
ExprKind::Lit(_) | ExprKind::Err(_) => {}
|
||||
ExprKind::Lit(lit) => try_visit!(visitor.visit_lit(expression.hir_id, lit, false)),
|
||||
ExprKind::Err(_) => {}
|
||||
}
|
||||
V::Result::output()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![feature(associated_type_defaults)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(closure_track_caller)]
|
||||
#![feature(debug_closure_helpers)]
|
||||
#![feature(exhaustive_patterns)]
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ use rustc_middle::span_bug;
|
|||
use rustc_middle::ty::error::TypeErrorToStringExt;
|
||||
use rustc_middle::ty::fold::{BottomUpFolder, fold_regions};
|
||||
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
|
||||
use rustc_middle::ty::util::{Discr, InspectCoroutineFields, IntTypeExt};
|
||||
use rustc_middle::ty::util::{Discr, IntTypeExt};
|
||||
use rustc_middle::ty::{
|
||||
AdtDef, GenericArgKind, RegionKind, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
|
||||
};
|
||||
|
|
@ -257,30 +257,9 @@ pub(super) fn check_opaque_for_cycles<'tcx>(
|
|||
|
||||
// First, try to look at any opaque expansion cycles, considering coroutine fields
|
||||
// (even though these aren't necessarily true errors).
|
||||
if tcx
|
||||
.try_expand_impl_trait_type(def_id.to_def_id(), args, InspectCoroutineFields::Yes)
|
||||
.is_err()
|
||||
{
|
||||
// Look for true opaque expansion cycles, but ignore coroutines.
|
||||
// This will give us any true errors. Coroutines are only problematic
|
||||
// if they cause layout computation errors.
|
||||
if tcx
|
||||
.try_expand_impl_trait_type(def_id.to_def_id(), args, InspectCoroutineFields::No)
|
||||
.is_err()
|
||||
{
|
||||
let reported = opaque_type_cycle_error(tcx, def_id);
|
||||
return Err(reported);
|
||||
}
|
||||
|
||||
// And also look for cycle errors in the layout of coroutines.
|
||||
if let Err(&LayoutError::Cycle(guar)) =
|
||||
tcx.layout_of(
|
||||
ty::TypingEnv::post_analysis(tcx, def_id.to_def_id())
|
||||
.as_query_input(Ty::new_opaque(tcx, def_id.to_def_id(), args)),
|
||||
)
|
||||
{
|
||||
return Err(guar);
|
||||
}
|
||||
if tcx.try_expand_impl_trait_type(def_id.to_def_id(), args).is_err() {
|
||||
let reported = opaque_type_cycle_error(tcx, def_id);
|
||||
return Err(reported);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -11,6 +11,15 @@ pub(crate) fn opaque_hidden_types(tcx: TyCtxt<'_>) {
|
|||
}
|
||||
|
||||
for id in tcx.hir_crate_items(()).opaques() {
|
||||
if let hir::OpaqueTyOrigin::FnReturn { parent: fn_def_id, .. }
|
||||
| hir::OpaqueTyOrigin::AsyncFn { parent: fn_def_id, .. } =
|
||||
tcx.hir().expect_opaque_ty(id).origin
|
||||
&& let hir::Node::TraitItem(trait_item) = tcx.hir_node_by_def_id(fn_def_id)
|
||||
&& let (_, hir::TraitFn::Required(..)) = trait_item.expect_fn()
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
let ty = tcx.type_of(id).instantiate_identity();
|
||||
let span = tcx.def_span(id);
|
||||
tcx.dcx().emit_err(crate::errors::TypeOf { span, ty });
|
||||
|
|
|
|||
|
|
@ -321,6 +321,10 @@ pub fn pat_to_string(ann: &dyn PpAnn, pat: &hir::Pat<'_>) -> String {
|
|||
to_string(ann, |s| s.print_pat(pat))
|
||||
}
|
||||
|
||||
pub fn expr_to_string(ann: &dyn PpAnn, pat: &hir::Expr<'_>) -> String {
|
||||
to_string(ann, |s| s.print_expr(pat))
|
||||
}
|
||||
|
||||
impl<'a> State<'a> {
|
||||
fn bclose_maybe_open(&mut self, span: rustc_span::Span, close_box: bool) {
|
||||
self.maybe_print_comment(span.hi());
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use std::{iter, mem};
|
||||
use std::{fmt, iter, mem};
|
||||
|
||||
use itertools::Itertools;
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
|
|
@ -13,7 +13,7 @@ use rustc_hir::{ExprKind, HirId, Node, QPath};
|
|||
use rustc_hir_analysis::check::intrinsicck::InlineAsmCtxt;
|
||||
use rustc_hir_analysis::check::potentially_plural_count;
|
||||
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
|
||||
use rustc_index::{Idx, IndexVec};
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_infer::infer::{DefineOpaqueTypes, InferOk, TypeTrace};
|
||||
use rustc_middle::ty::adjustment::AllowTwoPhase;
|
||||
use rustc_middle::ty::error::TypeError;
|
||||
|
|
@ -25,6 +25,7 @@ use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
|
|||
use rustc_trait_selection::error_reporting::infer::{FailureCode, ObligationCauseExt};
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt, SelectionContext};
|
||||
use smallvec::SmallVec;
|
||||
use tracing::debug;
|
||||
use {rustc_ast as ast, rustc_hir as hir};
|
||||
|
||||
|
|
@ -44,6 +45,12 @@ use crate::{
|
|||
struct_span_code_err,
|
||||
};
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
#[orderable]
|
||||
#[debug_format = "GenericIdx({})"]
|
||||
pub(crate) struct GenericIdx {}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub(crate) enum DivergingBlockBehavior {
|
||||
/// This is the current stable behavior:
|
||||
|
|
@ -1619,6 +1626,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
ast::LitKind::Int(_, ast::LitIntType::Unsuffixed) => {
|
||||
let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() {
|
||||
ty::Int(_) | ty::Uint(_) => Some(ty),
|
||||
// These exist to direct casts like `0x61 as char` to use
|
||||
// the right integer type to cast from, instead of falling back to
|
||||
// i32 due to no further constraints.
|
||||
ty::Char => Some(tcx.types.u8),
|
||||
ty::RawPtr(..) => Some(tcx.types.usize),
|
||||
ty::FnDef(..) | ty::FnPtr(..) => Some(tcx.types.usize),
|
||||
|
|
@ -2288,7 +2298,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// If we're calling a method of a Fn/FnMut/FnOnce trait object implicitly
|
||||
// (eg invoking a closure) we want to point at the underlying callable,
|
||||
// not the method implicitly invoked (eg call_once).
|
||||
if let Some(assoc_item) = self.tcx.opt_associated_item(def_id)
|
||||
// TupleArguments is set only when this is an implicit call (my_closure(...)) rather than explicit (my_closure.call(...))
|
||||
if tuple_arguments == TupleArguments
|
||||
&& let Some(assoc_item) = self.tcx.opt_associated_item(def_id)
|
||||
// Since this is an associated item, it might point at either an impl or a trait item.
|
||||
// We want it to always point to the trait item.
|
||||
// If we're pointing at an inherent function, we don't need to do anything,
|
||||
|
|
@ -2298,8 +2310,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// Just an easy way to check "trait_def_id == Fn/FnMut/FnOnce"
|
||||
&& let Some(call_kind) = self.tcx.fn_trait_kind_from_def_id(maybe_trait_def_id)
|
||||
&& let Some(callee_ty) = callee_ty
|
||||
// TupleArguments is set only when this is an implicit call (my_closure(...)) rather than explicit (my_closure.call(...))
|
||||
&& tuple_arguments == TupleArguments
|
||||
{
|
||||
let callee_ty = callee_ty.peel_refs();
|
||||
match *callee_ty.kind() {
|
||||
|
|
@ -2368,174 +2378,136 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
&& !def_span.is_dummy()
|
||||
{
|
||||
let mut spans: MultiSpan = def_span.into();
|
||||
|
||||
if let Some(params_with_generics) = self.get_hir_params_with_generics(def_id, is_method)
|
||||
if let Some((params_with_generics, hir_generics)) =
|
||||
self.get_hir_param_info(def_id, is_method)
|
||||
{
|
||||
struct MismatchedParam<'a> {
|
||||
idx: ExpectedIdx,
|
||||
generic: GenericIdx,
|
||||
param: &'a FnParam<'a>,
|
||||
deps: SmallVec<[ExpectedIdx; 4]>,
|
||||
}
|
||||
|
||||
debug_assert_eq!(params_with_generics.len(), matched_inputs.len());
|
||||
|
||||
let mut generics_with_unmatched_params = Vec::new();
|
||||
|
||||
let check_for_matched_generics = || {
|
||||
if matched_inputs.iter().any(|x| x.is_some())
|
||||
&& params_with_generics.iter().any(|(x, _)| x.is_some())
|
||||
{
|
||||
for (idx, (generic, _)) in params_with_generics.iter_enumerated() {
|
||||
// Param has to have a generic and be matched to be relevant
|
||||
if matched_inputs[idx].is_none() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let Some(generic) = generic else {
|
||||
continue;
|
||||
};
|
||||
|
||||
for unmatching_idx in
|
||||
idx.plus(1)..ExpectedIdx::from_usize(params_with_generics.len())
|
||||
{
|
||||
if matched_inputs[unmatching_idx].is_none()
|
||||
&& let Some(unmatched_idx_param_generic) =
|
||||
params_with_generics[unmatching_idx].0
|
||||
&& unmatched_idx_param_generic.name.ident()
|
||||
== generic.name.ident()
|
||||
{
|
||||
// We found a parameter that didn't match that needed to
|
||||
return true;
|
||||
// Gather all mismatched parameters with generics.
|
||||
let mut mismatched_params = Vec::<MismatchedParam<'_>>::new();
|
||||
if let Some(expected_idx) = expected_idx {
|
||||
let expected_idx = ExpectedIdx::from_usize(expected_idx);
|
||||
let &(expected_generic, ref expected_param) =
|
||||
¶ms_with_generics[expected_idx];
|
||||
if let Some(expected_generic) = expected_generic {
|
||||
mismatched_params.push(MismatchedParam {
|
||||
idx: expected_idx,
|
||||
generic: expected_generic,
|
||||
param: expected_param,
|
||||
deps: SmallVec::new(),
|
||||
});
|
||||
} else {
|
||||
// Still mark the mismatched parameter
|
||||
spans.push_span_label(expected_param.span(), "");
|
||||
}
|
||||
} else {
|
||||
mismatched_params.extend(
|
||||
params_with_generics.iter_enumerated().zip(matched_inputs).filter_map(
|
||||
|((idx, &(generic, ref param)), matched_idx)| {
|
||||
if matched_idx.is_some() {
|
||||
None
|
||||
} else if let Some(generic) = generic {
|
||||
Some(MismatchedParam {
|
||||
idx,
|
||||
generic,
|
||||
param,
|
||||
deps: SmallVec::new(),
|
||||
})
|
||||
} else {
|
||||
// Still mark mismatched parameters
|
||||
spans.push_span_label(param.span(), "");
|
||||
None
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if !mismatched_params.is_empty() {
|
||||
// For each mismatched paramter, create a two-way link to each matched parameter
|
||||
// of the same type.
|
||||
let mut dependants = IndexVec::<ExpectedIdx, _>::from_fn_n(
|
||||
|_| SmallVec::<[u32; 4]>::new(),
|
||||
params_with_generics.len(),
|
||||
);
|
||||
let mut generic_uses = IndexVec::<GenericIdx, _>::from_fn_n(
|
||||
|_| SmallVec::<[ExpectedIdx; 4]>::new(),
|
||||
hir_generics.params.len(),
|
||||
);
|
||||
for (idx, param) in mismatched_params.iter_mut().enumerate() {
|
||||
for ((other_idx, &(other_generic, _)), &other_matched_idx) in
|
||||
params_with_generics.iter_enumerated().zip(matched_inputs)
|
||||
{
|
||||
if other_generic == Some(param.generic) && other_matched_idx.is_some() {
|
||||
generic_uses[param.generic].extend([param.idx, other_idx]);
|
||||
dependants[other_idx].push(idx as u32);
|
||||
param.deps.push(other_idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
};
|
||||
|
||||
let check_for_matched_generics = check_for_matched_generics();
|
||||
|
||||
for (idx, &(generic_param, param)) in
|
||||
params_with_generics.iter_enumerated().filter(|&(idx, _)| {
|
||||
check_for_matched_generics
|
||||
|| expected_idx
|
||||
.is_none_or(|expected_idx| expected_idx == idx.as_usize())
|
||||
})
|
||||
{
|
||||
let Some(generic_param) = generic_param else {
|
||||
spans.push_span_label(param.span(), "");
|
||||
continue;
|
||||
};
|
||||
|
||||
let other_params_matched: Vec<(ExpectedIdx, FnParam<'_>)> =
|
||||
params_with_generics
|
||||
.iter_enumerated()
|
||||
.filter(|&(other_idx, &(other_generic_param, _))| {
|
||||
if other_idx == idx {
|
||||
return false;
|
||||
}
|
||||
let Some(other_generic_param) = other_generic_param else {
|
||||
return false;
|
||||
};
|
||||
if matched_inputs[idx].is_none()
|
||||
&& matched_inputs[other_idx].is_none()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if matched_inputs[idx].is_some()
|
||||
&& matched_inputs[other_idx].is_some()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
other_generic_param.name.ident() == generic_param.name.ident()
|
||||
})
|
||||
.map(|(other_idx, &(_, other_param))| (other_idx, other_param))
|
||||
.collect();
|
||||
|
||||
if !other_params_matched.is_empty() {
|
||||
let other_param_matched_names: Vec<String> = other_params_matched
|
||||
.iter()
|
||||
.map(|(idx, other_param)| {
|
||||
if let Some(name) = other_param.name() {
|
||||
format!("`{name}`")
|
||||
} else {
|
||||
format!("parameter #{}", idx.as_u32() + 1)
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let matched_ty = self
|
||||
.resolve_vars_if_possible(formal_and_expected_inputs[idx].1)
|
||||
.sort_string(self.tcx);
|
||||
|
||||
if matched_inputs[idx].is_some() {
|
||||
// Highlight each mismatched type along with a note about which other parameters
|
||||
// the type depends on (if any).
|
||||
for param in &mismatched_params {
|
||||
if let Some(deps_list) = listify(¶m.deps, |&dep| {
|
||||
params_with_generics[dep].1.display(dep.as_usize()).to_string()
|
||||
}) {
|
||||
spans.push_span_label(
|
||||
param.span(),
|
||||
param.param.span(),
|
||||
format!(
|
||||
"{} need{} to match the {} type of this parameter",
|
||||
listify(&other_param_matched_names, |n| n.to_string())
|
||||
.unwrap_or_default(),
|
||||
pluralize!(if other_param_matched_names.len() == 1 {
|
||||
0
|
||||
} else {
|
||||
1
|
||||
}),
|
||||
matched_ty,
|
||||
"this parameter needs to match the {} type of {deps_list}",
|
||||
self.resolve_vars_if_possible(
|
||||
formal_and_expected_inputs[param.deps[0]].1
|
||||
)
|
||||
.sort_string(self.tcx),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
// Still mark mismatched parameters
|
||||
spans.push_span_label(param.param.span(), "");
|
||||
}
|
||||
}
|
||||
// Highligh each parameter being depended on for a generic type.
|
||||
for ((&(_, param), deps), &(_, expected_ty)) in
|
||||
params_with_generics.iter().zip(&dependants).zip(formal_and_expected_inputs)
|
||||
{
|
||||
if let Some(deps_list) = listify(deps, |&dep| {
|
||||
let param = &mismatched_params[dep as usize];
|
||||
param.param.display(param.idx.as_usize()).to_string()
|
||||
}) {
|
||||
spans.push_span_label(
|
||||
param.span(),
|
||||
format!(
|
||||
"this parameter needs to match the {} type of {}",
|
||||
matched_ty,
|
||||
listify(&other_param_matched_names, |n| n.to_string())
|
||||
.unwrap_or_default(),
|
||||
"{deps_list} need{} to match the {} type of this parameter",
|
||||
pluralize!((deps.len() != 1) as u32),
|
||||
self.resolve_vars_if_possible(expected_ty)
|
||||
.sort_string(self.tcx),
|
||||
),
|
||||
);
|
||||
}
|
||||
generics_with_unmatched_params.push(generic_param);
|
||||
} else {
|
||||
spans.push_span_label(param.span(), "");
|
||||
}
|
||||
}
|
||||
|
||||
for generic_param in self
|
||||
.tcx
|
||||
.hir()
|
||||
.get_if_local(def_id)
|
||||
.and_then(|node| node.generics())
|
||||
.into_iter()
|
||||
.flat_map(|x| x.params)
|
||||
.filter(|x| {
|
||||
generics_with_unmatched_params
|
||||
.iter()
|
||||
.any(|y| x.name.ident() == y.name.ident())
|
||||
})
|
||||
{
|
||||
let param_idents_matching: Vec<String> = params_with_generics
|
||||
.iter_enumerated()
|
||||
.filter(|&(_, &(generic, _))| {
|
||||
if let Some(generic) = generic {
|
||||
generic.name.ident() == generic_param.name.ident()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
.map(|(idx, &(_, param))| {
|
||||
if let Some(name) = param.name() {
|
||||
format!("`{name}`")
|
||||
} else {
|
||||
format!("parameter #{}", idx.as_u32() + 1)
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
if !param_idents_matching.is_empty() {
|
||||
spans.push_span_label(
|
||||
generic_param.span,
|
||||
format!(
|
||||
"{} {} reference this parameter `{}`",
|
||||
listify(¶m_idents_matching, |n| n.to_string())
|
||||
.unwrap_or_default(),
|
||||
if param_idents_matching.len() == 2 { "both" } else { "all" },
|
||||
generic_param.name.ident().name,
|
||||
),
|
||||
);
|
||||
// Highlight each generic parameter in use.
|
||||
for (param, uses) in hir_generics.params.iter().zip(&mut generic_uses) {
|
||||
uses.sort();
|
||||
uses.dedup();
|
||||
if let Some(param_list) = listify(uses, |&idx| {
|
||||
params_with_generics[idx].1.display(idx.as_usize()).to_string()
|
||||
}) {
|
||||
spans.push_span_label(
|
||||
param.span,
|
||||
format!(
|
||||
"{param_list} {} reference this parameter `{}`",
|
||||
if uses.len() == 2 { "both" } else { "all" },
|
||||
param.name.ident().name,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2611,7 +2583,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
return;
|
||||
};
|
||||
|
||||
if let Some(params_with_generics) = self.get_hir_params_with_generics(def_id, is_method) {
|
||||
if let Some((params_with_generics, _)) = self.get_hir_param_info(def_id, is_method) {
|
||||
debug_assert_eq!(params_with_generics.len(), matched_inputs.len());
|
||||
for (idx, (generic_param, _)) in params_with_generics.iter_enumerated() {
|
||||
if matched_inputs[idx].is_none() {
|
||||
|
|
@ -2639,7 +2611,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
if matched_inputs[other_idx].is_some() {
|
||||
return false;
|
||||
}
|
||||
other_generic_param.name.ident() == generic_param.name.ident()
|
||||
other_generic_param == generic_param
|
||||
})
|
||||
.count();
|
||||
|
||||
|
|
@ -2671,11 +2643,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
/// Returns the parameters of a function, with their generic parameters if those are the full
|
||||
/// type of that parameter. Returns `None` if the function has no generics or the body is
|
||||
/// unavailable (eg is an instrinsic).
|
||||
fn get_hir_params_with_generics(
|
||||
fn get_hir_param_info(
|
||||
&self,
|
||||
def_id: DefId,
|
||||
is_method: bool,
|
||||
) -> Option<IndexVec<ExpectedIdx, (Option<&hir::GenericParam<'_>>, FnParam<'_>)>> {
|
||||
) -> Option<(IndexVec<ExpectedIdx, (Option<GenericIdx>, FnParam<'_>)>, &hir::Generics<'_>)>
|
||||
{
|
||||
let (sig, generics, body_id, param_names) = match self.tcx.hir().get_if_local(def_id)? {
|
||||
hir::Node::TraitItem(&hir::TraitItem {
|
||||
generics,
|
||||
|
|
@ -2705,7 +2678,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
&hir::Path { res: Res::Def(_, res_def_id), .. },
|
||||
)) = param.kind
|
||||
{
|
||||
generics.params.iter().find(|param| param.def_id.to_def_id() == res_def_id)
|
||||
generics
|
||||
.params
|
||||
.iter()
|
||||
.position(|param| param.def_id.to_def_id() == res_def_id)
|
||||
.map(GenericIdx::from_usize)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
@ -2717,12 +2694,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let params =
|
||||
params.get(is_method as usize..params.len() - sig.decl.c_variadic as usize)?;
|
||||
debug_assert_eq!(params.len(), fn_inputs.len());
|
||||
Some(fn_inputs.zip(params.iter().map(|param| FnParam::Param(param))).collect())
|
||||
Some((
|
||||
fn_inputs.zip(params.iter().map(|param| FnParam::Param(param))).collect(),
|
||||
generics,
|
||||
))
|
||||
}
|
||||
(None, Some(params)) => {
|
||||
let params = params.get(is_method as usize..)?;
|
||||
debug_assert_eq!(params.len(), fn_inputs.len());
|
||||
Some(fn_inputs.zip(params.iter().map(|param| FnParam::Name(param))).collect())
|
||||
Some((
|
||||
fn_inputs.zip(params.iter().map(|param| FnParam::Name(param))).collect(),
|
||||
generics,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2770,4 +2753,18 @@ impl FnParam<'_> {
|
|||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn display(&self, idx: usize) -> impl '_ + fmt::Display {
|
||||
struct D<'a>(FnParam<'a>, usize);
|
||||
impl fmt::Display for D<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if let Some(name) = self.0.name() {
|
||||
write!(f, "`{name}`")
|
||||
} else {
|
||||
write!(f, "parameter #{}", self.1 + 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
D(*self, idx)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -306,6 +306,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
lang_item_for_op(self.tcx, Op::Binary(op, is_assign), op.span);
|
||||
let missing_trait = trait_def_id
|
||||
.map(|def_id| with_no_trimmed_paths!(self.tcx.def_path_str(def_id)));
|
||||
let mut path = None;
|
||||
let lhs_ty_str = self.tcx.short_string(lhs_ty, &mut path);
|
||||
let rhs_ty_str = self.tcx.short_string(rhs_ty, &mut path);
|
||||
let (mut err, output_def_id) = match is_assign {
|
||||
IsAssign::Yes => {
|
||||
let mut err = struct_span_code_err!(
|
||||
|
|
@ -314,11 +317,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
E0368,
|
||||
"binary assignment operation `{}=` cannot be applied to type `{}`",
|
||||
op.node.as_str(),
|
||||
lhs_ty,
|
||||
lhs_ty_str,
|
||||
);
|
||||
err.span_label(
|
||||
lhs_expr.span,
|
||||
format!("cannot use `{}=` on type `{}`", op.node.as_str(), lhs_ty),
|
||||
format!("cannot use `{}=` on type `{}`", op.node.as_str(), lhs_ty_str),
|
||||
);
|
||||
self.note_unmet_impls_on_type(&mut err, errors, false);
|
||||
(err, None)
|
||||
|
|
@ -326,41 +329,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
IsAssign::No => {
|
||||
let message = match op.node {
|
||||
hir::BinOpKind::Add => {
|
||||
format!("cannot add `{rhs_ty}` to `{lhs_ty}`")
|
||||
format!("cannot add `{rhs_ty_str}` to `{lhs_ty_str}`")
|
||||
}
|
||||
hir::BinOpKind::Sub => {
|
||||
format!("cannot subtract `{rhs_ty}` from `{lhs_ty}`")
|
||||
format!("cannot subtract `{rhs_ty_str}` from `{lhs_ty_str}`")
|
||||
}
|
||||
hir::BinOpKind::Mul => {
|
||||
format!("cannot multiply `{lhs_ty}` by `{rhs_ty}`")
|
||||
format!("cannot multiply `{lhs_ty_str}` by `{rhs_ty_str}`")
|
||||
}
|
||||
hir::BinOpKind::Div => {
|
||||
format!("cannot divide `{lhs_ty}` by `{rhs_ty}`")
|
||||
format!("cannot divide `{lhs_ty_str}` by `{rhs_ty_str}`")
|
||||
}
|
||||
hir::BinOpKind::Rem => {
|
||||
format!(
|
||||
"cannot calculate the remainder of `{lhs_ty}` divided by `{rhs_ty}`"
|
||||
"cannot calculate the remainder of `{lhs_ty_str}` divided by \
|
||||
`{rhs_ty_str}`"
|
||||
)
|
||||
}
|
||||
hir::BinOpKind::BitAnd => {
|
||||
format!("no implementation for `{lhs_ty} & {rhs_ty}`")
|
||||
format!("no implementation for `{lhs_ty_str} & {rhs_ty_str}`")
|
||||
}
|
||||
hir::BinOpKind::BitXor => {
|
||||
format!("no implementation for `{lhs_ty} ^ {rhs_ty}`")
|
||||
format!("no implementation for `{lhs_ty_str} ^ {rhs_ty_str}`")
|
||||
}
|
||||
hir::BinOpKind::BitOr => {
|
||||
format!("no implementation for `{lhs_ty} | {rhs_ty}`")
|
||||
format!("no implementation for `{lhs_ty_str} | {rhs_ty_str}`")
|
||||
}
|
||||
hir::BinOpKind::Shl => {
|
||||
format!("no implementation for `{lhs_ty} << {rhs_ty}`")
|
||||
format!("no implementation for `{lhs_ty_str} << {rhs_ty_str}`")
|
||||
}
|
||||
hir::BinOpKind::Shr => {
|
||||
format!("no implementation for `{lhs_ty} >> {rhs_ty}`")
|
||||
format!("no implementation for `{lhs_ty_str} >> {rhs_ty_str}`")
|
||||
}
|
||||
_ => format!(
|
||||
"binary operation `{}` cannot be applied to type `{}`",
|
||||
op.node.as_str(),
|
||||
lhs_ty
|
||||
lhs_ty_str,
|
||||
),
|
||||
};
|
||||
let output_def_id = trait_def_id.and_then(|def_id| {
|
||||
|
|
@ -375,14 +379,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let mut err =
|
||||
struct_span_code_err!(self.dcx(), op.span, E0369, "{message}");
|
||||
if !lhs_expr.span.eq(&rhs_expr.span) {
|
||||
err.span_label(lhs_expr.span, lhs_ty.to_string());
|
||||
err.span_label(rhs_expr.span, rhs_ty.to_string());
|
||||
err.span_label(lhs_expr.span, lhs_ty_str.clone());
|
||||
err.span_label(rhs_expr.span, rhs_ty_str);
|
||||
}
|
||||
let suggest_derive = self.can_eq(self.param_env, lhs_ty, rhs_ty);
|
||||
self.note_unmet_impls_on_type(&mut err, errors, suggest_derive);
|
||||
(err, output_def_id)
|
||||
}
|
||||
};
|
||||
*err.long_ty_path() = path;
|
||||
|
||||
// Try to suggest a semicolon if it's `A \n *B` where `B` is a place expr
|
||||
let maybe_missing_semi = self.check_for_missing_semi(expr, &mut err);
|
||||
|
|
@ -417,7 +422,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
IsAssign::Yes => "=",
|
||||
IsAssign::No => "",
|
||||
},
|
||||
lhs_deref_ty,
|
||||
self.tcx.short_string(lhs_deref_ty, err.long_ty_path()),
|
||||
);
|
||||
err.span_suggestion_verbose(
|
||||
lhs_expr.span.shrink_to_lo(),
|
||||
|
|
@ -443,8 +448,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
)
|
||||
.is_ok()
|
||||
{
|
||||
let op_str = op.node.as_str();
|
||||
err.note(format!("an implementation for `{lhs_adjusted_ty} {op_str} {rhs_adjusted_ty}` exists"));
|
||||
let lhs = self.tcx.short_string(lhs_adjusted_ty, err.long_ty_path());
|
||||
let rhs = self.tcx.short_string(rhs_adjusted_ty, err.long_ty_path());
|
||||
let op = op.node.as_str();
|
||||
err.note(format!("an implementation for `{lhs} {op} {rhs}` exists"));
|
||||
|
||||
if let Some(lhs_new_mutbl) = lhs_new_mutbl
|
||||
&& let Some(rhs_new_mutbl) = rhs_new_mutbl
|
||||
|
|
@ -628,7 +635,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// When we know that a missing bound is responsible, we don't show
|
||||
// this note as it is redundant.
|
||||
err.note(format!(
|
||||
"the trait `{missing_trait}` is not implemented for `{lhs_ty}`"
|
||||
"the trait `{missing_trait}` is not implemented for `{lhs_ty_str}`"
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
@ -654,24 +661,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
hir::BinOpKind::Sub => {
|
||||
if lhs_ty.is_unsafe_ptr() && rhs_ty.is_integral() {
|
||||
err.multipart_suggestion(
|
||||
"consider using `wrapping_sub` or `sub` for pointer - {integer}",
|
||||
"consider using `wrapping_sub` or `sub` for \
|
||||
pointer - {integer}",
|
||||
vec![
|
||||
(lhs_expr.span.between(rhs_expr.span), ".wrapping_sub(".to_owned()),
|
||||
(
|
||||
lhs_expr.span.between(rhs_expr.span),
|
||||
".wrapping_sub(".to_owned(),
|
||||
),
|
||||
(rhs_expr.span.shrink_to_hi(), ")".to_owned()),
|
||||
],
|
||||
Applicability::MaybeIncorrect
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
|
||||
if lhs_ty.is_unsafe_ptr() && rhs_ty.is_unsafe_ptr() {
|
||||
err.multipart_suggestion(
|
||||
"consider using `offset_from` for pointer - pointer if the pointers point to the same allocation",
|
||||
"consider using `offset_from` for pointer - pointer if the \
|
||||
pointers point to the same allocation",
|
||||
vec![
|
||||
(lhs_expr.span.shrink_to_lo(), "unsafe { ".to_owned()),
|
||||
(lhs_expr.span.between(rhs_expr.span), ".offset_from(".to_owned()),
|
||||
(
|
||||
lhs_expr.span.between(rhs_expr.span),
|
||||
".offset_from(".to_owned(),
|
||||
),
|
||||
(rhs_expr.span.shrink_to_hi(), ") }".to_owned()),
|
||||
],
|
||||
Applicability::MaybeIncorrect
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -793,14 +808,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
Err(errors) => {
|
||||
let actual = self.resolve_vars_if_possible(operand_ty);
|
||||
let guar = actual.error_reported().err().unwrap_or_else(|| {
|
||||
let mut file = None;
|
||||
let ty_str = self.tcx.short_string(actual, &mut file);
|
||||
let mut err = struct_span_code_err!(
|
||||
self.dcx(),
|
||||
ex.span,
|
||||
E0600,
|
||||
"cannot apply unary operator `{}` to type `{}`",
|
||||
"cannot apply unary operator `{}` to type `{ty_str}`",
|
||||
op.as_str(),
|
||||
actual
|
||||
);
|
||||
*err.long_ty_path() = file;
|
||||
err.span_label(
|
||||
ex.span,
|
||||
format!("cannot apply unary operator `{}`", op.as_str()),
|
||||
|
|
|
|||
|
|
@ -137,6 +137,7 @@ impl<'a, 'tcx> At<'a, 'tcx> {
|
|||
expected,
|
||||
ty::Contravariant,
|
||||
actual,
|
||||
self.cause.span,
|
||||
)
|
||||
.map(|goals| self.goals_to_obligations(goals))
|
||||
} else {
|
||||
|
|
@ -163,8 +164,15 @@ impl<'a, 'tcx> At<'a, 'tcx> {
|
|||
T: ToTrace<'tcx>,
|
||||
{
|
||||
if self.infcx.next_trait_solver {
|
||||
NextSolverRelate::relate(self.infcx, self.param_env, expected, ty::Covariant, actual)
|
||||
.map(|goals| self.goals_to_obligations(goals))
|
||||
NextSolverRelate::relate(
|
||||
self.infcx,
|
||||
self.param_env,
|
||||
expected,
|
||||
ty::Covariant,
|
||||
actual,
|
||||
self.cause.span,
|
||||
)
|
||||
.map(|goals| self.goals_to_obligations(goals))
|
||||
} else {
|
||||
let mut op = TypeRelating::new(
|
||||
self.infcx,
|
||||
|
|
@ -208,8 +216,15 @@ impl<'a, 'tcx> At<'a, 'tcx> {
|
|||
T: Relate<TyCtxt<'tcx>>,
|
||||
{
|
||||
if self.infcx.next_trait_solver {
|
||||
NextSolverRelate::relate(self.infcx, self.param_env, expected, ty::Invariant, actual)
|
||||
.map(|goals| self.goals_to_obligations(goals))
|
||||
NextSolverRelate::relate(
|
||||
self.infcx,
|
||||
self.param_env,
|
||||
expected,
|
||||
ty::Invariant,
|
||||
actual,
|
||||
self.cause.span,
|
||||
)
|
||||
.map(|goals| self.goals_to_obligations(goals))
|
||||
} else {
|
||||
let mut op = TypeRelating::new(
|
||||
self.infcx,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use rustc_middle::ty::fold::TypeFoldable;
|
|||
use rustc_middle::ty::relate::RelateResult;
|
||||
use rustc_middle::ty::relate::combine::PredicateEmittingRelation;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_span::{DUMMY_SP, ErrorGuaranteed};
|
||||
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
|
||||
|
||||
use super::{BoundRegionConversionTime, InferCtxt, RegionVariableOrigin, SubregionOrigin};
|
||||
|
||||
|
|
@ -203,23 +203,23 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
|
|||
self.probe(|_| probe())
|
||||
}
|
||||
|
||||
fn sub_regions(&self, sub: ty::Region<'tcx>, sup: ty::Region<'tcx>) {
|
||||
fn sub_regions(&self, sub: ty::Region<'tcx>, sup: ty::Region<'tcx>, span: Span) {
|
||||
self.inner.borrow_mut().unwrap_region_constraints().make_subregion(
|
||||
SubregionOrigin::RelateRegionParamBound(DUMMY_SP, None),
|
||||
SubregionOrigin::RelateRegionParamBound(span, None),
|
||||
sub,
|
||||
sup,
|
||||
);
|
||||
}
|
||||
|
||||
fn equate_regions(&self, a: ty::Region<'tcx>, b: ty::Region<'tcx>) {
|
||||
fn equate_regions(&self, a: ty::Region<'tcx>, b: ty::Region<'tcx>, span: Span) {
|
||||
self.inner.borrow_mut().unwrap_region_constraints().make_eqregion(
|
||||
SubregionOrigin::RelateRegionParamBound(DUMMY_SP, None),
|
||||
SubregionOrigin::RelateRegionParamBound(span, None),
|
||||
a,
|
||||
b,
|
||||
);
|
||||
}
|
||||
|
||||
fn register_ty_outlives(&self, ty: Ty<'tcx>, r: ty::Region<'tcx>) {
|
||||
self.register_region_obligation_with_cause(ty, r, &ObligationCause::dummy());
|
||||
fn register_ty_outlives(&self, ty: Ty<'tcx>, r: ty::Region<'tcx>, span: Span) {
|
||||
self.register_region_obligation_with_cause(ty, r, &ObligationCause::dummy_with_span(span));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
use std::path::PathBuf;
|
||||
use std::result;
|
||||
use std::sync::Arc;
|
||||
|
||||
use rustc_ast::{LitKind, MetaItemKind, token};
|
||||
use rustc_codegen_ssa::traits::CodegenBackend;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::jobserver;
|
||||
use rustc_data_structures::stable_hasher::StableHasher;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::registry::Registry;
|
||||
use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed};
|
||||
use rustc_lint::LintStore;
|
||||
|
|
@ -442,7 +442,6 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
|
|||
locale_resources.push(codegen_backend.locale_resource());
|
||||
|
||||
let mut sess = rustc_session::build_session(
|
||||
early_dcx,
|
||||
config.opts,
|
||||
CompilerIO {
|
||||
input: config.input,
|
||||
|
|
@ -490,7 +489,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
|
|||
if let Some(register_lints) = config.register_lints.as_deref() {
|
||||
register_lints(&sess, &mut lint_store);
|
||||
}
|
||||
sess.lint_store = Some(Lrc::new(lint_store));
|
||||
sess.lint_store = Some(Arc::new(lint_store));
|
||||
|
||||
util::check_abi_required_features(&sess);
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use rustc_ast as ast;
|
|||
use rustc_codegen_ssa::traits::CodegenBackend;
|
||||
use rustc_data_structures::parallel;
|
||||
use rustc_data_structures::steal::Steal;
|
||||
use rustc_data_structures::sync::{AppendOnlyIndexVec, FreezeLock, Lrc, OnceLock, WorkerLocal};
|
||||
use rustc_data_structures::sync::{AppendOnlyIndexVec, FreezeLock, OnceLock, WorkerLocal};
|
||||
use rustc_expand::base::{ExtCtxt, LintStoreExpand};
|
||||
use rustc_feature::Features;
|
||||
use rustc_fs_util::try_canonicalize;
|
||||
|
|
@ -602,7 +602,7 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P
|
|||
fn resolver_for_lowering_raw<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
(): (),
|
||||
) -> (&'tcx Steal<(ty::ResolverAstLowering, Lrc<ast::Crate>)>, &'tcx ty::ResolverGlobalCtxt) {
|
||||
) -> (&'tcx Steal<(ty::ResolverAstLowering, Arc<ast::Crate>)>, &'tcx ty::ResolverGlobalCtxt) {
|
||||
let arenas = Resolver::arenas();
|
||||
let _ = tcx.registered_tools(()); // Uses `crate_for_resolver`.
|
||||
let (krate, pre_configured_attrs) = tcx.crate_for_resolver(()).steal();
|
||||
|
|
@ -624,7 +624,7 @@ fn resolver_for_lowering_raw<'tcx>(
|
|||
} = resolver.into_outputs();
|
||||
|
||||
let resolutions = tcx.arena.alloc(untracked_resolutions);
|
||||
(tcx.arena.alloc(Steal::new((untracked_resolver_for_lowering, Lrc::new(krate)))), resolutions)
|
||||
(tcx.arena.alloc(Steal::new((untracked_resolver_for_lowering, Arc::new(krate)))), resolutions)
|
||||
}
|
||||
|
||||
pub fn write_dep_info(tcx: TyCtxt<'_>) {
|
||||
|
|
@ -909,6 +909,11 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
|
|||
tcx.ensure_ok().check_coroutine_obligations(
|
||||
tcx.typeck_root_def_id(def_id.to_def_id()).expect_local(),
|
||||
);
|
||||
// Eagerly check the unsubstituted layout for cycles.
|
||||
tcx.ensure_ok().layout_of(
|
||||
ty::TypingEnv::post_analysis(tcx, def_id.to_def_id())
|
||||
.as_query_input(tcx.type_of(def_id).instantiate_identity()),
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -65,7 +65,6 @@ where
|
|||
static USING_INTERNAL_FEATURES: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
let sess = build_session(
|
||||
early_dcx,
|
||||
sessopts,
|
||||
io,
|
||||
None,
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ Rust lexer used by rustc. No stability guarantees are provided.
|
|||
|
||||
# Note that this crate purposefully does not depend on other rustc crates
|
||||
[dependencies]
|
||||
memchr = "2.7.4"
|
||||
unicode-xid = "0.2.0"
|
||||
|
||||
[dependencies.unicode-properties]
|
||||
|
|
|
|||
|
|
@ -103,4 +103,11 @@ impl<'a> Cursor<'a> {
|
|||
self.bump();
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn eat_until(&mut self, byte: u8) {
|
||||
self.chars = match memchr::memchr(byte, self.as_str().as_bytes()) {
|
||||
Some(index) => self.as_str()[index..].chars(),
|
||||
None => "".chars(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -483,7 +483,7 @@ impl Cursor<'_> {
|
|||
_ => None,
|
||||
};
|
||||
|
||||
self.eat_while(|c| c != '\n');
|
||||
self.eat_until(b'\n');
|
||||
LineComment { doc_style }
|
||||
}
|
||||
|
||||
|
|
@ -888,7 +888,7 @@ impl Cursor<'_> {
|
|||
// Skip the string contents and on each '#' character met, check if this is
|
||||
// a raw string termination.
|
||||
loop {
|
||||
self.eat_while(|c| c != '"');
|
||||
self.eat_until(b'"');
|
||||
|
||||
if self.is_eof() {
|
||||
return Err(RawStrError::NoTerminator {
|
||||
|
|
|
|||
|
|
@ -152,6 +152,10 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
|
|||
hir_visit::walk_pat(self, p);
|
||||
}
|
||||
|
||||
fn visit_lit(&mut self, hir_id: HirId, lit: &'tcx hir::Lit, negated: bool) {
|
||||
lint_callback!(self, check_lit, hir_id, lit, negated);
|
||||
}
|
||||
|
||||
fn visit_expr_field(&mut self, field: &'tcx hir::ExprField<'tcx>) {
|
||||
self.with_lint_attrs(field.hir_id, |cx| hir_visit::walk_expr_field(cx, field))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ macro_rules! late_lint_methods {
|
|||
fn check_stmt(a: &'tcx rustc_hir::Stmt<'tcx>);
|
||||
fn check_arm(a: &'tcx rustc_hir::Arm<'tcx>);
|
||||
fn check_pat(a: &'tcx rustc_hir::Pat<'tcx>);
|
||||
fn check_lit(hir_id: rustc_hir::HirId, a: &'tcx rustc_hir::Lit, negated: bool);
|
||||
fn check_expr(a: &'tcx rustc_hir::Expr<'tcx>);
|
||||
fn check_expr_post(a: &'tcx rustc_hir::Expr<'tcx>);
|
||||
fn check_ty(a: &'tcx rustc_hir::Ty<'tcx, rustc_hir::AmbigArg>);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use rustc_abi::{BackendRepr, ExternAbi, TagEncoding, VariantIdx, Variants, Wrapp
|
|||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::DiagMessage;
|
||||
use rustc_hir::intravisit::VisitorExt;
|
||||
use rustc_hir::{AmbigArg, Expr, ExprKind, LangItem};
|
||||
use rustc_hir::{AmbigArg, Expr, ExprKind, HirId, LangItem};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::layout::{LayoutOf, SizeSkeleton};
|
||||
use rustc_middle::ty::{
|
||||
|
|
@ -536,6 +536,16 @@ fn lint_fn_pointer<'tcx>(
|
|||
}
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for TypeLimits {
|
||||
fn check_lit(
|
||||
&mut self,
|
||||
cx: &LateContext<'tcx>,
|
||||
hir_id: HirId,
|
||||
lit: &'tcx hir::Lit,
|
||||
negated: bool,
|
||||
) {
|
||||
lint_literal(cx, self, hir_id, lit.span, lit, negated)
|
||||
}
|
||||
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx hir::Expr<'tcx>) {
|
||||
match e.kind {
|
||||
hir::ExprKind::Unary(hir::UnOp::Neg, expr) => {
|
||||
|
|
@ -557,7 +567,6 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
|
|||
}
|
||||
}
|
||||
}
|
||||
hir::ExprKind::Lit(lit) => lint_literal(cx, self, e, lit),
|
||||
hir::ExprKind::Call(path, [l, r])
|
||||
if let ExprKind::Path(ref qpath) = path.kind
|
||||
&& let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
use hir::{ExprKind, Node, is_range_literal};
|
||||
use rustc_abi::{Integer, Size};
|
||||
use rustc_hir::HirId;
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_middle::ty::layout::IntegerExt;
|
||||
use rustc_middle::{bug, ty};
|
||||
use rustc_span::Span;
|
||||
use {rustc_ast as ast, rustc_attr_parsing as attr, rustc_hir as hir};
|
||||
|
||||
use crate::LateContext;
|
||||
|
|
@ -21,21 +23,22 @@ fn lint_overflowing_range_endpoint<'tcx>(
|
|||
lit: &hir::Lit,
|
||||
lit_val: u128,
|
||||
max: u128,
|
||||
expr: &'tcx hir::Expr<'tcx>,
|
||||
hir_id: HirId,
|
||||
lit_span: Span,
|
||||
ty: &str,
|
||||
) -> bool {
|
||||
// Look past casts to support cases like `0..256 as u8`
|
||||
let (expr, lit_span) = if let Node::Expr(par_expr) = cx.tcx.parent_hir_node(expr.hir_id)
|
||||
let (hir_id, span) = if let Node::Expr(par_expr) = cx.tcx.parent_hir_node(hir_id)
|
||||
&& let ExprKind::Cast(_, _) = par_expr.kind
|
||||
{
|
||||
(par_expr, expr.span)
|
||||
(par_expr.hir_id, par_expr.span)
|
||||
} else {
|
||||
(expr, expr.span)
|
||||
(hir_id, lit_span)
|
||||
};
|
||||
|
||||
// We only want to handle exclusive (`..`) ranges,
|
||||
// which are represented as `ExprKind::Struct`.
|
||||
let Node::ExprField(field) = cx.tcx.parent_hir_node(expr.hir_id) else { return false };
|
||||
let Node::ExprField(field) = cx.tcx.parent_hir_node(hir_id) else { return false };
|
||||
let Node::Expr(struct_expr) = cx.tcx.parent_hir_node(field.hir_id) else { return false };
|
||||
if !is_range_literal(struct_expr) {
|
||||
return false;
|
||||
|
|
@ -45,7 +48,7 @@ fn lint_overflowing_range_endpoint<'tcx>(
|
|||
// We can suggest using an inclusive range
|
||||
// (`..=`) instead only if it is the `end` that is
|
||||
// overflowing and only by 1.
|
||||
if !(end.expr.hir_id == expr.hir_id && lit_val - 1 == max) {
|
||||
if !(end.expr.hir_id == hir_id && lit_val - 1 == max) {
|
||||
return false;
|
||||
};
|
||||
|
||||
|
|
@ -57,7 +60,7 @@ fn lint_overflowing_range_endpoint<'tcx>(
|
|||
_ => bug!(),
|
||||
};
|
||||
|
||||
let sub_sugg = if expr.span.lo() == lit_span.lo() {
|
||||
let sub_sugg = if span.lo() == lit_span.lo() {
|
||||
let Ok(start) = cx.sess().source_map().span_to_snippet(start.span) else { return false };
|
||||
UseInclusiveRange::WithoutParen {
|
||||
sugg: struct_expr.span.shrink_to_lo().to(lit_span.shrink_to_hi()),
|
||||
|
|
@ -67,7 +70,7 @@ fn lint_overflowing_range_endpoint<'tcx>(
|
|||
}
|
||||
} else {
|
||||
UseInclusiveRange::WithParen {
|
||||
eq_sugg: expr.span.shrink_to_lo(),
|
||||
eq_sugg: span.shrink_to_lo(),
|
||||
lit_sugg: lit_span,
|
||||
literal: lit_val - 1,
|
||||
suffix,
|
||||
|
|
@ -125,7 +128,8 @@ fn get_bin_hex_repr(cx: &LateContext<'_>, lit: &hir::Lit) -> Option<String> {
|
|||
|
||||
fn report_bin_hex_error(
|
||||
cx: &LateContext<'_>,
|
||||
expr: &hir::Expr<'_>,
|
||||
hir_id: HirId,
|
||||
span: Span,
|
||||
ty: attr::IntType,
|
||||
size: Size,
|
||||
repr_str: String,
|
||||
|
|
@ -144,11 +148,11 @@ fn report_bin_hex_error(
|
|||
};
|
||||
let sign =
|
||||
if negative { OverflowingBinHexSign::Negative } else { OverflowingBinHexSign::Positive };
|
||||
let sub = get_type_suggestion(cx.typeck_results().node_type(expr.hir_id), val, negative).map(
|
||||
let sub = get_type_suggestion(cx.typeck_results().node_type(hir_id), val, negative).map(
|
||||
|suggestion_ty| {
|
||||
if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') {
|
||||
let (sans_suffix, _) = repr_str.split_at(pos);
|
||||
OverflowingBinHexSub::Suggestion { span: expr.span, suggestion_ty, sans_suffix }
|
||||
OverflowingBinHexSub::Suggestion { span, suggestion_ty, sans_suffix }
|
||||
} else {
|
||||
OverflowingBinHexSub::Help { suggestion_ty }
|
||||
}
|
||||
|
|
@ -156,7 +160,7 @@ fn report_bin_hex_error(
|
|||
);
|
||||
let sign_bit_sub = (!negative)
|
||||
.then(|| {
|
||||
let ty::Int(int_ty) = cx.typeck_results().node_type(expr.hir_id).kind() else {
|
||||
let ty::Int(int_ty) = cx.typeck_results().node_type(hir_id).kind() else {
|
||||
return None;
|
||||
};
|
||||
|
||||
|
|
@ -177,7 +181,7 @@ fn report_bin_hex_error(
|
|||
};
|
||||
|
||||
Some(OverflowingBinHexSignBitSub {
|
||||
span: expr.span,
|
||||
span,
|
||||
lit_no_suffix,
|
||||
negative_val: actually.clone(),
|
||||
int_ty: int_ty.name_str(),
|
||||
|
|
@ -186,7 +190,7 @@ fn report_bin_hex_error(
|
|||
})
|
||||
.flatten();
|
||||
|
||||
cx.emit_span_lint(OVERFLOWING_LITERALS, expr.span, OverflowingBinHex {
|
||||
cx.emit_span_lint(OVERFLOWING_LITERALS, span, OverflowingBinHex {
|
||||
ty: t,
|
||||
lit: repr_str.clone(),
|
||||
dec: val,
|
||||
|
|
@ -236,15 +240,17 @@ fn literal_to_i128(val: u128, negative: bool) -> Option<i128> {
|
|||
fn lint_int_literal<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
type_limits: &TypeLimits,
|
||||
e: &'tcx hir::Expr<'tcx>,
|
||||
hir_id: HirId,
|
||||
span: Span,
|
||||
lit: &hir::Lit,
|
||||
t: ty::IntTy,
|
||||
v: u128,
|
||||
negated: bool,
|
||||
) {
|
||||
let int_type = t.normalize(cx.sess().target.pointer_width);
|
||||
let (min, max) = int_ty_range(int_type);
|
||||
let max = max as u128;
|
||||
let negative = type_limits.negated_expr_id == Some(e.hir_id);
|
||||
let negative = negated ^ (type_limits.negated_expr_id == Some(hir_id));
|
||||
|
||||
// Detect literal value out of range [min, max] inclusive
|
||||
// avoiding use of -min to prevent overflow/panic
|
||||
|
|
@ -252,7 +258,8 @@ fn lint_int_literal<'tcx>(
|
|||
if let Some(repr_str) = get_bin_hex_repr(cx, lit) {
|
||||
report_bin_hex_error(
|
||||
cx,
|
||||
e,
|
||||
hir_id,
|
||||
span,
|
||||
attr::IntType::SignedInt(ty::ast_int_ty(t)),
|
||||
Integer::from_int_ty(cx, t).size(),
|
||||
repr_str,
|
||||
|
|
@ -262,18 +269,18 @@ fn lint_int_literal<'tcx>(
|
|||
return;
|
||||
}
|
||||
|
||||
if lint_overflowing_range_endpoint(cx, lit, v, max, e, t.name_str()) {
|
||||
if lint_overflowing_range_endpoint(cx, lit, v, max, hir_id, span, t.name_str()) {
|
||||
// The overflowing literal lint was emitted by `lint_overflowing_range_endpoint`.
|
||||
return;
|
||||
}
|
||||
|
||||
let span = if negative { type_limits.negated_expr_span.unwrap() } else { e.span };
|
||||
let span = if negative { type_limits.negated_expr_span.unwrap() } else { span };
|
||||
let lit = cx
|
||||
.sess()
|
||||
.source_map()
|
||||
.span_to_snippet(span)
|
||||
.unwrap_or_else(|_| if negative { format!("-{v}") } else { v.to_string() });
|
||||
let help = get_type_suggestion(cx.typeck_results().node_type(e.hir_id), v, negative)
|
||||
let help = get_type_suggestion(cx.typeck_results().node_type(hir_id), v, negative)
|
||||
.map(|suggestion_ty| OverflowingIntHelp { suggestion_ty });
|
||||
|
||||
cx.emit_span_lint(OVERFLOWING_LITERALS, span, OverflowingInt {
|
||||
|
|
@ -288,7 +295,8 @@ fn lint_int_literal<'tcx>(
|
|||
|
||||
fn lint_uint_literal<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
e: &'tcx hir::Expr<'tcx>,
|
||||
hir_id: HirId,
|
||||
span: Span,
|
||||
lit: &hir::Lit,
|
||||
t: ty::UintTy,
|
||||
) {
|
||||
|
|
@ -302,7 +310,7 @@ fn lint_uint_literal<'tcx>(
|
|||
};
|
||||
|
||||
if lit_val < min || lit_val > max {
|
||||
if let Node::Expr(par_e) = cx.tcx.parent_hir_node(e.hir_id) {
|
||||
if let Node::Expr(par_e) = cx.tcx.parent_hir_node(hir_id) {
|
||||
match par_e.kind {
|
||||
hir::ExprKind::Cast(..) => {
|
||||
if let ty::Char = cx.typeck_results().expr_ty(par_e).kind() {
|
||||
|
|
@ -316,14 +324,15 @@ fn lint_uint_literal<'tcx>(
|
|||
_ => {}
|
||||
}
|
||||
}
|
||||
if lint_overflowing_range_endpoint(cx, lit, lit_val, max, e, t.name_str()) {
|
||||
if lint_overflowing_range_endpoint(cx, lit, lit_val, max, hir_id, span, t.name_str()) {
|
||||
// The overflowing literal lint was emitted by `lint_overflowing_range_endpoint`.
|
||||
return;
|
||||
}
|
||||
if let Some(repr_str) = get_bin_hex_repr(cx, lit) {
|
||||
report_bin_hex_error(
|
||||
cx,
|
||||
e,
|
||||
hir_id,
|
||||
span,
|
||||
attr::IntType::UnsignedInt(ty::ast_uint_ty(t)),
|
||||
Integer::from_uint_ty(cx, t).size(),
|
||||
repr_str,
|
||||
|
|
@ -332,7 +341,7 @@ fn lint_uint_literal<'tcx>(
|
|||
);
|
||||
return;
|
||||
}
|
||||
cx.emit_span_lint(OVERFLOWING_LITERALS, e.span, OverflowingUInt {
|
||||
cx.emit_span_lint(OVERFLOWING_LITERALS, span, OverflowingUInt {
|
||||
ty: t.name_str(),
|
||||
lit: cx
|
||||
.sess()
|
||||
|
|
@ -348,19 +357,24 @@ fn lint_uint_literal<'tcx>(
|
|||
pub(crate) fn lint_literal<'tcx>(
|
||||
cx: &LateContext<'tcx>,
|
||||
type_limits: &TypeLimits,
|
||||
e: &'tcx hir::Expr<'tcx>,
|
||||
hir_id: HirId,
|
||||
span: Span,
|
||||
lit: &hir::Lit,
|
||||
negated: bool,
|
||||
) {
|
||||
match *cx.typeck_results().node_type(e.hir_id).kind() {
|
||||
match *cx.typeck_results().node_type(hir_id).kind() {
|
||||
ty::Int(t) => {
|
||||
match lit.node {
|
||||
ast::LitKind::Int(v, ast::LitIntType::Signed(_) | ast::LitIntType::Unsuffixed) => {
|
||||
lint_int_literal(cx, type_limits, e, lit, t, v.get())
|
||||
lint_int_literal(cx, type_limits, hir_id, span, lit, t, v.get(), negated)
|
||||
}
|
||||
_ => bug!(),
|
||||
};
|
||||
}
|
||||
ty::Uint(t) => lint_uint_literal(cx, e, lit, t),
|
||||
ty::Uint(t) => {
|
||||
assert!(!negated);
|
||||
lint_uint_literal(cx, hir_id, span, lit, t)
|
||||
}
|
||||
ty::Float(t) => {
|
||||
let (is_infinite, sym) = match lit.node {
|
||||
ast::LitKind::Float(v, _) => match t {
|
||||
|
|
@ -374,7 +388,7 @@ pub(crate) fn lint_literal<'tcx>(
|
|||
_ => bug!(),
|
||||
};
|
||||
if is_infinite == Ok(true) {
|
||||
cx.emit_span_lint(OVERFLOWING_LITERALS, e.span, OverflowingLiteral {
|
||||
cx.emit_span_lint(OVERFLOWING_LITERALS, span, OverflowingLiteral {
|
||||
ty: t.name_str(),
|
||||
lit: cx
|
||||
.sess()
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use std::iter::TrustedLen;
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
use std::{io, iter, mem};
|
||||
|
||||
pub(super) use cstore_impl::provide;
|
||||
|
|
@ -11,7 +12,7 @@ use rustc_data_structures::captures::Captures;
|
|||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_data_structures::owned_slice::OwnedSlice;
|
||||
use rustc_data_structures::sync::{Lock, Lrc, OnceLock};
|
||||
use rustc_data_structures::sync::{Lock, OnceLock};
|
||||
use rustc_data_structures::unhash::UnhashMap;
|
||||
use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind};
|
||||
use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, DeriveProcMacro};
|
||||
|
|
@ -117,7 +118,7 @@ pub(crate) struct CrateMetadata {
|
|||
/// How to link (or not link) this crate to the currently compiled crate.
|
||||
dep_kind: CrateDepKind,
|
||||
/// Filesystem location of this crate.
|
||||
source: Lrc<CrateSource>,
|
||||
source: Arc<CrateSource>,
|
||||
/// Whether or not this crate should be consider a private dependency.
|
||||
/// Used by the 'exported_private_dependencies' lint, and for determining
|
||||
/// whether to emit suggestions that reference this crate.
|
||||
|
|
@ -149,7 +150,7 @@ struct ImportedSourceFile {
|
|||
/// The end of this SourceFile within the source_map of its original crate
|
||||
original_end_pos: rustc_span::BytePos,
|
||||
/// The imported SourceFile's representation within the local source_map
|
||||
translated_source_file: Lrc<rustc_span::SourceFile>,
|
||||
translated_source_file: Arc<rustc_span::SourceFile>,
|
||||
}
|
||||
|
||||
pub(super) struct DecodeContext<'a, 'tcx> {
|
||||
|
|
@ -1866,7 +1867,7 @@ impl CrateMetadata {
|
|||
cnum_map,
|
||||
dependencies,
|
||||
dep_kind,
|
||||
source: Lrc::new(source),
|
||||
source: Arc::new(source),
|
||||
private_dep,
|
||||
host_hash,
|
||||
used: false,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use std::any::Any;
|
||||
use std::mem;
|
||||
use std::sync::Arc;
|
||||
|
||||
use rustc_attr_parsing::Deprecation;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE};
|
||||
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
|
||||
|
|
@ -409,7 +409,7 @@ provide! { tcx, def_id, other, cdata,
|
|||
matches!(cdata.extern_crate, Some(extern_crate) if !extern_crate.is_direct())
|
||||
}
|
||||
|
||||
used_crate_source => { Lrc::clone(&cdata.source) }
|
||||
used_crate_source => { Arc::clone(&cdata.source) }
|
||||
debugger_visualizers => { cdata.get_debugger_visualizers() }
|
||||
|
||||
exported_symbols => {
|
||||
|
|
@ -548,7 +548,7 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) {
|
|||
visible_parent_map
|
||||
},
|
||||
|
||||
dependency_formats: |tcx, ()| Lrc::new(crate::dependency_format::calculate(tcx)),
|
||||
dependency_formats: |tcx, ()| Arc::new(crate::dependency_format::calculate(tcx)),
|
||||
has_global_allocator: |tcx, LocalCrate| CStore::from_tcx(tcx).has_global_allocator(),
|
||||
has_alloc_error_handler: |tcx, LocalCrate| CStore::from_tcx(tcx).has_alloc_error_handler(),
|
||||
postorder_cnums: |tcx, ()| {
|
||||
|
|
|
|||
|
|
@ -3,11 +3,12 @@ use std::collections::hash_map::Entry;
|
|||
use std::fs::File;
|
||||
use std::io::{Read, Seek, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
|
||||
use rustc_ast::attr::AttributeExt;
|
||||
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||
use rustc_data_structures::memmap::{Mmap, MmapMut};
|
||||
use rustc_data_structures::sync::{Lrc, join, par_for_each_in};
|
||||
use rustc_data_structures::sync::{join, par_for_each_in};
|
||||
use rustc_data_structures::temp_dir::MaybeTempDir;
|
||||
use rustc_data_structures::thousands::format_with_underscores;
|
||||
use rustc_feature::Features;
|
||||
|
|
@ -52,7 +53,7 @@ pub(super) struct EncodeContext<'a, 'tcx> {
|
|||
// This is used to speed up Span encoding.
|
||||
// The `usize` is an index into the `MonotonicVec`
|
||||
// that stores the `SourceFile`
|
||||
source_file_cache: (Lrc<SourceFile>, usize),
|
||||
source_file_cache: (Arc<SourceFile>, usize),
|
||||
// The indices (into the `SourceMap`'s `MonotonicVec`)
|
||||
// of all of the `SourceFiles` that we need to serialize.
|
||||
// When we serialize a `Span`, we insert the index of its
|
||||
|
|
@ -278,7 +279,7 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for SpanData {
|
|||
let source_map = s.tcx.sess.source_map();
|
||||
let source_file_index = source_map.lookup_source_file_idx(self.lo);
|
||||
s.source_file_cache =
|
||||
(Lrc::clone(&source_map.files()[source_file_index]), source_file_index);
|
||||
(Arc::clone(&source_map.files()[source_file_index]), source_file_index);
|
||||
}
|
||||
let (ref source_file, source_file_index) = s.source_file_cache;
|
||||
debug_assert!(source_file.contains(self.lo));
|
||||
|
|
@ -2306,7 +2307,7 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
|
|||
encoder.emit_raw_bytes(&0u64.to_le_bytes());
|
||||
|
||||
let source_map_files = tcx.sess.source_map().files();
|
||||
let source_file_cache = (Lrc::clone(&source_map_files[0]), 0);
|
||||
let source_file_cache = (Arc::clone(&source_map_files[0]), 0);
|
||||
let required_source_files = Some(FxIndexSet::default());
|
||||
drop(source_map_files);
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ macro_rules! arena_types {
|
|||
[decode] borrowck_result: rustc_middle::mir::BorrowCheckResult<'tcx>,
|
||||
[] resolver: rustc_data_structures::steal::Steal<(
|
||||
rustc_middle::ty::ResolverAstLowering,
|
||||
rustc_data_structures::sync::Lrc<rustc_ast::Crate>,
|
||||
std::sync::Arc<rustc_ast::Crate>,
|
||||
)>,
|
||||
[] crate_for_resolver: rustc_data_structures::steal::Steal<(rustc_ast::Crate, rustc_ast::AttrVec)>,
|
||||
[] resolutions: rustc_middle::ty::ResolverGlobalCtxt,
|
||||
|
|
|
|||
|
|
@ -98,6 +98,10 @@ declare_hooks! {
|
|||
hook save_dep_graph() -> ();
|
||||
|
||||
hook query_key_hash_verify_all() -> ();
|
||||
|
||||
/// Ensure the given scalar is valid for the given type.
|
||||
/// This checks non-recursive runtime validity.
|
||||
hook validate_scalar_in_layout(scalar: crate::ty::ScalarInt, ty: Ty<'tcx>) -> bool;
|
||||
}
|
||||
|
||||
#[cold]
|
||||
|
|
|
|||
|
|
@ -142,10 +142,6 @@ impl<'tcx, R> QueryResponse<'tcx, R> {
|
|||
pub type QueryOutlivesConstraint<'tcx> =
|
||||
(ty::OutlivesPredicate<'tcx, GenericArg<'tcx>>, ConstraintCategory<'tcx>);
|
||||
|
||||
TrivialTypeTraversalImpls! {
|
||||
crate::infer::canonical::Certainty,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct CanonicalParamEnvCache<'tcx> {
|
||||
map: Lock<
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_macros::{Decodable, Encodable, HashStable};
|
||||
|
||||
#[derive(HashStable)]
|
||||
|
|
@ -15,7 +15,7 @@ pub enum DebuggerVisualizerType {
|
|||
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable)]
|
||||
pub struct DebuggerVisualizerFile {
|
||||
/// The complete debugger visualizer source.
|
||||
pub src: Lrc<[u8]>,
|
||||
pub src: Arc<[u8]>,
|
||||
/// Indicates which visualizer type this targets.
|
||||
pub visualizer_type: DebuggerVisualizerType,
|
||||
/// The file path to the visualizer file. This is used for reporting
|
||||
|
|
@ -26,13 +26,13 @@ pub struct DebuggerVisualizerFile {
|
|||
}
|
||||
|
||||
impl DebuggerVisualizerFile {
|
||||
pub fn new(src: Lrc<[u8]>, visualizer_type: DebuggerVisualizerType, path: PathBuf) -> Self {
|
||||
pub fn new(src: Arc<[u8]>, visualizer_type: DebuggerVisualizerType, path: PathBuf) -> Self {
|
||||
DebuggerVisualizerFile { src, visualizer_type, path: Some(path) }
|
||||
}
|
||||
|
||||
pub fn path_erased(&self) -> Self {
|
||||
DebuggerVisualizerFile {
|
||||
src: Lrc::clone(&self.src),
|
||||
src: Arc::clone(&self.src),
|
||||
visualizer_type: self.visualizer_type,
|
||||
path: None,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -163,6 +163,7 @@ impl<'tcx> graph::Predecessors for BasicBlocks<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
// Done here instead of in `structural_impls.rs` because `Cache` is private, as is `basic_blocks`.
|
||||
TrivialTypeTraversalImpls! { Cache }
|
||||
|
||||
impl<S: Encoder> Encodable<S> for Cache {
|
||||
|
|
|
|||
|
|
@ -95,8 +95,6 @@ impl From<ReportedErrorInfo> for ErrorGuaranteed {
|
|||
}
|
||||
}
|
||||
|
||||
TrivialTypeTraversalImpls! { ErrorHandled }
|
||||
|
||||
pub type EvalToAllocationRawResult<'tcx> = Result<ConstAlloc<'tcx>, ErrorHandled>;
|
||||
pub type EvalStaticInitializerRawResult<'tcx> = Result<ConstAllocation<'tcx>, ErrorHandled>;
|
||||
pub type EvalToConstValueResult<'tcx> = Result<ConstValue<'tcx>, ErrorHandled>;
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ use self::visit::TyContext;
|
|||
use crate::mir::interpret::{AllocRange, Scalar};
|
||||
use crate::mir::visit::MirVisitable;
|
||||
use crate::ty::codec::{TyDecoder, TyEncoder};
|
||||
use crate::ty::fold::{FallibleTypeFolder, TypeFoldable};
|
||||
use crate::ty::print::{FmtPrinter, Printer, pretty_print_const, with_no_trimmed_paths};
|
||||
use crate::ty::visit::TypeVisitableExt;
|
||||
use crate::ty::{
|
||||
|
|
@ -59,7 +58,6 @@ pub mod tcx;
|
|||
mod terminator;
|
||||
|
||||
pub mod traversal;
|
||||
mod type_foldable;
|
||||
pub mod visit;
|
||||
|
||||
pub use consts::*;
|
||||
|
|
@ -927,8 +925,6 @@ pub enum BindingForm<'tcx> {
|
|||
RefForGuard,
|
||||
}
|
||||
|
||||
TrivialTypeTraversalImpls! { BindingForm<'tcx> }
|
||||
|
||||
mod binding_form_impl {
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_query_system::ich::StableHashingContext;
|
||||
|
|
|
|||
|
|
@ -1,67 +0,0 @@
|
|||
//! `TypeFoldable` implementations for MIR types
|
||||
|
||||
use rustc_ast::InlineAsmTemplatePiece;
|
||||
use rustc_hir::UnsafeBinderCastKind;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
|
||||
use super::*;
|
||||
|
||||
TrivialTypeTraversalImpls! {
|
||||
BlockTailInfo,
|
||||
MirPhase,
|
||||
SourceInfo,
|
||||
FakeReadCause,
|
||||
RetagKind,
|
||||
SourceScope,
|
||||
SourceScopeLocalData,
|
||||
UserTypeAnnotationIndex,
|
||||
BorrowKind,
|
||||
RawPtrKind,
|
||||
CastKind,
|
||||
BasicBlock,
|
||||
SwitchTargets,
|
||||
CoroutineKind,
|
||||
CoroutineSavedLocal,
|
||||
UnsafeBinderCastKind,
|
||||
}
|
||||
|
||||
TrivialTypeTraversalImpls! {
|
||||
ConstValue<'tcx>,
|
||||
NullOp<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx [InlineAsmTemplatePiece] {
|
||||
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
|
||||
self,
|
||||
_folder: &mut F,
|
||||
) -> Result<Self, F::Error> {
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx [Span] {
|
||||
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
|
||||
self,
|
||||
_folder: &mut F,
|
||||
) -> Result<Self, F::Error> {
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<LocalDefId> {
|
||||
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
|
||||
self,
|
||||
_folder: &mut F,
|
||||
) -> Result<Self, F::Error> {
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<PlaceElem<'tcx>> {
|
||||
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
|
||||
self,
|
||||
folder: &mut F,
|
||||
) -> Result<Self, F::Error> {
|
||||
ty::util::fold_list(self, folder, |tcx, v| tcx.mk_place_elems(v))
|
||||
}
|
||||
}
|
||||
|
|
@ -18,7 +18,6 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
|||
use rustc_data_structures::sorted_map::SortedMap;
|
||||
use rustc_data_structures::steal::Steal;
|
||||
use rustc_data_structures::svh::Svh;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_data_structures::unord::{UnordMap, UnordSet};
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_hir::def::{DefKind, DocLinkResMap};
|
||||
|
|
@ -125,7 +124,7 @@ rustc_queries! {
|
|||
desc { "getting the resolver outputs" }
|
||||
}
|
||||
|
||||
query resolver_for_lowering_raw(_: ()) -> (&'tcx Steal<(ty::ResolverAstLowering, Lrc<ast::Crate>)>, &'tcx ty::ResolverGlobalCtxt) {
|
||||
query resolver_for_lowering_raw(_: ()) -> (&'tcx Steal<(ty::ResolverAstLowering, Arc<ast::Crate>)>, &'tcx ty::ResolverGlobalCtxt) {
|
||||
eval_always
|
||||
no_hash
|
||||
desc { "getting the resolver for lowering" }
|
||||
|
|
@ -1628,7 +1627,7 @@ rustc_queries! {
|
|||
separate_provide_extern
|
||||
}
|
||||
|
||||
query dependency_formats(_: ()) -> &'tcx Lrc<crate::middle::dependency_format::Dependencies> {
|
||||
query dependency_formats(_: ()) -> &'tcx Arc<crate::middle::dependency_format::Dependencies> {
|
||||
arena_cache
|
||||
desc { "getting the linkage format of all dependencies" }
|
||||
}
|
||||
|
|
@ -2077,7 +2076,7 @@ rustc_queries! {
|
|||
desc { "seeing if we're missing an `extern crate` item for this crate" }
|
||||
separate_provide_extern
|
||||
}
|
||||
query used_crate_source(_: CrateNum) -> &'tcx Lrc<CrateSource> {
|
||||
query used_crate_source(_: CrateNum) -> &'tcx Arc<CrateSource> {
|
||||
arena_cache
|
||||
eval_always
|
||||
desc { "looking at the source for a crate" }
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
use std::collections::hash_map::Entry;
|
||||
use std::mem;
|
||||
use std::sync::Arc;
|
||||
|
||||
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
|
||||
use rustc_data_structures::memmap::Mmap;
|
||||
use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, RwLock};
|
||||
use rustc_data_structures::sync::{HashMapExt, Lock, RwLock};
|
||||
use rustc_data_structures::unhash::UnhashMap;
|
||||
use rustc_data_structures::unord::{UnordMap, UnordSet};
|
||||
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, LocalDefId, StableCrateId};
|
||||
|
|
@ -60,7 +61,7 @@ pub struct OnDiskCache {
|
|||
file_index_to_stable_id: FxHashMap<SourceFileIndex, EncodedSourceFileId>,
|
||||
|
||||
// Caches that are populated lazily during decoding.
|
||||
file_index_to_file: Lock<FxHashMap<SourceFileIndex, Lrc<SourceFile>>>,
|
||||
file_index_to_file: Lock<FxHashMap<SourceFileIndex, Arc<SourceFile>>>,
|
||||
|
||||
// A map from dep-node to the position of the cached query result in
|
||||
// `serialized_data`.
|
||||
|
|
@ -453,7 +454,7 @@ impl OnDiskCache {
|
|||
pub struct CacheDecoder<'a, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
opaque: MemDecoder<'a>,
|
||||
file_index_to_file: &'a Lock<FxHashMap<SourceFileIndex, Lrc<SourceFile>>>,
|
||||
file_index_to_file: &'a Lock<FxHashMap<SourceFileIndex, Arc<SourceFile>>>,
|
||||
file_index_to_stable_id: &'a FxHashMap<SourceFileIndex, EncodedSourceFileId>,
|
||||
alloc_decoding_session: AllocDecodingSession<'a>,
|
||||
syntax_contexts: &'a FxHashMap<u32, AbsoluteBytePos>,
|
||||
|
|
@ -464,10 +465,10 @@ pub struct CacheDecoder<'a, 'tcx> {
|
|||
|
||||
impl<'a, 'tcx> CacheDecoder<'a, 'tcx> {
|
||||
#[inline]
|
||||
fn file_index_to_file(&self, index: SourceFileIndex) -> Lrc<SourceFile> {
|
||||
fn file_index_to_file(&self, index: SourceFileIndex) -> Arc<SourceFile> {
|
||||
let CacheDecoder { tcx, file_index_to_file, file_index_to_stable_id, .. } = *self;
|
||||
|
||||
Lrc::clone(file_index_to_file.borrow_mut().entry(index).or_insert_with(|| {
|
||||
Arc::clone(file_index_to_file.borrow_mut().entry(index).or_insert_with(|| {
|
||||
let source_file_id = &file_index_to_stable_id[&index];
|
||||
let source_file_cnum = tcx.stable_crate_id_to_crate_num(source_file_id.stable_crate_id);
|
||||
|
||||
|
|
@ -824,7 +825,7 @@ pub struct CacheEncoder<'a, 'tcx> {
|
|||
|
||||
impl<'a, 'tcx> CacheEncoder<'a, 'tcx> {
|
||||
#[inline]
|
||||
fn source_file_index(&mut self, source_file: Lrc<SourceFile>) -> SourceFileIndex {
|
||||
fn source_file_index(&mut self, source_file: Arc<SourceFile>) -> SourceFileIndex {
|
||||
self.file_to_file_index[&(&raw const *source_file)]
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
use std::cmp::Ordering;
|
||||
use std::fmt;
|
||||
use std::ops::Index;
|
||||
use std::sync::Arc;
|
||||
|
||||
use rustc_abi::{FieldIdx, Integer, Size, VariantIdx};
|
||||
use rustc_ast::{AsmMacro, InlineAsmOptions, InlineAsmTemplatePiece};
|
||||
|
|
@ -618,7 +619,7 @@ pub enum InlineAsmOperand<'tcx> {
|
|||
#[derive(Debug, HashStable, TypeVisitable)]
|
||||
pub struct FieldPat<'tcx> {
|
||||
pub field: FieldIdx,
|
||||
pub pattern: Box<Pat<'tcx>>,
|
||||
pub pattern: Pat<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Debug, HashStable, TypeVisitable)]
|
||||
|
|
@ -679,7 +680,7 @@ impl<'tcx> Pat<'tcx> {
|
|||
Or { pats } => pats.iter().for_each(|p| p.walk_(it)),
|
||||
Array { box ref prefix, ref slice, box ref suffix }
|
||||
| Slice { box ref prefix, ref slice, box ref suffix } => {
|
||||
prefix.iter().chain(slice.iter()).chain(suffix.iter()).for_each(|p| p.walk_(it))
|
||||
prefix.iter().chain(slice.as_deref()).chain(suffix.iter()).for_each(|p| p.walk_(it))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -836,28 +837,28 @@ pub enum PatKind<'tcx> {
|
|||
subpattern: Box<Pat<'tcx>>,
|
||||
},
|
||||
|
||||
Range(Box<PatRange<'tcx>>),
|
||||
Range(Arc<PatRange<'tcx>>),
|
||||
|
||||
/// Matches against a slice, checking the length and extracting elements.
|
||||
/// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty.
|
||||
/// e.g., `&[ref xs @ ..]`.
|
||||
Slice {
|
||||
prefix: Box<[Box<Pat<'tcx>>]>,
|
||||
prefix: Box<[Pat<'tcx>]>,
|
||||
slice: Option<Box<Pat<'tcx>>>,
|
||||
suffix: Box<[Box<Pat<'tcx>>]>,
|
||||
suffix: Box<[Pat<'tcx>]>,
|
||||
},
|
||||
|
||||
/// Fixed match against an array; irrefutable.
|
||||
Array {
|
||||
prefix: Box<[Box<Pat<'tcx>>]>,
|
||||
prefix: Box<[Pat<'tcx>]>,
|
||||
slice: Option<Box<Pat<'tcx>>>,
|
||||
suffix: Box<[Box<Pat<'tcx>>]>,
|
||||
suffix: Box<[Pat<'tcx>]>,
|
||||
},
|
||||
|
||||
/// An or-pattern, e.g. `p | q`.
|
||||
/// Invariant: `pats.len() >= 2`.
|
||||
Or {
|
||||
pats: Box<[Box<Pat<'tcx>>]>,
|
||||
pats: Box<[Pat<'tcx>]>,
|
||||
},
|
||||
|
||||
/// A never pattern `!`.
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ mod structural_impls;
|
|||
|
||||
use std::borrow::Cow;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::sync::Arc;
|
||||
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::{Applicability, Diag, EmissionGuarantee};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::HirId;
|
||||
|
|
@ -157,7 +157,7 @@ pub struct UnifyReceiverContext<'tcx> {
|
|||
pub struct InternedObligationCauseCode<'tcx> {
|
||||
/// `None` for `ObligationCauseCode::Misc` (a common case, occurs ~60% of
|
||||
/// the time). `Some` otherwise.
|
||||
code: Option<Lrc<ObligationCauseCode<'tcx>>>,
|
||||
code: Option<Arc<ObligationCauseCode<'tcx>>>,
|
||||
}
|
||||
|
||||
impl<'tcx> std::fmt::Debug for InternedObligationCauseCode<'tcx> {
|
||||
|
|
@ -171,7 +171,7 @@ impl<'tcx> ObligationCauseCode<'tcx> {
|
|||
#[inline(always)]
|
||||
fn into(self) -> InternedObligationCauseCode<'tcx> {
|
||||
InternedObligationCauseCode {
|
||||
code: if let ObligationCauseCode::Misc = self { None } else { Some(Lrc::new(self)) },
|
||||
code: if let ObligationCauseCode::Misc = self { None } else { Some(Arc::new(self)) },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -427,10 +427,6 @@ pub enum IsConstable {
|
|||
Ctor,
|
||||
}
|
||||
|
||||
TrivialTypeTraversalAndLiftImpls! {
|
||||
IsConstable,
|
||||
}
|
||||
|
||||
/// The 'location' at which we try to perform HIR-based wf checking.
|
||||
/// This information is used to obtain an `hir::Ty`, which
|
||||
/// we can walk in order to obtain precise spans for any
|
||||
|
|
|
|||
|
|
@ -260,8 +260,6 @@ impl From<ErrorGuaranteed> for OverflowError {
|
|||
}
|
||||
}
|
||||
|
||||
TrivialTypeTraversalImpls! { OverflowError }
|
||||
|
||||
impl<'tcx> From<OverflowError> for SelectionError<'tcx> {
|
||||
fn from(overflow_error: OverflowError) -> SelectionError<'tcx> {
|
||||
match overflow_error {
|
||||
|
|
|
|||
|
|
@ -30,8 +30,6 @@ impl From<ErrorGuaranteed> for NotConstEvaluatable {
|
|||
}
|
||||
}
|
||||
|
||||
TrivialTypeTraversalImpls! { NotConstEvaluatable }
|
||||
|
||||
pub type BoundAbstractConst<'tcx> =
|
||||
Result<Option<EarlyBinder<'tcx, ty::Const<'tcx>>>, ErrorGuaranteed>;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use std::cmp::Ordering;
|
|||
use std::hash::{Hash, Hasher};
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::{Bound, Deref};
|
||||
use std::sync::OnceLock;
|
||||
use std::sync::{Arc, OnceLock};
|
||||
use std::{fmt, iter, mem};
|
||||
|
||||
use rustc_abi::{ExternAbi, FieldIdx, Layout, LayoutData, TargetDataLayout, VariantIdx};
|
||||
|
|
@ -24,7 +24,7 @@ use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
|
|||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_data_structures::steal::Steal;
|
||||
use rustc_data_structures::sync::{
|
||||
self, DynSend, DynSync, FreezeReadGuard, Lock, Lrc, RwLock, WorkerLocal,
|
||||
self, DynSend, DynSync, FreezeReadGuard, Lock, RwLock, WorkerLocal,
|
||||
};
|
||||
use rustc_data_structures::unord::UnordSet;
|
||||
use rustc_errors::{
|
||||
|
|
@ -76,11 +76,11 @@ use crate::traits::solve::{
|
|||
};
|
||||
use crate::ty::predicate::ExistentialPredicateStableCmpExt as _;
|
||||
use crate::ty::{
|
||||
self, AdtDef, AdtDefData, AdtKind, Binder, BoundConstness, Clause, Clauses, Const, GenericArg,
|
||||
GenericArgs, GenericArgsRef, GenericParamDefKind, ImplPolarity, List, ListWithCachedTypeInfo,
|
||||
ParamConst, ParamTy, Pattern, PatternKind, PolyExistentialPredicate, PolyFnSig, Predicate,
|
||||
PredicateKind, PredicatePolarity, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty,
|
||||
TyKind, TyVid, Visibility,
|
||||
self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Clauses, Const, GenericArg, GenericArgs,
|
||||
GenericArgsRef, GenericParamDefKind, List, ListWithCachedTypeInfo, ParamConst, ParamTy,
|
||||
Pattern, PatternKind, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind,
|
||||
PredicatePolarity, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid,
|
||||
Visibility,
|
||||
};
|
||||
|
||||
#[allow(rustc::usage_of_ty_tykind)]
|
||||
|
|
@ -1406,7 +1406,7 @@ impl<'tcx> GlobalCtxt<'tcx> {
|
|||
pub struct CurrentGcx {
|
||||
/// This stores a pointer to a `GlobalCtxt`. This is set to `Some` inside `GlobalCtxt::enter`
|
||||
/// and reset to `None` when that function returns or unwinds.
|
||||
value: Lrc<RwLock<Option<*const ()>>>,
|
||||
value: Arc<RwLock<Option<*const ()>>>,
|
||||
}
|
||||
|
||||
unsafe impl DynSend for CurrentGcx {}
|
||||
|
|
@ -1414,7 +1414,7 @@ unsafe impl DynSync for CurrentGcx {}
|
|||
|
||||
impl CurrentGcx {
|
||||
pub fn new() -> Self {
|
||||
Self { value: Lrc::new(RwLock::new(None)) }
|
||||
Self { value: Arc::new(RwLock::new(None)) }
|
||||
}
|
||||
|
||||
pub fn access<R>(&self, f: impl for<'tcx> FnOnce(&'tcx GlobalCtxt<'tcx>) -> R) -> R {
|
||||
|
|
@ -2243,21 +2243,23 @@ macro_rules! nop_list_lift {
|
|||
};
|
||||
}
|
||||
|
||||
nop_lift! {type_; Ty<'a> => Ty<'tcx>}
|
||||
nop_lift! {region; Region<'a> => Region<'tcx>}
|
||||
nop_lift! {const_; Const<'a> => Const<'tcx>}
|
||||
nop_lift! {pat; Pattern<'a> => Pattern<'tcx>}
|
||||
nop_lift! {const_allocation; ConstAllocation<'a> => ConstAllocation<'tcx>}
|
||||
nop_lift! {predicate; Predicate<'a> => Predicate<'tcx>}
|
||||
nop_lift! {predicate; Clause<'a> => Clause<'tcx>}
|
||||
nop_lift! {layout; Layout<'a> => Layout<'tcx>}
|
||||
nop_lift! { type_; Ty<'a> => Ty<'tcx> }
|
||||
nop_lift! { region; Region<'a> => Region<'tcx> }
|
||||
nop_lift! { const_; Const<'a> => Const<'tcx> }
|
||||
nop_lift! { pat; Pattern<'a> => Pattern<'tcx> }
|
||||
nop_lift! { const_allocation; ConstAllocation<'a> => ConstAllocation<'tcx> }
|
||||
nop_lift! { predicate; Predicate<'a> => Predicate<'tcx> }
|
||||
nop_lift! { predicate; Clause<'a> => Clause<'tcx> }
|
||||
nop_lift! { layout; Layout<'a> => Layout<'tcx> }
|
||||
|
||||
nop_list_lift! {type_lists; Ty<'a> => Ty<'tcx>}
|
||||
nop_list_lift! {poly_existential_predicates; PolyExistentialPredicate<'a> => PolyExistentialPredicate<'tcx>}
|
||||
nop_list_lift! {bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariableKind}
|
||||
nop_list_lift! { type_lists; Ty<'a> => Ty<'tcx> }
|
||||
nop_list_lift! {
|
||||
poly_existential_predicates; PolyExistentialPredicate<'a> => PolyExistentialPredicate<'tcx>
|
||||
}
|
||||
nop_list_lift! { bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariableKind }
|
||||
|
||||
// This is the impl for `&'a GenericArgs<'a>`.
|
||||
nop_list_lift! {args; GenericArg<'a> => GenericArg<'tcx>}
|
||||
nop_list_lift! { args; GenericArg<'a> => GenericArg<'tcx> }
|
||||
|
||||
macro_rules! nop_slice_lift {
|
||||
($ty:ty => $lifted:ty) => {
|
||||
|
|
@ -2277,11 +2279,7 @@ macro_rules! nop_slice_lift {
|
|||
};
|
||||
}
|
||||
|
||||
nop_slice_lift! {ty::ValTree<'a> => ty::ValTree<'tcx>}
|
||||
|
||||
TrivialLiftImpls! {
|
||||
ImplPolarity, PredicatePolarity, Promoted, BoundConstness,
|
||||
}
|
||||
nop_slice_lift! { ty::ValTree<'a> => ty::ValTree<'tcx> }
|
||||
|
||||
macro_rules! sty_debug_print {
|
||||
($fmt: expr, $ctxt: expr, $($variant: ident),*) => {{
|
||||
|
|
@ -3224,7 +3222,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
self.resolutions(()).module_children.get(&def_id).map_or(&[], |v| &v[..])
|
||||
}
|
||||
|
||||
pub fn resolver_for_lowering(self) -> &'tcx Steal<(ty::ResolverAstLowering, Lrc<ast::Crate>)> {
|
||||
pub fn resolver_for_lowering(self) -> &'tcx Steal<(ty::ResolverAstLowering, Arc<ast::Crate>)> {
|
||||
self.resolver_for_lowering_raw(()).0
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1741,7 +1741,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
" as ",
|
||||
)?;
|
||||
}
|
||||
ty::Pat(base_ty, pat) => {
|
||||
ty::Pat(base_ty, pat) if self.tcx().validate_scalar_in_layout(int, ty) => {
|
||||
self.pretty_print_const_scalar_int(int, *base_ty, print_ty)?;
|
||||
p!(write(" is {pat:?}"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,15 +6,18 @@
|
|||
use std::fmt::{self, Debug};
|
||||
|
||||
use rustc_abi::TyAndLayout;
|
||||
use rustc_ast::InlineAsmTemplatePiece;
|
||||
use rustc_ast_ir::try_visit;
|
||||
use rustc_ast_ir::visit::VisitorResult;
|
||||
use rustc_hir::def::Namespace;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_span::Span;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_type_ir::ConstKind;
|
||||
|
||||
use super::print::PrettyPrinter;
|
||||
use super::{GenericArg, GenericArgKind, Pattern, Region};
|
||||
use crate::mir::interpret;
|
||||
use crate::mir::PlaceElem;
|
||||
use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
|
||||
use crate::ty::print::{FmtPrinter, Printer, with_no_trimmed_paths};
|
||||
use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
|
||||
|
|
@ -221,76 +224,89 @@ impl<'tcx> fmt::Debug for Region<'tcx> {
|
|||
// copy...), just add them to one of these lists as appropriate.
|
||||
|
||||
// For things for which the type library provides traversal implementations
|
||||
// for all Interners, we only need to provide a Lift implementation:
|
||||
// for all Interners, we only need to provide a Lift implementation.
|
||||
TrivialLiftImpls! {
|
||||
(),
|
||||
bool,
|
||||
usize,
|
||||
u64,
|
||||
(),
|
||||
bool,
|
||||
usize,
|
||||
u64,
|
||||
// tidy-alphabetical-start
|
||||
crate::mir::interpret::AllocId,
|
||||
crate::mir::interpret::Scalar,
|
||||
crate::mir::Promoted,
|
||||
rustc_abi::ExternAbi,
|
||||
rustc_abi::Size,
|
||||
rustc_hir::Safety,
|
||||
rustc_type_ir::BoundConstness,
|
||||
rustc_type_ir::PredicatePolarity,
|
||||
// tidy-alphabetical-end
|
||||
}
|
||||
|
||||
// For some things about which the type library does not know, or does not
|
||||
// provide any traversal implementations, we need to provide a traversal
|
||||
// implementation (only for TyCtxt<'_> interners).
|
||||
TrivialTypeTraversalImpls! {
|
||||
::rustc_abi::FieldIdx,
|
||||
::rustc_abi::VariantIdx,
|
||||
crate::middle::region::Scope,
|
||||
::rustc_ast::InlineAsmOptions,
|
||||
::rustc_ast::InlineAsmTemplatePiece,
|
||||
::rustc_ast::NodeId,
|
||||
::rustc_hir::def::Res,
|
||||
::rustc_hir::def_id::LocalDefId,
|
||||
::rustc_hir::ByRef,
|
||||
::rustc_hir::HirId,
|
||||
::rustc_hir::MatchSource,
|
||||
::rustc_target::asm::InlineAsmRegOrRegClass,
|
||||
crate::mir::coverage::BlockMarkerId,
|
||||
crate::mir::coverage::CounterId,
|
||||
crate::mir::coverage::ExpressionId,
|
||||
crate::mir::coverage::ConditionId,
|
||||
// tidy-alphabetical-start
|
||||
crate::infer::canonical::Certainty,
|
||||
crate::mir::BasicBlock,
|
||||
crate::mir::BindingForm<'tcx>,
|
||||
crate::mir::BlockTailInfo,
|
||||
crate::mir::BorrowKind,
|
||||
crate::mir::CastKind,
|
||||
crate::mir::ConstValue<'tcx>,
|
||||
crate::mir::CoroutineSavedLocal,
|
||||
crate::mir::FakeReadCause,
|
||||
crate::mir::Local,
|
||||
crate::mir::MirPhase,
|
||||
crate::mir::NullOp<'tcx>,
|
||||
crate::mir::Promoted,
|
||||
crate::mir::RawPtrKind,
|
||||
crate::mir::RetagKind,
|
||||
crate::mir::SourceInfo,
|
||||
crate::mir::SourceScope,
|
||||
crate::mir::SourceScopeLocalData,
|
||||
crate::mir::SwitchTargets,
|
||||
crate::traits::IsConstable,
|
||||
crate::traits::OverflowError,
|
||||
crate::ty::abstract_const::NotConstEvaluatable,
|
||||
crate::ty::adjustment::AutoBorrowMutability,
|
||||
crate::ty::adjustment::PointerCoercion,
|
||||
crate::ty::AdtKind,
|
||||
crate::ty::BoundRegion,
|
||||
// Including `BoundRegionKind` is a *bit* dubious, but direct
|
||||
// references to bound region appear in `ty::Error`, and aren't
|
||||
// really meant to be folded. In general, we can only fold a fully
|
||||
// general `Region`.
|
||||
crate::ty::BoundRegionKind,
|
||||
crate::ty::AssocItem,
|
||||
crate::ty::AssocKind,
|
||||
crate::ty::BoundRegion,
|
||||
crate::ty::BoundVar,
|
||||
crate::ty::Placeholder<crate::ty::BoundRegion>,
|
||||
crate::ty::Placeholder<crate::ty::BoundTy>,
|
||||
crate::ty::Placeholder<ty::BoundVar>,
|
||||
crate::ty::LateParamRegion,
|
||||
crate::ty::adjustment::PointerCoercion,
|
||||
::rustc_span::Ident,
|
||||
::rustc_span::Span,
|
||||
::rustc_span::Symbol,
|
||||
ty::BoundVar,
|
||||
ty::ValTree<'tcx>,
|
||||
crate::ty::UserTypeAnnotationIndex,
|
||||
crate::ty::ValTree<'tcx>,
|
||||
rustc_abi::FieldIdx,
|
||||
rustc_abi::VariantIdx,
|
||||
rustc_ast::InlineAsmOptions,
|
||||
rustc_ast::InlineAsmTemplatePiece,
|
||||
rustc_hir::CoroutineKind,
|
||||
rustc_hir::def_id::LocalDefId,
|
||||
rustc_hir::HirId,
|
||||
rustc_hir::MatchSource,
|
||||
rustc_span::Ident,
|
||||
rustc_span::Span,
|
||||
rustc_span::Symbol,
|
||||
rustc_target::asm::InlineAsmRegOrRegClass,
|
||||
// tidy-alphabetical-end
|
||||
}
|
||||
|
||||
// For some things about which the type library does not know, or does not
|
||||
// provide any traversal implementations, we need to provide a traversal
|
||||
// implementation and a lift implementation (the former only for TyCtxt<'_>
|
||||
// interners).
|
||||
TrivialTypeTraversalAndLiftImpls! {
|
||||
::rustc_hir::def_id::DefId,
|
||||
crate::ty::ClosureKind,
|
||||
// tidy-alphabetical-start
|
||||
crate::ty::instance::ReifyReason,
|
||||
crate::ty::ParamConst,
|
||||
crate::ty::ParamTy,
|
||||
crate::ty::instance::ReifyReason,
|
||||
interpret::AllocId,
|
||||
interpret::CtfeProvenance,
|
||||
interpret::Scalar,
|
||||
rustc_abi::Size,
|
||||
}
|
||||
|
||||
TrivialLiftImpls! {
|
||||
::rustc_hir::Safety,
|
||||
::rustc_abi::ExternAbi,
|
||||
rustc_hir::def_id::DefId,
|
||||
// tidy-alphabetical-end
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -672,3 +688,39 @@ impl<'tcx, T: TypeFoldable<TyCtxt<'tcx>> + Debug + Clone> TypeFoldable<TyCtxt<'t
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx [InlineAsmTemplatePiece] {
|
||||
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
|
||||
self,
|
||||
_folder: &mut F,
|
||||
) -> Result<Self, F::Error> {
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx [Span] {
|
||||
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
|
||||
self,
|
||||
_folder: &mut F,
|
||||
) -> Result<Self, F::Error> {
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<LocalDefId> {
|
||||
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
|
||||
self,
|
||||
_folder: &mut F,
|
||||
) -> Result<Self, F::Error> {
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<PlaceElem<'tcx>> {
|
||||
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
|
||||
self,
|
||||
folder: &mut F,
|
||||
) -> Result<Self, F::Error> {
|
||||
ty::util::fold_list(self, folder, |tcx, v| tcx.mk_place_elems(v))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ pub struct TypeckResults<'tcx> {
|
|||
|
||||
/// Set of trait imports actually used in the method resolution.
|
||||
/// This is used for warning unused imports. During type
|
||||
/// checking, this `Lrc` should not be cloned: it must have a ref-count
|
||||
/// checking, this `Arc` should not be cloned: it must have a ref-count
|
||||
/// of 1 so that we can insert things into the set mutably.
|
||||
pub used_trait_imports: UnordSet<LocalDefId>,
|
||||
|
||||
|
|
|
|||
|
|
@ -777,7 +777,6 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
self,
|
||||
def_id: DefId,
|
||||
args: GenericArgsRef<'tcx>,
|
||||
inspect_coroutine_fields: InspectCoroutineFields,
|
||||
) -> Result<Ty<'tcx>, Ty<'tcx>> {
|
||||
let mut visitor = OpaqueTypeExpander {
|
||||
seen_opaque_tys: FxHashSet::default(),
|
||||
|
|
@ -786,9 +785,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
found_recursion: false,
|
||||
found_any_recursion: false,
|
||||
check_recursion: true,
|
||||
expand_coroutines: true,
|
||||
tcx: self,
|
||||
inspect_coroutine_fields,
|
||||
};
|
||||
|
||||
let expanded_type = visitor.expand_opaque_ty(def_id, args).unwrap();
|
||||
|
|
@ -965,19 +962,11 @@ struct OpaqueTypeExpander<'tcx> {
|
|||
primary_def_id: Option<DefId>,
|
||||
found_recursion: bool,
|
||||
found_any_recursion: bool,
|
||||
expand_coroutines: bool,
|
||||
/// Whether or not to check for recursive opaque types.
|
||||
/// This is `true` when we're explicitly checking for opaque type
|
||||
/// recursion, and 'false' otherwise to avoid unnecessary work.
|
||||
check_recursion: bool,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
inspect_coroutine_fields: InspectCoroutineFields,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub enum InspectCoroutineFields {
|
||||
No,
|
||||
Yes,
|
||||
}
|
||||
|
||||
impl<'tcx> OpaqueTypeExpander<'tcx> {
|
||||
|
|
@ -1009,41 +998,6 @@ impl<'tcx> OpaqueTypeExpander<'tcx> {
|
|||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn expand_coroutine(&mut self, def_id: DefId, args: GenericArgsRef<'tcx>) -> Option<Ty<'tcx>> {
|
||||
if self.found_any_recursion {
|
||||
return None;
|
||||
}
|
||||
let args = args.fold_with(self);
|
||||
if !self.check_recursion || self.seen_opaque_tys.insert(def_id) {
|
||||
let expanded_ty = match self.expanded_cache.get(&(def_id, args)) {
|
||||
Some(expanded_ty) => *expanded_ty,
|
||||
None => {
|
||||
if matches!(self.inspect_coroutine_fields, InspectCoroutineFields::Yes) {
|
||||
for bty in self.tcx.bound_coroutine_hidden_types(def_id) {
|
||||
let hidden_ty = self.tcx.instantiate_bound_regions_with_erased(
|
||||
bty.instantiate(self.tcx, args),
|
||||
);
|
||||
self.fold_ty(hidden_ty);
|
||||
}
|
||||
}
|
||||
let expanded_ty = Ty::new_coroutine_witness(self.tcx, def_id, args);
|
||||
self.expanded_cache.insert((def_id, args), expanded_ty);
|
||||
expanded_ty
|
||||
}
|
||||
};
|
||||
if self.check_recursion {
|
||||
self.seen_opaque_tys.remove(&def_id);
|
||||
}
|
||||
Some(expanded_ty)
|
||||
} else {
|
||||
// If another opaque type that we contain is recursive, then it
|
||||
// will report the error, so we don't have to.
|
||||
self.found_any_recursion = true;
|
||||
self.found_recursion = def_id == *self.primary_def_id.as_ref().unwrap();
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for OpaqueTypeExpander<'tcx> {
|
||||
|
|
@ -1052,19 +1006,13 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for OpaqueTypeExpander<'tcx> {
|
|||
}
|
||||
|
||||
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
|
||||
let mut t = if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) = *t.kind() {
|
||||
if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) = *t.kind() {
|
||||
self.expand_opaque_ty(def_id, args).unwrap_or(t)
|
||||
} else if t.has_opaque_types() || t.has_coroutines() {
|
||||
} else if t.has_opaque_types() {
|
||||
t.super_fold_with(self)
|
||||
} else {
|
||||
t
|
||||
};
|
||||
if self.expand_coroutines {
|
||||
if let ty::CoroutineWitness(def_id, args) = *t.kind() {
|
||||
t = self.expand_coroutine(def_id, args).unwrap_or(t);
|
||||
}
|
||||
}
|
||||
t
|
||||
}
|
||||
|
||||
fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
|
||||
|
|
@ -1753,9 +1701,7 @@ pub fn reveal_opaque_types_in_bounds<'tcx>(
|
|||
found_recursion: false,
|
||||
found_any_recursion: false,
|
||||
check_recursion: false,
|
||||
expand_coroutines: false,
|
||||
tcx,
|
||||
inspect_coroutine_fields: InspectCoroutineFields::No,
|
||||
};
|
||||
val.fold_with(&mut visitor)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::thir::{self, *};
|
||||
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
|
||||
|
|
@ -12,11 +14,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
/// [`PatKind::Leaf`].
|
||||
///
|
||||
/// Used internally by [`MatchPairTree::for_pattern`].
|
||||
fn field_match_pairs<'pat>(
|
||||
fn field_match_pairs(
|
||||
&mut self,
|
||||
place: PlaceBuilder<'tcx>,
|
||||
subpatterns: &'pat [FieldPat<'tcx>],
|
||||
) -> Vec<MatchPairTree<'pat, 'tcx>> {
|
||||
subpatterns: &[FieldPat<'tcx>],
|
||||
) -> Vec<MatchPairTree<'tcx>> {
|
||||
subpatterns
|
||||
.iter()
|
||||
.map(|fieldpat| {
|
||||
|
|
@ -31,13 +33,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
/// array pattern or slice pattern, and adds those trees to `match_pairs`.
|
||||
///
|
||||
/// Used internally by [`MatchPairTree::for_pattern`].
|
||||
fn prefix_slice_suffix<'pat>(
|
||||
fn prefix_slice_suffix(
|
||||
&mut self,
|
||||
match_pairs: &mut Vec<MatchPairTree<'pat, 'tcx>>,
|
||||
match_pairs: &mut Vec<MatchPairTree<'tcx>>,
|
||||
place: &PlaceBuilder<'tcx>,
|
||||
prefix: &'pat [Box<Pat<'tcx>>],
|
||||
opt_slice: &'pat Option<Box<Pat<'tcx>>>,
|
||||
suffix: &'pat [Box<Pat<'tcx>>],
|
||||
prefix: &[Pat<'tcx>],
|
||||
opt_slice: &Option<Box<Pat<'tcx>>>,
|
||||
suffix: &[Pat<'tcx>],
|
||||
) {
|
||||
let tcx = self.tcx;
|
||||
let (min_length, exact_size) = if let Some(place_resolved) = place.try_to_place(self) {
|
||||
|
|
@ -83,14 +85,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'pat, 'tcx> MatchPairTree<'pat, 'tcx> {
|
||||
impl<'tcx> MatchPairTree<'tcx> {
|
||||
/// Recursively builds a match pair tree for the given pattern and its
|
||||
/// subpatterns.
|
||||
pub(in crate::builder) fn for_pattern(
|
||||
mut place_builder: PlaceBuilder<'tcx>,
|
||||
pattern: &'pat Pat<'tcx>,
|
||||
pattern: &Pat<'tcx>,
|
||||
cx: &mut Builder<'_, 'tcx>,
|
||||
) -> MatchPairTree<'pat, 'tcx> {
|
||||
) -> MatchPairTree<'tcx> {
|
||||
// Force the place type to the pattern's type.
|
||||
// FIXME(oli-obk): can we use this to simplify slice/array pattern hacks?
|
||||
if let Some(resolved) = place_builder.resolve_upvar(cx) {
|
||||
|
|
@ -125,7 +127,7 @@ impl<'pat, 'tcx> MatchPairTree<'pat, 'tcx> {
|
|||
if range.is_full_range(cx.tcx) == Some(true) {
|
||||
default_irrefutable()
|
||||
} else {
|
||||
TestCase::Range(range)
|
||||
TestCase::Range(Arc::clone(range))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -255,6 +257,12 @@ impl<'pat, 'tcx> MatchPairTree<'pat, 'tcx> {
|
|||
PatKind::Never => TestCase::Never,
|
||||
};
|
||||
|
||||
MatchPairTree { place, test_case, subpairs, pattern }
|
||||
MatchPairTree {
|
||||
place,
|
||||
test_case,
|
||||
subpairs,
|
||||
pattern_ty: pattern.ty,
|
||||
pattern_span: pattern.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ mod util;
|
|||
use std::assert_matches::assert_matches;
|
||||
use std::borrow::Borrow;
|
||||
use std::mem;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Arguments to [`Builder::then_else_break_inner`] that are usually forwarded
|
||||
/// to recursive invocations.
|
||||
|
|
@ -361,11 +362,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
let scrutinee_place =
|
||||
unpack!(block = self.lower_scrutinee(block, scrutinee_id, scrutinee_span));
|
||||
|
||||
let arms = arms.iter().map(|arm| &self.thir[*arm]);
|
||||
let match_start_span = span.shrink_to_lo().to(scrutinee_span);
|
||||
let patterns = arms
|
||||
.clone()
|
||||
.map(|arm| {
|
||||
.iter()
|
||||
.map(|&arm| {
|
||||
let arm = &self.thir[arm];
|
||||
let has_match_guard =
|
||||
if arm.guard.is_some() { HasMatchGuard::Yes } else { HasMatchGuard::No };
|
||||
(&*arm.pattern, has_match_guard)
|
||||
|
|
@ -412,20 +413,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
/// (by [Builder::lower_match_tree]).
|
||||
///
|
||||
/// `outer_source_info` is the SourceInfo for the whole match.
|
||||
fn lower_match_arms<'pat>(
|
||||
fn lower_match_arms(
|
||||
&mut self,
|
||||
destination: Place<'tcx>,
|
||||
scrutinee_place_builder: PlaceBuilder<'tcx>,
|
||||
scrutinee_span: Span,
|
||||
arms: impl IntoIterator<Item = &'pat Arm<'tcx>>,
|
||||
arms: &[ArmId],
|
||||
built_match_tree: BuiltMatchTree<'tcx>,
|
||||
outer_source_info: SourceInfo,
|
||||
) -> BlockAnd<()>
|
||||
where
|
||||
'tcx: 'pat,
|
||||
{
|
||||
) -> BlockAnd<()> {
|
||||
let arm_end_blocks: Vec<BasicBlock> = arms
|
||||
.into_iter()
|
||||
.iter()
|
||||
.map(|&arm| &self.thir[arm])
|
||||
.zip(built_match_tree.branches)
|
||||
.map(|(arm, branch)| {
|
||||
debug!("lowering arm {:?}\ncorresponding branch = {:?}", arm, branch);
|
||||
|
|
@ -604,19 +603,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
// Optimize the case of `let x: T = ...` to write directly
|
||||
// into `x` and then require that `T == typeof(x)`.
|
||||
PatKind::AscribeUserType {
|
||||
subpattern:
|
||||
box Pat {
|
||||
kind:
|
||||
PatKind::Binding {
|
||||
mode: BindingMode(ByRef::No, _),
|
||||
var,
|
||||
subpattern: None,
|
||||
..
|
||||
},
|
||||
..
|
||||
},
|
||||
ref subpattern,
|
||||
ascription: thir::Ascription { ref annotation, variance: _ },
|
||||
} => {
|
||||
} if let PatKind::Binding {
|
||||
mode: BindingMode(ByRef::No, _),
|
||||
var,
|
||||
subpattern: None,
|
||||
..
|
||||
} = subpattern.kind =>
|
||||
{
|
||||
let place = self.storage_live_binding(
|
||||
block,
|
||||
var,
|
||||
|
|
@ -989,23 +984,19 @@ impl<'tcx> PatternExtraData<'tcx> {
|
|||
///
|
||||
/// Will typically be incorporated into a [`Candidate`].
|
||||
#[derive(Debug, Clone)]
|
||||
struct FlatPat<'pat, 'tcx> {
|
||||
struct FlatPat<'tcx> {
|
||||
/// To match the pattern, all of these must be satisfied...
|
||||
// Invariant: all the match pairs are recursively simplified.
|
||||
// Invariant: or-patterns must be sorted to the end.
|
||||
match_pairs: Vec<MatchPairTree<'pat, 'tcx>>,
|
||||
match_pairs: Vec<MatchPairTree<'tcx>>,
|
||||
|
||||
extra_data: PatternExtraData<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx, 'pat> FlatPat<'pat, 'tcx> {
|
||||
impl<'tcx> FlatPat<'tcx> {
|
||||
/// Creates a `FlatPat` containing a simplified [`MatchPairTree`] list/forest
|
||||
/// for the given pattern.
|
||||
fn new(
|
||||
place: PlaceBuilder<'tcx>,
|
||||
pattern: &'pat Pat<'tcx>,
|
||||
cx: &mut Builder<'_, 'tcx>,
|
||||
) -> Self {
|
||||
fn new(place: PlaceBuilder<'tcx>, pattern: &Pat<'tcx>, cx: &mut Builder<'_, 'tcx>) -> Self {
|
||||
// First, recursively build a tree of match pairs for the given pattern.
|
||||
let mut match_pairs = vec![MatchPairTree::for_pattern(place, pattern, cx)];
|
||||
let mut extra_data = PatternExtraData {
|
||||
|
|
@ -1033,7 +1024,7 @@ impl<'tcx, 'pat> FlatPat<'pat, 'tcx> {
|
|||
/// of candidates, where each "leaf" candidate represents one of the ways for
|
||||
/// the arm pattern to successfully match.
|
||||
#[derive(Debug)]
|
||||
struct Candidate<'pat, 'tcx> {
|
||||
struct Candidate<'tcx> {
|
||||
/// For the candidate to match, all of these must be satisfied...
|
||||
///
|
||||
/// ---
|
||||
|
|
@ -1055,7 +1046,7 @@ struct Candidate<'pat, 'tcx> {
|
|||
/// Invariants:
|
||||
/// - All [`TestCase::Irrefutable`] patterns have been removed by simplification.
|
||||
/// - All or-patterns ([`TestCase::Or`]) have been sorted to the end.
|
||||
match_pairs: Vec<MatchPairTree<'pat, 'tcx>>,
|
||||
match_pairs: Vec<MatchPairTree<'tcx>>,
|
||||
|
||||
/// ...and if this is non-empty, one of these subcandidates also has to match...
|
||||
///
|
||||
|
|
@ -1072,7 +1063,7 @@ struct Candidate<'pat, 'tcx> {
|
|||
/// Invariant: at the end of match tree lowering, this must not contain an
|
||||
/// `is_never` candidate, because that would break binding consistency.
|
||||
/// - See [`Builder::remove_never_subcandidates`].
|
||||
subcandidates: Vec<Candidate<'pat, 'tcx>>,
|
||||
subcandidates: Vec<Candidate<'tcx>>,
|
||||
|
||||
/// ...and if there is a guard it must be evaluated; if it's `false` then branch to `otherwise_block`.
|
||||
///
|
||||
|
|
@ -1107,10 +1098,10 @@ struct Candidate<'pat, 'tcx> {
|
|||
false_edge_start_block: Option<BasicBlock>,
|
||||
}
|
||||
|
||||
impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
|
||||
impl<'tcx> Candidate<'tcx> {
|
||||
fn new(
|
||||
place: PlaceBuilder<'tcx>,
|
||||
pattern: &'pat Pat<'tcx>,
|
||||
pattern: &Pat<'tcx>,
|
||||
has_guard: HasMatchGuard,
|
||||
cx: &mut Builder<'_, 'tcx>,
|
||||
) -> Self {
|
||||
|
|
@ -1123,7 +1114,7 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
|
|||
}
|
||||
|
||||
/// Incorporates an already-simplified [`FlatPat`] into a new candidate.
|
||||
fn from_flat_pat(flat_pat: FlatPat<'pat, 'tcx>, has_guard: bool) -> Self {
|
||||
fn from_flat_pat(flat_pat: FlatPat<'tcx>, has_guard: bool) -> Self {
|
||||
Candidate {
|
||||
match_pairs: flat_pat.match_pairs,
|
||||
extra_data: flat_pat.extra_data,
|
||||
|
|
@ -1172,7 +1163,7 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
|
|||
/// reference or by value, and to allow a mutable "context" to be shared by the
|
||||
/// traversal callbacks. Most traversals can use the simpler
|
||||
/// [`Candidate::visit_leaves`] wrapper instead.
|
||||
fn traverse_candidate<'pat, 'tcx: 'pat, C, T, I>(
|
||||
fn traverse_candidate<'tcx, C, T, I>(
|
||||
candidate: C,
|
||||
context: &mut T,
|
||||
// Called when visiting a "leaf" candidate (with no subcandidates).
|
||||
|
|
@ -1184,7 +1175,7 @@ fn traverse_candidate<'pat, 'tcx: 'pat, C, T, I>(
|
|||
// Called after visiting a "node" candidate's children.
|
||||
complete_children: impl Copy + Fn(&mut T),
|
||||
) where
|
||||
C: Borrow<Candidate<'pat, 'tcx>>, // Typically `Candidate` or `&mut Candidate`
|
||||
C: Borrow<Candidate<'tcx>>, // Typically `Candidate` or `&mut Candidate`
|
||||
I: Iterator<Item = C>,
|
||||
{
|
||||
if candidate.borrow().subcandidates.is_empty() {
|
||||
|
|
@ -1234,20 +1225,20 @@ struct Ascription<'tcx> {
|
|||
/// participate in or-pattern expansion, where they are transformed into subcandidates.
|
||||
/// - See [`Builder::expand_and_match_or_candidates`].
|
||||
#[derive(Debug, Clone)]
|
||||
enum TestCase<'pat, 'tcx> {
|
||||
enum TestCase<'tcx> {
|
||||
Irrefutable { binding: Option<Binding<'tcx>>, ascription: Option<Ascription<'tcx>> },
|
||||
Variant { adt_def: ty::AdtDef<'tcx>, variant_index: VariantIdx },
|
||||
Constant { value: mir::Const<'tcx> },
|
||||
Range(&'pat PatRange<'tcx>),
|
||||
Range(Arc<PatRange<'tcx>>),
|
||||
Slice { len: usize, variable_length: bool },
|
||||
Deref { temp: Place<'tcx>, mutability: Mutability },
|
||||
Never,
|
||||
Or { pats: Box<[FlatPat<'pat, 'tcx>]> },
|
||||
Or { pats: Box<[FlatPat<'tcx>]> },
|
||||
}
|
||||
|
||||
impl<'pat, 'tcx> TestCase<'pat, 'tcx> {
|
||||
fn as_range(&self) -> Option<&'pat PatRange<'tcx>> {
|
||||
if let Self::Range(v) = self { Some(*v) } else { None }
|
||||
impl<'tcx> TestCase<'tcx> {
|
||||
fn as_range(&self) -> Option<&PatRange<'tcx>> {
|
||||
if let Self::Range(v) = self { Some(v.as_ref()) } else { None }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1257,7 +1248,7 @@ impl<'pat, 'tcx> TestCase<'pat, 'tcx> {
|
|||
/// Each node also has a list of subpairs (possibly empty) that must also match,
|
||||
/// and a reference to the THIR pattern it represents.
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct MatchPairTree<'pat, 'tcx> {
|
||||
pub(crate) struct MatchPairTree<'tcx> {
|
||||
/// This place...
|
||||
///
|
||||
/// ---
|
||||
|
|
@ -1272,7 +1263,7 @@ pub(crate) struct MatchPairTree<'pat, 'tcx> {
|
|||
/// ---
|
||||
/// Invariant: after creation and simplification in [`FlatPat::new`],
|
||||
/// this must not be [`TestCase::Irrefutable`].
|
||||
test_case: TestCase<'pat, 'tcx>,
|
||||
test_case: TestCase<'tcx>,
|
||||
|
||||
/// ... and these subpairs must match.
|
||||
///
|
||||
|
|
@ -1283,8 +1274,10 @@ pub(crate) struct MatchPairTree<'pat, 'tcx> {
|
|||
/// that tests its field for the value `3`.
|
||||
subpairs: Vec<Self>,
|
||||
|
||||
/// The pattern this was created from.
|
||||
pattern: &'pat Pat<'tcx>,
|
||||
/// Type field of the pattern this node was created from.
|
||||
pattern_ty: Ty<'tcx>,
|
||||
/// Span field of the pattern this node was created from.
|
||||
pattern_span: Span,
|
||||
}
|
||||
|
||||
/// See [`Test`] for more.
|
||||
|
|
@ -1320,7 +1313,7 @@ enum TestKind<'tcx> {
|
|||
},
|
||||
|
||||
/// Test whether the value falls within an inclusive or exclusive range.
|
||||
Range(Box<PatRange<'tcx>>),
|
||||
Range(Arc<PatRange<'tcx>>),
|
||||
|
||||
/// Test that the length of the slice is `== len` or `>= len`.
|
||||
Len { len: u64, op: BinOp },
|
||||
|
|
@ -1423,7 +1416,7 @@ struct BuiltMatchTree<'tcx> {
|
|||
|
||||
impl<'tcx> MatchTreeSubBranch<'tcx> {
|
||||
fn from_sub_candidate(
|
||||
candidate: Candidate<'_, 'tcx>,
|
||||
candidate: Candidate<'tcx>,
|
||||
parent_data: &Vec<PatternExtraData<'tcx>>,
|
||||
) -> Self {
|
||||
debug_assert!(candidate.match_pairs.is_empty());
|
||||
|
|
@ -1449,12 +1442,12 @@ impl<'tcx> MatchTreeSubBranch<'tcx> {
|
|||
}
|
||||
|
||||
impl<'tcx> MatchTreeBranch<'tcx> {
|
||||
fn from_candidate(candidate: Candidate<'_, 'tcx>) -> Self {
|
||||
fn from_candidate(candidate: Candidate<'tcx>) -> Self {
|
||||
let mut sub_branches = Vec::new();
|
||||
traverse_candidate(
|
||||
candidate,
|
||||
&mut Vec::new(),
|
||||
&mut |candidate: Candidate<'_, '_>, parent_data: &mut Vec<PatternExtraData<'_>>| {
|
||||
&mut |candidate: Candidate<'_>, parent_data: &mut Vec<PatternExtraData<'_>>| {
|
||||
sub_branches.push(MatchTreeSubBranch::from_sub_candidate(candidate, parent_data));
|
||||
},
|
||||
|inner_candidate, parent_data| {
|
||||
|
|
@ -1485,23 +1478,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
/// `refutable` indicates whether the candidate list is refutable (for `if let` and `let else`)
|
||||
/// or not (for `let` and `match`). In the refutable case we return the block to which we branch
|
||||
/// on failure.
|
||||
fn lower_match_tree<'pat>(
|
||||
fn lower_match_tree(
|
||||
&mut self,
|
||||
block: BasicBlock,
|
||||
scrutinee_span: Span,
|
||||
scrutinee_place_builder: &PlaceBuilder<'tcx>,
|
||||
match_start_span: Span,
|
||||
patterns: Vec<(&'pat Pat<'tcx>, HasMatchGuard)>,
|
||||
patterns: Vec<(&Pat<'tcx>, HasMatchGuard)>,
|
||||
refutable: bool,
|
||||
) -> BuiltMatchTree<'tcx>
|
||||
where
|
||||
'tcx: 'pat,
|
||||
{
|
||||
) -> BuiltMatchTree<'tcx> {
|
||||
// Assemble the initial list of candidates. These top-level candidates are 1:1 with the
|
||||
// input patterns, but other parts of match lowering also introduce subcandidates (for
|
||||
// sub-or-patterns). So inside the algorithm, the candidates list may not correspond to
|
||||
// match arms directly.
|
||||
let mut candidates: Vec<Candidate<'_, '_>> = patterns
|
||||
let mut candidates: Vec<Candidate<'_>> = patterns
|
||||
.into_iter()
|
||||
.map(|(pat, has_guard)| {
|
||||
Candidate::new(scrutinee_place_builder.clone(), pat, has_guard, self)
|
||||
|
|
@ -1664,7 +1654,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
span: Span,
|
||||
scrutinee_span: Span,
|
||||
start_block: BasicBlock,
|
||||
candidates: &mut [&mut Candidate<'_, 'tcx>],
|
||||
candidates: &mut [&mut Candidate<'tcx>],
|
||||
) -> BasicBlock {
|
||||
ensure_sufficient_stack(|| {
|
||||
self.match_candidates_inner(span, scrutinee_span, start_block, candidates)
|
||||
|
|
@ -1678,7 +1668,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
span: Span,
|
||||
scrutinee_span: Span,
|
||||
mut start_block: BasicBlock,
|
||||
candidates: &mut [&mut Candidate<'_, 'tcx>],
|
||||
candidates: &mut [&mut Candidate<'tcx>],
|
||||
) -> BasicBlock {
|
||||
if let [first, ..] = candidates {
|
||||
if first.false_edge_start_block.is_none() {
|
||||
|
|
@ -1747,7 +1737,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
/// [otherwise block]: Candidate::otherwise_block
|
||||
fn select_matched_candidate(
|
||||
&mut self,
|
||||
candidate: &mut Candidate<'_, 'tcx>,
|
||||
candidate: &mut Candidate<'tcx>,
|
||||
start_block: BasicBlock,
|
||||
) -> BasicBlock {
|
||||
assert!(candidate.otherwise_block.is_none());
|
||||
|
|
@ -1765,13 +1755,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
/// Takes a list of candidates such that some of the candidates' first match pairs are
|
||||
/// or-patterns. This expands as many or-patterns as possible and processes the resulting
|
||||
/// candidates. Returns the unprocessed candidates if any.
|
||||
fn expand_and_match_or_candidates<'pat, 'b, 'c>(
|
||||
fn expand_and_match_or_candidates<'b, 'c>(
|
||||
&mut self,
|
||||
span: Span,
|
||||
scrutinee_span: Span,
|
||||
start_block: BasicBlock,
|
||||
candidates: &'b mut [&'c mut Candidate<'pat, 'tcx>],
|
||||
) -> BlockAnd<&'b mut [&'c mut Candidate<'pat, 'tcx>]> {
|
||||
candidates: &'b mut [&'c mut Candidate<'tcx>],
|
||||
) -> BlockAnd<&'b mut [&'c mut Candidate<'tcx>]> {
|
||||
// We can't expand or-patterns freely. The rule is:
|
||||
// - If a candidate doesn't start with an or-pattern, we include it in
|
||||
// the expansion list as-is (i.e. it "expands" to itself).
|
||||
|
|
@ -1865,14 +1855,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
/// Given a match-pair that corresponds to an or-pattern, expand each subpattern into a new
|
||||
/// subcandidate. Any candidate that has been expanded this way should also be postprocessed
|
||||
/// at the end of [`Self::expand_and_match_or_candidates`].
|
||||
fn create_or_subcandidates<'pat>(
|
||||
fn create_or_subcandidates(
|
||||
&mut self,
|
||||
candidate: &mut Candidate<'pat, 'tcx>,
|
||||
match_pair: MatchPairTree<'pat, 'tcx>,
|
||||
candidate: &mut Candidate<'tcx>,
|
||||
match_pair: MatchPairTree<'tcx>,
|
||||
) {
|
||||
let TestCase::Or { pats } = match_pair.test_case else { bug!() };
|
||||
debug!("expanding or-pattern: candidate={:#?}\npats={:#?}", candidate, pats);
|
||||
candidate.or_span = Some(match_pair.pattern.span);
|
||||
candidate.or_span = Some(match_pair.pattern_span);
|
||||
candidate.subcandidates = pats
|
||||
.into_vec()
|
||||
.into_iter()
|
||||
|
|
@ -1938,7 +1928,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
///
|
||||
/// Note that this takes place _after_ the subcandidates have participated
|
||||
/// in match tree lowering.
|
||||
fn merge_trivial_subcandidates(&mut self, candidate: &mut Candidate<'_, 'tcx>) {
|
||||
fn merge_trivial_subcandidates(&mut self, candidate: &mut Candidate<'tcx>) {
|
||||
assert!(!candidate.subcandidates.is_empty());
|
||||
if candidate.has_guard {
|
||||
// FIXME(or_patterns; matthewjasper) Don't give up if we have a guard.
|
||||
|
|
@ -1981,7 +1971,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
/// Never subcandidates may have a set of bindings inconsistent with their siblings,
|
||||
/// which would break later code. So we filter them out. Note that we can't filter out
|
||||
/// top-level candidates this way.
|
||||
fn remove_never_subcandidates(&mut self, candidate: &mut Candidate<'_, 'tcx>) {
|
||||
fn remove_never_subcandidates(&mut self, candidate: &mut Candidate<'tcx>) {
|
||||
if candidate.subcandidates.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
|
@ -2020,7 +2010,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
&mut self,
|
||||
span: Span,
|
||||
scrutinee_span: Span,
|
||||
candidate: &mut Candidate<'_, 'tcx>,
|
||||
candidate: &mut Candidate<'tcx>,
|
||||
) {
|
||||
if candidate.match_pairs.is_empty() {
|
||||
return;
|
||||
|
|
@ -2086,7 +2076,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
/// [`Switch`]: TestKind::Switch
|
||||
/// [`SwitchInt`]: TestKind::SwitchInt
|
||||
/// [`Range`]: TestKind::Range
|
||||
fn pick_test(&mut self, candidates: &[&mut Candidate<'_, 'tcx>]) -> (Place<'tcx>, Test<'tcx>) {
|
||||
fn pick_test(&mut self, candidates: &[&mut Candidate<'tcx>]) -> (Place<'tcx>, Test<'tcx>) {
|
||||
// Extract the match-pair from the highest priority candidate
|
||||
let match_pair = &candidates[0].match_pairs[0];
|
||||
let test = self.pick_test_for_match_pair(match_pair);
|
||||
|
|
@ -2137,18 +2127,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
/// The sorted candidates are mutated to remove entailed match pairs:
|
||||
/// - candidate 0 becomes `[z @ true]` since we know that `x` was `true`;
|
||||
/// - candidate 1 becomes `[y @ false]` since we know that `x` was `false`.
|
||||
fn sort_candidates<'b, 'c, 'pat>(
|
||||
fn sort_candidates<'b, 'c>(
|
||||
&mut self,
|
||||
match_place: Place<'tcx>,
|
||||
test: &Test<'tcx>,
|
||||
mut candidates: &'b mut [&'c mut Candidate<'pat, 'tcx>],
|
||||
mut candidates: &'b mut [&'c mut Candidate<'tcx>],
|
||||
) -> (
|
||||
&'b mut [&'c mut Candidate<'pat, 'tcx>],
|
||||
FxIndexMap<TestBranch<'tcx>, Vec<&'b mut Candidate<'pat, 'tcx>>>,
|
||||
&'b mut [&'c mut Candidate<'tcx>],
|
||||
FxIndexMap<TestBranch<'tcx>, Vec<&'b mut Candidate<'tcx>>>,
|
||||
) {
|
||||
// For each of the possible outcomes, collect vector of candidates that apply if the test
|
||||
// has that particular outcome.
|
||||
let mut target_candidates: FxIndexMap<_, Vec<&mut Candidate<'_, '_>>> = Default::default();
|
||||
let mut target_candidates: FxIndexMap<_, Vec<&mut Candidate<'_>>> = Default::default();
|
||||
|
||||
let total_candidate_count = candidates.len();
|
||||
|
||||
|
|
@ -2274,13 +2264,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
/// ```
|
||||
///
|
||||
/// We return the unprocessed candidates.
|
||||
fn test_candidates<'pat, 'b, 'c>(
|
||||
fn test_candidates<'b, 'c>(
|
||||
&mut self,
|
||||
span: Span,
|
||||
scrutinee_span: Span,
|
||||
candidates: &'b mut [&'c mut Candidate<'pat, 'tcx>],
|
||||
candidates: &'b mut [&'c mut Candidate<'tcx>],
|
||||
start_block: BasicBlock,
|
||||
) -> BlockAnd<&'b mut [&'c mut Candidate<'pat, 'tcx>]> {
|
||||
) -> BlockAnd<&'b mut [&'c mut Candidate<'tcx>]> {
|
||||
// Choose a match pair from the first candidate, and use it to determine a
|
||||
// test to perform that will confirm or refute that match pair.
|
||||
let (match_place, test) = self.pick_test(candidates);
|
||||
|
|
|
|||
|
|
@ -23,9 +23,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
/// Simplify a list of match pairs so they all require a test. Stores relevant bindings and
|
||||
/// ascriptions in `extra_data`.
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
pub(super) fn simplify_match_pairs<'pat>(
|
||||
pub(super) fn simplify_match_pairs(
|
||||
&mut self,
|
||||
match_pairs: &mut Vec<MatchPairTree<'pat, 'tcx>>,
|
||||
match_pairs: &mut Vec<MatchPairTree<'tcx>>,
|
||||
extra_data: &mut PatternExtraData<'tcx>,
|
||||
) {
|
||||
// In order to please the borrow checker, in a pattern like `x @ pat` we must lower the
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
// the candidates based on the result.
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use std::sync::Arc;
|
||||
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_hir::{LangItem, RangeEnd};
|
||||
|
|
@ -26,20 +27,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
/// Identifies what test is needed to decide if `match_pair` is applicable.
|
||||
///
|
||||
/// It is a bug to call this with a not-fully-simplified pattern.
|
||||
pub(super) fn pick_test_for_match_pair<'pat>(
|
||||
pub(super) fn pick_test_for_match_pair(
|
||||
&mut self,
|
||||
match_pair: &MatchPairTree<'pat, 'tcx>,
|
||||
match_pair: &MatchPairTree<'tcx>,
|
||||
) -> Test<'tcx> {
|
||||
let kind = match match_pair.test_case {
|
||||
TestCase::Variant { adt_def, variant_index: _ } => TestKind::Switch { adt_def },
|
||||
|
||||
TestCase::Constant { .. } if match_pair.pattern.ty.is_bool() => TestKind::If,
|
||||
TestCase::Constant { .. } if is_switch_ty(match_pair.pattern.ty) => TestKind::SwitchInt,
|
||||
TestCase::Constant { value } => TestKind::Eq { value, ty: match_pair.pattern.ty },
|
||||
TestCase::Constant { .. } if match_pair.pattern_ty.is_bool() => TestKind::If,
|
||||
TestCase::Constant { .. } if is_switch_ty(match_pair.pattern_ty) => TestKind::SwitchInt,
|
||||
TestCase::Constant { value } => TestKind::Eq { value, ty: match_pair.pattern_ty },
|
||||
|
||||
TestCase::Range(range) => {
|
||||
assert_eq!(range.ty, match_pair.pattern.ty);
|
||||
TestKind::Range(Box::new(range.clone()))
|
||||
TestCase::Range(ref range) => {
|
||||
assert_eq!(range.ty, match_pair.pattern_ty);
|
||||
TestKind::Range(Arc::clone(range))
|
||||
}
|
||||
|
||||
TestCase::Slice { len, variable_length } => {
|
||||
|
|
@ -56,13 +57,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
TestCase::Or { .. } => bug!("or-patterns should have already been handled"),
|
||||
|
||||
TestCase::Irrefutable { .. } => span_bug!(
|
||||
match_pair.pattern.span,
|
||||
match_pair.pattern_span,
|
||||
"simplifiable pattern found: {:?}",
|
||||
match_pair.pattern
|
||||
match_pair.pattern_span
|
||||
),
|
||||
};
|
||||
|
||||
Test { span: match_pair.pattern.span, kind }
|
||||
Test { span: match_pair.pattern_span, kind }
|
||||
}
|
||||
|
||||
#[instrument(skip(self, target_blocks, place), level = "debug")]
|
||||
|
|
@ -521,8 +522,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
&mut self,
|
||||
test_place: Place<'tcx>,
|
||||
test: &Test<'tcx>,
|
||||
candidate: &mut Candidate<'_, 'tcx>,
|
||||
sorted_candidates: &FxIndexMap<TestBranch<'tcx>, Vec<&mut Candidate<'_, 'tcx>>>,
|
||||
candidate: &mut Candidate<'tcx>,
|
||||
sorted_candidates: &FxIndexMap<TestBranch<'tcx>, Vec<&mut Candidate<'tcx>>>,
|
||||
) -> Option<TestBranch<'tcx>> {
|
||||
// Find the match_pair for this place (if any). At present,
|
||||
// afaik, there can be at most one. (In the future, if we
|
||||
|
|
@ -558,14 +559,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
// FIXME(#29623) we could use PatKind::Range to rule
|
||||
// things out here, in some cases.
|
||||
(TestKind::SwitchInt, &TestCase::Constant { value })
|
||||
if is_switch_ty(match_pair.pattern.ty) =>
|
||||
if is_switch_ty(match_pair.pattern_ty) =>
|
||||
{
|
||||
// An important invariant of candidate sorting is that a candidate
|
||||
// must not match in multiple branches. For `SwitchInt` tests, adding
|
||||
// a new value might invalidate that property for range patterns that
|
||||
// have already been sorted into the failure arm, so we must take care
|
||||
// not to add such values here.
|
||||
let is_covering_range = |test_case: &TestCase<'_, 'tcx>| {
|
||||
let is_covering_range = |test_case: &TestCase<'tcx>| {
|
||||
test_case.as_range().is_some_and(|range| {
|
||||
matches!(
|
||||
range.contains(value, self.tcx, self.typing_env()),
|
||||
|
|
@ -573,7 +574,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
)
|
||||
})
|
||||
};
|
||||
let is_conflicting_candidate = |candidate: &&mut Candidate<'_, 'tcx>| {
|
||||
let is_conflicting_candidate = |candidate: &&mut Candidate<'tcx>| {
|
||||
candidate
|
||||
.match_pairs
|
||||
.iter()
|
||||
|
|
@ -685,8 +686,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
(TestKind::Range(test), &TestCase::Range(pat)) => {
|
||||
if test.as_ref() == pat {
|
||||
(TestKind::Range(test), TestCase::Range(pat)) => {
|
||||
if test == pat {
|
||||
fully_matched = true;
|
||||
Some(TestBranch::Success)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
/// a MIR pass run after borrow checking.
|
||||
pub(super) fn collect_fake_borrows<'tcx>(
|
||||
cx: &mut Builder<'_, 'tcx>,
|
||||
candidates: &[Candidate<'_, 'tcx>],
|
||||
candidates: &[Candidate<'tcx>],
|
||||
temp_span: Span,
|
||||
scrutinee_base: PlaceBase,
|
||||
) -> Vec<(Place<'tcx>, Local, FakeBorrowKind)> {
|
||||
|
|
@ -135,7 +135,7 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn visit_candidate(&mut self, candidate: &Candidate<'_, 'tcx>) {
|
||||
fn visit_candidate(&mut self, candidate: &Candidate<'tcx>) {
|
||||
for binding in &candidate.extra_data.bindings {
|
||||
self.visit_binding(binding);
|
||||
}
|
||||
|
|
@ -144,7 +144,7 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn visit_flat_pat(&mut self, flat_pat: &FlatPat<'_, 'tcx>) {
|
||||
fn visit_flat_pat(&mut self, flat_pat: &FlatPat<'tcx>) {
|
||||
for binding in &flat_pat.extra_data.bindings {
|
||||
self.visit_binding(binding);
|
||||
}
|
||||
|
|
@ -153,7 +153,7 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn visit_match_pair(&mut self, match_pair: &MatchPairTree<'_, 'tcx>) {
|
||||
fn visit_match_pair(&mut self, match_pair: &MatchPairTree<'tcx>) {
|
||||
if let TestCase::Or { pats, .. } = &match_pair.test_case {
|
||||
for flat_pat in pats.iter() {
|
||||
self.visit_flat_pat(flat_pat)
|
||||
|
|
|
|||
|
|
@ -676,12 +676,14 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
|
|||
let mut interpreted_as_const = None;
|
||||
let mut interpreted_as_const_sugg = None;
|
||||
|
||||
if let PatKind::ExpandedConstant { def_id, is_inline: false, .. }
|
||||
| PatKind::AscribeUserType {
|
||||
subpattern:
|
||||
box Pat { kind: PatKind::ExpandedConstant { def_id, is_inline: false, .. }, .. },
|
||||
..
|
||||
} = pat.kind
|
||||
// These next few matches want to peek through `AscribeUserType` to see
|
||||
// the underlying pattern.
|
||||
let mut unpeeled_pat = pat;
|
||||
while let PatKind::AscribeUserType { ref subpattern, .. } = unpeeled_pat.kind {
|
||||
unpeeled_pat = subpattern;
|
||||
}
|
||||
|
||||
if let PatKind::ExpandedConstant { def_id, is_inline: false, .. } = unpeeled_pat.kind
|
||||
&& let DefKind::Const = self.tcx.def_kind(def_id)
|
||||
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(pat.span)
|
||||
// We filter out paths with multiple path::segments.
|
||||
|
|
@ -692,11 +694,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
|
|||
// When we encounter a constant as the binding name, point at the `const` definition.
|
||||
interpreted_as_const = Some(span);
|
||||
interpreted_as_const_sugg = Some(InterpretedAsConst { span: pat.span, variable });
|
||||
} else if let PatKind::Constant { .. }
|
||||
| PatKind::AscribeUserType {
|
||||
subpattern: box Pat { kind: PatKind::Constant { .. }, .. },
|
||||
..
|
||||
} = pat.kind
|
||||
} else if let PatKind::Constant { .. } = unpeeled_pat.kind
|
||||
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(pat.span)
|
||||
{
|
||||
// If the pattern to match is an integer literal:
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
let field = FieldIdx::new(idx);
|
||||
// Patterns can only use monomorphic types.
|
||||
let ty = self.tcx.normalize_erasing_regions(self.typing_env, ty);
|
||||
FieldPat { field, pattern: self.valtree_to_pat(val, ty) }
|
||||
FieldPat { field, pattern: *self.valtree_to_pat(val, ty) }
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
|
@ -277,7 +277,7 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
prefix: cv
|
||||
.unwrap_branch()
|
||||
.iter()
|
||||
.map(|val| self.valtree_to_pat(*val, *elem_ty))
|
||||
.map(|val| *self.valtree_to_pat(*val, *elem_ty))
|
||||
.collect(),
|
||||
slice: None,
|
||||
suffix: Box::new([]),
|
||||
|
|
@ -286,7 +286,7 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
prefix: cv
|
||||
.unwrap_branch()
|
||||
.iter()
|
||||
.map(|val| self.valtree_to_pat(*val, *elem_ty))
|
||||
.map(|val| *self.valtree_to_pat(*val, *elem_ty))
|
||||
.collect(),
|
||||
slice: None,
|
||||
suffix: Box::new([]),
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ mod check_match;
|
|||
mod const_to_pat;
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use std::sync::Arc;
|
||||
|
||||
use rustc_abi::{FieldIdx, Integer};
|
||||
use rustc_errors::MultiSpan;
|
||||
|
|
@ -262,7 +263,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||
let hi = lower_endpoint(hi_expr)?.unwrap_or(PatRangeBoundary::PosInfinity);
|
||||
|
||||
let cmp = lo.compare_with(hi, ty, self.tcx, self.typing_env);
|
||||
let mut kind = PatKind::Range(Box::new(PatRange { lo, hi, end, ty }));
|
||||
let mut kind = PatKind::Range(Arc::new(PatRange { lo, hi, end, ty }));
|
||||
match (end, cmp) {
|
||||
// `x..y` where `x < y`.
|
||||
(RangeEnd::Excluded, Some(Ordering::Less)) => {}
|
||||
|
|
@ -418,7 +419,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||
.iter()
|
||||
.map(|field| FieldPat {
|
||||
field: self.typeck_results.field_index(field.hir_id),
|
||||
pattern: self.lower_pattern(field.pat),
|
||||
pattern: *self.lower_pattern(field.pat),
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
|
@ -446,13 +447,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||
.enumerate_and_adjust(expected_len, gap_pos)
|
||||
.map(|(i, subpattern)| FieldPat {
|
||||
field: FieldIdx::new(i),
|
||||
pattern: self.lower_pattern(subpattern),
|
||||
pattern: *self.lower_pattern(subpattern),
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn lower_patterns(&mut self, pats: &'tcx [hir::Pat<'tcx>]) -> Box<[Box<Pat<'tcx>>]> {
|
||||
pats.iter().map(|p| self.lower_pattern(p)).collect()
|
||||
fn lower_patterns(&mut self, pats: &'tcx [hir::Pat<'tcx>]) -> Box<[Pat<'tcx>]> {
|
||||
pats.iter().map(|p| *self.lower_pattern(p)).collect()
|
||||
}
|
||||
|
||||
fn lower_opt_pattern(&mut self, pat: Option<&'tcx hir::Pat<'tcx>>) -> Option<Box<Pat<'tcx>>> {
|
||||
|
|
|
|||
|
|
@ -643,8 +643,8 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
|
|||
print_indented!(self, "}", depth_lvl);
|
||||
}
|
||||
|
||||
fn print_pat(&mut self, pat: &Box<Pat<'tcx>>, depth_lvl: usize) {
|
||||
let Pat { ty, span, kind } = &**pat;
|
||||
fn print_pat(&mut self, pat: &Pat<'tcx>, depth_lvl: usize) {
|
||||
let &Pat { ty, span, ref kind } = pat;
|
||||
|
||||
print_indented!(self, "Pat: {", depth_lvl);
|
||||
print_indented!(self, format!("ty: {:?}", ty), depth_lvl + 1);
|
||||
|
|
|
|||
|
|
@ -1367,16 +1367,17 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||
|
||||
fn simplify_cast(
|
||||
&mut self,
|
||||
kind: &mut CastKind,
|
||||
operand: &mut Operand<'tcx>,
|
||||
initial_kind: &mut CastKind,
|
||||
initial_operand: &mut Operand<'tcx>,
|
||||
to: Ty<'tcx>,
|
||||
location: Location,
|
||||
) -> Option<VnIndex> {
|
||||
use CastKind::*;
|
||||
use rustc_middle::ty::adjustment::PointerCoercion::*;
|
||||
|
||||
let mut from = operand.ty(self.local_decls, self.tcx);
|
||||
let mut value = self.simplify_operand(operand, location)?;
|
||||
let mut from = initial_operand.ty(self.local_decls, self.tcx);
|
||||
let mut kind = *initial_kind;
|
||||
let mut value = self.simplify_operand(initial_operand, location)?;
|
||||
if from == to {
|
||||
return Some(value);
|
||||
}
|
||||
|
|
@ -1400,7 +1401,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||
&& to.is_unsafe_ptr()
|
||||
&& self.pointers_have_same_metadata(from, to)
|
||||
{
|
||||
*kind = PtrToPtr;
|
||||
kind = PtrToPtr;
|
||||
was_updated_this_iteration = true;
|
||||
}
|
||||
|
||||
|
|
@ -1443,7 +1444,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||
to: inner_to,
|
||||
} = *self.get(value)
|
||||
{
|
||||
let new_kind = match (inner_kind, *kind) {
|
||||
let new_kind = match (inner_kind, kind) {
|
||||
// Even if there's a narrowing cast in here that's fine, because
|
||||
// things like `*mut [i32] -> *mut i32 -> *const i32` and
|
||||
// `*mut [i32] -> *const [i32] -> *const i32` can skip the middle in MIR.
|
||||
|
|
@ -1471,7 +1472,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||
_ => None,
|
||||
};
|
||||
if let Some(new_kind) = new_kind {
|
||||
*kind = new_kind;
|
||||
kind = new_kind;
|
||||
from = inner_from;
|
||||
value = inner_value;
|
||||
was_updated_this_iteration = true;
|
||||
|
|
@ -1489,10 +1490,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||
}
|
||||
|
||||
if was_ever_updated && let Some(op) = self.try_as_operand(value, location) {
|
||||
*operand = op;
|
||||
*initial_operand = op;
|
||||
*initial_kind = kind;
|
||||
}
|
||||
|
||||
Some(self.insert(Value::Cast { kind: *kind, value, from, to }))
|
||||
Some(self.insert(Value::Cast { kind, value, from, to }))
|
||||
}
|
||||
|
||||
fn simplify_len(&mut self, place: &mut Place<'tcx>, location: Location) -> Option<VnIndex> {
|
||||
|
|
|
|||
|
|
@ -4,15 +4,13 @@ use rustc_type_ir::fold::TypeFoldable;
|
|||
use rustc_type_ir::solve::{Certainty, Goal, NoSolution};
|
||||
use rustc_type_ir::{self as ty, InferCtxtLike, Interner};
|
||||
|
||||
pub trait SolverDelegate: Deref<Target = <Self as SolverDelegate>::Infcx> + Sized {
|
||||
type Infcx: InferCtxtLike<Interner = <Self as SolverDelegate>::Interner>;
|
||||
pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized {
|
||||
type Infcx: InferCtxtLike<Interner = Self::Interner>;
|
||||
type Interner: Interner;
|
||||
fn cx(&self) -> Self::Interner {
|
||||
(**self).cx()
|
||||
}
|
||||
|
||||
type Span: Copy;
|
||||
|
||||
fn build_with_canonical<V>(
|
||||
cx: Self::Interner,
|
||||
canonical: &ty::CanonicalQueryInput<Self::Interner, V>,
|
||||
|
|
@ -23,7 +21,7 @@ pub trait SolverDelegate: Deref<Target = <Self as SolverDelegate>::Infcx> + Size
|
|||
fn fresh_var_for_kind_with_span(
|
||||
&self,
|
||||
arg: <Self::Interner as Interner>::GenericArg,
|
||||
span: Self::Span,
|
||||
span: <Self::Interner as Interner>::Span,
|
||||
) -> <Self::Interner as Interner>::GenericArg;
|
||||
|
||||
// FIXME: Uplift the leak check into this crate.
|
||||
|
|
@ -61,6 +59,7 @@ pub trait SolverDelegate: Deref<Target = <Self as SolverDelegate>::Infcx> + Size
|
|||
fn instantiate_canonical_var_with_infer(
|
||||
&self,
|
||||
cv_info: ty::CanonicalVarInfo<Self::Interner>,
|
||||
span: <Self::Interner as Interner>::Span,
|
||||
universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
|
||||
) -> <Self::Interner as Interner>::GenericArg;
|
||||
|
||||
|
|
@ -86,6 +85,7 @@ pub trait SolverDelegate: Deref<Target = <Self as SolverDelegate>::Infcx> + Size
|
|||
&self,
|
||||
key: ty::OpaqueTypeKey<Self::Interner>,
|
||||
hidden_ty: <Self::Interner as Interner>::Ty,
|
||||
span: <Self::Interner as Interner>::Span,
|
||||
);
|
||||
|
||||
fn reset_opaque_types(&self);
|
||||
|
|
|
|||
|
|
@ -255,20 +255,29 @@ where
|
|||
self.delegate,
|
||||
&original_values,
|
||||
&response,
|
||||
self.origin_span,
|
||||
);
|
||||
|
||||
let Response { var_values, external_constraints, certainty } =
|
||||
self.delegate.instantiate_canonical(response, instantiation);
|
||||
|
||||
Self::unify_query_var_values(self.delegate, param_env, &original_values, var_values);
|
||||
Self::unify_query_var_values(
|
||||
self.delegate,
|
||||
param_env,
|
||||
&original_values,
|
||||
var_values,
|
||||
self.origin_span,
|
||||
);
|
||||
|
||||
let ExternalConstraintsData {
|
||||
region_constraints,
|
||||
opaque_types,
|
||||
normalization_nested_goals,
|
||||
} = &*external_constraints;
|
||||
|
||||
self.register_region_constraints(region_constraints);
|
||||
self.register_new_opaque_types(opaque_types);
|
||||
|
||||
(normalization_nested_goals.clone(), certainty)
|
||||
}
|
||||
|
||||
|
|
@ -279,6 +288,7 @@ where
|
|||
delegate: &D,
|
||||
original_values: &[I::GenericArg],
|
||||
response: &Canonical<I, T>,
|
||||
span: I::Span,
|
||||
) -> CanonicalVarValues<I> {
|
||||
// FIXME: Longterm canonical queries should deal with all placeholders
|
||||
// created inside of the query directly instead of returning them to the
|
||||
|
|
@ -331,7 +341,7 @@ where
|
|||
// A variable from inside a binder of the query. While ideally these shouldn't
|
||||
// exist at all (see the FIXME at the start of this method), we have to deal with
|
||||
// them for now.
|
||||
delegate.instantiate_canonical_var_with_infer(info, |idx| {
|
||||
delegate.instantiate_canonical_var_with_infer(info, span, |idx| {
|
||||
ty::UniverseIndex::from(prev_universe.index() + idx.index())
|
||||
})
|
||||
} else if info.is_existential() {
|
||||
|
|
@ -345,7 +355,7 @@ where
|
|||
if let Some(v) = opt_values[ty::BoundVar::from_usize(index)] {
|
||||
v
|
||||
} else {
|
||||
delegate.instantiate_canonical_var_with_infer(info, |_| prev_universe)
|
||||
delegate.instantiate_canonical_var_with_infer(info, span, |_| prev_universe)
|
||||
}
|
||||
} else {
|
||||
// For placeholders which were already part of the input, we simply map this
|
||||
|
|
@ -376,12 +386,13 @@ where
|
|||
param_env: I::ParamEnv,
|
||||
original_values: &[I::GenericArg],
|
||||
var_values: CanonicalVarValues<I>,
|
||||
span: I::Span,
|
||||
) {
|
||||
assert_eq!(original_values.len(), var_values.len());
|
||||
|
||||
for (&orig, response) in iter::zip(original_values, var_values.var_values.iter()) {
|
||||
let goals =
|
||||
delegate.eq_structurally_relating_aliases(param_env, orig, response).unwrap();
|
||||
delegate.eq_structurally_relating_aliases(param_env, orig, response, span).unwrap();
|
||||
assert!(goals.is_empty());
|
||||
}
|
||||
}
|
||||
|
|
@ -401,7 +412,7 @@ where
|
|||
|
||||
fn register_new_opaque_types(&mut self, opaque_types: &[(ty::OpaqueTypeKey<I>, I::Ty)]) {
|
||||
for &(key, ty) in opaque_types {
|
||||
self.delegate.inject_new_hidden_type_unchecked(key, ty);
|
||||
self.delegate.inject_new_hidden_type_unchecked(key, ty, self.origin_span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -431,7 +442,7 @@ where
|
|||
// `rustc_trait_selection::solve::inspect::analyse`.
|
||||
pub fn instantiate_canonical_state<D, I, T: TypeFoldable<I>>(
|
||||
delegate: &D,
|
||||
span: D::Span,
|
||||
span: I::Span,
|
||||
param_env: I::ParamEnv,
|
||||
orig_values: &mut Vec<I::GenericArg>,
|
||||
state: inspect::CanonicalState<I, T>,
|
||||
|
|
@ -442,19 +453,17 @@ where
|
|||
{
|
||||
// In case any fresh inference variables have been created between `state`
|
||||
// and the previous instantiation, extend `orig_values` for it.
|
||||
assert!(orig_values.len() <= state.value.var_values.len());
|
||||
for &arg in &state.value.var_values.var_values.as_slice()
|
||||
[orig_values.len()..state.value.var_values.len()]
|
||||
{
|
||||
let unconstrained = delegate.fresh_var_for_kind_with_span(arg, span);
|
||||
orig_values.push(unconstrained);
|
||||
}
|
||||
orig_values.extend(
|
||||
state.value.var_values.var_values.as_slice()[orig_values.len()..]
|
||||
.iter()
|
||||
.map(|&arg| delegate.fresh_var_for_kind_with_span(arg, span)),
|
||||
);
|
||||
|
||||
let instantiation =
|
||||
EvalCtxt::compute_query_response_instantiation_values(delegate, orig_values, &state);
|
||||
EvalCtxt::compute_query_response_instantiation_values(delegate, orig_values, &state, span);
|
||||
|
||||
let inspect::State { var_values, data } = delegate.instantiate_canonical(state, instantiation);
|
||||
|
||||
EvalCtxt::unify_query_var_values(delegate, param_env, orig_values, var_values);
|
||||
EvalCtxt::unify_query_var_values(delegate, param_env, orig_values, var_values, span);
|
||||
data
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,6 +78,8 @@ where
|
|||
|
||||
nested_goals: NestedGoals<I>,
|
||||
|
||||
pub(super) origin_span: I::Span,
|
||||
|
||||
// Has this `EvalCtxt` errored out with `NoSolution` in `try_evaluate_added_goals`?
|
||||
//
|
||||
// If so, then it can no longer be used to make a canonical query response,
|
||||
|
|
@ -134,6 +136,7 @@ pub trait SolverDelegateEvalExt: SolverDelegate {
|
|||
&self,
|
||||
goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>,
|
||||
generate_proof_tree: GenerateProofTree,
|
||||
span: <Self::Interner as Interner>::Span,
|
||||
) -> (
|
||||
Result<(HasChanged, Certainty), NoSolution>,
|
||||
Option<inspect::GoalEvaluation<Self::Interner>>,
|
||||
|
|
@ -174,8 +177,9 @@ where
|
|||
&self,
|
||||
goal: Goal<I, I::Predicate>,
|
||||
generate_proof_tree: GenerateProofTree,
|
||||
span: I::Span,
|
||||
) -> (Result<(HasChanged, Certainty), NoSolution>, Option<inspect::GoalEvaluation<I>>) {
|
||||
EvalCtxt::enter_root(self, self.cx().recursion_limit(), generate_proof_tree, |ecx| {
|
||||
EvalCtxt::enter_root(self, self.cx().recursion_limit(), generate_proof_tree, span, |ecx| {
|
||||
ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal)
|
||||
})
|
||||
}
|
||||
|
|
@ -186,7 +190,7 @@ where
|
|||
goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>,
|
||||
) -> bool {
|
||||
self.probe(|| {
|
||||
EvalCtxt::enter_root(self, root_depth, GenerateProofTree::No, |ecx| {
|
||||
EvalCtxt::enter_root(self, root_depth, GenerateProofTree::No, I::Span::dummy(), |ecx| {
|
||||
ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal)
|
||||
})
|
||||
.0
|
||||
|
|
@ -203,9 +207,13 @@ where
|
|||
Result<(NestedNormalizationGoals<I>, HasChanged, Certainty), NoSolution>,
|
||||
Option<inspect::GoalEvaluation<I>>,
|
||||
) {
|
||||
EvalCtxt::enter_root(self, self.cx().recursion_limit(), generate_proof_tree, |ecx| {
|
||||
ecx.evaluate_goal_raw(GoalEvaluationKind::Root, GoalSource::Misc, goal)
|
||||
})
|
||||
EvalCtxt::enter_root(
|
||||
self,
|
||||
self.cx().recursion_limit(),
|
||||
generate_proof_tree,
|
||||
I::Span::dummy(),
|
||||
|ecx| ecx.evaluate_goal_raw(GoalEvaluationKind::Root, GoalSource::Misc, goal),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -229,6 +237,7 @@ where
|
|||
delegate: &D,
|
||||
root_depth: usize,
|
||||
generate_proof_tree: GenerateProofTree,
|
||||
origin_span: I::Span,
|
||||
f: impl FnOnce(&mut EvalCtxt<'_, D>) -> R,
|
||||
) -> (R, Option<inspect::GoalEvaluation<I>>) {
|
||||
let mut search_graph = SearchGraph::new(root_depth);
|
||||
|
|
@ -248,6 +257,7 @@ where
|
|||
variables: Default::default(),
|
||||
var_values: CanonicalVarValues::dummy(),
|
||||
is_normalizes_to_goal: false,
|
||||
origin_span,
|
||||
tainted: Ok(()),
|
||||
};
|
||||
let result = f(&mut ecx);
|
||||
|
|
@ -289,12 +299,13 @@ where
|
|||
max_input_universe: canonical_input.canonical.max_universe,
|
||||
search_graph,
|
||||
nested_goals: NestedGoals::new(),
|
||||
origin_span: I::Span::dummy(),
|
||||
tainted: Ok(()),
|
||||
inspect: canonical_goal_evaluation.new_goal_evaluation_step(var_values),
|
||||
};
|
||||
|
||||
for &(key, ty) in &input.predefined_opaques_in_body.opaque_types {
|
||||
ecx.delegate.inject_new_hidden_type_unchecked(key, ty);
|
||||
ecx.delegate.inject_new_hidden_type_unchecked(key, ty, ecx.origin_span);
|
||||
}
|
||||
|
||||
if !ecx.nested_goals.is_empty() {
|
||||
|
|
@ -822,8 +833,12 @@ where
|
|||
let identity_args = self.fresh_args_for_item(alias.def_id);
|
||||
let rigid_ctor = ty::AliasTerm::new_from_args(cx, alias.def_id, identity_args);
|
||||
let ctor_term = rigid_ctor.to_term(cx);
|
||||
let obligations =
|
||||
self.delegate.eq_structurally_relating_aliases(param_env, term, ctor_term)?;
|
||||
let obligations = self.delegate.eq_structurally_relating_aliases(
|
||||
param_env,
|
||||
term,
|
||||
ctor_term,
|
||||
self.origin_span,
|
||||
)?;
|
||||
debug_assert!(obligations.is_empty());
|
||||
self.relate(param_env, alias, variance, rigid_ctor)
|
||||
} else {
|
||||
|
|
@ -841,7 +856,12 @@ where
|
|||
lhs: T,
|
||||
rhs: T,
|
||||
) -> Result<(), NoSolution> {
|
||||
let result = self.delegate.eq_structurally_relating_aliases(param_env, lhs, rhs)?;
|
||||
let result = self.delegate.eq_structurally_relating_aliases(
|
||||
param_env,
|
||||
lhs,
|
||||
rhs,
|
||||
self.origin_span,
|
||||
)?;
|
||||
assert_eq!(result, vec![]);
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -864,7 +884,7 @@ where
|
|||
variance: ty::Variance,
|
||||
rhs: T,
|
||||
) -> Result<(), NoSolution> {
|
||||
let goals = self.delegate.relate(param_env, lhs, variance, rhs)?;
|
||||
let goals = self.delegate.relate(param_env, lhs, variance, rhs, self.origin_span)?;
|
||||
self.add_goals(GoalSource::Misc, goals);
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -881,7 +901,7 @@ where
|
|||
lhs: T,
|
||||
rhs: T,
|
||||
) -> Result<Vec<Goal<I, I::Predicate>>, NoSolution> {
|
||||
Ok(self.delegate.relate(param_env, lhs, ty::Variance::Invariant, rhs)?)
|
||||
Ok(self.delegate.relate(param_env, lhs, ty::Variance::Invariant, rhs, self.origin_span)?)
|
||||
}
|
||||
|
||||
pub(super) fn instantiate_binder_with_infer<T: TypeFoldable<I> + Copy>(
|
||||
|
|
@ -917,12 +937,12 @@ where
|
|||
}
|
||||
|
||||
pub(super) fn register_ty_outlives(&self, ty: I::Ty, lt: I::Region) {
|
||||
self.delegate.register_ty_outlives(ty, lt);
|
||||
self.delegate.register_ty_outlives(ty, lt, self.origin_span);
|
||||
}
|
||||
|
||||
pub(super) fn register_region_outlives(&self, a: I::Region, b: I::Region) {
|
||||
// `b : a` ==> `a <= b`
|
||||
self.delegate.sub_regions(b, a);
|
||||
self.delegate.sub_regions(b, a, self.origin_span);
|
||||
}
|
||||
|
||||
/// Computes the list of goals required for `arg` to be well-formed
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ where
|
|||
max_input_universe,
|
||||
search_graph: outer_ecx.search_graph,
|
||||
nested_goals: outer_ecx.nested_goals.clone(),
|
||||
origin_span: outer_ecx.origin_span,
|
||||
tainted: outer_ecx.tainted,
|
||||
inspect: outer_ecx.inspect.take_and_enter_probe(),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -17,12 +17,12 @@
|
|||
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::str::Utf8Error;
|
||||
use std::sync::Arc;
|
||||
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast::{AttrItem, Attribute, MetaItemInner, token};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::{Diag, EmissionGuarantee, FatalError, PResult, pluralize};
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_span::source_map::SourceMap;
|
||||
|
|
@ -147,7 +147,7 @@ pub fn utf8_error<E: EmissionGuarantee>(
|
|||
/// the initial token stream.
|
||||
fn new_parser_from_source_file(
|
||||
psess: &ParseSess,
|
||||
source_file: Lrc<SourceFile>,
|
||||
source_file: Arc<SourceFile>,
|
||||
) -> Result<Parser<'_>, Vec<Diag<'_>>> {
|
||||
let end_pos = source_file.end_position();
|
||||
let stream = source_file_to_stream(psess, source_file, None)?;
|
||||
|
|
@ -172,7 +172,7 @@ pub fn source_str_to_stream(
|
|||
/// parsing the token stream.
|
||||
fn source_file_to_stream<'psess>(
|
||||
psess: &'psess ParseSess,
|
||||
source_file: Lrc<SourceFile>,
|
||||
source_file: Arc<SourceFile>,
|
||||
override_span: Option<Span>,
|
||||
) -> Result<TokenStream, Vec<Diag<'psess>>> {
|
||||
let src = source_file.src.as_ref().unwrap_or_else(|| {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use std::mem::take;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::sync::Arc;
|
||||
|
||||
use ast::token::IdentIsRaw;
|
||||
use rustc_ast as ast;
|
||||
|
|
@ -14,7 +15,6 @@ use rustc_ast::{
|
|||
};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::{
|
||||
Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, PResult, Subdiagnostic, Suggestions,
|
||||
pluralize,
|
||||
|
|
@ -2403,7 +2403,7 @@ impl<'a> Parser<'a> {
|
|||
let mut labels = vec![];
|
||||
while let TokenKind::Interpolated(nt) = &tok.kind {
|
||||
let tokens = nt.tokens();
|
||||
labels.push(Lrc::clone(nt));
|
||||
labels.push(Arc::clone(nt));
|
||||
if let Some(tokens) = tokens
|
||||
&& let tokens = tokens.to_attr_token_stream()
|
||||
&& let tokens = tokens.0.deref()
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ mod ty;
|
|||
|
||||
use std::assert_matches::debug_assert_matches;
|
||||
use std::ops::Range;
|
||||
use std::sync::Arc;
|
||||
use std::{fmt, mem, slice};
|
||||
|
||||
use attr_wrapper::{AttrWrapper, UsePreAttrPos};
|
||||
|
|
@ -34,7 +35,6 @@ use rustc_ast::{
|
|||
};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::{Applicability, Diag, FatalError, MultiSpan, PResult};
|
||||
use rustc_index::interval::IntervalSet;
|
||||
use rustc_session::parse::ParseSess;
|
||||
|
|
@ -1685,5 +1685,5 @@ pub enum ParseNtResult {
|
|||
Lifetime(Ident, IdentIsRaw),
|
||||
|
||||
/// This case will eventually be removed, along with `Token::Interpolate`.
|
||||
Nt(Lrc<Nonterminal>),
|
||||
Nt(Arc<Nonterminal>),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use rustc_ast::HasTokens;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token::Nonterminal::*;
|
||||
|
|
@ -7,7 +9,6 @@ use rustc_ast::token::{
|
|||
self, Delimiter, InvisibleOrigin, MetaVarKind, Nonterminal, NonterminalKind, Token,
|
||||
};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::PResult;
|
||||
use rustc_span::{Ident, kw};
|
||||
|
||||
|
|
@ -235,7 +236,7 @@ impl<'a> Parser<'a> {
|
|||
);
|
||||
}
|
||||
|
||||
Ok(ParseNtResult::Nt(Lrc::new(nt)))
|
||||
Ok(ParseNtResult::Nt(Arc::new(nt)))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ use rustc_ast::token::{self, Delimiter, Token};
|
|||
use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
|
||||
use rustc_ast::{self as ast, PatKind, visit};
|
||||
use rustc_ast_pretty::pprust::item_to_string;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::emitter::{HumanEmitter, OutputTheme};
|
||||
use rustc_errors::{DiagCtxt, MultiSpan, PResult};
|
||||
use rustc_session::parse::ParseSess;
|
||||
|
|
@ -27,7 +26,7 @@ use crate::parser::{ForceCollect, Parser};
|
|||
use crate::{new_parser_from_source_str, source_str_to_stream, unwrap_or_emit_fatal};
|
||||
|
||||
fn psess() -> ParseSess {
|
||||
ParseSess::new(vec![crate::DEFAULT_LOCALE_RESOURCE, crate::DEFAULT_LOCALE_RESOURCE])
|
||||
ParseSess::new(vec![crate::DEFAULT_LOCALE_RESOURCE])
|
||||
}
|
||||
|
||||
/// Map string to parser (via tts).
|
||||
|
|
@ -39,13 +38,11 @@ fn string_to_parser(psess: &ParseSess, source_str: String) -> Parser<'_> {
|
|||
))
|
||||
}
|
||||
|
||||
fn create_test_handler(theme: OutputTheme) -> (DiagCtxt, Lrc<SourceMap>, Arc<Mutex<Vec<u8>>>) {
|
||||
fn create_test_handler(theme: OutputTheme) -> (DiagCtxt, Arc<SourceMap>, Arc<Mutex<Vec<u8>>>) {
|
||||
let output = Arc::new(Mutex::new(Vec::new()));
|
||||
let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty()));
|
||||
let fallback_bundle = rustc_errors::fallback_fluent_bundle(
|
||||
vec![crate::DEFAULT_LOCALE_RESOURCE, crate::DEFAULT_LOCALE_RESOURCE],
|
||||
false,
|
||||
);
|
||||
let source_map = Arc::new(SourceMap::new(FilePathMapping::empty()));
|
||||
let fallback_bundle =
|
||||
rustc_errors::fallback_fluent_bundle(vec![crate::DEFAULT_LOCALE_RESOURCE], false);
|
||||
let mut emitter = HumanEmitter::new(Box::new(Shared { data: output.clone() }), fallback_bundle)
|
||||
.sm(Some(source_map.clone()))
|
||||
.diagnostic_width(Some(140));
|
||||
|
|
|
|||
|
|
@ -1851,6 +1851,34 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
let mut is_simd = false;
|
||||
let mut is_transparent = false;
|
||||
|
||||
// catch `repr()` with no arguments, applied to an item (i.e. not `#![repr()]`)
|
||||
if hints.is_empty() && item.is_some() {
|
||||
for attr in attrs.iter().filter(|attr| attr.has_name(sym::repr)) {
|
||||
match target {
|
||||
Target::Struct | Target::Union | Target::Enum => {}
|
||||
Target::Fn | Target::Method(_) => {
|
||||
feature_err(
|
||||
&self.tcx.sess,
|
||||
sym::fn_align,
|
||||
attr.span,
|
||||
fluent::passes_repr_align_function,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
_ => {
|
||||
self.dcx().emit_err(
|
||||
errors::AttrApplication::StructEnumFunctionMethodUnion {
|
||||
hint_span: attr.span,
|
||||
span,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for hint in &hints {
|
||||
if !hint.is_meta_item() {
|
||||
self.dcx().emit_err(errors::ReprIdent { span: hint.span() });
|
||||
|
|
@ -1883,24 +1911,19 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
}
|
||||
}
|
||||
sym::align => {
|
||||
if let (Target::Fn | Target::Method(MethodKind::Inherent), false) =
|
||||
(target, self.tcx.features().fn_align())
|
||||
{
|
||||
feature_err(
|
||||
&self.tcx.sess,
|
||||
sym::fn_align,
|
||||
hint.span(),
|
||||
fluent::passes_repr_align_function,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
|
||||
match target {
|
||||
Target::Struct
|
||||
| Target::Union
|
||||
| Target::Enum
|
||||
| Target::Fn
|
||||
| Target::Method(_) => {}
|
||||
Target::Struct | Target::Union | Target::Enum => {}
|
||||
Target::Fn | Target::Method(_) => {
|
||||
if !self.tcx.features().fn_align() {
|
||||
feature_err(
|
||||
&self.tcx.sess,
|
||||
sym::fn_align,
|
||||
hint.span(),
|
||||
fluent::passes_repr_align_function,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
self.dcx().emit_err(
|
||||
errors::AttrApplication::StructEnumFunctionMethodUnion {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
|||
use rustc_data_structures::profiling::{QueryInvocationId, SelfProfilerRef};
|
||||
use rustc_data_structures::sharded::{self, Sharded};
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_data_structures::sync::{AtomicU32, AtomicU64, Lock, Lrc};
|
||||
use rustc_data_structures::sync::{AtomicU32, AtomicU64, Lock};
|
||||
use rustc_data_structures::unord::UnordMap;
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_macros::{Decodable, Encodable};
|
||||
|
|
@ -29,13 +29,13 @@ use crate::query::{QueryContext, QuerySideEffects};
|
|||
|
||||
#[derive(Clone)]
|
||||
pub struct DepGraph<D: Deps> {
|
||||
data: Option<Lrc<DepGraphData<D>>>,
|
||||
data: Option<Arc<DepGraphData<D>>>,
|
||||
|
||||
/// This field is used for assigning DepNodeIndices when running in
|
||||
/// non-incremental mode. Even in non-incremental mode we make sure that
|
||||
/// each task has a `DepNodeIndex` that uniquely identifies it. This unique
|
||||
/// ID is used for self-profiling.
|
||||
virtual_dep_node_index: Lrc<AtomicU32>,
|
||||
virtual_dep_node_index: Arc<AtomicU32>,
|
||||
}
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
|
|
@ -171,7 +171,7 @@ impl<D: Deps> DepGraph<D> {
|
|||
}
|
||||
|
||||
DepGraph {
|
||||
data: Some(Lrc::new(DepGraphData {
|
||||
data: Some(Arc::new(DepGraphData {
|
||||
previous_work_products: prev_work_products,
|
||||
dep_node_debug: Default::default(),
|
||||
current,
|
||||
|
|
@ -180,12 +180,12 @@ impl<D: Deps> DepGraph<D> {
|
|||
colors,
|
||||
debug_loaded_from_disk: Default::default(),
|
||||
})),
|
||||
virtual_dep_node_index: Lrc::new(AtomicU32::new(0)),
|
||||
virtual_dep_node_index: Arc::new(AtomicU32::new(0)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_disabled() -> DepGraph<D> {
|
||||
DepGraph { data: None, virtual_dep_node_index: Lrc::new(AtomicU32::new(0)) }
|
||||
DepGraph { data: None, virtual_dep_node_index: Arc::new(AtomicU32::new(0)) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use rustc_ast as ast;
|
||||
use rustc_data_structures::stable_hasher::{HashStable, HashingControls, StableHasher};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::definitions::DefPathHash;
|
||||
use rustc_session::Session;
|
||||
|
|
@ -117,7 +118,7 @@ impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> {
|
|||
fn span_data_to_lines_and_cols(
|
||||
&mut self,
|
||||
span: &SpanData,
|
||||
) -> Option<(Lrc<SourceFile>, usize, BytePos, usize, BytePos)> {
|
||||
) -> Option<(Arc<SourceFile>, usize, BytePos, usize, BytePos)> {
|
||||
self.source_map().span_data_to_lines_and_cols(span)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
//! Imports are also considered items and placed into modules here, but not resolved yet.
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::sync::Arc;
|
||||
|
||||
use rustc_ast::visit::{self, AssocCtxt, Visitor, WalkItemKind};
|
||||
use rustc_ast::{
|
||||
|
|
@ -13,7 +14,6 @@ use rustc_ast::{
|
|||
ItemKind, MetaItemKind, NodeId, StmtKind,
|
||||
};
|
||||
use rustc_attr_parsing as attr;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_expand::base::ResolverExpand;
|
||||
use rustc_expand::expand::AstFragment;
|
||||
use rustc_hir::def::{self, *};
|
||||
|
|
@ -179,7 +179,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
LoadedMacro::MacroDef { def, ident, attrs, span, edition } => {
|
||||
self.compile_macro(&def, ident, &attrs, span, ast::DUMMY_NODE_ID, edition)
|
||||
}
|
||||
LoadedMacro::ProcMacro(ext) => MacroData::new(Lrc::new(ext)),
|
||||
LoadedMacro::ProcMacro(ext) => MacroData::new(Arc::new(ext)),
|
||||
};
|
||||
|
||||
self.macro_map.entry(def_id).or_insert(macro_data)
|
||||
|
|
|
|||
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