1
Fork 0

Auto merge of #105378 - matthiaskrgr:rollup-fjeorw5, r=matthiaskrgr

Rollup of 9 pull requests

Successful merges:

 - #104898 (Put all cached values into a central struct instead of just the stable hash)
 - #105004 (Fix `emit_unused_delims_expr` ICE)
 - #105174 (Suggest removing struct field from destructive binding only in shorthand scenario)
 - #105250 (Replace usage of `ResumeTy` in async lowering with `Context`)
 - #105286 (Add -Z maximal-hir-to-mir-coverage flag)
 - #105320 (rustdoc: simplify CSS selectors on top-doc and non-exhaustive toggles)
 - #105349 (Point at args in associated const fn pointers)
 - #105362 (Cleanup macro-expanded code in `rustc_type_ir`)
 - #105370 (Remove outdated syntax from trait alias pretty printing)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2022-12-06 18:51:14 +00:00
commit b28d30e1e3
46 changed files with 650 additions and 742 deletions

View file

@ -16,7 +16,7 @@ use rustc_hir::def::Res;
use rustc_hir::definitions::DefPathData; use rustc_hir::definitions::DefPathData;
use rustc_session::errors::report_lit_error; use rustc_session::errors::report_lit_error;
use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned}; use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned};
use rustc_span::symbol::{sym, Ident}; use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::DUMMY_SP; use rustc_span::DUMMY_SP;
use thin_vec::thin_vec; use thin_vec::thin_vec;
@ -594,14 +594,38 @@ impl<'hir> LoweringContext<'_, 'hir> {
) -> hir::ExprKind<'hir> { ) -> hir::ExprKind<'hir> {
let output = ret_ty.unwrap_or_else(|| hir::FnRetTy::DefaultReturn(self.lower_span(span))); let output = ret_ty.unwrap_or_else(|| hir::FnRetTy::DefaultReturn(self.lower_span(span)));
// Resume argument type: `ResumeTy` // Resume argument type, which should be `&mut Context<'_>`.
let unstable_span = // NOTE: Using the `'static` lifetime here is technically cheating.
self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone()); // The `Future::poll` argument really is `&'a mut Context<'b>`, but we cannot
let resume_ty = hir::QPath::LangItem(hir::LangItem::ResumeTy, unstable_span, None); // express the fact that we are not storing it across yield-points yet,
// and we would thus run into lifetime errors.
// See <https://github.com/rust-lang/rust/issues/68923>.
// Our lowering makes sure we are not mis-using the `_task_context` input type
// in the sense that we are indeed not using it across yield points. We
// get a fresh `&mut Context` for each resume / call of `Future::poll`.
// This "cheating" was previously done with a `ResumeTy` that contained a raw
// pointer, and a `get_context` accessor that pulled the `Context` lifetimes
// out of thin air.
let context_lifetime_ident = Ident::with_dummy_span(kw::StaticLifetime);
let context_lifetime = self.arena.alloc(hir::Lifetime {
hir_id: self.next_id(),
ident: context_lifetime_ident,
res: hir::LifetimeName::Static,
});
let context_path =
hir::QPath::LangItem(hir::LangItem::Context, self.lower_span(span), None);
let context_ty = hir::MutTy {
ty: self.arena.alloc(hir::Ty {
hir_id: self.next_id(),
kind: hir::TyKind::Path(context_path),
span: self.lower_span(span),
}),
mutbl: hir::Mutability::Mut,
};
let input_ty = hir::Ty { let input_ty = hir::Ty {
hir_id: self.next_id(), hir_id: self.next_id(),
kind: hir::TyKind::Path(resume_ty), kind: hir::TyKind::Rptr(context_lifetime, context_ty),
span: unstable_span, span: self.lower_span(span),
}; };
// The closure/generator `FnDecl` takes a single (resume) argument of type `input_ty`. // The closure/generator `FnDecl` takes a single (resume) argument of type `input_ty`.
@ -659,12 +683,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
.map_or(false, |attrs| attrs.into_iter().any(|attr| attr.has_name(sym::track_caller))); .map_or(false, |attrs| attrs.into_iter().any(|attr| attr.has_name(sym::track_caller)));
let hir_id = self.lower_node_id(closure_node_id); let hir_id = self.lower_node_id(closure_node_id);
let unstable_span =
self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone());
if track_caller { if track_caller {
let unstable_span = self.mark_span_with_reason(
DesugaringKind::Async,
span,
self.allow_gen_future.clone(),
);
self.lower_attrs( self.lower_attrs(
hir_id, hir_id,
&[Attribute { &[Attribute {
@ -711,7 +732,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
/// mut __awaitee => loop { /// mut __awaitee => loop {
/// match unsafe { ::std::future::Future::poll( /// match unsafe { ::std::future::Future::poll(
/// <::std::pin::Pin>::new_unchecked(&mut __awaitee), /// <::std::pin::Pin>::new_unchecked(&mut __awaitee),
/// ::std::future::get_context(task_context), /// task_context,
/// ) } { /// ) } {
/// ::std::task::Poll::Ready(result) => break result, /// ::std::task::Poll::Ready(result) => break result,
/// ::std::task::Poll::Pending => {} /// ::std::task::Poll::Pending => {}
@ -752,7 +773,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
// unsafe { // unsafe {
// ::std::future::Future::poll( // ::std::future::Future::poll(
// ::std::pin::Pin::new_unchecked(&mut __awaitee), // ::std::pin::Pin::new_unchecked(&mut __awaitee),
// ::std::future::get_context(task_context), // task_context,
// ) // )
// } // }
let poll_expr = { let poll_expr = {
@ -770,16 +791,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
arena_vec![self; ref_mut_awaitee], arena_vec![self; ref_mut_awaitee],
Some(expr_hir_id), Some(expr_hir_id),
); );
let get_context = self.expr_call_lang_item_fn_mut(
gen_future_span,
hir::LangItem::GetContext,
arena_vec![self; task_context],
Some(expr_hir_id),
);
let call = self.expr_call_lang_item_fn( let call = self.expr_call_lang_item_fn(
span, span,
hir::LangItem::FuturePoll, hir::LangItem::FuturePoll,
arena_vec![self; new_unchecked, get_context], arena_vec![self; new_unchecked, task_context],
Some(expr_hir_id), Some(expr_hir_id),
); );
self.arena.alloc(self.expr_unsafe(call)) self.arena.alloc(self.expr_unsafe(call))

View file

@ -348,21 +348,10 @@ impl<'a> State<'a> {
self.head(visibility_qualified(&item.vis, "trait")); self.head(visibility_qualified(&item.vis, "trait"));
self.print_ident(item.ident); self.print_ident(item.ident);
self.print_generic_params(&generics.params); self.print_generic_params(&generics.params);
let mut real_bounds = Vec::with_capacity(bounds.len());
// FIXME(durka) this seems to be some quite outdated syntax
for b in bounds.iter() {
if let GenericBound::Trait(ptr, ast::TraitBoundModifier::Maybe) = b {
self.space();
self.word_space("for ?");
self.print_trait_ref(&ptr.trait_ref);
} else {
real_bounds.push(b.clone());
}
}
self.nbsp(); self.nbsp();
if !real_bounds.is_empty() { if !bounds.is_empty() {
self.word_nbsp("="); self.word_nbsp("=");
self.print_type_bounds(&real_bounds); self.print_type_bounds(&bounds);
} }
self.print_where_clause(&generics.where_clause); self.print_where_clause(&generics.where_clause);
self.word(";"); self.word(";");

View file

@ -4,8 +4,6 @@ use std::hash::{Hash, Hasher};
use std::ops::Deref; use std::ops::Deref;
use std::ptr; use std::ptr;
use crate::fingerprint::Fingerprint;
mod private { mod private {
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
pub struct PrivateZst; pub struct PrivateZst;
@ -110,86 +108,5 @@ where
} }
} }
/// A helper type that you can wrap round your own type in order to automatically
/// cache the stable hash on creation and not recompute it whenever the stable hash
/// of the type is computed.
/// This is only done in incremental mode. You can also opt out of caching by using
/// StableHash::ZERO for the hash, in which case the hash gets computed each time.
/// This is useful if you have values that you intern but never (can?) use for stable
/// hashing.
#[derive(Copy, Clone)]
pub struct WithStableHash<T> {
pub internee: T,
pub stable_hash: Fingerprint,
}
impl<T: PartialEq> PartialEq for WithStableHash<T> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.internee.eq(&other.internee)
}
}
impl<T: Eq> Eq for WithStableHash<T> {}
impl<T: Ord> PartialOrd for WithStableHash<T> {
fn partial_cmp(&self, other: &WithStableHash<T>) -> Option<Ordering> {
Some(self.internee.cmp(&other.internee))
}
}
impl<T: Ord> Ord for WithStableHash<T> {
fn cmp(&self, other: &WithStableHash<T>) -> Ordering {
self.internee.cmp(&other.internee)
}
}
impl<T> Deref for WithStableHash<T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
&self.internee
}
}
impl<T: Hash> Hash for WithStableHash<T> {
#[inline]
fn hash<H: Hasher>(&self, s: &mut H) {
if self.stable_hash != Fingerprint::ZERO {
self.stable_hash.hash(s)
} else {
self.internee.hash(s)
}
}
}
impl<T: HashStable<CTX>, CTX> HashStable<CTX> for WithStableHash<T> {
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
if self.stable_hash == Fingerprint::ZERO || cfg!(debug_assertions) {
// No cached hash available. This can only mean that incremental is disabled.
// We don't cache stable hashes in non-incremental mode, because they are used
// so rarely that the performance actually suffers.
// We need to build the hash as if we cached it and then hash that hash, as
// otherwise the hashes will differ between cached and non-cached mode.
let stable_hash: Fingerprint = {
let mut hasher = StableHasher::new();
self.internee.hash_stable(hcx, &mut hasher);
hasher.finish()
};
if cfg!(debug_assertions) && self.stable_hash != Fingerprint::ZERO {
assert_eq!(
stable_hash, self.stable_hash,
"cached stable hash does not match freshly computed stable hash"
);
}
stable_hash.hash_stable(hcx, hasher);
} else {
self.stable_hash.hash_stable(hcx, hasher);
}
}
}
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;

View file

@ -286,10 +286,9 @@ language_item_table! {
// FIXME(swatinem): the following lang items are used for async lowering and // FIXME(swatinem): the following lang items are used for async lowering and
// should become obsolete eventually. // should become obsolete eventually.
ResumeTy, sym::ResumeTy, resume_ty, Target::Struct, GenericRequirement::None;
IdentityFuture, sym::identity_future, identity_future_fn, Target::Fn, GenericRequirement::None; IdentityFuture, sym::identity_future, identity_future_fn, Target::Fn, GenericRequirement::None;
GetContext, sym::get_context, get_context_fn, Target::Fn, GenericRequirement::None;
Context, sym::Context, context, Target::Struct, GenericRequirement::None;
FuturePoll, sym::poll, future_poll_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None; FuturePoll, sym::poll, future_poll_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
FromFrom, sym::from, from_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None; FromFrom, sym::from, from_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;

View file

@ -695,19 +695,8 @@ impl<'a> State<'a> {
self.head("trait"); self.head("trait");
self.print_ident(item.ident); self.print_ident(item.ident);
self.print_generic_params(generics.params); self.print_generic_params(generics.params);
let mut real_bounds = Vec::with_capacity(bounds.len());
// FIXME(durka) this seems to be some quite outdated syntax
for b in bounds {
if let GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = b {
self.space();
self.word_space("for ?");
self.print_trait_ref(&ptr.trait_ref);
} else {
real_bounds.push(b);
}
}
self.nbsp(); self.nbsp();
self.print_bounds("=", real_bounds); self.print_bounds("=", bounds);
self.print_where_clause(generics); self.print_where_clause(generics);
self.word(";"); self.word(";");
self.end(); // end inner head-block self.end(); // end inner head-block

View file

@ -1918,15 +1918,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
receiver: Option<&'tcx hir::Expr<'tcx>>, receiver: Option<&'tcx hir::Expr<'tcx>>,
args: &'tcx [hir::Expr<'tcx>], args: &'tcx [hir::Expr<'tcx>],
) -> bool { ) -> bool {
// Do not call `fn_sig` on non-functions. let ty = self.tcx.type_of(def_id);
if !matches!( if !ty.is_fn() {
self.tcx.def_kind(def_id),
DefKind::Fn | DefKind::AssocFn | DefKind::Variant | DefKind::Ctor(..)
) {
return false; return false;
} }
let sig = ty.fn_sig(self.tcx).skip_binder();
let sig = self.tcx.fn_sig(def_id).skip_binder();
let args_referencing_param: Vec<_> = sig let args_referencing_param: Vec<_> = sig
.inputs() .inputs()
.iter() .iter()

View file

@ -747,6 +747,7 @@ fn test_unstable_options_tracking_hash() {
tracked!(link_only, true); tracked!(link_only, true);
tracked!(llvm_plugins, vec![String::from("plugin_name")]); tracked!(llvm_plugins, vec![String::from("plugin_name")]);
tracked!(location_detail, LocationDetail { file: true, line: false, column: false }); tracked!(location_detail, LocationDetail { file: true, line: false, column: false });
tracked!(maximal_hir_to_mir_coverage, true);
tracked!(merge_functions, Some(MergeFunctions::Disabled)); tracked!(merge_functions, Some(MergeFunctions::Disabled));
tracked!(mir_emit_retag, true); tracked!(mir_emit_retag, true);
tracked!(mir_enable_passes, vec![("DestProp".to_string(), false)]); tracked!(mir_enable_passes, vec![("DestProp".to_string(), false)]);

View file

@ -10,7 +10,7 @@ declare_tool_lint! {
/// The `rustc_pass_by_value` lint marks a type with `#[rustc_pass_by_value]` requiring it to /// The `rustc_pass_by_value` lint marks a type with `#[rustc_pass_by_value]` requiring it to
/// always be passed by value. This is usually used for types that are thin wrappers around /// always be passed by value. This is usually used for types that are thin wrappers around
/// references, so there is no benefit to an extra layer of indirection. (Example: `Ty` which /// references, so there is no benefit to an extra layer of indirection. (Example: `Ty` which
/// is a reference to an `Interned<TyS>`) /// is a reference to an `Interned<TyKind>`)
pub rustc::PASS_BY_VALUE, pub rustc::PASS_BY_VALUE,
Warn, Warn,
"pass by reference of a type flagged as `#[rustc_pass_by_value]`", "pass by reference of a type flagged as `#[rustc_pass_by_value]`",

View file

@ -633,13 +633,34 @@ trait UnusedDelimLint {
left_pos: Option<BytePos>, left_pos: Option<BytePos>,
right_pos: Option<BytePos>, right_pos: Option<BytePos>,
) { ) {
// If `value` has `ExprKind::Err`, unused delim lint can be broken.
// For example, the following code caused ICE.
// This is because the `ExprKind::Call` in `value` has `ExprKind::Err` as its argument
// and this leads to wrong spans. #104897
//
// ```
// fn f(){(print!(á
// ```
use rustc_ast::visit::{walk_expr, Visitor};
struct ErrExprVisitor {
has_error: bool,
}
impl<'ast> Visitor<'ast> for ErrExprVisitor {
fn visit_expr(&mut self, expr: &'ast ast::Expr) {
if let ExprKind::Err = expr.kind {
self.has_error = true;
return;
}
walk_expr(self, expr)
}
}
let mut visitor = ErrExprVisitor { has_error: false };
visitor.visit_expr(value);
if visitor.has_error {
return;
}
let spans = match value.kind { let spans = match value.kind {
ast::ExprKind::Block(ref block, None) if block.stmts.len() == 1 => { ast::ExprKind::Block(ref block, None) if block.stmts.len() == 1 => {
if let StmtKind::Expr(expr) = &block.stmts[0].kind
&& let ExprKind::Err = expr.kind
{
return
}
if let Some(span) = block.stmts[0].span.find_ancestor_inside(value.span) { if let Some(span) = block.stmts[0].span.find_ancestor_inside(value.span) {
Some((value.span.with_hi(span.lo()), value.span.with_lo(span.hi()))) Some((value.span.with_hi(span.lo()), value.span.with_lo(span.hi())))
} else { } else {

View file

@ -1,3 +1,5 @@
#![allow(rustc::usage_of_ty_tykind)]
/// This higher-order macro declares a list of types which can be allocated by `Arena`. /// This higher-order macro declares a list of types which can be allocated by `Arena`.
/// ///
/// Specifying the `decode` modifier will add decode impls for `&T` and `&[T]` where `T` is the type /// Specifying the `decode` modifier will add decode impls for `&T` and `&[T]` where `T` is the type
@ -89,8 +91,8 @@ macro_rules! arena_types {
[] hir_id_set: rustc_hir::HirIdSet, [] hir_id_set: rustc_hir::HirIdSet,
// Interned types // Interned types
[] tys: rustc_data_structures::intern::WithStableHash<rustc_middle::ty::TyS<'tcx>>, [] tys: rustc_type_ir::WithCachedTypeInfo<rustc_middle::ty::TyKind<'tcx>>,
[] predicates: rustc_data_structures::intern::WithStableHash<rustc_middle::ty::PredicateS<'tcx>>, [] predicates: rustc_type_ir::WithCachedTypeInfo<rustc_middle::ty::PredicateKind<'tcx>>,
[] consts: rustc_middle::ty::ConstS<'tcx>, [] consts: rustc_middle::ty::ConstS<'tcx>,
// Note that this deliberately duplicates items in the `rustc_hir::arena`, // Note that this deliberately duplicates items in the `rustc_hir::arena`,

View file

@ -103,7 +103,7 @@ impl hash::Hash for Allocation {
/// Interned types generally have an `Outer` type and an `Inner` type, where /// Interned types generally have an `Outer` type and an `Inner` type, where
/// `Outer` is a newtype around `Interned<Inner>`, and all the operations are /// `Outer` is a newtype around `Interned<Inner>`, and all the operations are
/// done on `Outer`, because all occurrences are interned. E.g. `Ty` is an /// done on `Outer`, because all occurrences are interned. E.g. `Ty` is an
/// outer type and `TyS` is its inner type. /// outer type and `TyKind` is its inner type.
/// ///
/// Here things are different because only const allocations are interned. This /// Here things are different because only const allocations are interned. This
/// means that both the inner type (`Allocation`) and the outer type /// means that both the inner type (`Allocation`) and the outer type

View file

@ -1,5 +1,7 @@
//! Type context book-keeping. //! Type context book-keeping.
#![allow(rustc::usage_of_ty_tykind)]
use crate::arena::Arena; use crate::arena::Arena;
use crate::dep_graph::{DepGraph, DepKindStruct}; use crate::dep_graph::{DepGraph, DepKindStruct};
use crate::hir::place::Place as HirPlace; use crate::hir::place::Place as HirPlace;
@ -19,15 +21,15 @@ use crate::ty::{
self, AdtDef, AdtDefData, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig, self, AdtDef, AdtDefData, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig,
ClosureSizeProfileData, Const, ConstS, DefIdTree, FloatTy, FloatVar, FloatVid, ClosureSizeProfileData, Const, ConstS, DefIdTree, FloatTy, FloatVar, FloatVid,
GenericParamDefKind, InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy, GenericParamDefKind, InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy,
PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, PredicateS, ProjectionTy, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, ProjectionTy, Region,
Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar, TyVid, TypeAndMut, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, UintTy,
UintTy, Visibility, Visibility,
}; };
use crate::ty::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef, UserSubsts}; use crate::ty::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef, UserSubsts};
use rustc_ast as ast; use rustc_ast as ast;
use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::intern::{Interned, WithStableHash}; use rustc_data_structures::intern::Interned;
use rustc_data_structures::memmap::Mmap; use rustc_data_structures::memmap::Mmap;
use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::profiling::SelfProfilerRef;
use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap}; use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
@ -68,6 +70,7 @@ use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi::{Layout, LayoutS, TargetDataLayout, VariantIdx}; use rustc_target::abi::{Layout, LayoutS, TargetDataLayout, VariantIdx};
use rustc_target::spec::abi; use rustc_target::spec::abi;
use rustc_type_ir::sty::TyKind::*; use rustc_type_ir::sty::TyKind::*;
use rustc_type_ir::WithCachedTypeInfo;
use rustc_type_ir::{DynKind, InternAs, InternIteratorElement, Interner, TypeFlags}; use rustc_type_ir::{DynKind, InternAs, InternIteratorElement, Interner, TypeFlags};
use std::any::Any; use std::any::Any;
@ -137,13 +140,13 @@ pub struct CtxtInterners<'tcx> {
// Specifically use a speedy hash algorithm for these hash sets, since // Specifically use a speedy hash algorithm for these hash sets, since
// they're accessed quite often. // they're accessed quite often.
type_: InternedSet<'tcx, WithStableHash<TyS<'tcx>>>, type_: InternedSet<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>,
const_lists: InternedSet<'tcx, List<ty::Const<'tcx>>>, const_lists: InternedSet<'tcx, List<ty::Const<'tcx>>>,
substs: InternedSet<'tcx, InternalSubsts<'tcx>>, substs: InternedSet<'tcx, InternalSubsts<'tcx>>,
canonical_var_infos: InternedSet<'tcx, List<CanonicalVarInfo<'tcx>>>, canonical_var_infos: InternedSet<'tcx, List<CanonicalVarInfo<'tcx>>>,
region: InternedSet<'tcx, RegionKind<'tcx>>, region: InternedSet<'tcx, RegionKind<'tcx>>,
poly_existential_predicates: InternedSet<'tcx, List<PolyExistentialPredicate<'tcx>>>, poly_existential_predicates: InternedSet<'tcx, List<PolyExistentialPredicate<'tcx>>>,
predicate: InternedSet<'tcx, WithStableHash<PredicateS<'tcx>>>, predicate: InternedSet<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>,
predicates: InternedSet<'tcx, List<Predicate<'tcx>>>, predicates: InternedSet<'tcx, List<Predicate<'tcx>>>,
projs: InternedSet<'tcx, List<ProjectionKind>>, projs: InternedSet<'tcx, List<ProjectionKind>>,
place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>, place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
@ -194,15 +197,12 @@ impl<'tcx> CtxtInterners<'tcx> {
let stable_hash = let stable_hash =
self.stable_hash(&flags, sess, definitions, cstore, source_span, &kind); self.stable_hash(&flags, sess, definitions, cstore, source_span, &kind);
let ty_struct = TyS { InternedInSet(self.arena.alloc(WithCachedTypeInfo {
kind, internee: kind,
stable_hash,
flags: flags.flags, flags: flags.flags,
outer_exclusive_binder: flags.outer_exclusive_binder, outer_exclusive_binder: flags.outer_exclusive_binder,
}; }))
InternedInSet(
self.arena.alloc(WithStableHash { internee: ty_struct, stable_hash }),
)
}) })
.0, .0,
)) ))
@ -246,16 +246,12 @@ impl<'tcx> CtxtInterners<'tcx> {
let stable_hash = let stable_hash =
self.stable_hash(&flags, sess, definitions, cstore, source_span, &kind); self.stable_hash(&flags, sess, definitions, cstore, source_span, &kind);
let predicate_struct = PredicateS { InternedInSet(self.arena.alloc(WithCachedTypeInfo {
kind, internee: kind,
stable_hash,
flags: flags.flags, flags: flags.flags,
outer_exclusive_binder: flags.outer_exclusive_binder, outer_exclusive_binder: flags.outer_exclusive_binder,
}; }))
InternedInSet(
self.arena
.alloc(WithStableHash { internee: predicate_struct, stable_hash }),
)
}) })
.0, .0,
)) ))
@ -2104,7 +2100,7 @@ macro_rules! sty_debug_print {
let shards = tcx.interners.type_.lock_shards(); let shards = tcx.interners.type_.lock_shards();
let types = shards.iter().flat_map(|shard| shard.keys()); let types = shards.iter().flat_map(|shard| shard.keys());
for &InternedInSet(t) in types { for &InternedInSet(t) in types {
let variant = match t.kind { let variant = match t.internee {
ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) | ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) |
ty::Float(..) | ty::Str | ty::Never => continue, ty::Float(..) | ty::Str | ty::Never => continue,
ty::Error(_) => /* unimportant */ continue, ty::Error(_) => /* unimportant */ continue,
@ -2214,51 +2210,26 @@ impl<'tcx, T: 'tcx + ?Sized> IntoPointer for InternedInSet<'tcx, T> {
} }
#[allow(rustc::usage_of_ty_tykind)] #[allow(rustc::usage_of_ty_tykind)]
impl<'tcx> Borrow<TyKind<'tcx>> for InternedInSet<'tcx, WithStableHash<TyS<'tcx>>> { impl<'tcx, T> Borrow<T> for InternedInSet<'tcx, WithCachedTypeInfo<T>> {
fn borrow<'a>(&'a self) -> &'a TyKind<'tcx> { fn borrow<'a>(&'a self) -> &'a T {
&self.0.kind &self.0.internee
} }
} }
impl<'tcx> PartialEq for InternedInSet<'tcx, WithStableHash<TyS<'tcx>>> { impl<'tcx, T: PartialEq> PartialEq for InternedInSet<'tcx, WithCachedTypeInfo<T>> {
fn eq(&self, other: &InternedInSet<'tcx, WithStableHash<TyS<'tcx>>>) -> bool { fn eq(&self, other: &InternedInSet<'tcx, WithCachedTypeInfo<T>>) -> bool {
// The `Borrow` trait requires that `x.borrow() == y.borrow()` equals // The `Borrow` trait requires that `x.borrow() == y.borrow()` equals
// `x == y`. // `x == y`.
self.0.kind == other.0.kind self.0.internee == other.0.internee
} }
} }
impl<'tcx> Eq for InternedInSet<'tcx, WithStableHash<TyS<'tcx>>> {} impl<'tcx, T: Eq> Eq for InternedInSet<'tcx, WithCachedTypeInfo<T>> {}
impl<'tcx> Hash for InternedInSet<'tcx, WithStableHash<TyS<'tcx>>> { impl<'tcx, T: Hash> Hash for InternedInSet<'tcx, WithCachedTypeInfo<T>> {
fn hash<H: Hasher>(&self, s: &mut H) { fn hash<H: Hasher>(&self, s: &mut H) {
// The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`. // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`.
self.0.kind.hash(s) self.0.internee.hash(s)
}
}
impl<'tcx> Borrow<Binder<'tcx, PredicateKind<'tcx>>>
for InternedInSet<'tcx, WithStableHash<PredicateS<'tcx>>>
{
fn borrow<'a>(&'a self) -> &'a Binder<'tcx, PredicateKind<'tcx>> {
&self.0.kind
}
}
impl<'tcx> PartialEq for InternedInSet<'tcx, WithStableHash<PredicateS<'tcx>>> {
fn eq(&self, other: &InternedInSet<'tcx, WithStableHash<PredicateS<'tcx>>>) -> bool {
// The `Borrow` trait requires that `x.borrow() == y.borrow()` equals
// `x == y`.
self.0.kind == other.0.kind
}
}
impl<'tcx> Eq for InternedInSet<'tcx, WithStableHash<PredicateS<'tcx>>> {}
impl<'tcx> Hash for InternedInSet<'tcx, WithStableHash<PredicateS<'tcx>>> {
fn hash<H: Hasher>(&self, s: &mut H) {
// The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`.
self.0.kind.hash(s)
} }
} }

View file

@ -9,6 +9,8 @@
//! //!
//! ["The `ty` module: representing types"]: https://rustc-dev-guide.rust-lang.org/ty.html //! ["The `ty` module: representing types"]: https://rustc-dev-guide.rust-lang.org/ty.html
#![allow(rustc::usage_of_ty_tykind)]
pub use self::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable}; pub use self::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable};
pub use self::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; pub use self::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
pub use self::AssocItemContainer::*; pub use self::AssocItemContainer::*;
@ -32,7 +34,7 @@ use rustc_ast::node_id::NodeMap;
use rustc_attr as attr; use rustc_attr as attr;
use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
use rustc_data_structures::intern::{Interned, WithStableHash}; use rustc_data_structures::intern::Interned;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::tagged_ptr::CopyTaggedPtr; use rustc_data_structures::tagged_ptr::CopyTaggedPtr;
use rustc_hir as hir; use rustc_hir as hir;
@ -50,6 +52,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{ExpnId, Span}; use rustc_span::{ExpnId, Span};
use rustc_target::abi::{Align, Integer, IntegerType, VariantIdx}; use rustc_target::abi::{Align, Integer, IntegerType, VariantIdx};
pub use rustc_target::abi::{ReprFlags, ReprOptions}; pub use rustc_target::abi::{ReprFlags, ReprOptions};
use rustc_type_ir::WithCachedTypeInfo;
pub use subst::*; pub use subst::*;
pub use vtable::*; pub use vtable::*;
@ -445,86 +448,22 @@ pub struct CReaderCacheKey {
pub pos: usize, pub pos: usize,
} }
/// Represents a type. /// Use this rather than `TyKind`, whenever possible.
///
/// IMPORTANT:
/// - This is a very "dumb" struct (with no derives and no `impls`).
/// - Values of this type are always interned and thus unique, and are stored
/// as an `Interned<TyS>`.
/// - `Ty` (which contains a reference to a `Interned<TyS>`) or `Interned<TyS>`
/// should be used everywhere instead of `TyS`. In particular, `Ty` has most
/// of the relevant methods.
#[derive(PartialEq, Eq, PartialOrd, Ord)]
#[allow(rustc::usage_of_ty_tykind)]
pub(crate) struct TyS<'tcx> {
/// This field shouldn't be used directly and may be removed in the future.
/// Use `Ty::kind()` instead.
kind: TyKind<'tcx>,
/// This field provides fast access to information that is also contained
/// in `kind`.
///
/// This field shouldn't be used directly and may be removed in the future.
/// Use `Ty::flags()` instead.
flags: TypeFlags,
/// This field provides fast access to information that is also contained
/// in `kind`.
///
/// This is a kind of confusing thing: it stores the smallest
/// binder such that
///
/// (a) the binder itself captures nothing but
/// (b) all the late-bound things within the type are captured
/// by some sub-binder.
///
/// So, for a type without any late-bound things, like `u32`, this
/// will be *innermost*, because that is the innermost binder that
/// captures nothing. But for a type `&'D u32`, where `'D` is a
/// late-bound region with De Bruijn index `D`, this would be `D + 1`
/// -- the binder itself does not capture `D`, but `D` is captured
/// by an inner binder.
///
/// We call this concept an "exclusive" binder `D` because all
/// De Bruijn indices within the type are contained within `0..D`
/// (exclusive).
outer_exclusive_binder: ty::DebruijnIndex,
}
/// Use this rather than `TyS`, whenever possible.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)]
#[rustc_diagnostic_item = "Ty"] #[rustc_diagnostic_item = "Ty"]
#[rustc_pass_by_value] #[rustc_pass_by_value]
pub struct Ty<'tcx>(Interned<'tcx, WithStableHash<TyS<'tcx>>>); pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>);
impl<'tcx> TyCtxt<'tcx> { impl<'tcx> TyCtxt<'tcx> {
/// A "bool" type used in rustc_mir_transform unit tests when we /// A "bool" type used in rustc_mir_transform unit tests when we
/// have not spun up a TyCtxt. /// have not spun up a TyCtxt.
pub const BOOL_TY_FOR_UNIT_TESTING: Ty<'tcx> = Ty(Interned::new_unchecked(&WithStableHash { pub const BOOL_TY_FOR_UNIT_TESTING: Ty<'tcx> =
internee: TyS { Ty(Interned::new_unchecked(&WithCachedTypeInfo {
kind: ty::Bool, internee: ty::Bool,
stable_hash: Fingerprint::ZERO,
flags: TypeFlags::empty(), flags: TypeFlags::empty(),
outer_exclusive_binder: DebruijnIndex::from_usize(0), outer_exclusive_binder: DebruijnIndex::from_usize(0),
}, }));
stable_hash: Fingerprint::ZERO,
}));
}
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TyS<'tcx> {
#[inline]
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
let TyS {
kind,
// The other fields just provide fast access to information that is
// also contained in `kind`, so no need to hash them.
flags: _,
outer_exclusive_binder: _,
} = self;
kind.hash_stable(hcx, hasher)
}
} }
impl ty::EarlyBoundRegion { impl ty::EarlyBoundRegion {
@ -535,28 +474,18 @@ impl ty::EarlyBoundRegion {
} }
} }
/// Represents a predicate. /// Use this rather than `PredicateKind`, whenever possible.
///
/// See comments on `TyS`, which apply here too (albeit for
/// `PredicateS`/`Predicate` rather than `TyS`/`Ty`).
#[derive(Debug)]
pub(crate) struct PredicateS<'tcx> {
kind: Binder<'tcx, PredicateKind<'tcx>>,
flags: TypeFlags,
/// See the comment for the corresponding field of [TyS].
outer_exclusive_binder: ty::DebruijnIndex,
}
/// Use this rather than `PredicateS`, whenever possible.
#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)] #[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)]
#[rustc_pass_by_value] #[rustc_pass_by_value]
pub struct Predicate<'tcx>(Interned<'tcx, WithStableHash<PredicateS<'tcx>>>); pub struct Predicate<'tcx>(
Interned<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>,
);
impl<'tcx> Predicate<'tcx> { impl<'tcx> Predicate<'tcx> {
/// Gets the inner `Binder<'tcx, PredicateKind<'tcx>>`. /// Gets the inner `Binder<'tcx, PredicateKind<'tcx>>`.
#[inline] #[inline]
pub fn kind(self) -> Binder<'tcx, PredicateKind<'tcx>> { pub fn kind(self) -> Binder<'tcx, PredicateKind<'tcx>> {
self.0.kind self.0.internee
} }
#[inline(always)] #[inline(always)]
@ -631,21 +560,6 @@ impl<'tcx> Predicate<'tcx> {
} }
} }
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for PredicateS<'tcx> {
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
let PredicateS {
ref kind,
// The other fields just provide fast access to information that is
// also contained in `kind`, so no need to hash them.
flags: _,
outer_exclusive_binder: _,
} = self;
kind.hash_stable(hcx, hasher);
}
}
impl rustc_errors::IntoDiagnosticArg for Predicate<'_> { impl rustc_errors::IntoDiagnosticArg for Predicate<'_> {
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
rustc_errors::DiagnosticArgValue::Str(std::borrow::Cow::Owned(self.to_string())) rustc_errors::DiagnosticArgValue::Str(std::borrow::Cow::Owned(self.to_string()))
@ -1028,7 +942,7 @@ impl<'tcx> Term<'tcx> {
unsafe { unsafe {
match ptr & TAG_MASK { match ptr & TAG_MASK {
TYPE_TAG => TermKind::Ty(Ty(Interned::new_unchecked( TYPE_TAG => TermKind::Ty(Ty(Interned::new_unchecked(
&*((ptr & !TAG_MASK) as *const WithStableHash<ty::TyS<'tcx>>), &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::TyKind<'tcx>>),
))), ))),
CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked( CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked(
&*((ptr & !TAG_MASK) as *const ty::ConstS<'tcx>), &*((ptr & !TAG_MASK) as *const ty::ConstS<'tcx>),
@ -1072,7 +986,7 @@ impl<'tcx> TermKind<'tcx> {
TermKind::Ty(ty) => { TermKind::Ty(ty) => {
// Ensure we can use the tag bits. // Ensure we can use the tag bits.
assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0); assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0);
(TYPE_TAG, ty.0.0 as *const WithStableHash<ty::TyS<'tcx>> as usize) (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo<ty::TyKind<'tcx>> as usize)
} }
TermKind::Const(ct) => { TermKind::Const(ct) => {
// Ensure we can use the tag bits. // Ensure we can use the tag bits.
@ -2692,8 +2606,7 @@ mod size_asserts {
use super::*; use super::*;
use rustc_data_structures::static_assert_size; use rustc_data_structures::static_assert_size;
// tidy-alphabetical-start // tidy-alphabetical-start
static_assert_size!(PredicateS<'_>, 48); static_assert_size!(PredicateKind<'_>, 32);
static_assert_size!(TyS<'_>, 40); static_assert_size!(WithCachedTypeInfo<TyKind<'_>>, 56);
static_assert_size!(WithStableHash<TyS<'_>>, 56);
// tidy-alphabetical-end // tidy-alphabetical-end
} }

View file

@ -1611,7 +1611,7 @@ impl<'tcx> Region<'tcx> {
impl<'tcx> Ty<'tcx> { impl<'tcx> Ty<'tcx> {
#[inline(always)] #[inline(always)]
pub fn kind(self) -> &'tcx TyKind<'tcx> { pub fn kind(self) -> &'tcx TyKind<'tcx> {
&self.0.0.kind &self.0.0
} }
#[inline(always)] #[inline(always)]

View file

@ -6,10 +6,11 @@ use crate::ty::sty::{ClosureSubsts, GeneratorSubsts, InlineConstSubsts};
use crate::ty::visit::{TypeVisitable, TypeVisitor}; use crate::ty::visit::{TypeVisitable, TypeVisitor};
use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt}; use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt};
use rustc_data_structures::intern::{Interned, WithStableHash}; use rustc_data_structures::intern::Interned;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_macros::HashStable; use rustc_macros::HashStable;
use rustc_serialize::{self, Decodable, Encodable}; use rustc_serialize::{self, Decodable, Encodable};
use rustc_type_ir::WithCachedTypeInfo;
use smallvec::SmallVec; use smallvec::SmallVec;
use core::intrinsics; use core::intrinsics;
@ -84,7 +85,7 @@ impl<'tcx> GenericArgKind<'tcx> {
GenericArgKind::Type(ty) => { GenericArgKind::Type(ty) => {
// Ensure we can use the tag bits. // Ensure we can use the tag bits.
assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0); assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0);
(TYPE_TAG, ty.0.0 as *const WithStableHash<ty::TyS<'tcx>> as usize) (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo<ty::TyKind<'tcx>> as usize)
} }
GenericArgKind::Const(ct) => { GenericArgKind::Const(ct) => {
// Ensure we can use the tag bits. // Ensure we can use the tag bits.
@ -162,7 +163,7 @@ impl<'tcx> GenericArg<'tcx> {
&*((ptr & !TAG_MASK) as *const ty::RegionKind<'tcx>), &*((ptr & !TAG_MASK) as *const ty::RegionKind<'tcx>),
))), ))),
TYPE_TAG => GenericArgKind::Type(Ty(Interned::new_unchecked( TYPE_TAG => GenericArgKind::Type(Ty(Interned::new_unchecked(
&*((ptr & !TAG_MASK) as *const WithStableHash<ty::TyS<'tcx>>), &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::TyKind<'tcx>>),
))), ))),
CONST_TAG => GenericArgKind::Const(ty::Const(Interned::new_unchecked( CONST_TAG => GenericArgKind::Const(ty::Const(Interned::new_unchecked(
&*((ptr & !TAG_MASK) as *const ty::ConstS<'tcx>), &*((ptr & !TAG_MASK) as *const ty::ConstS<'tcx>),

View file

@ -948,20 +948,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
original_source_scope: SourceScope, original_source_scope: SourceScope,
pattern_span: Span, pattern_span: Span,
) { ) {
let tcx = self.tcx; let parent_id = self.source_scopes[original_source_scope]
let current_root = tcx.maybe_lint_level_root_bounded(arg_hir_id, self.hir_id); .local_data
let parent_root = tcx.maybe_lint_level_root_bounded( .as_ref()
self.source_scopes[original_source_scope] .assert_crate_local()
.local_data .lint_root;
.as_ref() self.maybe_new_source_scope(pattern_span, None, arg_hir_id, parent_id);
.assert_crate_local()
.lint_root,
self.hir_id,
);
if current_root != parent_root {
self.source_scope =
self.new_source_scope(pattern_span, LintLevel::Explicit(current_root), None);
}
} }
fn get_unit_temp(&mut self) -> Place<'tcx> { fn get_unit_temp(&mut self) -> Place<'tcx> {

View file

@ -85,6 +85,7 @@ use std::mem;
use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder, CFG}; use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder, CFG};
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_hir::HirId;
use rustc_index::vec::IndexVec; use rustc_index::vec::IndexVec;
use rustc_middle::middle::region; use rustc_middle::middle::region;
use rustc_middle::mir::*; use rustc_middle::mir::*;
@ -567,25 +568,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
F: FnOnce(&mut Builder<'a, 'tcx>) -> BlockAnd<R>, F: FnOnce(&mut Builder<'a, 'tcx>) -> BlockAnd<R>,
{ {
let source_scope = self.source_scope; let source_scope = self.source_scope;
let tcx = self.tcx;
if let LintLevel::Explicit(current_hir_id) = lint_level { if let LintLevel::Explicit(current_hir_id) = lint_level {
// Use `maybe_lint_level_root_bounded` with `root_lint_level` as a bound let parent_id =
// to avoid adding Hir dependencies on our parents. self.source_scopes[source_scope].local_data.as_ref().assert_crate_local().lint_root;
// We estimate the true lint roots here to avoid creating a lot of source scopes. self.maybe_new_source_scope(region_scope.1.span, None, current_hir_id, parent_id);
let parent_root = tcx.maybe_lint_level_root_bounded(
self.source_scopes[source_scope].local_data.as_ref().assert_crate_local().lint_root,
self.hir_id,
);
let current_root = tcx.maybe_lint_level_root_bounded(current_hir_id, self.hir_id);
if parent_root != current_root {
self.source_scope = self.new_source_scope(
region_scope.1.span,
LintLevel::Explicit(current_root),
None,
);
}
} }
self.push_scope(region_scope); self.push_scope(region_scope);
let mut block; let mut block;
@ -758,6 +744,40 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
)) ))
} }
/// Possibly creates a new source scope if `current_root` and `parent_root`
/// are different, or if -Zmaximal-hir-to-mir-coverage is enabled.
pub(crate) fn maybe_new_source_scope(
&mut self,
span: Span,
safety: Option<Safety>,
current_id: HirId,
parent_id: HirId,
) {
let (current_root, parent_root) =
if self.tcx.sess.opts.unstable_opts.maximal_hir_to_mir_coverage {
// Some consumers of rustc need to map MIR locations back to HIR nodes. Currently the
// the only part of rustc that tracks MIR -> HIR is the `SourceScopeLocalData::lint_root`
// field that tracks lint levels for MIR locations. Normally the number of source scopes
// is limited to the set of nodes with lint annotations. The -Zmaximal-hir-to-mir-coverage
// flag changes this behavior to maximize the number of source scopes, increasing the
// granularity of the MIR->HIR mapping.
(current_id, parent_id)
} else {
// Use `maybe_lint_level_root_bounded` with `self.hir_id` as a bound
// to avoid adding Hir dependencies on our parents.
// We estimate the true lint roots here to avoid creating a lot of source scopes.
(
self.tcx.maybe_lint_level_root_bounded(current_id, self.hir_id),
self.tcx.maybe_lint_level_root_bounded(parent_id, self.hir_id),
)
};
if current_root != parent_root {
let lint_level = LintLevel::Explicit(current_root);
self.source_scope = self.new_source_scope(span, lint_level, safety);
}
}
/// Creates a new source scope, nested in the current one. /// Creates a new source scope, nested in the current one.
pub(crate) fn new_source_scope( pub(crate) fn new_source_scope(
&mut self, &mut self,

View file

@ -1548,7 +1548,13 @@ impl<'tcx> Liveness<'_, 'tcx> {
.or_insert_with(|| (ln, var, vec![id_and_sp])); .or_insert_with(|| (ln, var, vec![id_and_sp]));
}); });
let can_remove = matches!(&pat.kind, hir::PatKind::Struct(_, _, true)); let can_remove = match pat.kind {
hir::PatKind::Struct(_, fields, true) => {
// if all fields are shorthand, remove the struct field, otherwise, mark with _ as prefix
fields.iter().all(|f| f.is_shorthand)
}
_ => false,
};
for (_, (ln, var, hir_ids_and_spans)) in vars { for (_, (ln, var, hir_ids_and_spans)) in vars {
if self.used_on_entry(ln, var) { if self.used_on_entry(ln, var) {

View file

@ -1382,6 +1382,9 @@ options! {
"list the symbols defined by a library crate (default: no)"), "list the symbols defined by a library crate (default: no)"),
macro_backtrace: bool = (false, parse_bool, [UNTRACKED], macro_backtrace: bool = (false, parse_bool, [UNTRACKED],
"show macro backtraces (default: no)"), "show macro backtraces (default: no)"),
maximal_hir_to_mir_coverage: bool = (false, parse_bool, [TRACKED],
"save as much information as possible about the correspondence between MIR and HIR \
as source scopes (default: no)"),
merge_functions: Option<MergeFunctions> = (None, parse_merge_functions, [TRACKED], merge_functions: Option<MergeFunctions> = (None, parse_merge_functions, [TRACKED],
"control the operation of the MergeFunctions LLVM pass, taking \ "control the operation of the MergeFunctions LLVM pass, taking \
the same values as the target option of the same name"), the same values as the target option of the same name"),

View file

@ -274,7 +274,7 @@ impl Ord for DefId {
impl PartialOrd for DefId { impl PartialOrd for DefId {
#[inline] #[inline]
fn partial_cmp(&self, other: &DefId) -> Option<std::cmp::Ordering> { fn partial_cmp(&self, other: &DefId) -> Option<std::cmp::Ordering> {
Some(Ord::cmp(self, other)) Some(self.cmp(other))
} }
} }

View file

@ -165,6 +165,7 @@ symbols! {
Capture, Capture,
Center, Center,
Clone, Clone,
Context,
Continue, Continue,
Copy, Copy,
Count, Count,
@ -264,7 +265,6 @@ symbols! {
Relaxed, Relaxed,
Release, Release,
Result, Result,
ResumeTy,
Return, Return,
Right, Right,
Rust, Rust,
@ -754,7 +754,6 @@ symbols! {
generic_associated_types_extended, generic_associated_types_extended,
generic_const_exprs, generic_const_exprs,
generic_param_attrs, generic_param_attrs,
get_context,
global_allocator, global_allocator,
global_asm, global_asm,
globs, globs,

View file

@ -19,9 +19,11 @@ use std::mem::discriminant;
pub mod codec; pub mod codec;
pub mod sty; pub mod sty;
pub mod ty_info;
pub use codec::*; pub use codec::*;
pub use sty::*; pub use sty::*;
pub use ty_info::*;
/// Needed so we can use #[derive(HashStable_Generic)] /// Needed so we can use #[derive(HashStable_Generic)]
pub trait HashStableContext {} pub trait HashStableContext {}

View file

@ -301,61 +301,44 @@ impl<I: Interner> Clone for TyKind<I> {
impl<I: Interner> PartialEq for TyKind<I> { impl<I: Interner> PartialEq for TyKind<I> {
#[inline] #[inline]
fn eq(&self, other: &TyKind<I>) -> bool { fn eq(&self, other: &TyKind<I>) -> bool {
let __self_vi = tykind_discriminant(self); tykind_discriminant(self) == tykind_discriminant(other)
let __arg_1_vi = tykind_discriminant(other); && match (self, other) {
if __self_vi == __arg_1_vi { (Int(a_i), Int(b_i)) => a_i == b_i,
match (&*self, &*other) { (Uint(a_u), Uint(b_u)) => a_u == b_u,
(&Int(ref __self_0), &Int(ref __arg_1_0)) => __self_0 == __arg_1_0, (Float(a_f), Float(b_f)) => a_f == b_f,
(&Uint(ref __self_0), &Uint(ref __arg_1_0)) => __self_0 == __arg_1_0, (Adt(a_d, a_s), Adt(b_d, b_s)) => a_d == b_d && a_s == b_s,
(&Float(ref __self_0), &Float(ref __arg_1_0)) => __self_0 == __arg_1_0, (Foreign(a_d), Foreign(b_d)) => a_d == b_d,
(&Adt(ref __self_0, ref __self_1), &Adt(ref __arg_1_0, ref __arg_1_1)) => { (Array(a_t, a_c), Array(b_t, b_c)) => a_t == b_t && a_c == b_c,
__self_0 == __arg_1_0 && __self_1 == __arg_1_1 (Slice(a_t), Slice(b_t)) => a_t == b_t,
(RawPtr(a_t), RawPtr(b_t)) => a_t == b_t,
(Ref(a_r, a_t, a_m), Ref(b_r, b_t, b_m)) => a_r == b_r && a_t == b_t && a_m == b_m,
(FnDef(a_d, a_s), FnDef(b_d, b_s)) => a_d == b_d && a_s == b_s,
(FnPtr(a_s), FnPtr(b_s)) => a_s == b_s,
(Dynamic(a_p, a_r, a_repr), Dynamic(b_p, b_r, b_repr)) => {
a_p == b_p && a_r == b_r && a_repr == b_repr
} }
(&Foreign(ref __self_0), &Foreign(ref __arg_1_0)) => __self_0 == __arg_1_0, (Closure(a_d, a_s), Closure(b_d, b_s)) => a_d == b_d && a_s == b_s,
(&Array(ref __self_0, ref __self_1), &Array(ref __arg_1_0, ref __arg_1_1)) => { (Generator(a_d, a_s, a_m), Generator(b_d, b_s, b_m)) => {
__self_0 == __arg_1_0 && __self_1 == __arg_1_1 a_d == b_d && a_s == b_s && a_m == b_m
} }
(&Slice(ref __self_0), &Slice(ref __arg_1_0)) => __self_0 == __arg_1_0, (GeneratorWitness(a_g), GeneratorWitness(b_g)) => a_g == b_g,
(&RawPtr(ref __self_0), &RawPtr(ref __arg_1_0)) => __self_0 == __arg_1_0, (Tuple(a_t), Tuple(b_t)) => a_t == b_t,
( (Projection(a_p), Projection(b_p)) => a_p == b_p,
&Ref(ref __self_0, ref __self_1, ref __self_2), (Opaque(a_d, a_s), Opaque(b_d, b_s)) => a_d == b_d && a_s == b_s,
&Ref(ref __arg_1_0, ref __arg_1_1, ref __arg_1_2), (Param(a_p), Param(b_p)) => a_p == b_p,
) => __self_0 == __arg_1_0 && __self_1 == __arg_1_1 && __self_2 == __arg_1_2, (Bound(a_d, a_b), Bound(b_d, b_b)) => a_d == b_d && a_b == b_b,
(&FnDef(ref __self_0, ref __self_1), &FnDef(ref __arg_1_0, ref __arg_1_1)) => { (Placeholder(a_p), Placeholder(b_p)) => a_p == b_p,
__self_0 == __arg_1_0 && __self_1 == __arg_1_1 (Infer(a_t), Infer(b_t)) => a_t == b_t,
(Error(a_e), Error(b_e)) => a_e == b_e,
(Bool, Bool) | (Char, Char) | (Str, Str) | (Never, Never) => true,
_ => {
debug_assert!(
false,
"This branch must be unreachable, maybe the match is missing an arm? self = self = {self:?}, other = {other:?}"
);
true
} }
(&FnPtr(ref __self_0), &FnPtr(ref __arg_1_0)) => __self_0 == __arg_1_0,
(
&Dynamic(ref __self_0, ref __self_1, ref self_repr),
&Dynamic(ref __arg_1_0, ref __arg_1_1, ref arg_repr),
) => __self_0 == __arg_1_0 && __self_1 == __arg_1_1 && self_repr == arg_repr,
(&Closure(ref __self_0, ref __self_1), &Closure(ref __arg_1_0, ref __arg_1_1)) => {
__self_0 == __arg_1_0 && __self_1 == __arg_1_1
}
(
&Generator(ref __self_0, ref __self_1, ref __self_2),
&Generator(ref __arg_1_0, ref __arg_1_1, ref __arg_1_2),
) => __self_0 == __arg_1_0 && __self_1 == __arg_1_1 && __self_2 == __arg_1_2,
(&GeneratorWitness(ref __self_0), &GeneratorWitness(ref __arg_1_0)) => {
__self_0 == __arg_1_0
}
(&Tuple(ref __self_0), &Tuple(ref __arg_1_0)) => __self_0 == __arg_1_0,
(&Projection(ref __self_0), &Projection(ref __arg_1_0)) => __self_0 == __arg_1_0,
(&Opaque(ref __self_0, ref __self_1), &Opaque(ref __arg_1_0, ref __arg_1_1)) => {
__self_0 == __arg_1_0 && __self_1 == __arg_1_1
}
(&Param(ref __self_0), &Param(ref __arg_1_0)) => __self_0 == __arg_1_0,
(&Bound(ref __self_0, ref __self_1), &Bound(ref __arg_1_0, ref __arg_1_1)) => {
__self_0 == __arg_1_0 && __self_1 == __arg_1_1
}
(&Placeholder(ref __self_0), &Placeholder(ref __arg_1_0)) => __self_0 == __arg_1_0,
(&Infer(ref __self_0), &Infer(ref __arg_1_0)) => __self_0 == __arg_1_0,
(&Error(ref __self_0), &Error(ref __arg_1_0)) => __self_0 == __arg_1_0,
_ => true,
} }
} else {
false
}
} }
} }
@ -366,7 +349,7 @@ impl<I: Interner> Eq for TyKind<I> {}
impl<I: Interner> PartialOrd for TyKind<I> { impl<I: Interner> PartialOrd for TyKind<I> {
#[inline] #[inline]
fn partial_cmp(&self, other: &TyKind<I>) -> Option<Ordering> { fn partial_cmp(&self, other: &TyKind<I>) -> Option<Ordering> {
Some(Ord::cmp(self, other)) Some(self.cmp(other))
} }
} }
@ -374,213 +357,106 @@ impl<I: Interner> PartialOrd for TyKind<I> {
impl<I: Interner> Ord for TyKind<I> { impl<I: Interner> Ord for TyKind<I> {
#[inline] #[inline]
fn cmp(&self, other: &TyKind<I>) -> Ordering { fn cmp(&self, other: &TyKind<I>) -> Ordering {
let __self_vi = tykind_discriminant(self); tykind_discriminant(self).cmp(&tykind_discriminant(other)).then_with(|| {
let __arg_1_vi = tykind_discriminant(other); match (self, other) {
if __self_vi == __arg_1_vi { (Int(a_i), Int(b_i)) => a_i.cmp(b_i),
match (&*self, &*other) { (Uint(a_u), Uint(b_u)) => a_u.cmp(b_u),
(&Int(ref __self_0), &Int(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0), (Float(a_f), Float(b_f)) => a_f.cmp(b_f),
(&Uint(ref __self_0), &Uint(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0), (Adt(a_d, a_s), Adt(b_d, b_s)) => a_d.cmp(b_d).then_with(|| a_s.cmp(b_s)),
(&Float(ref __self_0), &Float(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0), (Foreign(a_d), Foreign(b_d)) => a_d.cmp(b_d),
(&Adt(ref __self_0, ref __self_1), &Adt(ref __arg_1_0, ref __arg_1_1)) => { (Array(a_t, a_c), Array(b_t, b_c)) => a_t.cmp(b_t).then_with(|| a_c.cmp(b_c)),
match Ord::cmp(__self_0, __arg_1_0) { (Slice(a_t), Slice(b_t)) => a_t.cmp(b_t),
Ordering::Equal => Ord::cmp(__self_1, __arg_1_1), (RawPtr(a_t), RawPtr(b_t)) => a_t.cmp(b_t),
cmp => cmp, (Ref(a_r, a_t, a_m), Ref(b_r, b_t, b_m)) => {
} a_r.cmp(b_r).then_with(|| a_t.cmp(b_t).then_with(|| a_m.cmp(b_m)))
} }
(&Foreign(ref __self_0), &Foreign(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0), (FnDef(a_d, a_s), FnDef(b_d, b_s)) => a_d.cmp(b_d).then_with(|| a_s.cmp(b_s)),
(&Array(ref __self_0, ref __self_1), &Array(ref __arg_1_0, ref __arg_1_1)) => { (FnPtr(a_s), FnPtr(b_s)) => a_s.cmp(b_s),
match Ord::cmp(__self_0, __arg_1_0) { (Dynamic(a_p, a_r, a_repr), Dynamic(b_p, b_r, b_repr)) => {
Ordering::Equal => Ord::cmp(__self_1, __arg_1_1), a_p.cmp(b_p).then_with(|| a_r.cmp(b_r).then_with(|| a_repr.cmp(b_repr)))
cmp => cmp,
}
} }
(&Slice(ref __self_0), &Slice(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0), (Closure(a_p, a_s), Closure(b_p, b_s)) => a_p.cmp(b_p).then_with(|| a_s.cmp(b_s)),
(&RawPtr(ref __self_0), &RawPtr(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0), (Generator(a_d, a_s, a_m), Generator(b_d, b_s, b_m)) => {
( a_d.cmp(b_d).then_with(|| a_s.cmp(b_s).then_with(|| a_m.cmp(b_m)))
&Ref(ref __self_0, ref __self_1, ref __self_2),
&Ref(ref __arg_1_0, ref __arg_1_1, ref __arg_1_2),
) => match Ord::cmp(__self_0, __arg_1_0) {
Ordering::Equal => match Ord::cmp(__self_1, __arg_1_1) {
Ordering::Equal => Ord::cmp(__self_2, __arg_1_2),
cmp => cmp,
},
cmp => cmp,
},
(&FnDef(ref __self_0, ref __self_1), &FnDef(ref __arg_1_0, ref __arg_1_1)) => {
match Ord::cmp(__self_0, __arg_1_0) {
Ordering::Equal => Ord::cmp(__self_1, __arg_1_1),
cmp => cmp,
}
} }
(&FnPtr(ref __self_0), &FnPtr(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0), (GeneratorWitness(a_g), GeneratorWitness(b_g)) => a_g.cmp(b_g),
( (Tuple(a_t), Tuple(b_t)) => a_t.cmp(b_t),
&Dynamic(ref __self_0, ref __self_1, ref self_repr), (Projection(a_p), Projection(b_p)) => a_p.cmp(b_p),
&Dynamic(ref __arg_1_0, ref __arg_1_1, ref arg_repr), (Opaque(a_d, a_s), Opaque(b_d, b_s)) => a_d.cmp(b_d).then_with(|| a_s.cmp(b_s)),
) => match Ord::cmp(__self_0, __arg_1_0) { (Param(a_p), Param(b_p)) => a_p.cmp(b_p),
Ordering::Equal => match Ord::cmp(__self_1, __arg_1_1) { (Bound(a_d, a_b), Bound(b_d, b_b)) => a_d.cmp(b_d).then_with(|| a_b.cmp(b_b)),
Ordering::Equal => Ord::cmp(self_repr, arg_repr), (Placeholder(a_p), Placeholder(b_p)) => a_p.cmp(b_p),
cmp => cmp, (Infer(a_t), Infer(b_t)) => a_t.cmp(b_t),
}, (Error(a_e), Error(b_e)) => a_e.cmp(b_e),
cmp => cmp, (Bool, Bool) | (Char, Char) | (Str, Str) | (Never, Never) => Ordering::Equal,
}, _ => {
(&Closure(ref __self_0, ref __self_1), &Closure(ref __arg_1_0, ref __arg_1_1)) => { debug_assert!(false, "This branch must be unreachable, maybe the match is missing an arm? self = self = {self:?}, other = {other:?}");
match Ord::cmp(__self_0, __arg_1_0) { Ordering::Equal
Ordering::Equal => Ord::cmp(__self_1, __arg_1_1),
cmp => cmp,
}
} }
(
&Generator(ref __self_0, ref __self_1, ref __self_2),
&Generator(ref __arg_1_0, ref __arg_1_1, ref __arg_1_2),
) => match Ord::cmp(__self_0, __arg_1_0) {
Ordering::Equal => match Ord::cmp(__self_1, __arg_1_1) {
Ordering::Equal => Ord::cmp(__self_2, __arg_1_2),
cmp => cmp,
},
cmp => cmp,
},
(&GeneratorWitness(ref __self_0), &GeneratorWitness(ref __arg_1_0)) => {
Ord::cmp(__self_0, __arg_1_0)
}
(&Tuple(ref __self_0), &Tuple(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0),
(&Projection(ref __self_0), &Projection(ref __arg_1_0)) => {
Ord::cmp(__self_0, __arg_1_0)
}
(&Opaque(ref __self_0, ref __self_1), &Opaque(ref __arg_1_0, ref __arg_1_1)) => {
match Ord::cmp(__self_0, __arg_1_0) {
Ordering::Equal => Ord::cmp(__self_1, __arg_1_1),
cmp => cmp,
}
}
(&Param(ref __self_0), &Param(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0),
(&Bound(ref __self_0, ref __self_1), &Bound(ref __arg_1_0, ref __arg_1_1)) => {
match Ord::cmp(__self_0, __arg_1_0) {
Ordering::Equal => Ord::cmp(__self_1, __arg_1_1),
cmp => cmp,
}
}
(&Placeholder(ref __self_0), &Placeholder(ref __arg_1_0)) => {
Ord::cmp(__self_0, __arg_1_0)
}
(&Infer(ref __self_0), &Infer(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0),
(&Error(ref __self_0), &Error(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0),
_ => Ordering::Equal,
} }
} else { })
Ord::cmp(&__self_vi, &__arg_1_vi)
}
} }
} }
// This is manually implemented because a derive would require `I: Hash` // This is manually implemented because a derive would require `I: Hash`
impl<I: Interner> hash::Hash for TyKind<I> { impl<I: Interner> hash::Hash for TyKind<I> {
fn hash<__H: hash::Hasher>(&self, state: &mut __H) -> () { fn hash<__H: hash::Hasher>(&self, state: &mut __H) -> () {
match (&*self,) { tykind_discriminant(self).hash(state);
(&Int(ref __self_0),) => { match self {
hash::Hash::hash(&tykind_discriminant(self), state); Int(i) => i.hash(state),
hash::Hash::hash(__self_0, state) Uint(u) => u.hash(state),
Float(f) => f.hash(state),
Adt(d, s) => {
d.hash(state);
s.hash(state)
} }
(&Uint(ref __self_0),) => { Foreign(d) => d.hash(state),
hash::Hash::hash(&tykind_discriminant(self), state); Array(t, c) => {
hash::Hash::hash(__self_0, state) t.hash(state);
c.hash(state)
} }
(&Float(ref __self_0),) => { Slice(t) => t.hash(state),
hash::Hash::hash(&tykind_discriminant(self), state); RawPtr(t) => t.hash(state),
hash::Hash::hash(__self_0, state) Ref(r, t, m) => {
r.hash(state);
t.hash(state);
m.hash(state)
} }
(&Adt(ref __self_0, ref __self_1),) => { FnDef(d, s) => {
hash::Hash::hash(&tykind_discriminant(self), state); d.hash(state);
hash::Hash::hash(__self_0, state); s.hash(state)
hash::Hash::hash(__self_1, state)
} }
(&Foreign(ref __self_0),) => { FnPtr(s) => s.hash(state),
hash::Hash::hash(&tykind_discriminant(self), state); Dynamic(p, r, repr) => {
hash::Hash::hash(__self_0, state) p.hash(state);
r.hash(state);
repr.hash(state)
} }
(&Array(ref __self_0, ref __self_1),) => { Closure(d, s) => {
hash::Hash::hash(&tykind_discriminant(self), state); d.hash(state);
hash::Hash::hash(__self_0, state); s.hash(state)
hash::Hash::hash(__self_1, state)
} }
(&Slice(ref __self_0),) => { Generator(d, s, m) => {
hash::Hash::hash(&tykind_discriminant(self), state); d.hash(state);
hash::Hash::hash(__self_0, state) s.hash(state);
m.hash(state)
} }
(&RawPtr(ref __self_0),) => { GeneratorWitness(g) => g.hash(state),
hash::Hash::hash(&tykind_discriminant(self), state); Tuple(t) => t.hash(state),
hash::Hash::hash(__self_0, state) Projection(p) => p.hash(state),
Opaque(d, s) => {
d.hash(state);
s.hash(state)
} }
(&Ref(ref __self_0, ref __self_1, ref __self_2),) => { Param(p) => p.hash(state),
hash::Hash::hash(&tykind_discriminant(self), state); Bound(d, b) => {
hash::Hash::hash(__self_0, state); d.hash(state);
hash::Hash::hash(__self_1, state); b.hash(state)
hash::Hash::hash(__self_2, state)
} }
(&FnDef(ref __self_0, ref __self_1),) => { Placeholder(p) => p.hash(state),
hash::Hash::hash(&tykind_discriminant(self), state); Infer(t) => t.hash(state),
hash::Hash::hash(__self_0, state); Error(e) => e.hash(state),
hash::Hash::hash(__self_1, state) Bool | Char | Str | Never => (),
}
(&FnPtr(ref __self_0),) => {
hash::Hash::hash(&tykind_discriminant(self), state);
hash::Hash::hash(__self_0, state)
}
(&Dynamic(ref __self_0, ref __self_1, ref repr),) => {
hash::Hash::hash(&tykind_discriminant(self), state);
hash::Hash::hash(__self_0, state);
hash::Hash::hash(__self_1, state);
hash::Hash::hash(repr, state)
}
(&Closure(ref __self_0, ref __self_1),) => {
hash::Hash::hash(&tykind_discriminant(self), state);
hash::Hash::hash(__self_0, state);
hash::Hash::hash(__self_1, state)
}
(&Generator(ref __self_0, ref __self_1, ref __self_2),) => {
hash::Hash::hash(&tykind_discriminant(self), state);
hash::Hash::hash(__self_0, state);
hash::Hash::hash(__self_1, state);
hash::Hash::hash(__self_2, state)
}
(&GeneratorWitness(ref __self_0),) => {
hash::Hash::hash(&tykind_discriminant(self), state);
hash::Hash::hash(__self_0, state)
}
(&Tuple(ref __self_0),) => {
hash::Hash::hash(&tykind_discriminant(self), state);
hash::Hash::hash(__self_0, state)
}
(&Projection(ref __self_0),) => {
hash::Hash::hash(&tykind_discriminant(self), state);
hash::Hash::hash(__self_0, state)
}
(&Opaque(ref __self_0, ref __self_1),) => {
hash::Hash::hash(&tykind_discriminant(self), state);
hash::Hash::hash(__self_0, state);
hash::Hash::hash(__self_1, state)
}
(&Param(ref __self_0),) => {
hash::Hash::hash(&tykind_discriminant(self), state);
hash::Hash::hash(__self_0, state)
}
(&Bound(ref __self_0, ref __self_1),) => {
hash::Hash::hash(&tykind_discriminant(self), state);
hash::Hash::hash(__self_0, state);
hash::Hash::hash(__self_1, state)
}
(&Placeholder(ref __self_0),) => {
hash::Hash::hash(&tykind_discriminant(self), state);
hash::Hash::hash(__self_0, state)
}
(&Infer(ref __self_0),) => {
hash::Hash::hash(&tykind_discriminant(self), state);
hash::Hash::hash(__self_0, state)
}
(&Error(ref __self_0),) => {
hash::Hash::hash(&tykind_discriminant(self), state);
hash::Hash::hash(__self_0, state)
}
_ => hash::Hash::hash(&tykind_discriminant(self), state),
} }
} }
} }
@ -588,37 +464,34 @@ impl<I: Interner> hash::Hash for TyKind<I> {
// This is manually implemented because a derive would require `I: Debug` // This is manually implemented because a derive would require `I: Debug`
impl<I: Interner> fmt::Debug for TyKind<I> { impl<I: Interner> fmt::Debug for TyKind<I> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use std::fmt::*;
match self { match self {
Bool => Formatter::write_str(f, "Bool"), Bool => f.write_str("Bool"),
Char => Formatter::write_str(f, "Char"), Char => f.write_str("Char"),
Int(f0) => Formatter::debug_tuple_field1_finish(f, "Int", f0), Int(i) => f.debug_tuple_field1_finish("Int", i),
Uint(f0) => Formatter::debug_tuple_field1_finish(f, "Uint", f0), Uint(u) => f.debug_tuple_field1_finish("Uint", u),
Float(f0) => Formatter::debug_tuple_field1_finish(f, "Float", f0), Float(float) => f.debug_tuple_field1_finish("Float", float),
Adt(f0, f1) => Formatter::debug_tuple_field2_finish(f, "Adt", f0, f1), Adt(d, s) => f.debug_tuple_field2_finish("Adt", d, s),
Foreign(f0) => Formatter::debug_tuple_field1_finish(f, "Foreign", f0), Foreign(d) => f.debug_tuple_field1_finish("Foreign", d),
Str => Formatter::write_str(f, "Str"), Str => f.write_str("Str"),
Array(f0, f1) => Formatter::debug_tuple_field2_finish(f, "Array", f0, f1), Array(t, c) => f.debug_tuple_field2_finish("Array", t, c),
Slice(f0) => Formatter::debug_tuple_field1_finish(f, "Slice", f0), Slice(t) => f.debug_tuple_field1_finish("Slice", t),
RawPtr(f0) => Formatter::debug_tuple_field1_finish(f, "RawPtr", f0), RawPtr(t) => f.debug_tuple_field1_finish("RawPtr", t),
Ref(f0, f1, f2) => Formatter::debug_tuple_field3_finish(f, "Ref", f0, f1, f2), Ref(r, t, m) => f.debug_tuple_field3_finish("Ref", r, t, m),
FnDef(f0, f1) => Formatter::debug_tuple_field2_finish(f, "FnDef", f0, f1), FnDef(d, s) => f.debug_tuple_field2_finish("FnDef", d, s),
FnPtr(f0) => Formatter::debug_tuple_field1_finish(f, "FnPtr", f0), FnPtr(s) => f.debug_tuple_field1_finish("FnPtr", s),
Dynamic(f0, f1, f2) => Formatter::debug_tuple_field3_finish(f, "Dynamic", f0, f1, f2), Dynamic(p, r, repr) => f.debug_tuple_field3_finish("Dynamic", p, r, repr),
Closure(f0, f1) => Formatter::debug_tuple_field2_finish(f, "Closure", f0, f1), Closure(d, s) => f.debug_tuple_field2_finish("Closure", d, s),
Generator(f0, f1, f2) => { Generator(d, s, m) => f.debug_tuple_field3_finish("Generator", d, s, m),
Formatter::debug_tuple_field3_finish(f, "Generator", f0, f1, f2) GeneratorWitness(g) => f.debug_tuple_field1_finish("GeneratorWitness", g),
} Never => f.write_str("Never"),
GeneratorWitness(f0) => Formatter::debug_tuple_field1_finish(f, "GeneratorWitness", f0), Tuple(t) => f.debug_tuple_field1_finish("Tuple", t),
Never => Formatter::write_str(f, "Never"), Projection(p) => f.debug_tuple_field1_finish("Projection", p),
Tuple(f0) => Formatter::debug_tuple_field1_finish(f, "Tuple", f0), Opaque(d, s) => f.debug_tuple_field2_finish("Opaque", d, s),
Projection(f0) => Formatter::debug_tuple_field1_finish(f, "Projection", f0), Param(p) => f.debug_tuple_field1_finish("Param", p),
Opaque(f0, f1) => Formatter::debug_tuple_field2_finish(f, "Opaque", f0, f1), Bound(d, b) => f.debug_tuple_field2_finish("Bound", d, b),
Param(f0) => Formatter::debug_tuple_field1_finish(f, "Param", f0), Placeholder(p) => f.debug_tuple_field1_finish("Placeholder", p),
Bound(f0, f1) => Formatter::debug_tuple_field2_finish(f, "Bound", f0, f1), Infer(t) => f.debug_tuple_field1_finish("Infer", t),
Placeholder(f0) => Formatter::debug_tuple_field1_finish(f, "Placeholder", f0), TyKind::Error(e) => f.debug_tuple_field1_finish("Error", e),
Infer(f0) => Formatter::debug_tuple_field1_finish(f, "Infer", f0),
TyKind::Error(f0) => Formatter::debug_tuple_field1_finish(f, "Error", f0),
} }
} }
} }
@ -1091,12 +964,12 @@ where
impl<I: Interner> Clone for RegionKind<I> { impl<I: Interner> Clone for RegionKind<I> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
match self { match self {
ReEarlyBound(a) => ReEarlyBound(a.clone()), ReEarlyBound(r) => ReEarlyBound(r.clone()),
ReLateBound(a, b) => ReLateBound(a.clone(), b.clone()), ReLateBound(d, r) => ReLateBound(d.clone(), r.clone()),
ReFree(a) => ReFree(a.clone()), ReFree(r) => ReFree(r.clone()),
ReStatic => ReStatic, ReStatic => ReStatic,
ReVar(a) => ReVar(a.clone()), ReVar(r) => ReVar(r.clone()),
RePlaceholder(a) => RePlaceholder(a.clone()), RePlaceholder(r) => RePlaceholder(r.clone()),
ReErased => ReErased, ReErased => ReErased,
} }
} }
@ -1106,29 +979,23 @@ impl<I: Interner> Clone for RegionKind<I> {
impl<I: Interner> PartialEq for RegionKind<I> { impl<I: Interner> PartialEq for RegionKind<I> {
#[inline] #[inline]
fn eq(&self, other: &RegionKind<I>) -> bool { fn eq(&self, other: &RegionKind<I>) -> bool {
let __self_vi = regionkind_discriminant(self); regionkind_discriminant(self) == regionkind_discriminant(other)
let __arg_1_vi = regionkind_discriminant(other); && match (self, other) {
if __self_vi == __arg_1_vi { (ReEarlyBound(a_r), ReEarlyBound(b_r)) => a_r == b_r,
match (&*self, &*other) { (ReLateBound(a_d, a_r), ReLateBound(b_d, b_r)) => a_d == b_d && a_r == b_r,
(&ReEarlyBound(ref __self_0), &ReEarlyBound(ref __arg_1_0)) => { (ReFree(a_r), ReFree(b_r)) => a_r == b_r,
__self_0 == __arg_1_0 (ReStatic, ReStatic) => true,
(ReVar(a_r), ReVar(b_r)) => a_r == b_r,
(RePlaceholder(a_r), RePlaceholder(b_r)) => a_r == b_r,
(ReErased, ReErased) => true,
_ => {
debug_assert!(
false,
"This branch must be unreachable, maybe the match is missing an arm? self = self = {self:?}, other = {other:?}"
);
true
} }
(
&ReLateBound(ref __self_0, ref __self_1),
&ReLateBound(ref __arg_1_0, ref __arg_1_1),
) => __self_0 == __arg_1_0 && __self_1 == __arg_1_1,
(&ReFree(ref __self_0), &ReFree(ref __arg_1_0)) => __self_0 == __arg_1_0,
(&ReStatic, &ReStatic) => true,
(&ReVar(ref __self_0), &ReVar(ref __arg_1_0)) => __self_0 == __arg_1_0,
(&RePlaceholder(ref __self_0), &RePlaceholder(ref __arg_1_0)) => {
__self_0 == __arg_1_0
}
(&ReErased, &ReErased) => true,
_ => true,
} }
} else {
false
}
} }
} }
@ -1139,7 +1006,7 @@ impl<I: Interner> Eq for RegionKind<I> {}
impl<I: Interner> PartialOrd for RegionKind<I> { impl<I: Interner> PartialOrd for RegionKind<I> {
#[inline] #[inline]
fn partial_cmp(&self, other: &RegionKind<I>) -> Option<Ordering> { fn partial_cmp(&self, other: &RegionKind<I>) -> Option<Ordering> {
Some(Ord::cmp(self, other)) Some(self.cmp(other))
} }
} }
@ -1147,66 +1014,41 @@ impl<I: Interner> PartialOrd for RegionKind<I> {
impl<I: Interner> Ord for RegionKind<I> { impl<I: Interner> Ord for RegionKind<I> {
#[inline] #[inline]
fn cmp(&self, other: &RegionKind<I>) -> Ordering { fn cmp(&self, other: &RegionKind<I>) -> Ordering {
let __self_vi = regionkind_discriminant(self); regionkind_discriminant(self).cmp(&regionkind_discriminant(other)).then_with(|| {
let __arg_1_vi = regionkind_discriminant(other); match (self, other) {
if __self_vi == __arg_1_vi { (ReEarlyBound(a_r), ReEarlyBound(b_r)) => a_r.cmp(b_r),
match (&*self, &*other) { (ReLateBound(a_d, a_r), ReLateBound(b_d, b_r)) => {
(&ReEarlyBound(ref __self_0), &ReEarlyBound(ref __arg_1_0)) => { a_d.cmp(b_d).then_with(|| a_r.cmp(b_r))
Ord::cmp(__self_0, __arg_1_0)
} }
( (ReFree(a_r), ReFree(b_r)) => a_r.cmp(b_r),
&ReLateBound(ref __self_0, ref __self_1), (ReStatic, ReStatic) => Ordering::Equal,
&ReLateBound(ref __arg_1_0, ref __arg_1_1), (ReVar(a_r), ReVar(b_r)) => a_r.cmp(b_r),
) => match Ord::cmp(__self_0, __arg_1_0) { (RePlaceholder(a_r), RePlaceholder(b_r)) => a_r.cmp(b_r),
Ordering::Equal => Ord::cmp(__self_1, __arg_1_1), (ReErased, ReErased) => Ordering::Equal,
cmp => cmp, _ => {
}, debug_assert!(false, "This branch must be unreachable, maybe the match is missing an arm? self = self = {self:?}, other = {other:?}");
(&ReFree(ref __self_0), &ReFree(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0), Ordering::Equal
(&ReStatic, &ReStatic) => Ordering::Equal,
(&ReVar(ref __self_0), &ReVar(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0),
(&RePlaceholder(ref __self_0), &RePlaceholder(ref __arg_1_0)) => {
Ord::cmp(__self_0, __arg_1_0)
} }
(&ReErased, &ReErased) => Ordering::Equal,
_ => Ordering::Equal,
} }
} else { })
Ord::cmp(&__self_vi, &__arg_1_vi)
}
} }
} }
// This is manually implemented because a derive would require `I: Hash` // This is manually implemented because a derive would require `I: Hash`
impl<I: Interner> hash::Hash for RegionKind<I> { impl<I: Interner> hash::Hash for RegionKind<I> {
fn hash<__H: hash::Hasher>(&self, state: &mut __H) -> () { fn hash<H: hash::Hasher>(&self, state: &mut H) -> () {
match (&*self,) { regionkind_discriminant(self).hash(state);
(&ReEarlyBound(ref __self_0),) => { match self {
hash::Hash::hash(&regionkind_discriminant(self), state); ReEarlyBound(r) => r.hash(state),
hash::Hash::hash(__self_0, state) ReLateBound(d, r) => {
} d.hash(state);
(&ReLateBound(ref __self_0, ref __self_1),) => { r.hash(state)
hash::Hash::hash(&regionkind_discriminant(self), state);
hash::Hash::hash(__self_0, state);
hash::Hash::hash(__self_1, state)
}
(&ReFree(ref __self_0),) => {
hash::Hash::hash(&regionkind_discriminant(self), state);
hash::Hash::hash(__self_0, state)
}
(&ReStatic,) => {
hash::Hash::hash(&regionkind_discriminant(self), state);
}
(&ReVar(ref __self_0),) => {
hash::Hash::hash(&regionkind_discriminant(self), state);
hash::Hash::hash(__self_0, state)
}
(&RePlaceholder(ref __self_0),) => {
hash::Hash::hash(&regionkind_discriminant(self), state);
hash::Hash::hash(__self_0, state)
}
(&ReErased,) => {
hash::Hash::hash(&regionkind_discriminant(self), state);
} }
ReFree(r) => r.hash(state),
ReStatic => (),
ReVar(r) => r.hash(state),
RePlaceholder(r) => r.hash(state),
ReErased => (),
} }
} }
} }
@ -1215,21 +1057,21 @@ impl<I: Interner> hash::Hash for RegionKind<I> {
impl<I: Interner> fmt::Debug for RegionKind<I> { impl<I: Interner> fmt::Debug for RegionKind<I> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
ReEarlyBound(ref data) => write!(f, "ReEarlyBound({:?})", data), ReEarlyBound(data) => write!(f, "ReEarlyBound({:?})", data),
ReLateBound(binder_id, ref bound_region) => { ReLateBound(binder_id, bound_region) => {
write!(f, "ReLateBound({:?}, {:?})", binder_id, bound_region) write!(f, "ReLateBound({:?}, {:?})", binder_id, bound_region)
} }
ReFree(ref fr) => fr.fmt(f), ReFree(fr) => fr.fmt(f),
ReStatic => write!(f, "ReStatic"), ReStatic => f.write_str("ReStatic"),
ReVar(ref vid) => vid.fmt(f), ReVar(vid) => vid.fmt(f),
RePlaceholder(placeholder) => write!(f, "RePlaceholder({:?})", placeholder), RePlaceholder(placeholder) => write!(f, "RePlaceholder({:?})", placeholder),
ReErased => write!(f, "ReErased"), ReErased => f.write_str("ReErased"),
} }
} }
} }
@ -1317,18 +1159,18 @@ where
ReErased | ReStatic => { ReErased | ReStatic => {
// No variant fields to hash for these ... // No variant fields to hash for these ...
} }
ReLateBound(db, br) => { ReLateBound(d, r) => {
db.hash_stable(hcx, hasher); d.hash_stable(hcx, hasher);
br.hash_stable(hcx, hasher); r.hash_stable(hcx, hasher);
} }
ReEarlyBound(eb) => { ReEarlyBound(r) => {
eb.hash_stable(hcx, hasher); r.hash_stable(hcx, hasher);
} }
ReFree(ref free_region) => { ReFree(r) => {
free_region.hash_stable(hcx, hasher); r.hash_stable(hcx, hasher);
} }
RePlaceholder(p) => { RePlaceholder(r) => {
p.hash_stable(hcx, hasher); r.hash_stable(hcx, hasher);
} }
ReVar(_) => { ReVar(_) => {
panic!("region variables should not be hashed: {self:?}") panic!("region variables should not be hashed: {self:?}")

View file

@ -0,0 +1,122 @@
use std::{
cmp::Ordering,
hash::{Hash, Hasher},
ops::Deref,
};
use rustc_data_structures::{
fingerprint::Fingerprint,
stable_hasher::{HashStable, StableHasher},
};
use crate::{DebruijnIndex, TypeFlags};
/// A helper type that you can wrap round your own type in order to automatically
/// cache the stable hash, type flags and debruijn index on creation and
/// not recompute it whenever the information is needed.
/// This is only done in incremental mode. You can also opt out of caching by using
/// StableHash::ZERO for the hash, in which case the hash gets computed each time.
/// This is useful if you have values that you intern but never (can?) use for stable
/// hashing.
#[derive(Copy, Clone)]
pub struct WithCachedTypeInfo<T> {
pub internee: T,
pub stable_hash: Fingerprint,
/// This field provides fast access to information that is also contained
/// in `kind`.
///
/// This field shouldn't be used directly and may be removed in the future.
/// Use `Ty::flags()` instead.
pub flags: TypeFlags,
/// This field provides fast access to information that is also contained
/// in `kind`.
///
/// This is a kind of confusing thing: it stores the smallest
/// binder such that
///
/// (a) the binder itself captures nothing but
/// (b) all the late-bound things within the type are captured
/// by some sub-binder.
///
/// So, for a type without any late-bound things, like `u32`, this
/// will be *innermost*, because that is the innermost binder that
/// captures nothing. But for a type `&'D u32`, where `'D` is a
/// late-bound region with De Bruijn index `D`, this would be `D + 1`
/// -- the binder itself does not capture `D`, but `D` is captured
/// by an inner binder.
///
/// We call this concept an "exclusive" binder `D` because all
/// De Bruijn indices within the type are contained within `0..D`
/// (exclusive).
pub outer_exclusive_binder: DebruijnIndex,
}
impl<T: PartialEq> PartialEq for WithCachedTypeInfo<T> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.internee.eq(&other.internee)
}
}
impl<T: Eq> Eq for WithCachedTypeInfo<T> {}
impl<T: Ord> PartialOrd for WithCachedTypeInfo<T> {
fn partial_cmp(&self, other: &WithCachedTypeInfo<T>) -> Option<Ordering> {
Some(self.internee.cmp(&other.internee))
}
}
impl<T: Ord> Ord for WithCachedTypeInfo<T> {
fn cmp(&self, other: &WithCachedTypeInfo<T>) -> Ordering {
self.internee.cmp(&other.internee)
}
}
impl<T> Deref for WithCachedTypeInfo<T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
&self.internee
}
}
impl<T: Hash> Hash for WithCachedTypeInfo<T> {
#[inline]
fn hash<H: Hasher>(&self, s: &mut H) {
if self.stable_hash != Fingerprint::ZERO {
self.stable_hash.hash(s)
} else {
self.internee.hash(s)
}
}
}
impl<T: HashStable<CTX>, CTX> HashStable<CTX> for WithCachedTypeInfo<T> {
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
if self.stable_hash == Fingerprint::ZERO || cfg!(debug_assertions) {
// No cached hash available. This can only mean that incremental is disabled.
// We don't cache stable hashes in non-incremental mode, because they are used
// so rarely that the performance actually suffers.
// We need to build the hash as if we cached it and then hash that hash, as
// otherwise the hashes will differ between cached and non-cached mode.
let stable_hash: Fingerprint = {
let mut hasher = StableHasher::new();
self.internee.hash_stable(hcx, &mut hasher);
hasher.finish()
};
if cfg!(debug_assertions) && self.stable_hash != Fingerprint::ZERO {
assert_eq!(
stable_hash, self.stable_hash,
"cached stable hash does not match freshly computed stable hash"
);
}
stable_hash.hash_stable(hcx, hasher);
} else {
self.stable_hash.hash_stable(hcx, hasher);
}
}
}

View file

@ -44,7 +44,7 @@ pub use poll_fn::{poll_fn, PollFn};
/// non-Send/Sync as well, and we don't want that. /// non-Send/Sync as well, and we don't want that.
/// ///
/// It also simplifies the HIR lowering of `.await`. /// It also simplifies the HIR lowering of `.await`.
#[cfg_attr(not(bootstrap), lang = "ResumeTy")] // FIXME(swatinem): This type can be removed when bumping the bootstrap compiler
#[doc(hidden)] #[doc(hidden)]
#[unstable(feature = "gen_future", issue = "50547")] #[unstable(feature = "gen_future", issue = "50547")]
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
@ -61,6 +61,7 @@ unsafe impl Sync for ResumeTy {}
/// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give /// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give
/// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`). /// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`).
// This is `const` to avoid extra errors after we recover from `const async fn` // This is `const` to avoid extra errors after we recover from `const async fn`
// FIXME(swatinem): This fn can be removed when bumping the bootstrap compiler
#[cfg_attr(bootstrap, lang = "from_generator")] #[cfg_attr(bootstrap, lang = "from_generator")]
#[doc(hidden)] #[doc(hidden)]
#[unstable(feature = "gen_future", issue = "50547")] #[unstable(feature = "gen_future", issue = "50547")]
@ -102,7 +103,8 @@ where
GenFuture(gen) GenFuture(gen)
} }
#[lang = "get_context"] // FIXME(swatinem): This fn can be removed when bumping the bootstrap compiler
#[cfg_attr(bootstrap, lang = "get_context")]
#[doc(hidden)] #[doc(hidden)]
#[unstable(feature = "gen_future", issue = "50547")] #[unstable(feature = "gen_future", issue = "50547")]
#[must_use] #[must_use]
@ -113,6 +115,10 @@ pub unsafe fn get_context<'a, 'b>(cx: ResumeTy) -> &'a mut Context<'b> {
unsafe { &mut *cx.0.as_ptr().cast() } unsafe { &mut *cx.0.as_ptr().cast() }
} }
// FIXME(swatinem): This fn is currently needed to work around shortcomings
// in type and lifetime inference.
// See the comment at the bottom of `LoweringContext::make_async_expr` and
// <https://github.com/rust-lang/rust/issues/104826>.
#[cfg_attr(not(bootstrap), lang = "identity_future")] #[cfg_attr(not(bootstrap), lang = "identity_future")]
#[doc(hidden)] #[doc(hidden)]
#[unstable(feature = "gen_future", issue = "50547")] #[unstable(feature = "gen_future", issue = "50547")]

View file

@ -174,6 +174,7 @@ impl RawWakerVTable {
/// Currently, `Context` only serves to provide access to a [`&Waker`](Waker) /// Currently, `Context` only serves to provide access to a [`&Waker`](Waker)
/// which can be used to wake the current task. /// which can be used to wake the current task.
#[stable(feature = "futures_api", since = "1.36.0")] #[stable(feature = "futures_api", since = "1.36.0")]
#[cfg_attr(not(bootstrap), lang = "Context")]
pub struct Context<'a> { pub struct Context<'a> {
waker: &'a Waker, waker: &'a Waker,
// Ensure we future-proof against variance changes by forcing // Ensure we future-proof against variance changes by forcing

View file

@ -195,8 +195,7 @@ h1, h2, h3, h4, h5, h6,
span.since, span.since,
a.srclink, a.srclink,
#help-button > a, #help-button > a,
details.rustdoc-toggle.top-doc > summary, summary.hideme,
details.rustdoc-toggle.non-exhaustive > summary,
.scraped-example-list, .scraped-example-list,
/* This selector is for the items listed in the "all items" page. */ /* This selector is for the items listed in the "all items" page. */
ul.all-items { ul.all-items {
@ -1484,6 +1483,7 @@ details.rustdoc-toggle {
"Expand description" or "Show methods". */ "Expand description" or "Show methods". */
details.rustdoc-toggle > summary.hideme { details.rustdoc-toggle > summary.hideme {
cursor: pointer; cursor: pointer;
font-size: 1rem;
} }
details.rustdoc-toggle > summary { details.rustdoc-toggle > summary {
@ -1546,13 +1546,6 @@ details.rustdoc-toggle > summary:focus-visible::before {
outline-offset: 1px; outline-offset: 1px;
} }
details.rustdoc-toggle.top-doc > summary,
details.rustdoc-toggle.top-doc > summary::before,
details.rustdoc-toggle.non-exhaustive > summary,
details.rustdoc-toggle.non-exhaustive > summary::before {
font-size: 1rem;
}
details.non-exhaustive { details.non-exhaustive {
margin-bottom: 8px; margin-bottom: 8px;
} }

View file

@ -3,3 +3,8 @@ goto: "file://" + |DOC_PATH| + "/test_docs/enum.WhoLetTheDogOut.html"
assert-css: (".variants > .variant", {"margin": "0px 0px 12px"}) assert-css: (".variants > .variant", {"margin": "0px 0px 12px"})
assert-css: (".variants > .docblock", {"margin": "0px 0px 32px 24px"}) assert-css: (".variants > .docblock", {"margin": "0px 0px 32px 24px"})
assert-css: (
"details.non-exhaustive > summary",
{"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'},
)

View file

@ -76,6 +76,7 @@ impl AsRef<str> for Foo {
/// ///
/// # title! /// # title!
#[doc(alias = "ThisIsAnAlias")] #[doc(alias = "ThisIsAnAlias")]
#[non_exhaustive]
pub enum WhoLetTheDogOut { pub enum WhoLetTheDogOut {
/// Woof! /// Woof!
Woof, Woof,

View file

@ -7,6 +7,10 @@ wait-for: 50
// This is now collapsed so there shouldn't be the "open" attribute on details. // This is now collapsed so there shouldn't be the "open" attribute on details.
assert-attribute-false: ("#main-content > details.top-doc", {"open": ""}) assert-attribute-false: ("#main-content > details.top-doc", {"open": ""})
assert-text: ("#toggle-all-docs", "[+]") assert-text: ("#toggle-all-docs", "[+]")
assert-css: (
"#main-content > details.top-doc > summary",
{"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'},
)
click: "#toggle-all-docs" click: "#toggle-all-docs"
// Not collapsed anymore so the "open" attribute should be back. // Not collapsed anymore so the "open" attribute should be back.
wait-for-attribute: ("#main-content > details.top-doc", {"open": ""}) wait-for-attribute: ("#main-content > details.top-doc", {"open": ""})

View file

@ -77,6 +77,7 @@
-Z location-detail=val -- what location details should be tracked when using caller_location, either `none`, or a comma separated list of location details, for which valid options are `file`, `line`, and `column` (default: `file,line,column`) -Z location-detail=val -- what location details should be tracked when using caller_location, either `none`, or a comma separated list of location details, for which valid options are `file`, `line`, and `column` (default: `file,line,column`)
-Z ls=val -- list the symbols defined by a library crate (default: no) -Z ls=val -- list the symbols defined by a library crate (default: no)
-Z macro-backtrace=val -- show macro backtraces (default: no) -Z macro-backtrace=val -- show macro backtraces (default: no)
-Z maximal-hir-to-mir-coverage=val -- save as much information as possible about the correspondence between MIR and HIR as source scopes (default: no)
-Z merge-functions=val -- control the operation of the MergeFunctions LLVM pass, taking the same values as the target option of the same name -Z merge-functions=val -- control the operation of the MergeFunctions LLVM pass, taking the same values as the target option of the same name
-Z meta-stats=val -- gather metadata statistics (default: no) -Z meta-stats=val -- gather metadata statistics (default: no)
-Z mir-emit-retag=val -- emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 (default: no) -Z mir-emit-retag=val -- emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 (default: no)

View file

@ -40,7 +40,7 @@ LL | async fn bar2<T>(_: T) -> ! {
LL | | panic!() LL | | panic!()
LL | | } LL | | }
| |_^ | |_^
= note: required because it captures the following types: `ResumeTy`, `Option<bool>`, `impl Future<Output = !>`, `()` = note: required because it captures the following types: `&mut Context<'_>`, `Option<bool>`, `impl Future<Output = !>`, `()`
note: required because it's used within this `async fn` body note: required because it's used within this `async fn` body
--> $DIR/async-await-let-else.rs:21:32 --> $DIR/async-await-let-else.rs:21:32
| |

View file

@ -57,7 +57,7 @@ note: required because it appears within the type `impl Future<Output = Arc<RefC
| |
LL | fn make_non_send_future2() -> impl Future<Output = Arc<RefCell<i32>>> { LL | fn make_non_send_future2() -> impl Future<Output = Arc<RefCell<i32>>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: required because it captures the following types: `ResumeTy`, `impl Future<Output = Arc<RefCell<i32>>>`, `()`, `Ready<i32>` = note: required because it captures the following types: `&mut Context<'_>`, `impl Future<Output = Arc<RefCell<i32>>>`, `()`, `Ready<i32>`
note: required because it's used within this `async` block note: required because it's used within this `async` block
--> $DIR/issue-68112.rs:60:20 --> $DIR/issue-68112.rs:60:20
| |

View file

@ -57,7 +57,7 @@ note: required because it appears within the type `impl Future<Output = Arc<RefC
| |
LL | fn make_non_send_future2() -> impl Future<Output = Arc<RefCell<i32>>> { LL | fn make_non_send_future2() -> impl Future<Output = Arc<RefCell<i32>>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: required because it captures the following types: `ResumeTy`, `impl Future<Output = Arc<RefCell<i32>>>`, `()`, `i32`, `Ready<i32>` = note: required because it captures the following types: `&mut Context<'_>`, `impl Future<Output = Arc<RefCell<i32>>>`, `()`, `i32`, `Ready<i32>`
note: required because it's used within this `async` block note: required because it's used within this `async` block
--> $DIR/issue-68112.rs:60:20 --> $DIR/issue-68112.rs:60:20
| |

View file

@ -14,6 +14,9 @@ LL | | });
| |
= note: `FnMut` closures only have access to their captured variables while they are executing... = note: `FnMut` closures only have access to their captured variables while they are executing...
= note: ...therefore, they cannot allow references to captured variables to escape = note: ...therefore, they cannot allow references to captured variables to escape
= note: requirement occurs because of a mutable reference to `Context<'_>`
= note: mutable references are invariant over their type parameter
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error: aborting due to previous error error: aborting due to previous error

View file

@ -18,7 +18,7 @@ LL | async fn baz<T>(_c: impl FnMut() -> T) where T: Future<Output=()> {
| ___________________________________________________________________^ | ___________________________________________________________________^
LL | | } LL | | }
| |_^ | |_^
= note: required because it captures the following types: `ResumeTy`, `impl Future<Output = ()>`, `()` = note: required because it captures the following types: `&mut Context<'_>`, `impl Future<Output = ()>`, `()`
note: required because it's used within this `async` block note: required because it's used within this `async` block
--> $DIR/issue-70935-complex-spans.rs:16:5 --> $DIR/issue-70935-complex-spans.rs:16:5
| |

View file

@ -11,7 +11,7 @@ LL | async fn foo() {
| |
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `NotSend` = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `NotSend`
= note: required because it appears within the type `(NotSend,)` = note: required because it appears within the type `(NotSend,)`
= note: required because it captures the following types: `ResumeTy`, `(NotSend,)`, `()`, `impl Future<Output = ()>` = note: required because it captures the following types: `&mut Context<'_>`, `(NotSend,)`, `()`, `impl Future<Output = ()>`
note: required because it's used within this `async fn` body note: required because it's used within this `async fn` body
--> $DIR/partial-drop-partial-reinit.rs:31:16 --> $DIR/partial-drop-partial-reinit.rs:31:16
| |

View file

@ -11,7 +11,7 @@ LL | async fn foo() {
| |
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `NotSend` = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `NotSend`
= note: required because it appears within the type `(NotSend,)` = note: required because it appears within the type `(NotSend,)`
= note: required because it captures the following types: `ResumeTy`, `(NotSend,)`, `impl Future<Output = ()>`, `()` = note: required because it captures the following types: `&mut Context<'_>`, `(NotSend,)`, `impl Future<Output = ()>`, `()`
note: required because it's used within this `async fn` body note: required because it's used within this `async fn` body
--> $DIR/partial-drop-partial-reinit.rs:31:16 --> $DIR/partial-drop-partial-reinit.rs:31:16
| |

View file

@ -0,0 +1,6 @@
// error-pattern: this file contains an unclosed delimiter
// error-pattern: this file contains an unclosed delimiter
// error-pattern: this file contains an unclosed delimiter
// error-pattern: format argument must be a string literal
fn f(){(print!(á

View file

@ -0,0 +1,43 @@
error: this file contains an unclosed delimiter
--> $DIR/issue-104897.rs:6:18
|
LL | fn f(){(print!(á
| -- - ^
| || |
| || unclosed delimiter
| |unclosed delimiter
| unclosed delimiter
error: this file contains an unclosed delimiter
--> $DIR/issue-104897.rs:6:18
|
LL | fn f(){(print!(á
| -- - ^
| || |
| || unclosed delimiter
| |unclosed delimiter
| unclosed delimiter
error: this file contains an unclosed delimiter
--> $DIR/issue-104897.rs:6:18
|
LL | fn f(){(print!(á
| -- - ^
| || |
| || unclosed delimiter
| |unclosed delimiter
| unclosed delimiter
error: format argument must be a string literal
--> $DIR/issue-104897.rs:6:16
|
LL | fn f(){(print!(á
| ^
|
help: you might be missing a string literal to format with
|
LL | fn f(){(print!("{}", á
| +++++
error: aborting due to 4 previous errors

View file

@ -0,0 +1,10 @@
// compile-flags: -Zmaximal-hir-to-mir-coverage
// run-pass
// Just making sure this flag is accepted and doesn't crash the compiler
fn main() {
let x = 1;
let y = x + 1;
println!("{y}");
}

View file

@ -22,11 +22,11 @@ fn good_generic_fn<T>() {
// This should fail because `T` ends up in the upvars of the closure. // This should fail because `T` ends up in the upvars of the closure.
fn bad_generic_fn<T: Copy>(t: T) { fn bad_generic_fn<T: Copy>(t: T) {
assert_static(opaque(async move { t; }).next()); assert_static(opaque(async move { t; }).next());
//~^ ERROR the associated type `<impl Iterator as Iterator>::Item` may not live long enough //~^ ERROR the parameter type `T` may not live long enough
assert_static(opaque(move || { t; }).next()); assert_static(opaque(move || { t; }).next());
//~^ ERROR the associated type `<impl Iterator as Iterator>::Item` may not live long enough //~^ ERROR the associated type `<impl Iterator as Iterator>::Item` may not live long enough
assert_static(opaque(opaque(async move { t; }).next()).next()); assert_static(opaque(opaque(async move { t; }).next()).next());
//~^ ERROR the associated type `<impl Iterator as Iterator>::Item` may not live long enough //~^ ERROR the parameter type `T` may not live long enough
} }
fn main() {} fn main() {}

View file

@ -1,11 +1,13 @@
error[E0310]: the associated type `<impl Iterator as Iterator>::Item` may not live long enough error[E0310]: the parameter type `T` may not live long enough
--> $DIR/closure-in-projection-issue-97405.rs:24:5 --> $DIR/closure-in-projection-issue-97405.rs:24:5
| |
LL | assert_static(opaque(async move { t; }).next()); LL | assert_static(opaque(async move { t; }).next());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
| |
= help: consider adding an explicit lifetime bound `<impl Iterator as Iterator>::Item: 'static`... help: consider adding an explicit lifetime bound...
= note: ...so that the type `<impl Iterator as Iterator>::Item` will meet its required lifetime bounds |
LL | fn bad_generic_fn<T: Copy + 'static>(t: T) {
| +++++++++
error[E0310]: the associated type `<impl Iterator as Iterator>::Item` may not live long enough error[E0310]: the associated type `<impl Iterator as Iterator>::Item` may not live long enough
--> $DIR/closure-in-projection-issue-97405.rs:26:5 --> $DIR/closure-in-projection-issue-97405.rs:26:5
@ -16,14 +18,16 @@ LL | assert_static(opaque(move || { t; }).next());
= help: consider adding an explicit lifetime bound `<impl Iterator as Iterator>::Item: 'static`... = help: consider adding an explicit lifetime bound `<impl Iterator as Iterator>::Item: 'static`...
= note: ...so that the type `<impl Iterator as Iterator>::Item` will meet its required lifetime bounds = note: ...so that the type `<impl Iterator as Iterator>::Item` will meet its required lifetime bounds
error[E0310]: the associated type `<impl Iterator as Iterator>::Item` may not live long enough error[E0310]: the parameter type `T` may not live long enough
--> $DIR/closure-in-projection-issue-97405.rs:28:5 --> $DIR/closure-in-projection-issue-97405.rs:28:5
| |
LL | assert_static(opaque(opaque(async move { t; }).next()).next()); LL | assert_static(opaque(opaque(async move { t; }).next()).next());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
| |
= help: consider adding an explicit lifetime bound `<impl Iterator as Iterator>::Item: 'static`... help: consider adding an explicit lifetime bound...
= note: ...so that the type `<impl Iterator as Iterator>::Item` will meet its required lifetime bounds |
LL | fn bad_generic_fn<T: Copy + 'static>(t: T) {
| +++++++++
error: aborting due to 3 previous errors error: aborting due to 3 previous errors

View file

@ -1,8 +1,10 @@
error[E0277]: the trait bound `T: GlUniformScalar` is not satisfied error[E0277]: the trait bound `T: GlUniformScalar` is not satisfied
--> $DIR/assoc-const-as-fn.rs:14:5 --> $DIR/assoc-const-as-fn.rs:14:40
| |
LL | <T as GlUniformScalar>::FACTORY(1, value); LL | <T as GlUniformScalar>::FACTORY(1, value);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `GlUniformScalar` is not implemented for `T` | ------------------------------- ^^^^^ the trait `GlUniformScalar` is not implemented for `T`
| |
| required by a bound introduced by this call
| |
help: consider further restricting this bound help: consider further restricting this bound
| |

View file

@ -14,4 +14,19 @@ fn use_foo(x: Foo) -> i32 {
return foo; return foo;
} }
// issue #105028, suggest removing the field only for shorthand
fn use_match(x: Foo) {
match x {
Foo { foo: unused, .. } => { //~ WARNING unused variable
//~| help: if this is intentional, prefix it with an underscore
}
}
match x {
Foo { foo, .. } => { //~ WARNING unused variable
//~| help: try removing the field
}
}
}
fn main() {} fn main() {}

View file

@ -8,5 +8,19 @@ LL | let Foo { foo, bar, .. } = x;
| |
= note: `#[warn(unused_variables)]` on by default = note: `#[warn(unused_variables)]` on by default
warning: 1 warning emitted warning: unused variable: `unused`
--> $DIR/try-removing-the-field.rs:20:20
|
LL | Foo { foo: unused, .. } => {
| ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused`
warning: unused variable: `foo`
--> $DIR/try-removing-the-field.rs:26:15
|
LL | Foo { foo, .. } => {
| ^^^-
| |
| help: try removing the field
warning: 3 warnings emitted