diff options
Diffstat (limited to 'compiler/rustc_middle/src/ty')
33 files changed, 888 insertions, 708 deletions
diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs index 85181720d..a2794a100 100644 --- a/compiler/rustc_middle/src/ty/_match.rs +++ b/compiler/rustc_middle/src/ty/_match.rs @@ -20,12 +20,11 @@ use crate::ty::{self, InferConst, Ty, TyCtxt}; /// affects any type variables or unification state. pub struct MatchAgainstFreshVars<'tcx> { tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, } impl<'tcx> MatchAgainstFreshVars<'tcx> { - pub fn new(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> MatchAgainstFreshVars<'tcx> { - MatchAgainstFreshVars { tcx, param_env } + pub fn new(tcx: TyCtxt<'tcx>) -> MatchAgainstFreshVars<'tcx> { + MatchAgainstFreshVars { tcx } } } @@ -33,13 +32,11 @@ impl<'tcx> TypeRelation<'tcx> for MatchAgainstFreshVars<'tcx> { fn tag(&self) -> &'static str { "MatchAgainstFreshVars" } + fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } - fn param_env(&self) -> ty::ParamEnv<'tcx> { - self.param_env - } fn a_is_expected(&self) -> bool { true } // irrelevant diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index f50969dd9..1d9a25628 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -99,7 +99,7 @@ pub struct AdtDefData { impl PartialOrd for AdtDefData { fn partial_cmp(&self, other: &AdtDefData) -> Option<Ordering> { - Some(self.cmp(&other)) + Some(self.cmp(other)) } } @@ -375,7 +375,7 @@ impl<'tcx> AdtDef<'tcx> { /// Asserts this is a struct or union and returns its unique variant. pub fn non_enum_variant(self) -> &'tcx VariantDef { assert!(self.is_struct() || self.is_union()); - &self.variant(FIRST_VARIANT) + self.variant(FIRST_VARIANT) } #[inline] @@ -481,7 +481,7 @@ impl<'tcx> AdtDef<'tcx> { ErrorHandled::Reported(..) => "enum discriminant evaluation failed", ErrorHandled::TooGeneric(..) => "enum discriminant depends on generics", }; - tcx.sess.delay_span_bug(tcx.def_span(expr_did), msg); + tcx.sess.span_delayed_bug(tcx.def_span(expr_did), msg); None } } diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index 74bdd07a1..8c29bc5a4 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs @@ -7,14 +7,13 @@ use std::fmt::Write; use crate::query::Providers; use rustc_data_structures::fx::FxIndexMap; -use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg}; -use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::{self as hir, LangItem}; +use rustc_hir as hir; +use rustc_hir::def_id::LocalDefId; use rustc_span::def_id::LocalDefIdMap; use rustc_span::symbol::Ident; use rustc_span::{Span, Symbol}; -use super::{Ty, TyCtxt}; +use super::TyCtxt; use self::BorrowKind::*; @@ -73,72 +72,6 @@ pub type RootVariableMinCaptureList<'tcx> = FxIndexMap<hir::HirId, MinCaptureLis /// Part of `MinCaptureInformationMap`; List of `CapturePlace`s. pub type MinCaptureList<'tcx> = Vec<CapturedPlace<'tcx>>; -/// Represents the various closure traits in the language. This -/// will determine the type of the environment (`self`, in the -/// desugaring) argument that the closure expects. -/// -/// You can get the environment type of a closure using -/// `tcx.closure_env_ty()`. -#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] -#[derive(HashStable)] -pub enum ClosureKind { - // Warning: Ordering is significant here! The ordering is chosen - // because the trait Fn is a subtrait of FnMut and so in turn, and - // hence we order it so that Fn < FnMut < FnOnce. - Fn, - FnMut, - FnOnce, -} - -impl ClosureKind { - /// This is the initial value used when doing upvar inference. - pub const LATTICE_BOTTOM: ClosureKind = ClosureKind::Fn; - - pub const fn as_str(self) -> &'static str { - match self { - ClosureKind::Fn => "Fn", - ClosureKind::FnMut => "FnMut", - ClosureKind::FnOnce => "FnOnce", - } - } - - /// Returns `true` if a type that impls this closure kind - /// must also implement `other`. - pub fn extends(self, other: ty::ClosureKind) -> bool { - self <= other - } - - /// Converts `self` to a [`DefId`] of the corresponding trait. - /// - /// Note: the inverse of this function is [`TyCtxt::fn_trait_kind_from_def_id`]. - pub fn to_def_id(&self, tcx: TyCtxt<'_>) -> DefId { - tcx.require_lang_item( - match self { - ClosureKind::Fn => LangItem::Fn, - ClosureKind::FnMut => LangItem::FnMut, - ClosureKind::FnOnce => LangItem::FnOnce, - }, - None, - ) - } - - /// Returns the representative scalar type for this closure kind. - /// See `Ty::to_opt_closure_kind` for more details. - pub fn to_ty<'tcx>(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { - match self { - ClosureKind::Fn => tcx.types.i8, - ClosureKind::FnMut => tcx.types.i16, - ClosureKind::FnOnce => tcx.types.i32, - } - } -} - -impl IntoDiagnosticArg for ClosureKind { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { - DiagnosticArgValue::Str(self.as_str().into()) - } -} - /// A composite describing a `Place` that is captured by a closure. #[derive(PartialEq, Clone, Debug, TyEncodable, TyDecodable, HashStable)] #[derive(TypeFoldable, TypeVisitable)] @@ -247,6 +180,13 @@ impl<'tcx> CapturedPlace<'tcx> { .span } } + + pub fn is_by_ref(&self) -> bool { + match self.info.capture_kind { + ty::UpvarCapture::ByValue => false, + ty::UpvarCapture::ByRef(..) => true, + } + } } #[derive(Copy, Clone, Debug, HashStable)] @@ -262,7 +202,7 @@ fn closure_typeinfo<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ClosureTypeInfo let user_provided_sig = typeck_results.user_provided_sigs[&def]; let captures = typeck_results.closure_min_captures_flattened(def); let captures = tcx.arena.alloc_from_iter(captures); - let hir_id = tcx.hir().local_def_id_to_hir_id(def); + let hir_id = tcx.local_def_id_to_hir_id(def); let kind_origin = typeck_results.closure_kind_origins().get(hir_id); ClosureTypeInfo { user_provided_sig, captures, kind_origin } } diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 8b67e3966..69ae05ca8 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -8,6 +8,7 @@ use crate::arena::ArenaAllocatable; use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos}; +use crate::mir::interpret::CtfeProvenance; use crate::mir::{ self, interpret::{AllocId, ConstAllocation}, @@ -164,6 +165,13 @@ impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for AllocId { } } +impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for CtfeProvenance { + fn encode(&self, e: &mut E) { + self.alloc_id().encode(e); + self.immutable().encode(e); + } +} + impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::ParamEnv<'tcx> { fn encode(&self, e: &mut E) { self.caller_bounds().encode(e); @@ -295,9 +303,18 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for AllocId { } } +impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for CtfeProvenance { + fn decode(decoder: &mut D) -> Self { + let alloc_id: AllocId = Decodable::decode(decoder); + let prov = CtfeProvenance::from(alloc_id); + let immutable: bool = Decodable::decode(decoder); + if immutable { prov.as_immutable() } else { prov } + } +} + impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::SymbolName<'tcx> { fn decode(decoder: &mut D) -> Self { - ty::SymbolName::new(decoder.interner(), &decoder.read_str()) + ty::SymbolName::new(decoder.interner(), decoder.read_str()) } } diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index af5ffc20d..2d3ee3348 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -1,5 +1,5 @@ use crate::middle::resolve_bound_vars as rbv; -use crate::mir::interpret::{AllocId, ErrorHandled, LitToConstInput, Scalar}; +use crate::mir::interpret::{ErrorHandled, LitToConstInput, Scalar}; use crate::ty::{self, GenericArgs, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt}; use rustc_data_structures::intern::Interned; use rustc_error_messages::MultiSpan; @@ -7,6 +7,7 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::LocalDefId; use rustc_macros::HashStable; +use rustc_type_ir::{ConstTy, IntoKind, TypeFlags, WithCachedTypeInfo}; mod int; mod kind; @@ -23,10 +24,25 @@ use super::sty::ConstKind; /// Use this rather than `ConstData`, whenever possible. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)] #[rustc_pass_by_value] -pub struct Const<'tcx>(pub(super) Interned<'tcx, ConstData<'tcx>>); +pub struct Const<'tcx>(pub(super) Interned<'tcx, WithCachedTypeInfo<ConstData<'tcx>>>); + +impl<'tcx> IntoKind for Const<'tcx> { + type Kind = ConstKind<'tcx>; + + fn kind(self) -> ConstKind<'tcx> { + self.kind() + } +} + +impl<'tcx> ConstTy<TyCtxt<'tcx>> for Const<'tcx> { + fn ty(self) -> Ty<'tcx> { + self.ty() + } +} /// Typed constant value. -#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, TyEncodable, TyDecodable)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(HashStable, TyEncodable, TyDecodable)] pub struct ConstData<'tcx> { pub ty: Ty<'tcx>, pub kind: ConstKind<'tcx>, @@ -43,7 +59,17 @@ impl<'tcx> Const<'tcx> { #[inline] pub fn kind(self) -> ConstKind<'tcx> { - self.0.kind.clone() + self.0.kind + } + + #[inline] + pub fn flags(self) -> TypeFlags { + self.0.flags + } + + #[inline] + pub fn outer_exclusive_binder(self) -> ty::DebruijnIndex { + self.0.outer_exclusive_binder } #[inline] @@ -133,7 +159,7 @@ impl<'tcx> Const<'tcx> { span: S, msg: &'static str, ) -> Const<'tcx> { - let reported = tcx.sess.delay_span_bug(span, msg); + let reported = tcx.sess.span_delayed_bug(span, msg); Const::new_error(tcx, reported, ty) } @@ -141,7 +167,7 @@ impl<'tcx> Const<'tcx> { /// becomes `Unevaluated`. #[instrument(skip(tcx), level = "debug")] pub fn from_anon_const(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Self { - let body_id = match tcx.hir().get_by_def_id(def) { + let body_id = match tcx.hir_node_by_def_id(def) { hir::Node::AnonConst(ac) => ac.body, _ => span_bug!( tcx.def_span(def.to_def_id()), @@ -183,11 +209,9 @@ impl<'tcx> Const<'tcx> { }; let lit_input = match expr.kind { - hir::ExprKind::Lit(ref lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }), - hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => match expr.kind { - hir::ExprKind::Lit(ref lit) => { - Some(LitToConstInput { lit: &lit.node, ty, neg: true }) - } + hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }), + hir::ExprKind::Unary(hir::UnOp::Neg, expr) => match expr.kind { + hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: true }), _ => None, }, _ => None, @@ -199,7 +223,7 @@ impl<'tcx> Const<'tcx> { match tcx.at(expr.span).lit_to_const(lit_input) { Ok(c) => return Some(c), Err(e) => { - tcx.sess.delay_span_bug( + tcx.sess.span_delayed_bug( expr.span, format!("Const::from_anon_const: couldn't lit_to_const {e:?}"), ); @@ -207,6 +231,10 @@ impl<'tcx> Const<'tcx> { } } + // FIXME(const_generics): We currently have to special case parameters because `min_const_generics` + // does not provide the parents generics to anonymous constants. We still allow generic const + // parameters by themselves however, e.g. `N`. These constants would cause an ICE if we were to + // ever try to substitute the generic parameters in their bodies. match expr.kind { hir::ExprKind::Path(hir::QPath::Resolved( _, @@ -291,8 +319,16 @@ impl<'tcx> Const<'tcx> { let (param_env, unevaluated) = unevaluated.prepare_for_eval(tcx, param_env); // try to resolve e.g. associated constants to their definition on an impl, and then // evaluate the const. - let c = tcx.const_eval_resolve_for_typeck(param_env, unevaluated, span)?; - Ok(c.expect("`ty::Const::eval` called on a non-valtree-compatible type")) + let Some(c) = tcx.const_eval_resolve_for_typeck(param_env, unevaluated, span)? + else { + // This can happen when we run on ill-typed code. + let e = tcx.sess.span_delayed_bug( + span.unwrap_or(DUMMY_SP), + "`ty::Const::eval` called on a non-valtree-compatible type", + ); + return Err(e.into()); + }; + Ok(c) } ConstKind::Value(val) => Ok(val), ConstKind::Error(g) => Err(g.into()), @@ -392,7 +428,7 @@ impl<'tcx> Const<'tcx> { } #[inline] - pub fn try_to_scalar(self) -> Option<Scalar<AllocId>> { + pub fn try_to_scalar(self) -> Option<Scalar> { self.try_to_valtree()?.try_to_scalar() } @@ -407,7 +443,7 @@ impl<'tcx> Const<'tcx> { } pub fn const_param_default(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Const<'_>> { - let default_def_id = match tcx.hir().get_by_def_id(def_id) { + let default_def_id = match tcx.hir_node_by_def_id(def_id) { hir::Node::GenericParam(hir::GenericParam { kind: hir::GenericParamKind::Const { default: Some(ac), .. }, .. diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index 9d99344d5..310cf113b 100644 --- a/compiler/rustc_middle/src/ty/consts/int.rs +++ b/compiler/rustc_middle/src/ty/consts/int.rs @@ -71,7 +71,7 @@ impl std::fmt::Debug for ConstInt { (4, _) => write!(fmt, "_i32")?, (8, _) => write!(fmt, "_i64")?, (16, _) => write!(fmt, "_i128")?, - _ => bug!(), + (sz, _) => bug!("unexpected int size i{sz}"), } } Ok(()) @@ -105,7 +105,7 @@ impl std::fmt::Debug for ConstInt { (4, _) => write!(fmt, "_u32")?, (8, _) => write!(fmt, "_u64")?, (16, _) => write!(fmt, "_u128")?, - _ => bug!(), + (sz, _) => bug!("unexpected unsigned int size u{sz}"), } } Ok(()) diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index 4af841fcf..16e7b16a0 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -3,7 +3,6 @@ use crate::mir; use crate::ty::abstract_const::CastKind; use crate::ty::GenericArgsRef; use crate::ty::{self, visit::TypeVisitableExt as _, List, Ty, TyCtxt}; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; @@ -77,28 +76,3 @@ static_assert_size!(Expr<'_>, 24); #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(super::ConstKind<'_>, 32); - -/// An inference variable for a const, for use in const generics. -#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)] -pub enum InferConst { - /// Infer the value of the const. - Var(ty::ConstVid), - /// Infer the value of the effect. - /// - /// For why this is separate from the `Var` variant above, see the - /// documentation on `EffectVid`. - EffectVar(ty::EffectVid), - /// A fresh const variable. See `infer::freshen` for more details. - Fresh(u32), -} - -impl<CTX> HashStable<CTX> for InferConst { - fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { - match self { - InferConst::Var(_) | InferConst::EffectVar(_) => { - panic!("const variables should not be hashed: {self:?}") - } - InferConst::Fresh(i) => i.hash_stable(hcx, hasher), - } - } -} diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs index fb7bf78ba..ffa0e89c4 100644 --- a/compiler/rustc_middle/src/ty/consts/valtree.rs +++ b/compiler/rustc_middle/src/ty/consts/valtree.rs @@ -1,5 +1,5 @@ use super::ScalarInt; -use crate::mir::interpret::{AllocId, Scalar}; +use crate::mir::interpret::Scalar; use crate::ty::{self, Ty, TyCtxt}; use rustc_macros::{HashStable, TyDecodable, TyEncodable}; @@ -67,7 +67,7 @@ impl<'tcx> ValTree<'tcx> { Self::Leaf(i) } - pub fn try_to_scalar(self) -> Option<Scalar<AllocId>> { + pub fn try_to_scalar(self) -> Option<Scalar> { self.try_to_scalar_int().map(Scalar::Int) } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 551c4a15d..b5ca700c2 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -6,7 +6,7 @@ pub mod tls; use crate::arena::Arena; use crate::dep_graph::{DepGraph, DepKindStruct}; -use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos}; +use crate::infer::canonical::{CanonicalParamEnvCache, CanonicalVarInfo, CanonicalVarInfos}; use crate::lint::struct_lint_level; use crate::metadata::ModChild; use crate::middle::codegen_fn_attrs::CodegenFnAttrs; @@ -26,9 +26,9 @@ use crate::traits::solve::{ }; use crate::ty::{ self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Const, ConstData, GenericParamDefKind, - ImplPolarity, InferTy, List, ParamConst, ParamTy, PolyExistentialPredicate, PolyFnSig, - Predicate, PredicateKind, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, - TyVid, TypeAndMut, Visibility, + ImplPolarity, List, ParamConst, ParamTy, PolyExistentialPredicate, PolyFnSig, Predicate, + PredicateKind, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid, + Visibility, }; use crate::ty::{GenericArg, GenericArgs, GenericArgsRef}; use rustc_ast::{self as ast, attr}; @@ -39,7 +39,9 @@ use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::steal::Steal; -use rustc_data_structures::sync::{self, FreezeReadGuard, Lock, Lrc, WorkerLocal}; +use rustc_data_structures::sync::{self, FreezeReadGuard, Lock, WorkerLocal}; +#[cfg(parallel_compiler)] +use rustc_data_structures::sync::{DynSend, DynSync}; use rustc_data_structures::unord::UnordSet; use rustc_errors::{ DecorateLint, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, MultiSpan, @@ -69,7 +71,6 @@ use rustc_type_ir::TyKind::*; use rustc_type_ir::WithCachedTypeInfo; use rustc_type_ir::{CollectAndApply, Interner, TypeFlags}; -use std::any::Any; use std::borrow::Borrow; use std::cmp::Ordering; use std::fmt; @@ -87,7 +88,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type Term = ty::Term<'tcx>; type Binder<T> = Binder<'tcx, T>; - type TypeAndMut = TypeAndMut<'tcx>; type CanonicalVars = CanonicalVarInfos<'tcx>; type Ty = Ty<'tcx>; @@ -96,7 +96,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type ParamTy = ParamTy; type BoundTy = ty::BoundTy; type PlaceholderTy = ty::PlaceholderType; - type InferTy = InferTy; type ErrorGuaranteed = ErrorGuaranteed; type BoundExistentialPredicates = &'tcx List<PolyExistentialPredicate<'tcx>>; @@ -104,7 +103,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type AllocId = crate::mir::interpret::AllocId; type Const = ty::Const<'tcx>; - type InferConst = ty::InferConst; type AliasConst = ty::UnevaluatedConst<'tcx>; type PlaceholderConst = ty::PlaceholderConst; type ParamConst = ty::ParamConst; @@ -113,9 +111,9 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type ExprConst = ty::Expr<'tcx>; type Region = Region<'tcx>; - type EarlyBoundRegion = ty::EarlyBoundRegion; + type EarlyParamRegion = ty::EarlyParamRegion; type BoundRegion = ty::BoundRegion; - type FreeRegion = ty::FreeRegion; + type LateParamRegion = ty::LateParamRegion; type InferRegion = ty::RegionVid; type PlaceholderRegion = ty::PlaceholderRegion; @@ -124,14 +122,34 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type RegionOutlivesPredicate = ty::RegionOutlivesPredicate<'tcx>; type TypeOutlivesPredicate = ty::TypeOutlivesPredicate<'tcx>; type ProjectionPredicate = ty::ProjectionPredicate<'tcx>; + type NormalizesTo = ty::NormalizesTo<'tcx>; type SubtypePredicate = ty::SubtypePredicate<'tcx>; type CoercePredicate = ty::CoercePredicate<'tcx>; type ClosureKind = ty::ClosureKind; - fn ty_and_mut_to_parts( - TypeAndMut { ty, mutbl }: TypeAndMut<'tcx>, - ) -> (Self::Ty, ty::Mutability) { - (ty, mutbl) + fn mk_canonical_var_infos(self, infos: &[ty::CanonicalVarInfo<Self>]) -> Self::CanonicalVars { + self.mk_canonical_var_infos(infos) + } + + fn mk_bound_ty(self, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self::Ty { + Ty::new_bound(self, debruijn, ty::BoundTy { var, kind: ty::BoundTyKind::Anon }) + } + + fn mk_bound_region(self, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self::Region { + Region::new_bound( + self, + debruijn, + ty::BoundRegion { var, kind: ty::BoundRegionKind::BrAnon }, + ) + } + + fn mk_bound_const( + self, + debruijn: ty::DebruijnIndex, + var: ty::BoundVar, + ty: Self::Ty, + ) -> Self::Const { + Const::new_bound(self, debruijn, var, ty) } } @@ -154,7 +172,7 @@ pub struct CtxtInterners<'tcx> { clauses: InternedSet<'tcx, List<Clause<'tcx>>>, projs: InternedSet<'tcx, List<ProjectionKind>>, place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>, - const_: InternedSet<'tcx, ConstData<'tcx>>, + const_: InternedSet<'tcx, WithCachedTypeInfo<ConstData<'tcx>>>, const_allocation: InternedSet<'tcx, Allocation>, bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>, layout: InternedSet<'tcx, LayoutS<FieldIdx, VariantIdx>>, @@ -215,6 +233,32 @@ impl<'tcx> CtxtInterners<'tcx> { )) } + /// Interns a const. (Use `mk_*` functions instead, where possible.) + #[allow(rustc::usage_of_ty_tykind)] + #[inline(never)] + fn intern_const( + &self, + data: ty::ConstData<'tcx>, + sess: &Session, + untracked: &Untracked, + ) -> Const<'tcx> { + Const(Interned::new_unchecked( + self.const_ + .intern(data, |data: ConstData<'_>| { + let flags = super::flags::FlagComputation::for_const(&data.kind, data.ty); + let stable_hash = self.stable_hash(&flags, sess, untracked, &data); + + InternedInSet(self.arena.alloc(WithCachedTypeInfo { + internee: data, + stable_hash, + flags: flags.flags, + outer_exclusive_binder: flags.outer_exclusive_binder, + })) + }) + .0, + )) + } + fn stable_hash<'a, T: HashStable<StableHashingContext<'a>>>( &self, flags: &ty::flags::FlagComputation, @@ -327,7 +371,7 @@ pub struct CommonLifetimes<'tcx> { pub re_vars: Vec<Region<'tcx>>, /// Pre-interned values of the form: - /// `ReLateBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon })` + /// `ReBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon })` /// for small values of `i` and `v`. pub re_late_bounds: Vec<Vec<Region<'tcx>>>, } @@ -402,7 +446,7 @@ impl<'tcx> CommonLifetimes<'tcx> { .map(|i| { (0..NUM_PREINTERNED_RE_LATE_BOUNDS_V) .map(|v| { - mk(ty::ReLateBound( + mk(ty::ReBound( ty::DebruijnIndex::from(i), ty::BoundRegion { var: ty::BoundVar::from(v), kind: ty::BrAnon }, )) @@ -421,11 +465,17 @@ impl<'tcx> CommonLifetimes<'tcx> { } impl<'tcx> CommonConsts<'tcx> { - fn new(interners: &CtxtInterners<'tcx>, types: &CommonTypes<'tcx>) -> CommonConsts<'tcx> { + fn new( + interners: &CtxtInterners<'tcx>, + types: &CommonTypes<'tcx>, + sess: &Session, + untracked: &Untracked, + ) -> CommonConsts<'tcx> { let mk_const = |c| { - Const(Interned::new_unchecked( - interners.const_.intern(c, |c| InternedInSet(interners.arena.alloc(c))).0, - )) + interners.intern_const( + c, sess, // This is only used to create a stable hashing context. + untracked, + ) }; CommonConsts { @@ -445,14 +495,14 @@ impl<'tcx> CommonConsts<'tcx> { } } -/// This struct contains information regarding the `ReFree(FreeRegion)` corresponding to a lifetime -/// conflict. +/// This struct contains information regarding a free parameter region, +/// either a `ReEarlyParam` or `ReLateParam`. #[derive(Debug)] pub struct FreeRegionInfo { - /// `LocalDefId` corresponding to FreeRegion + /// `LocalDefId` of the free region. pub def_id: LocalDefId, - /// the bound region corresponding to FreeRegion - pub boundregion: ty::BoundRegionKind, + /// the bound region corresponding to free region. + pub bound_region: ty::BoundRegionKind, /// checks if bound region is in Impl Item pub is_impl_item: bool, } @@ -472,6 +522,9 @@ impl<'tcx> TyCtxt<'tcx> { pub fn feed_local_crate(self) -> TyCtxtFeed<'tcx, CrateNum> { TyCtxtFeed { tcx: self, key: LOCAL_CRATE } } + pub fn feed_local_def_id(self, key: LocalDefId) -> TyCtxtFeed<'tcx, LocalDefId> { + TyCtxtFeed { tcx: self, key } + } /// In order to break cycles involving `AnonConst`, we need to set the expected type by side /// effect. However, we do not want this as a general capability, so this interface restricts @@ -520,6 +573,16 @@ pub struct TyCtxt<'tcx> { gcx: &'tcx GlobalCtxt<'tcx>, } +// Explicitly implement `DynSync` and `DynSend` for `TyCtxt` to short circuit trait resolution. +#[cfg(parallel_compiler)] +unsafe impl DynSend for TyCtxt<'_> {} +#[cfg(parallel_compiler)] +unsafe impl DynSync for TyCtxt<'_> {} +fn _assert_tcx_fields() { + sync::assert_dyn_sync::<&'_ GlobalCtxt<'_>>(); + sync::assert_dyn_send::<&'_ GlobalCtxt<'_>>(); +} + impl<'tcx> Deref for TyCtxt<'tcx> { type Target = &'tcx GlobalCtxt<'tcx>; #[inline(always)] @@ -544,12 +607,6 @@ pub struct GlobalCtxt<'tcx> { /// `rustc_symbol_mangling` crate for more information. stable_crate_id: StableCrateId, - /// This only ever stores a `LintStore` but we don't want a dependency on that type here. - /// - /// FIXME(Centril): consider `dyn LintStoreMarker` once - /// we can upcast to `Any` for some additional type safety. - pub lint_store: Lrc<dyn Any + sync::DynSync + sync::DynSend>, - pub dep_graph: DepGraph, pub prof: SelfProfilerRef, @@ -589,6 +646,8 @@ pub struct GlobalCtxt<'tcx> { pub new_solver_evaluation_cache: solve::EvaluationCache<'tcx>, pub new_solver_coherence_evaluation_cache: solve::EvaluationCache<'tcx>, + pub canonical_param_env_cache: CanonicalParamEnvCache<'tcx>, + /// Data layout specification for the current target. pub data_layout: TargetDataLayout, @@ -606,6 +665,10 @@ impl<'tcx> GlobalCtxt<'tcx> { let icx = tls::ImplicitCtxt::new(self); tls::enter_context(&icx, || f(icx.tcx)) } + + pub fn finish(&self) -> FileEncodeResult { + self.dep_graph.finish_encoding(&self.sess.prof) + } } impl<'tcx> TyCtxt<'tcx> { @@ -684,8 +747,10 @@ impl<'tcx> TyCtxt<'tcx> { { Bound::Included(a) } else { - self.sess - .delay_span_bug(attr.span, "invalid rustc_layout_scalar_valid_range attribute"); + self.sess.span_delayed_bug( + attr.span, + "invalid rustc_layout_scalar_valid_range attribute", + ); Bound::Unbounded } }; @@ -709,7 +774,6 @@ impl<'tcx> TyCtxt<'tcx> { s: &'tcx Session, crate_types: Vec<CrateType>, stable_crate_id: StableCrateId, - lint_store: Lrc<dyn Any + sync::DynSend + sync::DynSync>, arena: &'tcx WorkerLocal<Arena<'tcx>>, hir_arena: &'tcx WorkerLocal<hir::Arena<'tcx>>, untracked: Untracked, @@ -724,13 +788,12 @@ impl<'tcx> TyCtxt<'tcx> { let interners = CtxtInterners::new(arena); let common_types = CommonTypes::new(&interners, s, &untracked); let common_lifetimes = CommonLifetimes::new(&interners); - let common_consts = CommonConsts::new(&interners, &common_types); + let common_consts = CommonConsts::new(&interners, &common_types, s, &untracked); GlobalCtxt { sess: s, crate_types, stable_crate_id, - lint_store, arena, hir_arena, interners, @@ -749,6 +812,7 @@ impl<'tcx> TyCtxt<'tcx> { evaluation_cache: Default::default(), new_solver_evaluation_cache: Default::default(), new_solver_coherence_evaluation_cache: Default::default(), + canonical_param_env_cache: Default::default(), data_layout, alloc_map: Lock::new(interpret::AllocMap::new()), } @@ -779,6 +843,10 @@ impl<'tcx> TyCtxt<'tcx> { self.diagnostic_items(did.krate).name_to_id.get(&name) == Some(&did) } + pub fn is_coroutine(self, def_id: DefId) -> bool { + self.coroutine_kind(def_id).is_some() + } + /// Returns `true` if the node pointed to by `def_id` is a coroutine for an async construct. pub fn coroutine_is_async(self, def_id: DefId) -> bool { matches!(self.coroutine_kind(def_id), Some(hir::CoroutineKind::Async(_))) @@ -790,11 +858,16 @@ impl<'tcx> TyCtxt<'tcx> { matches!(self.coroutine_kind(def_id), Some(hir::CoroutineKind::Coroutine)) } - /// Returns `true` if the node pointed to by `def_id` is a coroutine for a gen construct. + /// Returns `true` if the node pointed to by `def_id` is a coroutine for a `gen` construct. pub fn coroutine_is_gen(self, def_id: DefId) -> bool { matches!(self.coroutine_kind(def_id), Some(hir::CoroutineKind::Gen(_))) } + /// Returns `true` if the node pointed to by `def_id` is a coroutine for a `async gen` construct. + pub fn coroutine_is_async_gen(self, def_id: DefId) -> bool { + matches!(self.coroutine_kind(def_id), Some(hir::CoroutineKind::AsyncGen(_))) + } + pub fn stability(self) -> &'tcx stability::Index { self.stability_index(()) } @@ -943,7 +1016,8 @@ impl<'tcx> TyCtxtAt<'tcx> { pub fn create_def( self, parent: LocalDefId, - data: hir::definitions::DefPathData, + name: Symbol, + def_kind: DefKind, ) -> TyCtxtFeed<'tcx, LocalDefId> { // This function modifies `self.definitions` using a side-effect. // We need to ensure that these side effects are re-run by the incr. comp. engine. @@ -965,15 +1039,34 @@ impl<'tcx> TyCtxtAt<'tcx> { // This is fine because: // - those queries are `eval_always` so we won't miss their result changing; // - this write will have happened before these queries are called. - let key = self.untracked.definitions.write().create_def(parent, data); + let def_id = self.tcx.create_def(parent, name, def_kind); - let feed = TyCtxtFeed { tcx: self.tcx, key }; + let feed = self.tcx.feed_local_def_id(def_id); feed.def_span(self.span); feed } } impl<'tcx> TyCtxt<'tcx> { + /// `tcx`-dependent operations performed for every created definition. + pub fn create_def(self, parent: LocalDefId, name: Symbol, def_kind: DefKind) -> LocalDefId { + let data = def_kind.def_path_data(name); + let def_id = self.untracked.definitions.write().create_def(parent, data); + + let feed = self.feed_local_def_id(def_id); + feed.def_kind(def_kind); + // Unique types created for closures participate in type privacy checking. + // They have visibilities inherited from the module they are defined in. + // Visibilities for opaque types are meaningless, but still provided + // so that all items have visibilities. + if matches!(def_kind, DefKind::Closure | DefKind::OpaqueTy) { + let parent_mod = self.parent_module_from_def_id(def_id).to_def_id(); + feed.visibility(ty::Visibility::Restricted(parent_mod)); + } + + def_id + } + pub fn iter_local_def_id(self) -> impl Iterator<Item = LocalDefId> + 'tcx { // Create a dependency to the red node to be sure we re-execute this when the amount of // definitions change. @@ -1080,8 +1173,8 @@ impl<'tcx> TyCtxt<'tcx> { pub fn is_suitable_region(self, mut region: Region<'tcx>) -> Option<FreeRegionInfo> { let (suitable_region_binding_scope, bound_region) = loop { let def_id = match region.kind() { - ty::ReFree(fr) => fr.bound_region.get_id()?.as_local()?, - ty::ReEarlyBound(ebr) => ebr.def_id.expect_local(), + ty::ReLateParam(fr) => fr.bound_region.get_id()?.as_local()?, + ty::ReEarlyParam(ebr) => ebr.def_id.expect_local(), _ => return None, // not a free region }; let scope = self.local_parent(def_id); @@ -1094,7 +1187,7 @@ impl<'tcx> TyCtxt<'tcx> { break (scope, ty::BrNamed(def_id.into(), self.item_name(def_id.into()))); }; - let is_impl_item = match self.hir().find_by_def_id(suitable_region_binding_scope) { + let is_impl_item = match self.opt_hir_node_by_def_id(suitable_region_binding_scope) { Some(Node::Item(..) | Node::TraitItem(..)) => false, Some(Node::ImplItem(..)) => { self.is_bound_region_in_impl_item(suitable_region_binding_scope) @@ -1102,11 +1195,7 @@ impl<'tcx> TyCtxt<'tcx> { _ => false, }; - Some(FreeRegionInfo { - def_id: suitable_region_binding_scope, - boundregion: bound_region, - is_impl_item, - }) + Some(FreeRegionInfo { def_id: suitable_region_binding_scope, bound_region, is_impl_item }) } /// Given a `DefId` for an `fn`, return all the `dyn` and `impl` traits in its return type. @@ -1114,7 +1203,7 @@ impl<'tcx> TyCtxt<'tcx> { self, scope_def_id: LocalDefId, ) -> Vec<&'tcx hir::Ty<'tcx>> { - let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id); + let hir_id = self.local_def_id_to_hir_id(scope_def_id); let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) = self.hir().fn_decl_by_hir_id(hir_id) else { @@ -1133,7 +1222,7 @@ impl<'tcx> TyCtxt<'tcx> { self, scope_def_id: LocalDefId, ) -> Option<(Vec<&'tcx hir::Ty<'tcx>>, Span, Option<Span>)> { - let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id); + let hir_id = self.local_def_id_to_hir_id(scope_def_id); let mut v = TraitObjectVisitor(vec![], self.hir()); // when the return type is a type alias if let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) = self.hir().fn_decl_by_hir_id(hir_id) @@ -1141,8 +1230,8 @@ impl<'tcx> TyCtxt<'tcx> { None, hir::Path { res: hir::def::Res::Def(DefKind::TyAlias, def_id), .. }, )) = hir_output.kind && let Some(local_id) = def_id.as_local() - && let Some(alias_ty) = self.hir().get_by_def_id(local_id).alias_ty() // it is type alias - && let Some(alias_generics) = self.hir().get_by_def_id(local_id).generics() + && let Some(alias_ty) = self.hir_node_by_def_id(local_id).alias_ty() // it is type alias + && let Some(alias_generics) = self.hir_node_by_def_id(local_id).generics() { v.visit_ty(alias_ty); if !v.0.is_empty() { @@ -1548,7 +1637,6 @@ macro_rules! direct_interners { // crate only, and have a corresponding `mk_` function. direct_interners! { region: pub(crate) intern_region(RegionKind<'tcx>): Region -> Region<'tcx>, - const_: intern_const(ConstData<'tcx>): Const -> Const<'tcx>, const_allocation: pub mk_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>, layout: pub mk_layout(LayoutS<FieldIdx, VariantIdx>): Layout -> Layout<'tcx>, adt_def: pub mk_adt_def_from_data(AdtDefData): AdtDef -> AdtDef<'tcx>, @@ -1725,7 +1813,12 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_ct_from_kind(self, kind: ty::ConstKind<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { - self.intern_const(ty::ConstData { kind, ty }) + self.interners.intern_const( + ty::ConstData { kind, ty }, + self.sess, + // This is only used to create a stable hashing context. + &self.untracked, + ) } // Avoid this in favour of more specific `Ty::new_*` methods, where possible. @@ -1743,7 +1836,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> GenericArg<'tcx> { match param.kind { GenericParamDefKind::Lifetime => { - ty::Region::new_early_bound(self, param.to_early_bound_region_data()).into() + ty::Region::new_early_param(self, param.to_early_bound_region_data()).into() } GenericParamDefKind::Type { .. } => Ty::new_param(self, param.index, param.name).into(), GenericParamDefKind::Const { .. } => ty::Const::new_param( @@ -1954,14 +2047,12 @@ impl<'tcx> TyCtxt<'tcx> { let msg = decorator.msg(); let (level, src) = self.lint_level_at_node(lint, hir_id); struct_lint_level(self.sess, lint, level, src, Some(span.into()), msg, |diag| { - decorator.decorate_lint(diag) + decorator.decorate_lint(diag); }) } /// Emit a lint at the appropriate level for a hir node, with an associated span. /// - /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation. - /// /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature #[rustc_lint_diagnostics] #[track_caller] @@ -1971,9 +2062,7 @@ impl<'tcx> TyCtxt<'tcx> { hir_id: HirId, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>, - decorate: impl for<'a, 'b> FnOnce( - &'b mut DiagnosticBuilder<'a, ()>, - ) -> &'b mut DiagnosticBuilder<'a, ()>, + decorate: impl for<'a, 'b> FnOnce(&'b mut DiagnosticBuilder<'a, ()>), ) { let (level, src) = self.lint_level_at_node(lint, hir_id); struct_lint_level(self.sess, lint, level, src, Some(span.into()), msg, decorate); @@ -1988,13 +2077,13 @@ impl<'tcx> TyCtxt<'tcx> { id: HirId, decorator: impl for<'a> DecorateLint<'a, ()>, ) { - self.struct_lint_node(lint, id, decorator.msg(), |diag| decorator.decorate_lint(diag)) + self.struct_lint_node(lint, id, decorator.msg(), |diag| { + decorator.decorate_lint(diag); + }) } /// Emit a lint at the appropriate level for a hir node. /// - /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation. - /// /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature #[rustc_lint_diagnostics] #[track_caller] @@ -2003,9 +2092,7 @@ impl<'tcx> TyCtxt<'tcx> { lint: &'static Lint, id: HirId, msg: impl Into<DiagnosticMessage>, - decorate: impl for<'a, 'b> FnOnce( - &'b mut DiagnosticBuilder<'a, ()>, - ) -> &'b mut DiagnosticBuilder<'a, ()>, + decorate: impl for<'a, 'b> FnOnce(&'b mut DiagnosticBuilder<'a, ()>), ) { let (level, src) = self.lint_level_at_node(lint, id); struct_lint_level(self.sess, lint, level, src, None, msg, decorate); @@ -2040,7 +2127,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Given the def-id of an early-bound lifetime on an RPIT corresponding to /// a duplicated captured lifetime, map it back to the early- or late-bound /// lifetime of the function from which it originally as captured. If it is - /// a late-bound lifetime, this will represent the liberated (`ReFree`) lifetime + /// a late-bound lifetime, this will represent the liberated (`ReLateParam`) lifetime /// of the signature. // FIXME(RPITIT): if we ever synthesize new lifetimes for RPITITs and not just // re-use the generics of the opaque, this function will need to be tweaked slightly. @@ -2057,7 +2144,7 @@ impl<'tcx> TyCtxt<'tcx> { loop { let parent = self.local_parent(rpit_lifetime_param_def_id); let hir::OpaqueTy { lifetime_mapping, .. } = - self.hir().get_by_def_id(parent).expect_item().expect_opaque_ty(); + self.hir_node_by_def_id(parent).expect_item().expect_opaque_ty(); let Some((lifetime, _)) = lifetime_mapping .iter() @@ -2079,9 +2166,9 @@ impl<'tcx> TyCtxt<'tcx> { } let generics = self.generics_of(new_parent); - return ty::Region::new_early_bound( + return ty::Region::new_early_param( self, - ty::EarlyBoundRegion { + ty::EarlyParamRegion { def_id: ebv, index: generics .param_def_id_to_index(self, ebv) @@ -2092,7 +2179,7 @@ impl<'tcx> TyCtxt<'tcx> { } Some(resolve_bound_vars::ResolvedArg::LateBound(_, _, lbv)) => { let new_parent = self.parent(lbv); - return ty::Region::new_free( + return ty::Region::new_late_param( self, new_parent, ty::BoundRegionKind::BrNamed( @@ -2141,15 +2228,14 @@ impl<'tcx> TyCtxt<'tcx> { /// Whether the trait impl is marked const. This does not consider stability or feature gates. pub fn is_const_trait_impl_raw(self, def_id: DefId) -> bool { let Some(local_def_id) = def_id.as_local() else { return false }; - let hir_id = self.local_def_id_to_hir_id(local_def_id); - let node = self.hir().get(hir_id); + let node = self.hir_node_by_def_id(local_def_id); matches!( node, hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(hir::Impl { generics, .. }), .. - }) if generics.params.iter().any(|p| self.has_attr(p.def_id, sym::rustc_host)) + }) if generics.params.iter().any(|p| matches!(p.kind, hir::GenericParamKind::Const { is_host_effect: true, .. })) ) } @@ -2158,15 +2244,11 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn next_trait_solver_globally(self) -> bool { - self.sess.opts.unstable_opts.trait_solver == rustc_session::config::TraitSolver::Next + self.sess.opts.unstable_opts.next_solver.map_or(false, |c| c.globally) } pub fn next_trait_solver_in_coherence(self) -> bool { - matches!( - self.sess.opts.unstable_opts.trait_solver, - rustc_session::config::TraitSolver::Next - | rustc_session::config::TraitSolver::NextCoherence - ) + self.sess.opts.unstable_opts.next_solver.map_or(false, |c| c.coherence) } pub fn is_impl_trait_in_trait(self, def_id: DefId) -> bool { diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs index 3371ea3be..cfd36fd8c 100644 --- a/compiler/rustc_middle/src/ty/erase_regions.rs +++ b/compiler/rustc_middle/src/ty/erase_regions.rs @@ -53,16 +53,11 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RegionEraserVisitor<'tcx> { } fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - // because late-bound regions affect subtyping, we can't - // erase the bound/free distinction, but we can replace - // all free regions with 'erased. - // - // Note that we *CAN* replace early-bound regions -- the - // type system never "sees" those, they get substituted - // away. In codegen, they will always be erased to 'erased - // whenever a substitution occurs. + // We must not erase bound regions. `for<'a> fn(&'a ())` and + // `fn(&'free ())` are different types: they may implement different + // traits and have a different `TypeId`. match *r { - ty::ReLateBound(..) => r, + ty::ReBound(..) => r, _ => self.tcx.lifetimes.re_erased, } } diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 738bb5e8b..0e4487852 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -7,8 +7,7 @@ use rustc_hir::def_id::DefId; use rustc_span::symbol::Symbol; use rustc_target::spec::abi; use std::borrow::Cow; -use std::collections::hash_map::DefaultHasher; -use std::hash::{Hash, Hasher}; +use std::hash::{DefaultHasher, Hash, Hasher}; use std::path::PathBuf; #[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable, TypeVisitable)] @@ -236,7 +235,7 @@ impl<'tcx> Ty<'tcx> { _ => "fn item".into(), }, ty::FnPtr(_) => "fn pointer".into(), - ty::Dynamic(ref inner, ..) if let Some(principal) = inner.principal() => { + ty::Dynamic(inner, ..) if let Some(principal) = inner.principal() => { format!("`dyn {}`", tcx.def_path_str(principal.def_id())).into() } ty::Dynamic(..) => "trait object".into(), @@ -282,7 +281,7 @@ impl<'tcx> Ty<'tcx> { | ty::Float(_) | ty::Str | ty::Never => "type".into(), - ty::Tuple(ref tys) if tys.is_empty() => "unit type".into(), + ty::Tuple(tys) if tys.is_empty() => "unit type".into(), ty::Adt(def, _) => def.descr().into(), ty::Foreign(_) => "extern type".into(), ty::Array(..) => "array".into(), @@ -346,33 +345,35 @@ impl<'tcx> TyCtxt<'tcx> { short } - pub fn short_ty_string(self, ty: Ty<'tcx>) -> (String, Option<PathBuf>) { + pub fn short_ty_string(self, ty: Ty<'tcx>, path: &mut Option<PathBuf>) -> String { let regular = FmtPrinter::print_string(self, hir::def::Namespace::TypeNS, |cx| { cx.pretty_print_type(ty) }) .expect("could not write to `String`"); if !self.sess.opts.unstable_opts.write_long_types_to_disk { - return (regular, None); + return regular; } let width = self.sess.diagnostic_width(); let length_limit = width.saturating_sub(30); if regular.len() <= width { - return (regular, None); + return regular; } let short = self.ty_string_with_limit(ty, length_limit); if regular == short { - return (regular, None); + return regular; } - // Multiple types might be shortened in a single error, ensure we create a file for each. + // Ensure we create an unique file for the type passed in when we create a file. let mut s = DefaultHasher::new(); ty.hash(&mut s); let hash = s.finish(); - let path = self.output_filenames(()).temp_path_ext(&format!("long-type-{hash}.txt"), None); - match std::fs::write(&path, ®ular) { - Ok(_) => (short, Some(path)), - Err(_) => (regular, None), + *path = Some(path.take().unwrap_or_else(|| { + self.output_filenames(()).temp_path_ext(&format!("long-type-{hash}.txt"), None) + })); + match std::fs::write(path.as_ref().unwrap(), &format!("{regular}\n")) { + Ok(_) => short, + Err(_) => regular, } } } diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index 75ea53195..38a9cabca 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -62,7 +62,7 @@ pub enum TreatParams { /// /// N.B. during deep rejection, this acts identically to `ForLookup`. /// - /// FIXME(-Ztrait-solver=next): Remove this variant and cleanup + /// FIXME(-Znext-solver): Remove this variant and cleanup /// the code. NextSolverLookup, } @@ -189,14 +189,14 @@ pub struct DeepRejectCtxt { } impl DeepRejectCtxt { - pub fn args_refs_may_unify<'tcx>( + pub fn args_may_unify<'tcx>( self, obligation_args: GenericArgsRef<'tcx>, impl_args: GenericArgsRef<'tcx>, ) -> bool { iter::zip(obligation_args, impl_args).all(|(obl, imp)| { match (obl.unpack(), imp.unpack()) { - // We don't fast reject based on regions for now. + // We don't fast reject based on regions. (GenericArgKind::Lifetime(_), GenericArgKind::Lifetime(_)) => true, (GenericArgKind::Type(obl), GenericArgKind::Type(imp)) => { self.types_may_unify(obl, imp) @@ -231,7 +231,7 @@ impl DeepRejectCtxt { | ty::Never | ty::Tuple(..) | ty::FnPtr(..) - | ty::Foreign(..) => {} + | ty::Foreign(..) => debug_assert!(impl_ty.is_known_rigid()), ty::FnDef(..) | ty::Closure(..) | ty::Coroutine(..) @@ -260,7 +260,7 @@ impl DeepRejectCtxt { }, ty::Adt(obl_def, obl_args) => match k { &ty::Adt(impl_def, impl_args) => { - obl_def == impl_def && self.args_refs_may_unify(obl_args, impl_args) + obl_def == impl_def && self.args_may_unify(obl_args, impl_args) } _ => false, }, diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index ec36bdc5a..f9a2385b1 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -28,10 +28,11 @@ impl FlagComputation { result } - pub fn for_const(c: ty::Const<'_>) -> TypeFlags { + pub fn for_const(c: &ty::ConstKind<'_>, t: Ty<'_>) -> FlagComputation { let mut result = FlagComputation::new(); - result.add_const(c); - result.flags + result.add_const_kind(c); + result.add_ty(t); + result } fn add_flags(&mut self, flags: TypeFlags) { @@ -137,7 +138,7 @@ impl FlagComputation { &ty::Bound(debruijn, _) => { self.add_bound_var(debruijn); - self.add_flags(TypeFlags::HAS_TY_LATE_BOUND); + self.add_flags(TypeFlags::HAS_TY_BOUND); } &ty::Placeholder(..) => { @@ -263,9 +264,6 @@ impl FlagComputation { self.add_args(slice::from_ref(&arg)); } ty::PredicateKind::ObjectSafe(_def_id) => {} - ty::PredicateKind::ClosureKind(_def_id, args, _kind) => { - self.add_args(args); - } ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(uv)) => { self.add_const(uv); } @@ -274,6 +272,10 @@ impl FlagComputation { self.add_const(found); } ty::PredicateKind::Ambiguous => {} + ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term }) => { + self.add_alias_ty(alias); + self.add_term(term); + } ty::PredicateKind::AliasRelate(t1, t2, _) => { self.add_term(t1); self.add_term(t2); @@ -294,14 +296,18 @@ impl FlagComputation { fn add_region(&mut self, r: ty::Region<'_>) { self.add_flags(r.type_flags()); - if let ty::ReLateBound(debruijn, _) = *r { + if let ty::ReBound(debruijn, _) = *r { self.add_bound_var(debruijn); } } fn add_const(&mut self, c: ty::Const<'_>) { - self.add_ty(c.ty()); - match c.kind() { + self.add_flags(c.flags()); + self.add_exclusive_binder(c.outer_exclusive_binder()); + } + + fn add_const_kind(&mut self, c: &ty::ConstKind<'_>) { + match *c { ty::ConstKind::Unevaluated(uv) => { self.add_args(uv.args); self.add_flags(TypeFlags::HAS_CT_PROJECTION); @@ -317,7 +323,7 @@ impl FlagComputation { } ty::ConstKind::Bound(debruijn, _) => { self.add_bound_var(debruijn); - self.add_flags(TypeFlags::HAS_CT_LATE_BOUND); + self.add_flags(TypeFlags::HAS_CT_BOUND); } ty::ConstKind::Param(_) => { self.add_flags(TypeFlags::HAS_CT_PARAM); diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 00529a1e0..3e64f9a2a 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -68,12 +68,10 @@ impl<'tcx> TyCtxt<'tcx> { /// Folds over the substructure of a type, visiting its component /// types and all regions that occur *free* within it. /// -/// That is, `Ty` can contain function or method types that bind -/// regions at the call site (`ReLateBound`), and occurrences of -/// regions (aka "lifetimes") that are bound within a type are not -/// visited by this folder; only regions that occur free will be +/// That is, function pointer types and trait object can introduce +/// new bound regions which are not visited by this visitors as +/// they are not free; only regions that occur free will be /// visited by `fld_r`. - pub struct RegionFolder<'a, 'tcx> { tcx: TyCtxt<'tcx>, @@ -117,7 +115,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> { #[instrument(skip(self), level = "debug", ret)] fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { match *r { - ty::ReLateBound(debruijn, _) if debruijn < self.current_index => { + ty::ReBound(debruijn, _) if debruijn < self.current_index => { debug!(?self.current_index, "skipped bound region"); r } @@ -205,15 +203,15 @@ where fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { match *r { - ty::ReLateBound(debruijn, br) if debruijn == self.current_index => { + ty::ReBound(debruijn, br) if debruijn == self.current_index => { let region = self.delegate.replace_region(br); - if let ty::ReLateBound(debruijn1, br) = *region { - // If the callback returns a late-bound region, + if let ty::ReBound(debruijn1, br) = *region { + // If the callback returns a bound region, // that region should always use the INNERMOST // debruijn index. Then we adjust it to the // correct depth. assert_eq!(debruijn1, ty::INNERMOST); - ty::Region::new_late_bound(self.tcx, debruijn, br) + ty::Region::new_bound(self.tcx, debruijn, br) } else { region } @@ -252,7 +250,7 @@ impl<'tcx> TyCtxt<'tcx> { /// /// This method only replaces late bound regions. Any types or /// constants bound by `value` will cause an ICE. - pub fn replace_late_bound_regions<T, F>( + pub fn instantiate_bound_regions<T, F>( self, value: Binder<'tcx, T>, mut fld_r: F, @@ -263,11 +261,11 @@ impl<'tcx> TyCtxt<'tcx> { { let mut region_map = BTreeMap::new(); let real_fld_r = |br: ty::BoundRegion| *region_map.entry(br).or_insert_with(|| fld_r(br)); - let value = self.replace_late_bound_regions_uncached(value, real_fld_r); + let value = self.instantiate_bound_regions_uncached(value, real_fld_r); (value, region_map) } - pub fn replace_late_bound_regions_uncached<T, F>( + pub fn instantiate_bound_regions_uncached<T, F>( self, value: Binder<'tcx, T>, mut replace_regions: F, @@ -327,8 +325,8 @@ impl<'tcx> TyCtxt<'tcx> { where T: TypeFoldable<TyCtxt<'tcx>>, { - self.replace_late_bound_regions_uncached(value, |br| { - ty::Region::new_free(self, all_outlive_scope, br.kind) + self.instantiate_bound_regions_uncached(value, |br| { + ty::Region::new_late_param(self, all_outlive_scope, br.kind) }) } @@ -341,7 +339,7 @@ impl<'tcx> TyCtxt<'tcx> { value, FnMutDelegate { regions: &mut |r: ty::BoundRegion| { - ty::Region::new_late_bound( + ty::Region::new_bound( self, ty::INNERMOST, ty::BoundRegion { var: shift_bv(r.var), kind: r.kind }, @@ -363,11 +361,11 @@ impl<'tcx> TyCtxt<'tcx> { /// Replaces any late-bound regions bound in `value` with `'erased`. Useful in codegen but also /// method lookup and a few other places where precise region relationships are not required. - pub fn erase_late_bound_regions<T>(self, value: Binder<'tcx, T>) -> T + pub fn instantiate_bound_regions_with_erased<T>(self, value: Binder<'tcx, T>) -> T where T: TypeFoldable<TyCtxt<'tcx>>, { - self.replace_late_bound_regions(value, |_| self.lifetimes.re_erased).0 + self.instantiate_bound_regions(value, |_| self.lifetimes.re_erased).0 } /// Anonymize all bound variables in `value`, this is mostly used to improve caching. @@ -388,7 +386,7 @@ impl<'tcx> TyCtxt<'tcx> { .or_insert_with(|| ty::BoundVariableKind::Region(ty::BrAnon)) .expect_region(); let br = ty::BoundRegion { var, kind }; - ty::Region::new_late_bound(self.tcx, ty::INNERMOST, br) + ty::Region::new_bound(self.tcx, ty::INNERMOST, br) } fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> { let entry = self.map.entry(bt.var); @@ -454,9 +452,9 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Shifter<'tcx> { fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { match *r { - ty::ReLateBound(debruijn, br) if debruijn >= self.current_index => { + ty::ReBound(debruijn, br) if debruijn >= self.current_index => { let debruijn = debruijn.shifted_in(self.amount); - ty::Region::new_late_bound(self.tcx, debruijn, br) + ty::Region::new_bound(self.tcx, debruijn, br) } _ => r, } @@ -496,8 +494,8 @@ pub fn shift_region<'tcx>( amount: u32, ) -> ty::Region<'tcx> { match *region { - ty::ReLateBound(debruijn, br) if amount > 0 => { - ty::Region::new_late_bound(tcx, debruijn.shifted_in(amount), br) + ty::ReBound(debruijn, br) if amount > 0 => { + ty::Region::new_bound(tcx, debruijn.shifted_in(amount), br) } _ => region, } diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index 41a1bf04e..63f4bab79 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -10,7 +10,7 @@ use rustc_data_structures::intern::Interned; use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg}; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; -use rustc_serialize::{self, Decodable, Encodable}; +use rustc_serialize::{Decodable, Encodable}; use rustc_type_ir::WithCachedTypeInfo; use smallvec::SmallVec; @@ -70,7 +70,7 @@ impl<'tcx> GenericArgKind<'tcx> { GenericArgKind::Const(ct) => { // Ensure we can use the tag bits. assert_eq!(mem::align_of_val(&*ct.0.0) & TAG_MASK, 0); - (CONST_TAG, ct.0.0 as *const ty::ConstData<'tcx> as usize) + (CONST_TAG, ct.0.0 as *const WithCachedTypeInfo<ty::ConstData<'tcx>> as usize) } }; @@ -86,7 +86,7 @@ impl<'tcx> Ord for GenericArg<'tcx> { impl<'tcx> PartialOrd for GenericArg<'tcx> { fn partial_cmp(&self, other: &GenericArg<'tcx>) -> Option<Ordering> { - Some(self.cmp(&other)) + Some(self.cmp(other)) } } @@ -136,7 +136,7 @@ impl<'tcx> GenericArg<'tcx> { &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::TyKind<'tcx>>), ))), CONST_TAG => GenericArgKind::Const(ty::Const(Interned::new_unchecked( - &*((ptr & !TAG_MASK) as *const ty::ConstData<'tcx>), + &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::ConstData<'tcx>>), ))), _ => intrinsics::unreachable(), } @@ -604,13 +604,6 @@ impl<T> EarlyBinder<Option<T>> { } } -impl<T, U> EarlyBinder<(T, U)> { - pub fn transpose_tuple2(self) -> (EarlyBinder<T>, EarlyBinder<U>) { - let EarlyBinder { value: (lhs, rhs) } = self; - (EarlyBinder { value: lhs }, EarlyBinder { value: rhs }) - } -} - impl<'tcx, 's, I: IntoIterator> EarlyBinder<I> where I::Item: TypeFoldable<TyCtxt<'tcx>>, @@ -809,7 +802,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ArgFolder<'a, 'tcx> { fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { #[cold] #[inline(never)] - fn region_param_out_of_range(data: ty::EarlyBoundRegion, args: &[GenericArg<'_>]) -> ! { + fn region_param_out_of_range(data: ty::EarlyParamRegion, args: &[GenericArg<'_>]) -> ! { bug!( "Region parameter out of range when substituting in region {} (index={}, args = {:?})", data.name, @@ -820,7 +813,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ArgFolder<'a, 'tcx> { #[cold] #[inline(never)] - fn region_param_invalid(data: ty::EarlyBoundRegion, other: GenericArgKind<'_>) -> ! { + fn region_param_invalid(data: ty::EarlyParamRegion, other: GenericArgKind<'_>) -> ! { bug!( "Unexpected parameter {:?} when substituting in region {} (index={})", other, @@ -835,7 +828,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ArgFolder<'a, 'tcx> { // regions that appear in a function signature is done using // the specialized routine `ty::replace_late_regions()`. match *r { - ty::ReEarlyBound(data) => { + ty::ReEarlyParam(data) => { let rk = self.args.get(data.index as usize).map(|k| k.unpack()); match rk { Some(GenericArgKind::Lifetime(lt)) => self.shift_region_through_binders(lt), @@ -843,8 +836,8 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ArgFolder<'a, 'tcx> { None => region_param_out_of_range(data, self.args), } } - ty::ReLateBound(..) - | ty::ReFree(_) + ty::ReBound(..) + | ty::ReLateParam(_) | ty::ReStatic | ty::RePlaceholder(_) | ty::ReErased diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 888ee1d23..c3699b114 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -6,7 +6,7 @@ use rustc_hir::def_id::DefId; use rustc_span::symbol::{kw, Symbol}; use rustc_span::Span; -use super::{Clause, EarlyBoundRegion, InstantiatedPredicates, ParamConst, ParamTy, Ty, TyCtxt}; +use super::{Clause, InstantiatedPredicates, ParamConst, ParamTy, Ty, TyCtxt}; #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] pub enum GenericParamDefKind { @@ -62,9 +62,9 @@ pub struct GenericParamDef { } impl GenericParamDef { - pub fn to_early_bound_region_data(&self) -> ty::EarlyBoundRegion { + pub fn to_early_bound_region_data(&self) -> ty::EarlyParamRegion { if let GenericParamDefKind::Lifetime = self.kind { - ty::EarlyBoundRegion { def_id: self.def_id, index: self.index, name: self.name } + ty::EarlyParamRegion { def_id: self.def_id, index: self.index, name: self.name } } else { bug!("cannot convert a non-lifetime parameter def to an early bound region") } @@ -260,10 +260,10 @@ impl<'tcx> Generics { } } - /// Returns the `GenericParamDef` associated with this `EarlyBoundRegion`. + /// Returns the `GenericParamDef` associated with this `EarlyParamRegion`. pub fn region_param( &'tcx self, - param: &EarlyBoundRegion, + param: &ty::EarlyParamRegion, tcx: TyCtxt<'tcx>, ) -> &'tcx GenericParamDef { let param = self.param_at(param.index as usize, tcx); @@ -326,6 +326,8 @@ impl<'tcx> Generics { own_params.start = 1; } + let verbose = tcx.sess.verbose(); + // Filter the default arguments. // // This currently uses structural equality instead @@ -340,6 +342,8 @@ impl<'tcx> Generics { param.default_value(tcx).is_some_and(|default| { default.instantiate(tcx, args) == args[param.index as usize] }) + // filter out trailing effect params, if we're not in `-Zverbose`. + || (!verbose && matches!(param.kind, GenericParamDefKind::Const { is_host_effect: true, .. })) }) .count(); @@ -354,7 +358,7 @@ impl<'tcx> Generics { args: &'tcx [ty::GenericArg<'tcx>], ) -> &'tcx [ty::GenericArg<'tcx>] { let own = &args[self.parent_count..][..self.params.len()]; - if self.has_self && self.parent.is_none() { &own[1..] } else { &own } + if self.has_self && self.parent.is_none() { &own[1..] } else { own } } } diff --git a/compiler/rustc_middle/src/ty/impls_ty.rs b/compiler/rustc_middle/src/ty/impls_ty.rs index b03874a90..129d94769 100644 --- a/compiler/rustc_middle/src/ty/impls_ty.rs +++ b/compiler/rustc_middle/src/ty/impls_ty.rs @@ -29,7 +29,7 @@ where } let mut hasher = StableHasher::new(); - (&self[..]).hash_stable(hcx, &mut hasher); + self[..].hash_stable(hcx, &mut hasher); let hash: Fingerprint = hasher.finish(); cache.borrow_mut().insert(key, hash); @@ -84,6 +84,14 @@ impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::AllocId { } } +// CtfeProvenance is an AllocId and a bool. +impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::CtfeProvenance { + fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + self.alloc_id().hash_stable(hcx, hasher); + self.immutable().hash_stable(hcx, hasher); + } +} + impl<'a> ToStableHashKey<StableHashingContext<'a>> for region::Scope { type KeyType = region::Scope; diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs index f278cace9..ae1794278 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs @@ -1,3 +1,5 @@ +use smallvec::SmallVec; + use crate::ty::context::TyCtxt; use crate::ty::{self, DefId, ParamEnv, Ty}; @@ -31,27 +33,31 @@ impl<'tcx> InhabitedPredicate<'tcx> { /// Returns true if the corresponding type is inhabited in the given /// `ParamEnv` and module pub fn apply(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, module_def_id: DefId) -> bool { - let Ok(result) = self - .apply_inner::<!>(tcx, param_env, &|id| Ok(tcx.is_descendant_of(module_def_id, id))); + let Ok(result) = self.apply_inner::<!>(tcx, param_env, &mut Default::default(), &|id| { + Ok(tcx.is_descendant_of(module_def_id, id)) + }); result } /// Same as `apply`, but returns `None` if self contains a module predicate pub fn apply_any_module(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<bool> { - self.apply_inner(tcx, param_env, &|_| Err(())).ok() + self.apply_inner(tcx, param_env, &mut Default::default(), &|_| Err(())).ok() } /// Same as `apply`, but `NotInModule(_)` predicates yield `false`. That is, /// privately uninhabited types are considered always uninhabited. pub fn apply_ignore_module(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> bool { - let Ok(result) = self.apply_inner::<!>(tcx, param_env, &|_| Ok(true)); + let Ok(result) = + self.apply_inner::<!>(tcx, param_env, &mut Default::default(), &|_| Ok(true)); result } - fn apply_inner<E>( + #[instrument(level = "debug", skip(tcx, param_env, in_module), ret)] + fn apply_inner<E: std::fmt::Debug>( self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, + eval_stack: &mut SmallVec<[Ty<'tcx>; 1]>, // for cycle detection in_module: &impl Fn(DefId) -> Result<bool, E>, ) -> Result<bool, E> { match self { @@ -71,11 +77,25 @@ impl<'tcx> InhabitedPredicate<'tcx> { match normalized_pred { // We don't have more information than we started with, so consider inhabited. Self::GenericType(_) => Ok(true), - pred => pred.apply_inner(tcx, param_env, in_module), + pred => { + // A type which is cyclic when monomorphized can happen here since the + // layout error would only trigger later. See e.g. `tests/ui/sized/recursive-type-2.rs`. + if eval_stack.contains(&t) { + return Ok(true); // Recover; this will error later. + } + eval_stack.push(t); + let ret = pred.apply_inner(tcx, param_env, eval_stack, in_module); + eval_stack.pop(); + ret + } } } - Self::And([a, b]) => try_and(a, b, |x| x.apply_inner(tcx, param_env, in_module)), - Self::Or([a, b]) => try_or(a, b, |x| x.apply_inner(tcx, param_env, in_module)), + Self::And([a, b]) => { + try_and(a, b, |x| x.apply_inner(tcx, param_env, eval_stack, in_module)) + } + Self::Or([a, b]) => { + try_or(a, b, |x| x.apply_inner(tcx, param_env, eval_stack, in_module)) + } } } @@ -197,7 +217,7 @@ impl<'tcx> InhabitedPredicate<'tcx> { // this is basically like `f(a)? && f(b)?` but different in the case of // `Ok(false) && Err(_) -> Ok(false)` -fn try_and<T, E>(a: T, b: T, f: impl Fn(T) -> Result<bool, E>) -> Result<bool, E> { +fn try_and<T, E>(a: T, b: T, mut f: impl FnMut(T) -> Result<bool, E>) -> Result<bool, E> { let a = f(a); if matches!(a, Ok(false)) { return Ok(false); @@ -209,7 +229,7 @@ fn try_and<T, E>(a: T, b: T, f: impl Fn(T) -> Result<bool, E>) -> Result<bool, E } } -fn try_or<T, E>(a: T, b: T, f: impl Fn(T) -> Result<bool, E>) -> Result<bool, E> { +fn try_or<T, E>(a: T, b: T, mut f: impl FnMut(T) -> Result<bool, E>) -> Result<bool, E> { let a = f(a); if matches!(a, Ok(true)) { return Ok(true); diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs index 68ac54e89..d67fb9fd0 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs @@ -103,6 +103,7 @@ impl<'tcx> VariantDef { } impl<'tcx> Ty<'tcx> { + #[instrument(level = "debug", skip(tcx), ret)] pub fn inhabited_predicate(self, tcx: TyCtxt<'tcx>) -> InhabitedPredicate<'tcx> { match self.kind() { // For now, unions are always considered inhabited diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index cebefbccc..1c7a7545e 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -215,7 +215,7 @@ impl<'tcx> InstanceDef<'tcx> { }; matches!( tcx.def_key(def_id).disambiguated_data.data, - DefPathData::Ctor | DefPathData::ClosureExpr + DefPathData::Ctor | DefPathData::Closure ) } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 4223e503f..225dd2178 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -2,10 +2,10 @@ use crate::error::UnsupportedFnAbi; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::query::TyCtxtAt; use crate::ty::normalize_erasing_regions::NormalizationError; -use crate::ty::{self, ConstKind, ReprOptions, Ty, TyCtxt, TypeVisitableExt}; +use crate::ty::{self, ConstKind, Ty, TyCtxt, TypeVisitableExt}; use rustc_error_messages::DiagnosticMessage; use rustc_errors::{ - DiagnosticArgValue, DiagnosticBuilder, Handler, IntoDiagnostic, IntoDiagnosticArg, + DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, IntoDiagnostic, IntoDiagnosticArg, }; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -215,7 +215,7 @@ pub enum LayoutError<'tcx> { SizeOverflow(Ty<'tcx>), NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>), ReferencesError(ErrorGuaranteed), - Cycle, + Cycle(ErrorGuaranteed), } impl<'tcx> LayoutError<'tcx> { @@ -226,7 +226,7 @@ impl<'tcx> LayoutError<'tcx> { Unknown(_) => middle_unknown_layout, SizeOverflow(_) => middle_values_too_big, NormalizationFailure(_, _) => middle_cannot_be_normalized, - Cycle => middle_cycle, + Cycle(_) => middle_cycle, ReferencesError(_) => middle_layout_references_error, } } @@ -240,7 +240,7 @@ impl<'tcx> LayoutError<'tcx> { NormalizationFailure(ty, e) => { E::NormalizationFailure { ty, failure_ty: e.get_type_for_failure() } } - Cycle => E::Cycle, + Cycle(_) => E::Cycle, ReferencesError(_) => E::ReferencesError, } } @@ -261,7 +261,7 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> { t, e.get_type_for_failure() ), - LayoutError::Cycle => write!(f, "a cycle occurred during layout computation"), + LayoutError::Cycle(_) => write!(f, "a cycle occurred during layout computation"), LayoutError::ReferencesError(_) => write!(f, "the type has an unknown layout"), } } @@ -282,8 +282,8 @@ pub struct LayoutCx<'tcx, C> { impl<'tcx> LayoutCalculator for LayoutCx<'tcx, TyCtxt<'tcx>> { type TargetDataLayoutRef = &'tcx TargetDataLayout; - fn delay_bug(&self, txt: String) { - self.tcx.sess.delay_span_bug(DUMMY_SP, txt); + fn delayed_bug(&self, txt: String) { + self.tcx.sess.span_delayed_bug(DUMMY_SP, txt); } fn current_data_layout(&self) -> Self::TargetDataLayoutRef { @@ -333,7 +333,7 @@ impl<'tcx> SizeSkeleton<'tcx> { Err(err @ LayoutError::Unknown(_)) => err, // We can't extract SizeSkeleton info from other layout errors Err( - e @ LayoutError::Cycle + e @ LayoutError::Cycle(_) | e @ LayoutError::SizeOverflow(_) | e @ LayoutError::NormalizationFailure(..) | e @ LayoutError::ReferencesError(_), @@ -899,13 +899,13 @@ where ty::Str => TyMaybeWithLayout::Ty(tcx.types.u8), // Tuples, coroutines and closures. - ty::Closure(_, ref args) => field_ty_or_layout( + ty::Closure(_, args) => field_ty_or_layout( TyAndLayout { ty: args.as_closure().tupled_upvars_ty(), ..this }, cx, i, ), - ty::Coroutine(def_id, ref args, _) => match this.variants { + ty::Coroutine(def_id, args, _) => match this.variants { Variants::Single { index } => TyMaybeWithLayout::Ty( args.as_coroutine() .state_tys(def_id, tcx) @@ -1273,13 +1273,13 @@ pub enum FnAbiError<'tcx> { } impl<'a, 'b> IntoDiagnostic<'a, !> for FnAbiError<'b> { - fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, !> { + fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, !> { match self { - Self::Layout(e) => e.into_diagnostic().into_diagnostic(handler), + Self::Layout(e) => e.into_diagnostic().into_diagnostic(dcx), Self::AdjustForForeignAbi(call::AdjustForForeignAbiError::Unsupported { arch, abi, - }) => UnsupportedFnAbi { arch, abi: abi.name() }.into_diagnostic(handler), + }) => UnsupportedFnAbi { arch, abi: abi.name() }.into_diagnostic(dcx), } } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index e1c616ba0..35c135830 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -42,7 +42,6 @@ use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, StashKey}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap}; -use rustc_hir::Node; use rustc_index::IndexVec; use rustc_macros::HashStable; use rustc_query_system::ich::StableHashingContext; @@ -66,27 +65,20 @@ use std::ops::ControlFlow; use std::{fmt, str}; pub use crate::ty::diagnostics::*; -pub use rustc_type_ir::AliasKind::*; pub use rustc_type_ir::ConstKind::{ Bound as BoundCt, Error as ErrorCt, Expr as ExprCt, Infer as InferCt, Param as ParamCt, Placeholder as PlaceholderCt, Unevaluated, Value, }; -pub use rustc_type_ir::DynKind::*; -pub use rustc_type_ir::InferTy::*; -pub use rustc_type_ir::RegionKind::*; -pub use rustc_type_ir::TyKind::*; pub use rustc_type_ir::*; pub use self::binding::BindingMode; pub use self::binding::BindingMode::*; pub use self::closure::{ is_ancestor_or_same_capture, place_to_string_for_capture, BorrowKind, CaptureInfo, - CapturedPlace, ClosureKind, ClosureTypeInfo, MinCaptureInformationMap, MinCaptureList, + CapturedPlace, ClosureTypeInfo, MinCaptureInformationMap, MinCaptureList, RootVariableMinCaptureList, UpvarCapture, UpvarId, UpvarPath, CAPTURE_STRUCT_LOCAL, }; -pub use self::consts::{ - Const, ConstData, ConstInt, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree, -}; +pub use self::consts::{Const, ConstData, ConstInt, Expr, ScalarInt, UnevaluatedConst, ValTree}; pub use self::context::{ tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed, }; @@ -96,13 +88,13 @@ pub use self::parameterized::ParameterizedOverTcx; pub use self::rvalue_scopes::RvalueScopes; pub use self::sty::BoundRegionKind::*; pub use self::sty::{ - AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar, + AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig, ClauseKind, ClosureArgs, ClosureArgsParts, ConstKind, - ConstVid, CoroutineArgs, CoroutineArgsParts, EarlyBoundRegion, EffectVid, ExistentialPredicate, - ExistentialProjection, ExistentialTraitRef, FnSig, FreeRegion, GenSig, InlineConstArgs, - InlineConstArgsParts, ParamConst, ParamTy, PolyExistentialPredicate, PolyExistentialProjection, - PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef, PredicateKind, Region, - RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarArgs, VarianceDiagInfo, + CoroutineArgs, CoroutineArgsParts, EarlyParamRegion, ExistentialPredicate, + ExistentialProjection, ExistentialTraitRef, FnSig, GenSig, InlineConstArgs, + InlineConstArgsParts, LateParamRegion, ParamConst, ParamTy, PolyExistentialPredicate, + PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyTraitRef, PredicateKind, + Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarArgs, VarianceDiagInfo, }; pub use self::trait_def::TraitDef; pub use self::typeck_results::{ @@ -160,7 +152,7 @@ pub struct ResolverOutputs { #[derive(Debug)] pub struct ResolverGlobalCtxt { - pub visibilities: FxHashMap<LocalDefId, Visibility>, + pub visibilities_for_hashing: Vec<(LocalDefId, Visibility)>, /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`. pub expn_that_defined: FxHashMap<LocalDefId, ExpnId>, pub effective_visibilities: EffectiveVisibilities, @@ -200,13 +192,10 @@ pub struct ResolverAstLowering { pub next_node_id: ast::NodeId, - pub node_id_to_def_id: FxHashMap<ast::NodeId, LocalDefId>, + pub node_id_to_def_id: NodeMap<LocalDefId>, pub def_id_to_node_id: IndexVec<LocalDefId, ast::NodeId>, pub trait_map: NodeMap<Vec<hir::TraitCandidate>>, - /// A small map keeping true kinds of built-in macros that appear to be fn-like on - /// the surface (`macro` items in libcore), but are actually attributes or derives. - pub builtin_macro_kinds: FxHashMap<LocalDefId, MacroKind>, /// List functions and methods for which lifetime elision was successful. pub lifetime_elision_allowed: FxHashSet<ast::NodeId>, @@ -301,6 +290,23 @@ pub enum Visibility<Id = LocalDefId> { Restricted(Id), } +impl Visibility { + pub fn to_string(self, def_id: LocalDefId, tcx: TyCtxt<'_>) -> String { + match self { + ty::Visibility::Restricted(restricted_id) => { + if restricted_id.is_top_level_module() { + "pub(crate)".to_string() + } else if restricted_id == tcx.parent_module_from_def_id(def_id).to_local_def_id() { + "pub(self)".to_string() + } else { + format!("pub({})", tcx.item_name(restricted_id.to_def_id())) + } + } + ty::Visibility::Public => "pub".to_string(), + } + } +} + #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)] pub enum BoundConstness { /// `T: Trait` @@ -463,7 +469,15 @@ pub struct CReaderCacheKey { #[rustc_pass_by_value] pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>); -impl ty::EarlyBoundRegion { +impl<'tcx> IntoKind for Ty<'tcx> { + type Kind = TyKind<'tcx>; + + fn kind(self) -> TyKind<'tcx> { + *self.kind() + } +} + +impl EarlyParamRegion { /// Does this early bound region have a name? Early bound regions normally /// always have names except when using anonymous lifetimes (`'_`). pub fn has_name(&self) -> bool { @@ -542,6 +556,10 @@ impl<'tcx> Predicate<'tcx> { pub fn allow_normalization(self) -> bool { match self.kind().skip_binder() { PredicateKind::Clause(ClauseKind::WellFormed(_)) => false, + // `NormalizesTo` is only used in the new solver, so this shouldn't + // matter. Normalizing `term` would be 'wrong' however, as it changes whether + // `normalizes-to(<T as Trait>::Assoc, <T as Trait>::Assoc)` holds. + PredicateKind::NormalizesTo(..) => false, PredicateKind::Clause(ClauseKind::Trait(_)) | PredicateKind::Clause(ClauseKind::RegionOutlives(_)) | PredicateKind::Clause(ClauseKind::TypeOutlives(_)) @@ -549,7 +567,6 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::Clause(ClauseKind::ConstArgHasType(..)) | PredicateKind::AliasRelate(..) | PredicateKind::ObjectSafe(_) - | PredicateKind::ClosureKind(_, _, _) | PredicateKind::Subtype(_) | PredicateKind::Coerce(_) | PredicateKind::Clause(ClauseKind::ConstEvaluatable(_)) @@ -902,7 +919,7 @@ impl<'tcx> Term<'tcx> { &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::TyKind<'tcx>>), ))), CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked( - &*((ptr & !TAG_MASK) as *const ty::ConstData<'tcx>), + &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::ConstData<'tcx>>), ))), _ => core::intrinsics::unreachable(), } @@ -969,7 +986,7 @@ impl<'tcx> TermKind<'tcx> { TermKind::Const(ct) => { // Ensure we can use the tag bits. assert_eq!(mem::align_of_val(&*ct.0.0) & TAG_MASK, 0); - (CONST_TAG, ct.0.0 as *const ty::ConstData<'tcx> as usize) + (CONST_TAG, ct.0.0 as *const WithCachedTypeInfo<ty::ConstData<'tcx>> as usize) } }; @@ -1083,6 +1100,33 @@ impl<'tcx> PolyProjectionPredicate<'tcx> { } } +/// Used by the new solver. Unlike a `ProjectionPredicate` this can only be +/// proven by actually normalizing `alias`. +#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +pub struct NormalizesTo<'tcx> { + pub alias: AliasTy<'tcx>, + pub term: Term<'tcx>, +} + +impl<'tcx> NormalizesTo<'tcx> { + pub fn self_ty(self) -> Ty<'tcx> { + self.alias.self_ty() + } + + pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> NormalizesTo<'tcx> { + Self { alias: self.alias.with_self_ty(tcx, self_ty), ..self } + } + + pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId { + self.alias.trait_def_id(tcx) + } + + pub fn def_id(self) -> DefId { + self.alias.def_id + } +} + pub trait ToPolyTraitRef<'tcx> { fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>; } @@ -1264,6 +1308,12 @@ impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyProjectionPredicate<'tcx> { } } +impl<'tcx> ToPredicate<'tcx> for NormalizesTo<'tcx> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + PredicateKind::NormalizesTo(self).to_predicate(tcx) + } +} + impl<'tcx> Predicate<'tcx> { pub fn to_opt_poly_trait_pred(self) -> Option<PolyTraitPredicate<'tcx>> { let predicate = self.kind(); @@ -1271,13 +1321,13 @@ impl<'tcx> Predicate<'tcx> { PredicateKind::Clause(ClauseKind::Trait(t)) => Some(predicate.rebind(t)), PredicateKind::Clause(ClauseKind::Projection(..)) | PredicateKind::Clause(ClauseKind::ConstArgHasType(..)) + | PredicateKind::NormalizesTo(..) | PredicateKind::AliasRelate(..) | PredicateKind::Subtype(..) | PredicateKind::Coerce(..) | PredicateKind::Clause(ClauseKind::RegionOutlives(..)) | PredicateKind::Clause(ClauseKind::WellFormed(..)) | PredicateKind::ObjectSafe(..) - | PredicateKind::ClosureKind(..) | PredicateKind::Clause(ClauseKind::TypeOutlives(..)) | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..)) | PredicateKind::ConstEquate(..) @@ -1291,13 +1341,13 @@ impl<'tcx> Predicate<'tcx> { PredicateKind::Clause(ClauseKind::Projection(t)) => Some(predicate.rebind(t)), PredicateKind::Clause(ClauseKind::Trait(..)) | PredicateKind::Clause(ClauseKind::ConstArgHasType(..)) + | PredicateKind::NormalizesTo(..) | PredicateKind::AliasRelate(..) | PredicateKind::Subtype(..) | PredicateKind::Coerce(..) | PredicateKind::Clause(ClauseKind::RegionOutlives(..)) | PredicateKind::Clause(ClauseKind::WellFormed(..)) | PredicateKind::ObjectSafe(..) - | PredicateKind::ClosureKind(..) | PredicateKind::Clause(ClauseKind::TypeOutlives(..)) | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..)) | PredicateKind::ConstEquate(..) @@ -1305,26 +1355,6 @@ impl<'tcx> Predicate<'tcx> { } } - pub fn to_opt_type_outlives(self) -> Option<PolyTypeOutlivesPredicate<'tcx>> { - let predicate = self.kind(); - match predicate.skip_binder() { - PredicateKind::Clause(ClauseKind::TypeOutlives(data)) => Some(predicate.rebind(data)), - PredicateKind::Clause(ClauseKind::Trait(..)) - | PredicateKind::Clause(ClauseKind::ConstArgHasType(..)) - | PredicateKind::Clause(ClauseKind::Projection(..)) - | PredicateKind::AliasRelate(..) - | PredicateKind::Subtype(..) - | PredicateKind::Coerce(..) - | PredicateKind::Clause(ClauseKind::RegionOutlives(..)) - | PredicateKind::Clause(ClauseKind::WellFormed(..)) - | PredicateKind::ObjectSafe(..) - | PredicateKind::ClosureKind(..) - | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..)) - | PredicateKind::ConstEquate(..) - | PredicateKind::Ambiguous => None, - } - } - /// Matches a `PredicateKind::Clause` and turns it into a `Clause`, otherwise returns `None`. pub fn as_clause(self) -> Option<Clause<'tcx>> { match self.kind().skip_binder() { @@ -1377,7 +1407,7 @@ impl<'tcx> InstantiatedPredicates<'tcx> { } pub fn iter(&self) -> <&Self as IntoIterator>::IntoIter { - (&self).into_iter() + self.into_iter() } } @@ -1454,7 +1484,7 @@ impl<'tcx> OpaqueHiddenType<'tcx> { ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { if let Some(diag) = tcx .sess - .diagnostic() + .dcx() .steal_diagnostic(tcx.def_span(opaque_def_id), StashKey::OpaqueHiddenTypeMismatch) { diag.cancel(); @@ -1518,8 +1548,44 @@ pub struct Placeholder<T> { pub type PlaceholderRegion = Placeholder<BoundRegion>; +impl PlaceholderLike for PlaceholderRegion { + fn universe(self) -> UniverseIndex { + self.universe + } + + fn var(self) -> BoundVar { + self.bound.var + } + + fn with_updated_universe(self, ui: UniverseIndex) -> Self { + Placeholder { universe: ui, ..self } + } + + fn new(ui: UniverseIndex, var: BoundVar) -> Self { + Placeholder { universe: ui, bound: BoundRegion { var, kind: BoundRegionKind::BrAnon } } + } +} + pub type PlaceholderType = Placeholder<BoundTy>; +impl PlaceholderLike for PlaceholderType { + fn universe(self) -> UniverseIndex { + self.universe + } + + fn var(self) -> BoundVar { + self.bound.var + } + + fn with_updated_universe(self, ui: UniverseIndex) -> Self { + Placeholder { universe: ui, ..self } + } + + fn new(ui: UniverseIndex, var: BoundVar) -> Self { + Placeholder { universe: ui, bound: BoundTy { var, kind: BoundTyKind::Anon } } + } +} + #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] #[derive(TyEncodable, TyDecodable, PartialOrd, Ord)] pub struct BoundConst<'tcx> { @@ -1529,6 +1595,24 @@ pub struct BoundConst<'tcx> { pub type PlaceholderConst = Placeholder<BoundVar>; +impl PlaceholderLike for PlaceholderConst { + fn universe(self) -> UniverseIndex { + self.universe + } + + fn var(self) -> BoundVar { + self.bound + } + + fn with_updated_universe(self, ui: UniverseIndex) -> Self { + Placeholder { universe: ui, ..self } + } + + fn new(ui: UniverseIndex, var: BoundVar) -> Self { + Placeholder { universe: ui, bound: var } + } +} + /// When type checking, we use the `ParamEnv` to track /// details about the set of where-clauses that are in scope at this /// particular point. @@ -2021,7 +2105,7 @@ impl<'tcx> TyCtxt<'tcx> { } for attr in self.get_attrs(did, sym::repr) { - for r in attr::parse_repr_attr(&self.sess, attr) { + for r in attr::parse_repr_attr(self.sess, attr) { flags.insert(match r { attr::ReprRust => ReprFlags::empty(), attr::ReprC => ReprFlags::IS_C, @@ -2256,7 +2340,7 @@ impl<'tcx> TyCtxt<'tcx> { // FIXME(@lcnr): Remove this function. pub fn get_attrs_unchecked(self, did: DefId) -> &'tcx [ast::Attribute] { if let Some(did) = did.as_local() { - self.hir().attrs(self.hir().local_def_id_to_hir_id(did)) + self.hir().attrs(self.local_def_id_to_hir_id(did)) } else { self.item_attrs(did) } @@ -2271,7 +2355,7 @@ impl<'tcx> TyCtxt<'tcx> { let did: DefId = did.into(); let filter_fn = move |a: &&ast::Attribute| a.has_name(attr); if let Some(did) = did.as_local() { - self.hir().attrs(self.hir().local_def_id_to_hir_id(did)).iter().filter(filter_fn) + self.hir().attrs(self.local_def_id_to_hir_id(did)).iter().filter(filter_fn) } else if cfg!(debug_assertions) && rustc_feature::is_builtin_only_local(attr) { bug!("tried to access the `only_local` attribute `{}` from an extern crate", attr); } else { @@ -2287,9 +2371,9 @@ impl<'tcx> TyCtxt<'tcx> { where 'tcx: 'attr, { - let filter_fn = move |a: &&ast::Attribute| a.path_matches(&attr); + let filter_fn = move |a: &&ast::Attribute| a.path_matches(attr); if let Some(did) = did.as_local() { - self.hir().attrs(self.hir().local_def_id_to_hir_id(did)).iter().filter(filter_fn) + self.hir().attrs(self.local_def_id_to_hir_id(did)).iter().filter(filter_fn) } else { self.item_attrs(did).iter().filter(filter_fn) } @@ -2495,22 +2579,6 @@ impl<'tcx> TyCtxt<'tcx> { } } -/// Yields the parent function's `LocalDefId` if `def_id` is an `impl Trait` definition. -pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<LocalDefId> { - let def_id = def_id.as_local()?; - if let Node::Item(item) = tcx.hir().get_by_def_id(def_id) { - if let hir::ItemKind::OpaqueTy(ref opaque_ty) = item.kind { - return match opaque_ty.origin { - hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent) => { - Some(parent) - } - hir::OpaqueTyOrigin::TyAlias { .. } => None, - }; - } - } - None -} - pub fn int_ty(ity: ast::IntTy) -> IntTy { match ity { ast::IntTy::Isize => IntTy::Isize, @@ -2599,9 +2667,7 @@ pub struct SymbolName<'tcx> { impl<'tcx> SymbolName<'tcx> { pub fn new(tcx: TyCtxt<'tcx>, name: &str) -> SymbolName<'tcx> { - SymbolName { - name: unsafe { str::from_utf8_unchecked(tcx.arena.alloc_slice(name.as_bytes())) }, - } + SymbolName { name: tcx.arena.alloc_str(name) } } } diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs index fd125af20..27c436c82 100644 --- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs +++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs @@ -97,6 +97,10 @@ impl<'tcx> TyCtxt<'tcx> { /// N.B., currently, higher-ranked type bounds inhibit /// normalization. Therefore, each time we erase them in /// codegen, we need to normalize the contents. + // FIXME(@lcnr): This method should not be necessary, we now normalize + // inside of binders. We should be able to only use + // `tcx.instantiate_bound_regions_with_erased`. Same for the `try_X` + // variant. #[tracing::instrument(level = "debug", skip(self, param_env))] pub fn normalize_erasing_late_bound_regions<T>( self, @@ -106,7 +110,7 @@ impl<'tcx> TyCtxt<'tcx> { where T: TypeFoldable<TyCtxt<'tcx>>, { - let value = self.erase_late_bound_regions(value); + let value = self.instantiate_bound_regions_with_erased(value); self.normalize_erasing_regions(param_env, value) } @@ -126,7 +130,7 @@ impl<'tcx> TyCtxt<'tcx> { where T: TypeFoldable<TyCtxt<'tcx>>, { - let value = self.erase_late_bound_regions(value); + let value = self.instantiate_bound_regions_with_erased(value); self.try_normalize_erasing_regions(param_env, value) } diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs index 8d895732d..1305f63bd 100644 --- a/compiler/rustc_middle/src/ty/opaque_types.rs +++ b/compiler/rustc_middle/src/ty/opaque_types.rs @@ -102,8 +102,9 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> { // Ignore bound regions and `'static` regions that appear in the // type, we only need to remap regions that reference lifetimes // from the function declaration. - // This would ignore `'r` in a type like `for<'r> fn(&'r u32)`. - ty::ReLateBound(..) | ty::ReStatic => return r, + // + // E.g. We ignore `'r` in a type like `for<'r> fn(&'r u32)`. + ty::ReBound(..) | ty::ReStatic => return r, // If regions have been erased (by writeback), don't try to unerase // them. @@ -112,7 +113,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> { ty::ReError(_) => return r, // The regions that we expect from borrow checking. - ty::ReEarlyBound(_) | ty::ReFree(_) => {} + ty::ReEarlyParam(_) | ty::ReLateParam(_) => {} ty::RePlaceholder(_) | ty::ReVar(_) => { // All of the regions in the type should either have been diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index 9afa50cf5..a63a4eff5 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -59,6 +59,7 @@ trivially_parameterized_over_tcx! { crate::middle::codegen_fn_attrs::CodegenFnAttrs, crate::middle::debugger_visualizer::DebuggerVisualizerFile, crate::middle::exported_symbols::SymbolExportInfo, + crate::middle::lib_features::FeatureStability, crate::middle::resolve_bound_vars::ObjectLifetimeDefault, crate::mir::ConstQualifs, ty::AssocItemContainer, diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 6bbc8f70f..5e0915478 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -131,7 +131,7 @@ pub trait Printer<'tcx>: Sized { match key.disambiguated_data.data { // Closures' own generics are only captures, don't print them. - DefPathData::ClosureExpr => {} + DefPathData::Closure => {} // This covers both `DefKind::AnonConst` and `DefKind::InlineConst`. // Anon consts doesn't have their own generics, and inline consts' own // generics are their inferred types, so don't print them. @@ -250,7 +250,7 @@ fn characteristic_def_id_of_type_cached<'a>( ty::Ref(_, ty, _) => characteristic_def_id_of_type_cached(ty, visited), - ty::Tuple(ref tys) => tys.iter().find_map(|ty| { + ty::Tuple(tys) => tys.iter().find_map(|ty| { if visited.insert(ty) { return characteristic_def_id_of_type_cached(ty, visited); } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index baf160bcc..8e045397b 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2,23 +2,22 @@ use crate::mir::interpret::{AllocRange, GlobalAlloc, Pointer, Provenance, Scalar use crate::query::IntoQueryParam; use crate::query::Providers; use crate::traits::util::supertraits_for_pretty_printing; +use crate::ty::GenericArgKind; use crate::ty::{ - self, ConstInt, ParamConst, ScalarInt, Term, TermKind, Ty, TyCtxt, TypeFoldable, - TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, + ConstInt, ParamConst, ScalarInt, Term, TermKind, TypeFoldable, TypeSuperFoldable, + TypeSuperVisitable, TypeVisitable, TypeVisitableExt, }; -use crate::ty::{GenericArg, GenericArgKind}; use rustc_apfloat::ieee::{Double, Single}; +use rustc_apfloat::Float; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; -use rustc_data_structures::sso::SsoHashSet; use rustc_hir as hir; use rustc_hir::def::{self, CtorKind, DefKind, Namespace}; -use rustc_hir::def_id::{DefId, DefIdSet, ModDefId, CRATE_DEF_ID, LOCAL_CRATE}; -use rustc_hir::definitions::{DefKey, DefPathData, DefPathDataName, DisambiguatedDefPathData}; +use rustc_hir::def_id::{DefIdSet, ModDefId, CRATE_DEF_ID, LOCAL_CRATE}; +use rustc_hir::definitions::{DefKey, DefPathDataName}; use rustc_hir::LangItem; use rustc_session::config::TrimmedDefPaths; use rustc_session::cstore::{ExternCrate, ExternCrateSource}; use rustc_session::Limit; -use rustc_span::sym; use rustc_span::symbol::{kw, Ident, Symbol}; use rustc_span::FileNameDisplayPreference; use rustc_target::abi::Size; @@ -282,7 +281,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { /// from at least one local module, and returns `true`. If the crate defining `def_id` is /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`. fn try_print_visible_def_path(&mut self, def_id: DefId) -> Result<bool, PrintError> { - if NO_VISIBLE_PATH.with(|flag| flag.get()) { + if with_no_visible_paths() { return Ok(false); } @@ -322,7 +321,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { && let Some(symbol) = self.tcx().trimmed_def_paths(()).get(&def_id) { // If `Assoc` is unique, we don't want to talk about `Trait::Assoc`. - self.write_str(get_local_name(&self, *symbol, def_id, key).as_str())?; + self.write_str(get_local_name(self, *symbol, def_id, key).as_str())?; return Ok(true); } if let Some(symbol) = key.get_opt_name() { @@ -332,7 +331,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { && let Some(symbol) = parent_key.get_opt_name() { // Trait - self.write_str(get_local_name(&self, symbol, parent, parent_key).as_str())?; + self.write_str(get_local_name(self, symbol, parent, parent_key).as_str())?; self.write_str("::")?; } else if let DefKind::Variant = kind && let Some(parent) = self.tcx().opt_parent(def_id) @@ -343,7 +342,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { // For associated items and variants, we want the "full" path, namely, include // the parent type in the path. For example, `Iterator::Item`. - self.write_str(get_local_name(&self, symbol, parent, parent_key).as_str())?; + self.write_str(get_local_name(self, symbol, parent, parent_key).as_str())?; self.write_str("::")?; } else if let DefKind::Struct | DefKind::Union @@ -358,7 +357,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { // If not covered above, like for example items out of `impl` blocks, fallback. return Ok(false); } - self.write_str(get_local_name(&self, symbol, def_id, key).as_str())?; + self.write_str(get_local_name(self, symbol, def_id, key).as_str())?; return Ok(true); } Ok(false) @@ -366,7 +365,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { /// Try to see if this path can be trimmed to a unique symbol name. fn try_print_trimmed_def_path(&mut self, def_id: DefId) -> Result<bool, PrintError> { - if FORCE_TRIMMED_PATH.with(|flag| flag.get()) { + if with_forced_trimmed_paths() { let trimmed = self.force_print_trimmed_def_path(def_id)?; if trimmed { return Ok(true); @@ -374,8 +373,8 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { } if !self.tcx().sess.opts.unstable_opts.trim_diagnostic_paths || matches!(self.tcx().sess.opts.trimmed_def_paths, TrimmedDefPaths::Never) - || NO_TRIMMED_PATH.with(|flag| flag.get()) - || SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get()) + || with_no_trimmed_paths() + || with_crate_prefix() { return Ok(false); } @@ -660,7 +659,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { p!(print(ty::TypeAndMut { ty, mutbl })) } ty::Never => p!("!"), - ty::Tuple(ref tys) => { + ty::Tuple(tys) => { p!("(", comma_sep(tys.iter())); if tys.len() == 1 { p!(","); @@ -860,7 +859,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { p!("@", print_def_path(did.to_def_id(), args)); } else { let span = self.tcx().def_span(did); - let preference = if FORCE_TRIMMED_PATH.with(|flag| flag.get()) { + let preference = if with_forced_trimmed_paths() { FileNameDisplayPreference::Short } else { FileNameDisplayPreference::Remapped @@ -1101,7 +1100,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { write!(self, "Sized")?; } - if !FORCE_TRIMMED_PATH.with(|flag| flag.get()) { + if !with_forced_trimmed_paths() { for re in lifetimes { write!(self, " + ")?; self.print_region(re)?; @@ -1409,14 +1408,14 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { ) -> Result<(), PrintError> { define_scoped_cx!(self); - let (alloc_id, offset) = ptr.into_parts(); + let (prov, offset) = ptr.into_parts(); match ty.kind() { // Byte strings (&[u8; N]) ty::Ref(_, inner, _) => { if let ty::Array(elem, len) = inner.kind() { if let ty::Uint(ty::UintTy::U8) = elem.kind() { if let ty::ConstKind::Value(ty::ValTree::Leaf(int)) = len.kind() { - match self.tcx().try_get_global_alloc(alloc_id) { + match self.tcx().try_get_global_alloc(prov.alloc_id()) { Some(GlobalAlloc::Memory(alloc)) => { let len = int.assert_bits(self.tcx().data_layout.pointer_size); let range = @@ -1446,7 +1445,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { // FIXME: We should probably have a helper method to share code with the "Byte strings" // printing above (which also has to handle pointers to all sorts of things). if let Some(GlobalAlloc::Function(instance)) = - self.tcx().try_get_global_alloc(alloc_id) + self.tcx().try_get_global_alloc(prov.alloc_id()) { self.typed_value( |this| this.print_value_path(instance.def_id(), instance.args), @@ -1477,10 +1476,12 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { ty::Bool if int == ScalarInt::TRUE => p!("true"), // Float ty::Float(ty::FloatTy::F32) => { - p!(write("{}f32", Single::try_from(int).unwrap())) + let val = Single::try_from(int).unwrap(); + p!(write("{}{}f32", val, if val.is_finite() { "" } else { "_" })) } ty::Float(ty::FloatTy::F64) => { - p!(write("{}f64", Double::try_from(int).unwrap())) + let val = Double::try_from(int).unwrap(); + p!(write("{}{}f64", val, if val.is_finite() { "" } else { "_" })) } // Int ty::Uint(_) | ty::Int(_) => { @@ -1679,7 +1680,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { self.wrap_binder(&sig, |sig, cx| { define_scoped_cx!(cx); - p!(print(kind), "("); + p!(write("{kind}(")); for (i, arg) in sig.inputs()[0].tuple_fields().iter().enumerate() { if i > 0 { p!(", "); @@ -1801,13 +1802,13 @@ impl<'a, 'tcx> FmtPrinter<'a, 'tcx> { // (but also some things just print a `DefId` generally so maybe we need this?) fn guess_def_namespace(tcx: TyCtxt<'_>, def_id: DefId) -> Namespace { match tcx.def_key(def_id).disambiguated_data.data { - DefPathData::TypeNs(..) | DefPathData::CrateRoot | DefPathData::ImplTrait => { + DefPathData::TypeNs(..) | DefPathData::CrateRoot | DefPathData::OpaqueTy => { Namespace::TypeNS } DefPathData::ValueNs(..) | DefPathData::AnonConst - | DefPathData::ClosureExpr + | DefPathData::Closure | DefPathData::Ctor => Namespace::ValueNS, DefPathData::MacroNs(..) => Namespace::MacroNS, @@ -1883,7 +1884,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { // available, and filename/line-number is mostly uninteresting. let use_types = !def_id.is_local() || { // Otherwise, use filename/line-number if forced. - let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get()); + let force_no_types = with_forced_impl_filename_line(); !force_no_types }; @@ -1948,7 +1949,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { if cnum == LOCAL_CRATE { if self.tcx.sess.at_least_rust_2018() { // We add the `crate::` keyword on Rust 2018, only when desired. - if SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get()) { + if with_crate_prefix() { write!(self, "{}", kw::Crate)?; self.empty_path = false; } @@ -2031,37 +2032,11 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { ) -> Result<(), PrintError> { print_prefix(self)?; - let tcx = self.tcx; - - let args = args.iter().copied(); - - let args: Vec<_> = if !tcx.sess.verbose() { - // skip host param as those are printed as `~const` - args.filter(|arg| match arg.unpack() { - // FIXME(effects) there should be a better way than just matching the name - GenericArgKind::Const(c) - if tcx.features().effects - && matches!( - c.kind(), - ty::ConstKind::Param(ty::ParamConst { name: sym::host, .. }) - ) => - { - false - } - _ => true, - }) - .collect() - } else { - // If -Zverbose is passed, we should print the host parameter instead - // of eating it. - args.collect() - }; - if !args.is_empty() { if self.in_value { write!(self, "::")?; } - self.generic_delimiters(|cx| cx.comma_sep(args.into_iter())) + self.generic_delimiters(|cx| cx.comma_sep(args.iter().copied())) } else { Ok(()) } @@ -2151,17 +2126,17 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { return true; } - if FORCE_TRIMMED_PATH.with(|flag| flag.get()) { + if with_forced_trimmed_paths() { return false; } let identify_regions = self.tcx.sess.opts.unstable_opts.identify_regions; match *region { - ty::ReEarlyBound(ref data) => data.has_name(), + ty::ReEarlyParam(ref data) => data.has_name(), - ty::ReLateBound(_, ty::BoundRegion { kind: br, .. }) - | ty::ReFree(ty::FreeRegion { bound_region: br, .. }) + ty::ReBound(_, ty::BoundRegion { kind: br, .. }) + | ty::ReLateParam(ty::LateParamRegion { bound_region: br, .. }) | ty::RePlaceholder(ty::Placeholder { bound: ty::BoundRegion { kind: br, .. }, .. }) => { @@ -2228,14 +2203,14 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { // to fit that into a short string. Hence the recommendation to use // `explain_region()` or `note_and_explain_region()`. match *region { - ty::ReEarlyBound(ref data) => { + ty::ReEarlyParam(ref data) => { if data.name != kw::Empty { p!(write("{}", data.name)); return Ok(()); } } - ty::ReLateBound(_, ty::BoundRegion { kind: br, .. }) - | ty::ReFree(ty::FreeRegion { bound_region: br, .. }) + ty::ReBound(_, ty::BoundRegion { kind: br, .. }) + | ty::ReLateParam(ty::LateParamRegion { bound_region: br, .. }) | ty::RePlaceholder(ty::Placeholder { bound: ty::BoundRegion { kind: br, .. }, .. }) => { @@ -2315,7 +2290,7 @@ impl<'a, 'tcx> ty::TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> { fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { let name = &mut self.name; let region = match *r { - ty::ReLateBound(db, br) if db >= self.current_index => { + ty::ReBound(db, br) if db >= self.current_index => { *self.region_map.entry(br).or_insert_with(|| name(Some(db), self.current_index, br)) } ty::RePlaceholder(ty::PlaceholderRegion { @@ -2338,9 +2313,9 @@ impl<'a, 'tcx> ty::TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> { } _ => return r, }; - if let ty::ReLateBound(debruijn1, br) = *region { + if let ty::ReBound(debruijn1, br) = *region { assert_eq!(debruijn1, ty::INNERMOST); - ty::Region::new_late_bound(self.tcx, self.current_index, br) + ty::Region::new_bound(self.tcx, self.current_index, br) } else { region } @@ -2399,7 +2374,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { let possible_names = ('a'..='z').rev().map(|s| Symbol::intern(&format!("'{s}"))); let mut available_names = possible_names - .filter(|name| !self.used_region_names.contains(&name)) + .filter(|name| !self.used_region_names.contains(name)) .collect::<Vec<_>>(); debug!(?available_names); let num_available = available_names.len(); @@ -2434,7 +2409,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { } else { let tcx = self.tcx; - let trim_path = FORCE_TRIMMED_PATH.with(|flag| flag.get()); + let trim_path = with_forced_trimmed_paths(); // Closure used in `RegionFolder` to create names for anonymous late-bound // regions. We use two `DebruijnIndex`es (one for the currently folded // late-bound region and the other for the binder level) to determine @@ -2445,12 +2420,12 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { br: ty::BoundRegion| { let (name, kind) = match br.kind { ty::BrAnon | ty::BrEnv => { - let name = next_name(&self); + let name = next_name(self); if let Some(lt_idx) = lifetime_idx { if lt_idx > binder_level_idx { let kind = ty::BrNamed(CRATE_DEF_ID.to_def_id(), name); - return ty::Region::new_late_bound( + return ty::Region::new_bound( tcx, ty::INNERMOST, ty::BoundRegion { var: br.var, kind }, @@ -2461,12 +2436,12 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { (name, ty::BrNamed(CRATE_DEF_ID.to_def_id(), name)) } ty::BrNamed(def_id, kw::UnderscoreLifetime | kw::Empty) => { - let name = next_name(&self); + let name = next_name(self); if let Some(lt_idx) = lifetime_idx { if lt_idx > binder_level_idx { let kind = ty::BrNamed(def_id, name); - return ty::Region::new_late_bound( + return ty::Region::new_bound( tcx, ty::INNERMOST, ty::BoundRegion { var: br.var, kind }, @@ -2480,7 +2455,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { if let Some(lt_idx) = lifetime_idx { if lt_idx > binder_level_idx { let kind = br.kind; - return ty::Region::new_late_bound( + return ty::Region::new_bound( tcx, ty::INNERMOST, ty::BoundRegion { var: br.var, kind }, @@ -2496,11 +2471,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { start_or_continue(self, "for<", ", "); do_continue(self, name); } - ty::Region::new_late_bound( - tcx, - ty::INNERMOST, - ty::BoundRegion { var: br.var, kind }, - ) + ty::Region::new_bound(tcx, ty::INNERMOST, ty::BoundRegion { var: br.var, kind }) }; let mut folder = RegionFolder { tcx, @@ -2642,6 +2613,23 @@ impl<'tcx> fmt::Debug for TraitRefPrintOnlyTraitPath<'tcx> { } /// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only +/// the trait path, and additionally tries to "sugar" `Fn(...)` trait bounds. +#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)] +pub struct TraitRefPrintSugared<'tcx>(ty::TraitRef<'tcx>); + +impl<'tcx> rustc_errors::IntoDiagnosticArg for TraitRefPrintSugared<'tcx> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + self.to_string().into_diagnostic_arg() + } +} + +impl<'tcx> fmt::Debug for TraitRefPrintSugared<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, f) + } +} + +/// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only /// the trait name. That is, it will print `Trait` instead of /// `<T as Trait<U>>`. #[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)] @@ -2658,6 +2646,10 @@ impl<'tcx> ty::TraitRef<'tcx> { TraitRefPrintOnlyTraitPath(self) } + pub fn print_trait_sugared(self) -> TraitRefPrintSugared<'tcx> { + TraitRefPrintSugared(self) + } + pub fn print_only_trait_name(self) -> TraitRefPrintOnlyTraitName<'tcx> { TraitRefPrintOnlyTraitName(self) } @@ -2667,6 +2659,10 @@ impl<'tcx> ty::Binder<'tcx, ty::TraitRef<'tcx>> { pub fn print_only_trait_path(self) -> ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>> { self.map_bound(|tr| tr.print_only_trait_path()) } + + pub fn print_trait_sugared(self) -> ty::Binder<'tcx, TraitRefPrintSugared<'tcx>> { + self.map_bound(|tr| tr.print_trait_sugared()) + } } #[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)] @@ -2746,6 +2742,7 @@ forward_display_to_print! { ty::PolyExistentialTraitRef<'tcx>, ty::Binder<'tcx, ty::TraitRef<'tcx>>, ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, + ty::Binder<'tcx, TraitRefPrintSugared<'tcx>>, ty::Binder<'tcx, ty::FnSig<'tcx>>, ty::Binder<'tcx, ty::TraitPredicate<'tcx>>, ty::Binder<'tcx, TraitPredPrintModifiersAndPath<'tcx>>, @@ -2757,6 +2754,10 @@ forward_display_to_print! { define_print! { (self, cx): + ty::TypeAndMut<'tcx> { + p!(write("{}", self.mutbl.prefix_str()), print(self.ty)) + } + ty::ClauseKind<'tcx> { match *self { ty::ClauseKind::Trait(ref data) => { @@ -2785,15 +2786,11 @@ define_print! { ty::PredicateKind::ObjectSafe(trait_def_id) => { p!("the trait `", print_def_path(trait_def_id, &[]), "` is object-safe") } - ty::PredicateKind::ClosureKind(closure_def_id, _closure_args, kind) => p!( - "the closure `", - print_value_path(closure_def_id, &[]), - write("` implements the trait `{}`", kind) - ), ty::PredicateKind::ConstEquate(c1, c2) => { p!("the constant `", print(c1), "` equals `", print(c2), "`") } ty::PredicateKind::Ambiguous => p!("ambiguous"), + ty::PredicateKind::NormalizesTo(data) => p!(print(data)), ty::PredicateKind::AliasRelate(t1, t2, dir) => p!(print(t1), write(" {} ", dir), print(t2)), } } @@ -2806,10 +2803,6 @@ define_print_and_forward_display! { p!("{{", comma_sep(self.iter()), "}}") } - ty::TypeAndMut<'tcx> { - p!(write("{}", self.mutbl.prefix_str()), print(self.ty)) - } - ty::ExistentialTraitRef<'tcx> { // Use a type that can't appear in defaults of type parameters. let dummy_self = Ty::new_fresh(cx.tcx(),0); @@ -2850,16 +2843,39 @@ define_print_and_forward_display! { p!(print_def_path(self.0.def_id, self.0.args)); } + TraitRefPrintSugared<'tcx> { + if !with_no_queries() + && let Some(kind) = cx.tcx().fn_trait_kind_from_def_id(self.0.def_id) + && let ty::Tuple(args) = self.0.args.type_at(1).kind() + { + p!(write("{}", kind.as_str()), "("); + for (i, arg) in args.iter().enumerate() { + if i > 0 { + p!(", "); + } + p!(print(arg)); + } + p!(")"); + } else { + p!(print_def_path(self.0.def_id, self.0.args)); + } + } + TraitRefPrintOnlyTraitName<'tcx> { p!(print_def_path(self.0.def_id, &[])); } TraitPredPrintModifiersAndPath<'tcx> { - // FIXME(effects) print `~const` here + if let Some(idx) = cx.tcx().generics_of(self.0.trait_ref.def_id).host_effect_index + { + let arg = self.0.trait_ref.args.const_at(idx); + if arg != cx.tcx().consts.true_ && !arg.has_infer() { + p!("~const "); + } + } if let ty::ImplPolarity::Negative = self.0.polarity { p!("!") } - p!(print(self.0.trait_ref.print_only_trait_path())); } @@ -2894,11 +2910,10 @@ define_print_and_forward_display! { p!("~const "); } } - // FIXME(effects) print `~const` here if let ty::ImplPolarity::Negative = self.polarity { p!("!"); } - p!(print(self.trait_ref.print_only_trait_path())) + p!(print(self.trait_ref.print_trait_sugared())) } ty::ProjectionPredicate<'tcx> { @@ -2907,6 +2922,12 @@ define_print_and_forward_display! { p!(print(self.term)) } + ty::NormalizesTo<'tcx> { + p!(print(self.alias), " normalizes-to "); + cx.reset_type_limit(); + p!(print(self.term)) + } + ty::Term<'tcx> { match self.unpack() { ty::TermKind::Ty(ty) => p!(print(ty)), @@ -2922,10 +2943,6 @@ define_print_and_forward_display! { } } - ty::ClosureKind { - p!(write("{}", self.as_str())) - } - ty::Predicate<'tcx> { p!(print(self.kind())) } @@ -3022,7 +3039,8 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N /// The implementation uses similar import discovery logic to that of 'use' suggestions. /// /// See also [`DelayDm`](rustc_error_messages::DelayDm) and [`with_no_trimmed_paths!`]. -fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> FxHashMap<DefId, Symbol> { +// this is pub to be able to intra-doc-link it +pub fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> FxHashMap<DefId, Symbol> { let mut map: FxHashMap<DefId, Symbol> = FxHashMap::default(); if let TrimmedDefPaths::GoodPath = tcx.sess.opts.trimmed_def_paths { @@ -3030,7 +3048,7 @@ fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> FxHashMap<DefId, Symbol> { // // For good paths causing this bug, the `rustc_middle::ty::print::with_no_trimmed_paths` // wrapper can be used to suppress this query, in exchange for full paths being formatted. - tcx.sess.delay_good_path_bug( + tcx.sess.good_path_delayed_bug( "trimmed_def_paths constructed but no error emitted; use `DelayDm` for lints or `with_no_trimmed_paths` for debugging", ); } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 27e9be37f..9d92f81db 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -23,8 +23,6 @@ pub enum Cause { pub trait TypeRelation<'tcx>: Sized { fn tcx(&self) -> TyCtxt<'tcx>; - fn param_env(&self) -> ty::ParamEnv<'tcx>; - /// Returns a static string we can use for printouts. fn tag(&self) -> &'static str; @@ -482,7 +480,7 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( // the (anonymous) type of the same closure expression. So // all of their regions should be equated. let args = relate_args_invariantly(relation, a_args, b_args)?; - Ok(Ty::new_closure(tcx, a_id, &args)) + Ok(Ty::new_closure(tcx, a_id, args)) } (&ty::RawPtr(a_mt), &ty::RawPtr(b_mt)) => { @@ -505,13 +503,9 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( Err(err) => { // Check whether the lengths are both concrete/known values, // but are unequal, for better diagnostics. - // - // It might seem dubious to eagerly evaluate these constants here, - // we however cannot end up with errors in `Relate` during both - // `type_of` and `predicates_of`. This means that evaluating the - // constants should not cause cycle errors here. - let sz_a = sz_a.try_eval_target_usize(tcx, relation.param_env()); - let sz_b = sz_b.try_eval_target_usize(tcx, relation.param_env()); + let sz_a = sz_a.try_to_target_usize(tcx); + let sz_b = sz_b.try_to_target_usize(tcx); + match (sz_a, sz_b) { (Some(sz_a_val), Some(sz_b_val)) if sz_a_val != sz_b_val => Err( TypeError::FixedArraySize(expected_found(relation, sz_a_val, sz_b_val)), diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 6af68bc5d..1c75d73e5 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -79,9 +79,9 @@ impl fmt::Debug for ty::BoundRegionKind { } } -impl fmt::Debug for ty::FreeRegion { +impl fmt::Debug for ty::LateParamRegion { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "ReFree({:?}, {:?})", self.scope, self.bound_region) + write!(f, "ReLateParam({:?}, {:?})", self.scope, self.bound_region) } } @@ -173,6 +173,12 @@ impl<'tcx> fmt::Debug for ty::ProjectionPredicate<'tcx> { } } +impl<'tcx> fmt::Debug for ty::NormalizesTo<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "NormalizesTo({:?}, {:?})", self.alias, self.term) + } +} + impl<'tcx> fmt::Debug for ty::Predicate<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}", self.kind()) @@ -202,34 +208,6 @@ impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for AliasTy<'tcx> { } } -impl fmt::Debug for ty::InferConst { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - InferConst::Var(var) => write!(f, "{var:?}"), - InferConst::EffectVar(var) => write!(f, "{var:?}"), - InferConst::Fresh(var) => write!(f, "Fresh({var:?})"), - } - } -} -impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::InferConst { - fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>( - this: WithInfcx<'_, Infcx, &Self>, - f: &mut core::fmt::Formatter<'_>, - ) -> core::fmt::Result { - use ty::InferConst::*; - match this.infcx.universe_of_ct(*this.data) { - None => write!(f, "{:?}", this.data), - Some(universe) => match *this.data { - Var(vid) => write!(f, "?{}_{}c", vid.index(), universe.index()), - EffectVar(vid) => write!(f, "?{}_{}e", vid.index(), universe.index()), - Fresh(_) => { - unreachable!() - } - }, - } - } -} - impl<'tcx> fmt::Debug for ty::consts::Expr<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { WithInfcx::with_no_infcx(self).fmt(f) @@ -444,7 +422,7 @@ TrivialTypeTraversalImpls! { crate::ty::Placeholder<crate::ty::BoundRegion>, crate::ty::Placeholder<crate::ty::BoundTy>, crate::ty::Placeholder<ty::BoundVar>, - crate::ty::FreeRegion, + crate::ty::LateParamRegion, crate::ty::InferTy, crate::ty::IntVarValue, crate::ty::adjustment::PointerCoercion, @@ -462,14 +440,14 @@ TrivialTypeTraversalImpls! { // interners). TrivialTypeTraversalAndLiftImpls! { ::rustc_hir::def_id::DefId, - ::rustc_hir::Mutability, ::rustc_hir::Unsafety, ::rustc_target::spec::abi::Abi, crate::ty::ClosureKind, crate::ty::ParamConst, crate::ty::ParamTy, - interpret::Scalar, interpret::AllocId, + interpret::CtfeProvenance, + interpret::Scalar, rustc_target::abi::Size, } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 44592b10d..a0debc8a1 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -6,7 +6,7 @@ use crate::infer::canonical::Canonical; use crate::ty::visit::ValidateBoundVars; use crate::ty::InferTy::*; use crate::ty::{ - self, AdtDef, Discr, Term, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable, + self, AdtDef, Discr, IntoKind, Term, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, }; use crate::ty::{GenericArg, GenericArgs, GenericArgsRef}; @@ -15,7 +15,9 @@ use hir::def::DefKind; use polonius_engine::Atom; use rustc_data_structures::captures::Captures; use rustc_data_structures::intern::Interned; -use rustc_errors::{DiagnosticArgValue, ErrorGuaranteed, IntoDiagnosticArg, MultiSpan}; +use rustc_errors::{ + DiagnosticArgValue, DiagnosticMessage, ErrorGuaranteed, IntoDiagnosticArg, MultiSpan, +}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::LangItem; @@ -32,6 +34,7 @@ use std::fmt; use std::ops::{ControlFlow, Deref, Range}; use ty::util::IntTypeExt; +use rustc_type_ir::BoundVar; use rustc_type_ir::ClauseKind as IrClauseKind; use rustc_type_ir::CollectAndApply; use rustc_type_ir::ConstKind as IrConstKind; @@ -41,29 +44,24 @@ use rustc_type_ir::PredicateKind as IrPredicateKind; use rustc_type_ir::RegionKind as IrRegionKind; use rustc_type_ir::TyKind as IrTyKind; use rustc_type_ir::TyKind::*; +use rustc_type_ir::TypeAndMut as IrTypeAndMut; use super::GenericParamDefKind; -// Re-export the `TyKind` from `rustc_type_ir` here for convenience +// Re-export and re-parameterize some `I = TyCtxt<'tcx>` types here #[rustc_diagnostic_item = "TyKind"] pub type TyKind<'tcx> = IrTyKind<TyCtxt<'tcx>>; pub type RegionKind<'tcx> = IrRegionKind<TyCtxt<'tcx>>; pub type ConstKind<'tcx> = IrConstKind<TyCtxt<'tcx>>; pub type PredicateKind<'tcx> = IrPredicateKind<TyCtxt<'tcx>>; pub type ClauseKind<'tcx> = IrClauseKind<TyCtxt<'tcx>>; - -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct TypeAndMut<'tcx> { - pub ty: Ty<'tcx>, - pub mutbl: hir::Mutability, -} +pub type TypeAndMut<'tcx> = IrTypeAndMut<TyCtxt<'tcx>>; #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, TyEncodable, TyDecodable, Copy)] #[derive(HashStable)] -/// A "free" region `fr` can be interpreted as "some region +/// The parameter representation of late-bound function parameters, "some region /// at least as big as the scope `fr.scope`". -pub struct FreeRegion { +pub struct LateParamRegion { pub scope: DefId, pub bound_region: BoundRegionKind, } @@ -467,16 +465,6 @@ impl<'tcx> CoroutineArgs<'tcx> { self.split().return_ty.expect_ty() } - /// Returns the "coroutine signature", which consists of its yield - /// and return types. - /// - /// N.B., some bits of the code prefers to see this wrapped in a - /// binder, but it never contains bound regions. Probably this - /// function should be removed. - pub fn poly_sig(self) -> PolyGenSig<'tcx> { - ty::Binder::dummy(self.sig()) - } - /// Returns the "coroutine signature", which consists of its resume, yield /// and return types. pub fn sig(self) -> GenSig<'tcx> { @@ -1036,7 +1024,7 @@ impl<'tcx, T> Binder<'tcx, T> { /// risky thing to do because it's easy to get confused about /// De Bruijn indices and the like. It is usually better to /// discharge the binder using `no_bound_vars` or - /// `replace_late_bound_regions` or something like + /// `instantiate_bound_regions` or something like /// that. `skip_binder` is only valid when you are either /// extracting data that has nothing to do with bound vars, you /// are doing some sort of test that does not involve bound @@ -1245,6 +1233,28 @@ impl<'tcx> AliasTy<'tcx> { } } + /// Whether this alias type is an opaque. + pub fn is_opaque(self, tcx: TyCtxt<'tcx>) -> bool { + matches!(self.opt_kind(tcx), Some(ty::AliasKind::Opaque)) + } + + /// FIXME: rename `AliasTy` to `AliasTerm` and always handle + /// constants. This function can then be removed. + pub fn opt_kind(self, tcx: TyCtxt<'tcx>) -> Option<ty::AliasKind> { + match tcx.def_kind(self.def_id) { + DefKind::AssocTy + if let DefKind::Impl { of_trait: false } = + tcx.def_kind(tcx.parent(self.def_id)) => + { + Some(ty::Inherent) + } + DefKind::AssocTy => Some(ty::Projection), + DefKind::OpaqueTy => Some(ty::Opaque), + DefKind::TyAlias => Some(ty::Weak), + _ => None, + } + } + pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { Ty::new_alias(tcx, self.kind(tcx), self) } @@ -1329,8 +1339,6 @@ pub struct GenSig<'tcx> { pub return_ty: Ty<'tcx>, } -pub type PolyGenSig<'tcx> = Binder<'tcx, GenSig<'tcx>>; - /// Signature of a function type, which we have arbitrarily /// decided to use to refer to the input/output types. /// @@ -1466,17 +1474,25 @@ impl ParamConst { #[rustc_pass_by_value] pub struct Region<'tcx>(pub Interned<'tcx, RegionKind<'tcx>>); +impl<'tcx> IntoKind for Region<'tcx> { + type Kind = RegionKind<'tcx>; + + fn kind(self) -> RegionKind<'tcx> { + *self + } +} + impl<'tcx> Region<'tcx> { #[inline] - pub fn new_early_bound( + pub fn new_early_param( tcx: TyCtxt<'tcx>, - early_bound_region: ty::EarlyBoundRegion, + early_bound_region: ty::EarlyParamRegion, ) -> Region<'tcx> { - tcx.intern_region(ty::ReEarlyBound(early_bound_region)) + tcx.intern_region(ty::ReEarlyParam(early_bound_region)) } #[inline] - pub fn new_late_bound( + pub fn new_bound( tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, bound_region: ty::BoundRegion, @@ -1488,17 +1504,17 @@ impl<'tcx> Region<'tcx> { { re } else { - tcx.intern_region(ty::ReLateBound(debruijn, bound_region)) + tcx.intern_region(ty::ReBound(debruijn, bound_region)) } } #[inline] - pub fn new_free( + pub fn new_late_param( tcx: TyCtxt<'tcx>, scope: DefId, bound_region: ty::BoundRegionKind, ) -> Region<'tcx> { - tcx.intern_region(ty::ReFree(ty::FreeRegion { scope, bound_region })) + tcx.intern_region(ty::ReLateParam(ty::LateParamRegion { scope, bound_region })) } #[inline] @@ -1522,7 +1538,7 @@ impl<'tcx> Region<'tcx> { tcx.intern_region(ty::ReError(reported)) } - /// Constructs a `RegionKind::ReError` region and registers a `delay_span_bug` to ensure it + /// Constructs a `RegionKind::ReError` region and registers a `span_delayed_bug` to ensure it /// gets used. #[track_caller] pub fn new_error_misc(tcx: TyCtxt<'tcx>) -> Region<'tcx> { @@ -1533,7 +1549,7 @@ impl<'tcx> Region<'tcx> { ) } - /// Constructs a `RegionKind::ReError` region and registers a `delay_span_bug` with the given + /// Constructs a `RegionKind::ReError` region and registers a `span_delayed_bug` with the given /// `msg` to ensure it gets used. #[track_caller] pub fn new_error_with_message<S: Into<MultiSpan>>( @@ -1541,7 +1557,7 @@ impl<'tcx> Region<'tcx> { span: S, msg: &'static str, ) -> Region<'tcx> { - let reported = tcx.sess.delay_span_bug(span, msg); + let reported = tcx.sess.span_delayed_bug(span, msg); Region::new_error(tcx, reported) } @@ -1549,10 +1565,10 @@ impl<'tcx> Region<'tcx> { /// to avoid the cost of the `match`. pub fn new_from_kind(tcx: TyCtxt<'tcx>, kind: RegionKind<'tcx>) -> Region<'tcx> { match kind { - ty::ReEarlyBound(region) => Region::new_early_bound(tcx, region), - ty::ReLateBound(debruijn, region) => Region::new_late_bound(tcx, debruijn, region), - ty::ReFree(ty::FreeRegion { scope, bound_region }) => { - Region::new_free(tcx, scope, bound_region) + ty::ReEarlyParam(region) => Region::new_early_param(tcx, region), + ty::ReBound(debruijn, region) => Region::new_bound(tcx, debruijn, region), + ty::ReLateParam(ty::LateParamRegion { scope, bound_region }) => { + Region::new_late_param(tcx, scope, bound_region) } ty::ReStatic => tcx.lifetimes.re_static, ty::ReVar(vid) => Region::new_var(tcx, vid), @@ -1568,45 +1584,29 @@ impl<'tcx> Deref for Region<'tcx> { #[inline] fn deref(&self) -> &RegionKind<'tcx> { - &self.0.0 + self.0.0 } } #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, PartialOrd, Ord)] #[derive(HashStable)] -pub struct EarlyBoundRegion { +pub struct EarlyParamRegion { pub def_id: DefId, pub index: u32, pub name: Symbol, } -impl fmt::Debug for EarlyBoundRegion { +impl fmt::Debug for EarlyParamRegion { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}, {}, {}", self.def_id, self.index, self.name) } } rustc_index::newtype_index! { - /// A **`const`** **v**ariable **ID**. - #[debug_format = "?{}c"] - pub struct ConstVid {} -} - -rustc_index::newtype_index! { - /// An **effect** **v**ariable **ID**. - /// - /// Handling effect infer variables happens separately from const infer variables - /// because we do not want to reuse any of the const infer machinery. If we try to - /// relate an effect variable with a normal one, we would ICE, which can catch bugs - /// where we are not correctly using the effect var for an effect param. Fallback - /// is also implemented on top of having separate effect and normal const variables. - #[debug_format = "?{}e"] - pub struct EffectVid {} -} - -rustc_index::newtype_index! { /// A **region** (lifetime) **v**ariable **ID**. #[derive(HashStable)] + #[encodable] + #[orderable] #[debug_format = "'?{}"] pub struct RegionVid {} } @@ -1617,12 +1617,6 @@ impl Atom for RegionVid { } } -rustc_index::newtype_index! { - #[derive(HashStable)] - #[debug_format = "{}"] - pub struct BoundVar {} -} - #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)] #[derive(HashStable)] pub struct BoundTy { @@ -1722,9 +1716,9 @@ impl<'tcx> Region<'tcx> { pub fn get_name(self) -> Option<Symbol> { if self.has_name() { match *self { - ty::ReEarlyBound(ebr) => Some(ebr.name), - ty::ReLateBound(_, br) => br.kind.get_name(), - ty::ReFree(fr) => fr.bound_region.get_name(), + ty::ReEarlyParam(ebr) => Some(ebr.name), + ty::ReBound(_, br) => br.kind.get_name(), + ty::ReLateParam(fr) => fr.bound_region.get_name(), ty::ReStatic => Some(kw::StaticLifetime), ty::RePlaceholder(placeholder) => placeholder.bound.kind.get_name(), _ => None, @@ -1744,9 +1738,9 @@ impl<'tcx> Region<'tcx> { /// Is this region named by the user? pub fn has_name(self) -> bool { match *self { - ty::ReEarlyBound(ebr) => ebr.has_name(), - ty::ReLateBound(_, br) => br.kind.is_named(), - ty::ReFree(fr) => fr.bound_region.is_named(), + ty::ReEarlyParam(ebr) => ebr.has_name(), + ty::ReBound(_, br) => br.kind.is_named(), + ty::ReLateParam(fr) => fr.bound_region.is_named(), ty::ReStatic => true, ty::ReVar(..) => false, ty::RePlaceholder(placeholder) => placeholder.bound.kind.is_named(), @@ -1771,8 +1765,8 @@ impl<'tcx> Region<'tcx> { } #[inline] - pub fn is_late_bound(self) -> bool { - matches!(*self, ty::ReLateBound(..)) + pub fn is_bound(self) -> bool { + matches!(*self, ty::ReBound(..)) } #[inline] @@ -1783,7 +1777,7 @@ impl<'tcx> Region<'tcx> { #[inline] pub fn bound_at_or_above_binder(self, index: ty::DebruijnIndex) -> bool { match *self { - ty::ReLateBound(debruijn, _) => debruijn >= index, + ty::ReBound(debruijn, _) => debruijn >= index, _ => false, } } @@ -1802,20 +1796,20 @@ impl<'tcx> Region<'tcx> { flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; flags = flags | TypeFlags::HAS_RE_PLACEHOLDER; } - ty::ReEarlyBound(..) => { + ty::ReEarlyParam(..) => { flags = flags | TypeFlags::HAS_FREE_REGIONS; flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; flags = flags | TypeFlags::HAS_RE_PARAM; } - ty::ReFree { .. } => { + ty::ReLateParam { .. } => { flags = flags | TypeFlags::HAS_FREE_REGIONS; flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; } ty::ReStatic => { flags = flags | TypeFlags::HAS_FREE_REGIONS; } - ty::ReLateBound(..) => { - flags = flags | TypeFlags::HAS_RE_LATE_BOUND; + ty::ReBound(..) => { + flags = flags | TypeFlags::HAS_RE_BOUND; } ty::ReErased => { flags = flags | TypeFlags::HAS_RE_ERASED; @@ -1851,22 +1845,28 @@ impl<'tcx> Region<'tcx> { /// function might return the `DefId` of a closure. pub fn free_region_binding_scope(self, tcx: TyCtxt<'_>) -> DefId { match *self { - ty::ReEarlyBound(br) => tcx.parent(br.def_id), - ty::ReFree(fr) => fr.scope, + ty::ReEarlyParam(br) => tcx.parent(br.def_id), + ty::ReLateParam(fr) => fr.scope, _ => bug!("free_region_binding_scope invoked on inappropriate region: {:?}", self), } } /// True for free regions other than `'static`. - pub fn is_free(self) -> bool { - matches!(*self, ty::ReEarlyBound(_) | ty::ReFree(_)) + pub fn is_param(self) -> bool { + matches!(*self, ty::ReEarlyParam(_) | ty::ReLateParam(_)) } - /// True if `self` is a free region or static. - pub fn is_free_or_static(self) -> bool { + /// True for free region in the current context. + /// + /// This is the case for `'static` and param regions. + pub fn is_free(self) -> bool { match *self { - ty::ReStatic => true, - _ => self.is_free(), + ty::ReStatic | ty::ReEarlyParam(..) | ty::ReLateParam(..) => true, + ty::ReVar(..) + | ty::RePlaceholder(..) + | ty::ReBound(..) + | ty::ReErased + | ty::ReError(..) => false, } } @@ -1990,21 +1990,21 @@ impl<'tcx> Ty<'tcx> { Ty::new(tcx, Error(reported)) } - /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used. + /// Constructs a `TyKind::Error` type and registers a `span_delayed_bug` to ensure it gets used. #[track_caller] pub fn new_misc_error(tcx: TyCtxt<'tcx>) -> Ty<'tcx> { Ty::new_error_with_message(tcx, DUMMY_SP, "TyKind::Error constructed but no error reported") } - /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg` to + /// Constructs a `TyKind::Error` type and registers a `span_delayed_bug` with the given `msg` to /// ensure it gets used. #[track_caller] pub fn new_error_with_message<S: Into<MultiSpan>>( tcx: TyCtxt<'tcx>, span: S, - msg: impl Into<String>, + msg: impl Into<DiagnosticMessage>, ) -> Ty<'tcx> { - let reported = tcx.sess.delay_span_bug(span, msg); + let reported = tcx.sess.span_delayed_bug(span, msg); Ty::new(tcx, Error(reported)) } @@ -2104,7 +2104,7 @@ impl<'tcx> Ty<'tcx> { #[inline] pub fn new_tup(tcx: TyCtxt<'tcx>, ts: &[Ty<'tcx>]) -> Ty<'tcx> { - if ts.is_empty() { tcx.types.unit } else { Ty::new(tcx, Tuple(tcx.mk_type_list(&ts))) } + if ts.is_empty() { tcx.types.unit } else { Ty::new(tcx, Tuple(tcx.mk_type_list(ts))) } } pub fn new_tup_from_iter<I, T>(tcx: TyCtxt<'tcx>, iter: I) -> T::Output @@ -2260,7 +2260,7 @@ impl<'tcx> Ty<'tcx> { impl<'tcx> Ty<'tcx> { #[inline(always)] pub fn kind(self) -> &'tcx TyKind<'tcx> { - &self.0.0 + self.0.0 } #[inline(always)] @@ -2271,7 +2271,7 @@ impl<'tcx> Ty<'tcx> { #[inline] pub fn is_unit(self) -> bool { match self.kind() { - Tuple(ref tys) => tys.is_empty(), + Tuple(tys) => tys.is_empty(), _ => false, } } @@ -2813,6 +2813,15 @@ impl<'tcx> Ty<'tcx> { } } + /// Inverse of [`Ty::to_opt_closure_kind`]. + pub fn from_closure_kind(tcx: TyCtxt<'tcx>, kind: ty::ClosureKind) -> Ty<'tcx> { + match kind { + ty::ClosureKind::Fn => tcx.types.i8, + ty::ClosureKind::FnMut => tcx.types.i16, + ty::ClosureKind::FnOnce => tcx.types.i32, + } + } + /// Fast path helper for testing if a type is `Sized`. /// /// Returning true means the type is known to be sized. Returning diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index e9240d1b2..d372c1cd6 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -126,7 +126,7 @@ pub struct TypeckResults<'tcx> { /// fn(&'a u32) -> u32 /// ``` /// - /// Note that `'a` is not bound (it would be an `ReFree`) and + /// Note that `'a` is not bound (it would be an `ReLateParam`) and /// that the `Foo` opaque type is replaced by its hidden type. liberated_fn_sigs: ItemLocalMap<ty::FnSig<'tcx>>, @@ -241,7 +241,7 @@ impl<'tcx> TypeckResults<'tcx> { /// Returns the final resolution of a `QPath` in an `Expr` or `Pat` node. pub fn qpath_res(&self, qpath: &hir::QPath<'_>, id: hir::HirId) -> Res { match *qpath { - hir::QPath::Resolved(_, ref path) => path.res, + hir::QPath::Resolved(_, path) => path.res, hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self .type_dependent_def(id) .map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), @@ -391,7 +391,7 @@ impl<'tcx> TypeckResults<'tcx> { pub fn extract_binding_mode(&self, s: &Session, id: HirId, sp: Span) -> Option<BindingMode> { self.pat_binding_modes().get(id).copied().or_else(|| { - s.delay_span_bug(sp, "missing binding mode"); + s.span_delayed_bug(sp, "missing binding mode"); None }) } @@ -578,6 +578,7 @@ impl<'a, V> LocalTableInContextMut<'a, V> { rustc_index::newtype_index! { #[derive(HashStable)] + #[encodable] #[debug_format = "UserType({})"] pub struct UserTypeAnnotationIndex { const START_INDEX = 0; @@ -638,7 +639,7 @@ impl<'tcx> IsIdentity for CanonicalUserType<'tcx> { }, GenericArgKind::Lifetime(r) => match *r { - ty::ReLateBound(debruijn, br) => { + ty::ReBound(debruijn, br) => { // We only allow a `ty::INNERMOST` index in substitutions. assert_eq!(debruijn, ty::INNERMOST); cvar == br.var diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index a251518d1..8b2b76764 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -35,12 +35,14 @@ pub struct Discr<'tcx> { #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum CheckRegions { No, - /// Only permit early bound regions. This is useful for Adts which - /// can never have late bound regions. - OnlyEarlyBound, - /// Permit both late bound and early bound regions. Use this for functions, - /// which frequently have late bound regions. - Bound, + /// Only permit parameter regions. This should be used + /// for everything apart from functions, which may use + /// `ReBound` to represent late-bound regions. + OnlyParam, + /// Check region parameters from a function definition. + /// Allows `ReEarlyParam` and `ReBound` to handle early + /// and late-bound region parameters. + FromFunction, } #[derive(Copy, Clone, Debug)] @@ -359,7 +361,7 @@ impl<'tcx> TyCtxt<'tcx> { let Some(item_id) = self.associated_item_def_ids(impl_did).first() else { self.sess - .delay_span_bug(self.def_span(impl_did), "Drop impl without drop function"); + .span_delayed_bug(self.def_span(impl_did), "Drop impl without drop function"); return; }; @@ -419,19 +421,16 @@ impl<'tcx> TyCtxt<'tcx> { let impl_args = match *self.type_of(impl_def_id).instantiate_identity().kind() { ty::Adt(def_, args) if def_ == def => args, - _ => bug!(), + _ => span_bug!(self.def_span(impl_def_id), "expected ADT for self type of `Drop` impl"), }; - let item_args = match *self.type_of(def.did()).instantiate_identity().kind() { - ty::Adt(def_, args) if def_ == def => args, - _ => bug!(), - }; + let item_args = ty::GenericArgs::identity_for_item(self, def.did()); let result = iter::zip(item_args, impl_args) .filter(|&(_, k)| { match k.unpack() { GenericArgKind::Lifetime(region) => match region.kind() { - ty::ReEarlyBound(ref ebr) => { + ty::ReEarlyParam(ref ebr) => { !impl_generics.region_param(ebr, self).pure_wrt_drop } // Error: not a region param @@ -468,17 +467,17 @@ impl<'tcx> TyCtxt<'tcx> { for arg in args { match arg.unpack() { GenericArgKind::Lifetime(lt) => match (ignore_regions, lt.kind()) { - (CheckRegions::Bound, ty::ReLateBound(di, reg)) => { + (CheckRegions::FromFunction, ty::ReBound(di, reg)) => { if !seen_late.insert((di, reg)) { return Err(NotUniqueParam::DuplicateParam(lt.into())); } } - (CheckRegions::OnlyEarlyBound | CheckRegions::Bound, ty::ReEarlyBound(p)) => { + (CheckRegions::OnlyParam | CheckRegions::FromFunction, ty::ReEarlyParam(p)) => { if !seen.insert(p.index) { return Err(NotUniqueParam::DuplicateParam(lt.into())); } } - (CheckRegions::OnlyEarlyBound | CheckRegions::Bound, _) => { + (CheckRegions::OnlyParam | CheckRegions::FromFunction, _) => { return Err(NotUniqueParam::NotParam(lt.into())); } (CheckRegions::No, _) => {} @@ -548,16 +547,13 @@ impl<'tcx> TyCtxt<'tcx> { /// those are not yet phased out). The parent of the closure's /// `DefId` will also be the context where it appears. pub fn is_closure(self, def_id: DefId) -> bool { - matches!(self.def_kind(def_id), DefKind::Closure | DefKind::Coroutine) + matches!(self.def_kind(def_id), DefKind::Closure) } /// Returns `true` if `def_id` refers to a definition that does not have its own /// type-checking context, i.e. closure, coroutine or inline const. pub fn is_typeck_child(self, def_id: DefId) -> bool { - matches!( - self.def_kind(def_id), - DefKind::Closure | DefKind::Coroutine | DefKind::InlineConst - ) + matches!(self.def_kind(def_id), DefKind::Closure | DefKind::InlineConst) } /// Returns `true` if `def_id` refers to a trait (i.e., `trait Foo { ... }`). @@ -699,22 +695,6 @@ impl<'tcx> TyCtxt<'tcx> { .map(|decl| ty::EarlyBinder::bind(decl.ty)) } - /// Normalizes all opaque types in the given value, replacing them - /// with their underlying types. - pub fn expand_opaque_types(self, val: Ty<'tcx>) -> Ty<'tcx> { - let mut visitor = OpaqueTypeExpander { - seen_opaque_tys: FxHashSet::default(), - expanded_cache: FxHashMap::default(), - primary_def_id: None, - found_recursion: false, - found_any_recursion: false, - check_recursion: false, - expand_coroutines: false, - tcx: self, - }; - val.fold_with(&mut visitor) - } - /// Expands the given impl trait type, stopping if the type is recursive. #[instrument(skip(self), level = "debug", ret)] pub fn try_expand_impl_trait_type( @@ -746,11 +726,14 @@ impl<'tcx> TyCtxt<'tcx> { pub fn def_kind_descr(self, def_kind: DefKind, def_id: DefId) -> &'static str { match def_kind { DefKind::AssocFn if self.associated_item(def_id).fn_has_self_parameter => "method", - DefKind::Coroutine => match self.coroutine_kind(def_id).unwrap() { - rustc_hir::CoroutineKind::Async(..) => "async closure", - rustc_hir::CoroutineKind::Coroutine => "coroutine", - rustc_hir::CoroutineKind::Gen(..) => "gen closure", - }, + DefKind::Closure if let Some(coroutine_kind) = self.coroutine_kind(def_id) => { + match coroutine_kind { + rustc_hir::CoroutineKind::Async(..) => "async closure", + rustc_hir::CoroutineKind::AsyncGen(..) => "async gen closure", + rustc_hir::CoroutineKind::Coroutine => "coroutine", + rustc_hir::CoroutineKind::Gen(..) => "gen closure", + } + } _ => def_kind.descr(def_id), } } @@ -764,11 +747,14 @@ impl<'tcx> TyCtxt<'tcx> { pub fn def_kind_descr_article(self, def_kind: DefKind, def_id: DefId) -> &'static str { match def_kind { DefKind::AssocFn if self.associated_item(def_id).fn_has_self_parameter => "a", - DefKind::Coroutine => match self.coroutine_kind(def_id).unwrap() { - rustc_hir::CoroutineKind::Async(..) => "an", - rustc_hir::CoroutineKind::Coroutine => "a", - rustc_hir::CoroutineKind::Gen(..) => "a", - }, + DefKind::Closure if let Some(coroutine_kind) = self.coroutine_kind(def_id) => { + match coroutine_kind { + rustc_hir::CoroutineKind::Async(..) => "an", + rustc_hir::CoroutineKind::AsyncGen(..) => "an", + rustc_hir::CoroutineKind::Coroutine => "a", + rustc_hir::CoroutineKind::Gen(..) => "a", + } + } _ => def_kind.article(), } } @@ -790,7 +776,60 @@ impl<'tcx> TyCtxt<'tcx> { // If `extern_crate` is `None`, then the crate was injected (e.g., by the allocator). // Treat that kind of crate as "indirect", since it's an implementation detail of // the language. - || self.extern_crate(key.as_def_id()).map_or(false, |e| e.is_direct()) + || self.extern_crate(key.as_def_id()).is_some_and(|e| e.is_direct()) + } + + pub fn expected_host_effect_param_for_body(self, def_id: impl Into<DefId>) -> ty::Const<'tcx> { + let def_id = def_id.into(); + // FIXME(effects): This is suspicious and should probably not be done, + // especially now that we enforce host effects and then properly handle + // effect vars during fallback. + let mut host_always_on = + !self.features().effects || self.sess.opts.unstable_opts.unleash_the_miri_inside_of_you; + + // Compute the constness required by the context. + let const_context = self.hir().body_const_context(def_id); + + let kind = self.def_kind(def_id); + debug_assert_ne!(kind, DefKind::ConstParam); + + if self.has_attr(def_id, sym::rustc_do_not_const_check) { + trace!("do not const check this context"); + host_always_on = true; + } + + match const_context { + _ if host_always_on => self.consts.true_, + Some(hir::ConstContext::Static(_) | hir::ConstContext::Const { .. }) => { + self.consts.false_ + } + Some(hir::ConstContext::ConstFn) => { + let host_idx = self + .generics_of(def_id) + .host_effect_index + .expect("ConstContext::Maybe must have host effect param"); + ty::GenericArgs::identity_for_item(self, def_id).const_at(host_idx) + } + None => self.consts.true_, + } + } + + /// Constructs generic args for an item, optionally appending a const effect param type + pub fn with_opt_host_effect_param( + self, + caller_def_id: LocalDefId, + callee_def_id: DefId, + args: impl IntoIterator<Item: Into<ty::GenericArg<'tcx>>>, + ) -> ty::GenericArgsRef<'tcx> { + let generics = self.generics_of(callee_def_id); + assert_eq!(generics.parent, None); + + let opt_const_param = generics + .host_effect_index + .is_some() + .then(|| ty::GenericArg::from(self.expected_host_effect_param_for_body(caller_def_id))); + + self.mk_args_from_iter(args.into_iter().map(|arg| arg.into()).chain(opt_const_param)) } } diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index 8fc5c0302..e1ce94125 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -1,4 +1,4 @@ -use crate::ty::{self, flags::FlagComputation, Binder, Ty, TyCtxt, TypeFlags}; +use crate::ty::{self, Binder, Ty, TyCtxt, TypeFlags}; use rustc_errors::ErrorGuaranteed; use rustc_data_structures::fx::FxHashSet; @@ -111,16 +111,16 @@ pub trait TypeVisitableExt<'tcx>: TypeVisitable<TyCtxt<'tcx>> { } /// True if there are any late-bound regions - fn has_late_bound_regions(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND) + fn has_bound_regions(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_RE_BOUND) } /// True if there are any late-bound non-region variables - fn has_non_region_late_bound(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_LATE_BOUND - TypeFlags::HAS_RE_LATE_BOUND) + fn has_non_region_bound_vars(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_BOUND_VARS - TypeFlags::HAS_RE_BOUND) } - /// True if there are any late-bound variables - fn has_late_bound_vars(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_LATE_BOUND) + /// True if there are any bound variables + fn has_bound_vars(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_BOUND_VARS) } /// Indicates whether this value still has parameters/placeholders/inference variables @@ -204,7 +204,7 @@ impl<'tcx> TyCtxt<'tcx> { fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { match *r { - ty::ReLateBound(debruijn, _) if debruijn < self.outer_index => { + ty::ReBound(debruijn, _) if debruijn < self.outer_index => { ControlFlow::Continue(()) } _ => { @@ -337,7 +337,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ValidateBoundVars<'tcx> { fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { match *r { - ty::ReLateBound(index, br) if index == self.binder_index => { + ty::ReBound(index, br) if index == self.binder_index => { if self.bound_vars.len() <= br.var.as_usize() { bug!("Not enough bound vars: {:?} not found in {:?}", br, self.bound_vars); } @@ -440,16 +440,15 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasEscapingVarsVisitor { } fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { - // we don't have a `visit_infer_const` callback, so we have to - // hook in here to catch this case (annoying...), but - // otherwise we do want to remember to visit the rest of the - // const, as it has types/regions embedded in a lot of other - // places. - match ct.kind() { - ty::ConstKind::Bound(debruijn, _) if debruijn >= self.outer_index => { - ControlFlow::Break(FoundEscapingVars) - } - _ => ct.super_visit_with(self), + // If the outer-exclusive-binder is *strictly greater* than + // `outer_index`, that means that `ct` contains some content + // bound at `outer_index` or above (because + // `outer_exclusive_binder` is always 1 higher than the + // content in `t`). Therefore, `t` has some escaping vars. + if ct.outer_exclusive_binder() > self.outer_index { + ControlFlow::Break(FoundEscapingVars) + } else { + ControlFlow::Continue(()) } } @@ -529,9 +528,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasTypeFlagsVisitor { #[inline] fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { // Note: no `super_visit_with` call. - let flags = FlagComputation::for_const(c); - trace!(r.flags=?flags); - if flags.intersects(self.flags) { + if c.flags().intersects(self.flags) { ControlFlow::Break(FoundFlags) } else { ControlFlow::Continue(()) @@ -613,7 +610,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for LateBoundRegionsCollector { } fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { - if let ty::ReLateBound(debruijn, br) = *r { + if let ty::ReBound(debruijn, br) = *r { if debruijn == self.current_index { self.regions.insert(br.kind); } |