diff options
Diffstat (limited to 'compiler/rustc_middle/src/ty')
36 files changed, 1436 insertions, 1298 deletions
diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs index e6aab30a1..cd147d7e5 100644 --- a/compiler/rustc_middle/src/ty/_match.rs +++ b/compiler/rustc_middle/src/ty/_match.rs @@ -36,6 +36,11 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } + + fn intercrate(&self) -> bool { + false + } + fn param_env(&self) -> ty::ParamEnv<'tcx> { self.param_env } @@ -43,6 +48,10 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> { true } // irrelevant + fn mark_ambiguous(&mut self) { + bug!() + } + fn relate_with_variance<T: Relate<'tcx>>( &mut self, _: ty::Variance, diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs index 1aa4df778..5de758ad9 100644 --- a/compiler/rustc_middle/src/ty/abstract_const.rs +++ b/compiler/rustc_middle/src/ty/abstract_const.rs @@ -1,98 +1,13 @@ //! A subset of a mir body used for const evaluatability checking. -use crate::mir; -use crate::ty::visit::TypeVisitable; -use crate::ty::{self, DelaySpanBugEmitted, EarlyBinder, SubstsRef, Ty, TyCtxt}; +use crate::ty::{ + self, Const, EarlyBinder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, + TypeVisitable, +}; use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::DefId; -use std::cmp; -use std::ops::ControlFlow; -rustc_index::newtype_index! { - /// An index into an `AbstractConst`. - pub struct NodeId { - derive [HashStable] - DEBUG_FORMAT = "n{}", - } -} - -/// A tree representing an anonymous constant. -/// -/// This is only able to represent a subset of `MIR`, -/// and should not leak any information about desugarings. -#[derive(Debug, Clone, Copy)] -pub struct AbstractConst<'tcx> { - // FIXME: Consider adding something like `IndexSlice` - // and use this here. - inner: &'tcx [Node<'tcx>], - substs: SubstsRef<'tcx>, -} - -impl<'tcx> AbstractConst<'tcx> { - pub fn new( - tcx: TyCtxt<'tcx>, - uv: ty::UnevaluatedConst<'tcx>, - ) -> Result<Option<AbstractConst<'tcx>>, ErrorGuaranteed> { - let inner = tcx.thir_abstract_const_opt_const_arg(uv.def)?; - debug!("AbstractConst::new({:?}) = {:?}", uv, inner); - Ok(inner.map(|inner| AbstractConst { inner, substs: tcx.erase_regions(uv.substs) })) - } - - pub fn from_const( - tcx: TyCtxt<'tcx>, - ct: ty::Const<'tcx>, - ) -> Result<Option<AbstractConst<'tcx>>, ErrorGuaranteed> { - match ct.kind() { - ty::ConstKind::Unevaluated(uv) => AbstractConst::new(tcx, uv), - ty::ConstKind::Error(DelaySpanBugEmitted { reported, .. }) => Err(reported), - _ => Ok(None), - } - } - - #[inline] - pub fn subtree(self, node: NodeId) -> AbstractConst<'tcx> { - AbstractConst { inner: &self.inner[..=node.index()], substs: self.substs } - } - - #[inline] - pub fn root(self, tcx: TyCtxt<'tcx>) -> Node<'tcx> { - let node = self.inner.last().copied().unwrap(); - match node { - Node::Leaf(leaf) => Node::Leaf(EarlyBinder(leaf).subst(tcx, self.substs)), - Node::Cast(kind, operand, ty) => { - Node::Cast(kind, operand, EarlyBinder(ty).subst(tcx, self.substs)) - } - // Don't perform substitution on the following as they can't directly contain generic params - Node::Binop(_, _, _) | Node::UnaryOp(_, _) | Node::FunctionCall(_, _) => node, - } - } - - pub fn unify_failure_kind(self, tcx: TyCtxt<'tcx>) -> FailureKind { - let mut failure_kind = FailureKind::Concrete; - walk_abstract_const::<!, _>(tcx, self, |node| { - match node.root(tcx) { - Node::Leaf(leaf) => { - if leaf.has_non_region_infer() { - failure_kind = FailureKind::MentionsInfer; - } else if leaf.has_non_region_param() { - failure_kind = cmp::min(failure_kind, FailureKind::MentionsParam); - } - } - Node::Cast(_, _, ty) => { - if ty.has_non_region_infer() { - failure_kind = FailureKind::MentionsInfer; - } else if ty.has_non_region_param() { - failure_kind = cmp::min(failure_kind, FailureKind::MentionsParam); - } - } - Node::Binop(_, _, _) | Node::UnaryOp(_, _) | Node::FunctionCall(_, _) => {} - } - ControlFlow::CONTINUE - }); - failure_kind - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] +#[derive(Hash, Debug, Clone, Copy, Ord, PartialOrd, PartialEq, Eq)] +#[derive(TyDecodable, TyEncodable, HashStable, TypeVisitable, TypeFoldable)] pub enum CastKind { /// thir::ExprKind::As As, @@ -100,16 +15,6 @@ pub enum CastKind { Use, } -/// A node of an `AbstractConst`. -#[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] -pub enum Node<'tcx> { - Leaf(ty::Const<'tcx>), - Binop(mir::BinOp, NodeId, NodeId), - UnaryOp(mir::UnOp, NodeId), - FunctionCall(NodeId, &'tcx [NodeId]), - Cast(CastKind, NodeId, Ty<'tcx>), -} - #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] pub enum NotConstEvaluatable { Error(ErrorGuaranteed), @@ -127,68 +32,53 @@ TrivialTypeTraversalAndLiftImpls! { NotConstEvaluatable, } +pub type BoundAbstractConst<'tcx> = Result<Option<EarlyBinder<ty::Const<'tcx>>>, ErrorGuaranteed>; + impl<'tcx> TyCtxt<'tcx> { - #[inline] - pub fn thir_abstract_const_opt_const_arg( + /// Returns a const without substs applied + pub fn bound_abstract_const( self, - def: ty::WithOptConstParam<DefId>, - ) -> Result<Option<&'tcx [Node<'tcx>]>, ErrorGuaranteed> { - if let Some((did, param_did)) = def.as_const_arg() { + uv: ty::WithOptConstParam<DefId>, + ) -> BoundAbstractConst<'tcx> { + let ac = if let Some((did, param_did)) = uv.as_const_arg() { self.thir_abstract_const_of_const_arg((did, param_did)) } else { - self.thir_abstract_const(def.did) - } + self.thir_abstract_const(uv.did) + }; + Ok(ac?.map(|ac| EarlyBinder(ac))) } -} -#[instrument(skip(tcx, f), level = "debug")] -pub fn walk_abstract_const<'tcx, R, F>( - tcx: TyCtxt<'tcx>, - ct: AbstractConst<'tcx>, - mut f: F, -) -> ControlFlow<R> -where - F: FnMut(AbstractConst<'tcx>) -> ControlFlow<R>, -{ - #[instrument(skip(tcx, f), level = "debug")] - fn recurse<'tcx, R>( - tcx: TyCtxt<'tcx>, - ct: AbstractConst<'tcx>, - f: &mut dyn FnMut(AbstractConst<'tcx>) -> ControlFlow<R>, - ) -> ControlFlow<R> { - f(ct)?; - let root = ct.root(tcx); - debug!(?root); - match root { - Node::Leaf(_) => ControlFlow::CONTINUE, - Node::Binop(_, l, r) => { - recurse(tcx, ct.subtree(l), f)?; - recurse(tcx, ct.subtree(r), f) + pub fn expand_abstract_consts<T: TypeFoldable<'tcx>>(self, ac: T) -> T { + struct Expander<'tcx> { + tcx: TyCtxt<'tcx>, + } + + impl<'tcx> TypeFolder<'tcx> for Expander<'tcx> { + fn tcx(&self) -> TyCtxt<'tcx> { + self.tcx } - Node::UnaryOp(_, v) => recurse(tcx, ct.subtree(v), f), - Node::FunctionCall(func, args) => { - recurse(tcx, ct.subtree(func), f)?; - args.iter().try_for_each(|&arg| recurse(tcx, ct.subtree(arg), f)) + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + if ty.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) { + ty.super_fold_with(self) + } else { + ty + } + } + fn fold_const(&mut self, c: Const<'tcx>) -> Const<'tcx> { + let ct = match c.kind() { + ty::ConstKind::Unevaluated(uv) => match self.tcx.bound_abstract_const(uv.def) { + Err(e) => self.tcx.const_error_with_guaranteed(c.ty(), e), + Ok(Some(bac)) => { + let substs = self.tcx.erase_regions(uv.substs); + bac.subst(self.tcx, substs) + } + Ok(None) => c, + }, + _ => c, + }; + ct.super_fold_with(self) } - Node::Cast(_, operand, _) => recurse(tcx, ct.subtree(operand), f), } + ac.fold_with(&mut Expander { tcx: self }) } - - recurse(tcx, ct, &mut f) -} - -// We were unable to unify the abstract constant with -// a constant found in the caller bounds, there are -// now three possible cases here. -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] -pub enum FailureKind { - /// The abstract const still references an inference - /// variable, in this case we return `TooGeneric`. - MentionsInfer, - /// The abstract const references a generic parameter, - /// this means that we emit an error here. - MentionsParam, - /// The substs are concrete enough that we can simply - /// try and evaluate the given constant. - Concrete, } diff --git a/compiler/rustc_middle/src/ty/adjustment.rs b/compiler/rustc_middle/src/ty/adjustment.rs index 4682ac96b..7036c4a7b 100644 --- a/compiler/rustc_middle/src/ty/adjustment.rs +++ b/compiler/rustc_middle/src/ty/adjustment.rs @@ -1,7 +1,5 @@ -use crate::ty::subst::SubstsRef; use crate::ty::{self, Ty, TyCtxt}; use rustc_hir as hir; -use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_macros::HashStable; use rustc_span::Span; @@ -121,7 +119,8 @@ pub struct OverloadedDeref<'tcx> { } impl<'tcx> OverloadedDeref<'tcx> { - pub fn method_call(&self, tcx: TyCtxt<'tcx>, source: Ty<'tcx>) -> (DefId, SubstsRef<'tcx>) { + /// Get the zst function item type for this method call. + pub fn method_call(&self, tcx: TyCtxt<'tcx>, source: Ty<'tcx>) -> Ty<'tcx> { let trait_def_id = match self.mutbl { hir::Mutability::Not => tcx.require_lang_item(LangItem::Deref, None), hir::Mutability::Mut => tcx.require_lang_item(LangItem::DerefMut, None), @@ -132,7 +131,7 @@ impl<'tcx> OverloadedDeref<'tcx> { .find(|m| m.kind == ty::AssocKind::Fn) .unwrap() .def_id; - (method_def_id, tcx.mk_substs_trait(source, &[])) + tcx.mk_fn_def(method_def_id, tcx.mk_substs_trait(source, [])) } } @@ -160,6 +159,18 @@ pub enum AutoBorrowMutability { Not, } +impl AutoBorrowMutability { + /// Creates an `AutoBorrowMutability` from a mutability and allowance of two phase borrows. + /// + /// Note that when `mutbl.is_not()`, `allow_two_phase_borrow` is ignored + pub fn new(mutbl: hir::Mutability, allow_two_phase_borrow: AllowTwoPhase) -> Self { + match mutbl { + hir::Mutability::Not => Self::Not, + hir::Mutability::Mut => Self::Mut { allow_two_phase_borrow }, + } + } +} + impl From<AutoBorrowMutability> for hir::Mutability { fn from(m: AutoBorrowMutability) -> Self { match m { diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index b0a2412ab..d3d667f68 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -14,7 +14,7 @@ use rustc_index::vec::{Idx, IndexVec}; use rustc_query_system::ich::StableHashingContext; use rustc_session::DataTypeKind; use rustc_span::symbol::sym; -use rustc_target::abi::VariantIdx; +use rustc_target::abi::{ReprOptions, VariantIdx}; use std::cell::RefCell; use std::cmp::Ordering; @@ -22,9 +22,7 @@ use std::hash::{Hash, Hasher}; use std::ops::Range; use std::str; -use super::{ - Destructor, FieldDef, GenericPredicates, ReprOptions, Ty, TyCtxt, VariantDef, VariantDiscr, -}; +use super::{Destructor, FieldDef, GenericPredicates, Ty, TyCtxt, VariantDef, VariantDiscr}; bitflags! { #[derive(HashStable, TyEncodable, TyDecodable)] @@ -230,7 +228,7 @@ impl AdtDefData { AdtKind::Struct => AdtFlags::IS_STRUCT, }; - if kind == AdtKind::Struct && variants[VariantIdx::new(0)].ctor_def_id.is_some() { + if kind == AdtKind::Struct && variants[VariantIdx::new(0)].ctor.is_some() { flags |= AdtFlags::HAS_CTOR; } @@ -386,11 +384,9 @@ impl<'tcx> AdtDef<'tcx> { // Baz = 3, // } // ``` - if self - .variants() - .iter() - .any(|v| matches!(v.discr, VariantDiscr::Explicit(_)) && v.ctor_kind != CtorKind::Const) - { + if self.variants().iter().any(|v| { + matches!(v.discr, VariantDiscr::Explicit(_)) && v.ctor_kind() != Some(CtorKind::Const) + }) { return false; } self.variants().iter().all(|v| v.fields.is_empty()) @@ -405,7 +401,7 @@ impl<'tcx> AdtDef<'tcx> { pub fn variant_with_ctor_id(self, cid: DefId) -> &'tcx VariantDef { self.variants() .iter() - .find(|v| v.ctor_def_id == Some(cid)) + .find(|v| v.ctor_def_id() == Some(cid)) .expect("variant_with_ctor_id: unknown variant") } @@ -422,7 +418,7 @@ impl<'tcx> AdtDef<'tcx> { pub fn variant_index_with_ctor_id(self, cid: DefId) -> VariantIdx { self.variants() .iter_enumerated() - .find(|(_, v)| v.ctor_def_id == Some(cid)) + .find(|(_, v)| v.ctor_def_id() == Some(cid)) .expect("variant_index_with_ctor_id: unknown variant") .0 } @@ -463,9 +459,7 @@ impl<'tcx> AdtDef<'tcx> { } Err(err) => { let msg = match err { - ErrorHandled::Reported(_) | ErrorHandled::Linted => { - "enum discriminant evaluation failed" - } + ErrorHandled::Reported(_) => "enum discriminant evaluation failed", ErrorHandled::TooGeneric => "enum discriminant depends on generics", }; tcx.sess.delay_span_bug(tcx.def_span(expr_did), msg); diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index 0d6c26a58..d00553cba 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs @@ -5,6 +5,7 @@ use crate::{mir, ty}; use std::fmt::Write; +use hir::LangItem; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -14,8 +15,8 @@ use super::{Ty, TyCtxt}; use self::BorrowKind::*; -// Captures are represented using fields inside a structure. -// This represents accessing self in the closure structure +/// Captures are represented using fields inside a structure. +/// This represents accessing self in the closure structure pub const CAPTURE_STRUCT_LOCAL: mir::Local = mir::Local::from_u32(1); #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] @@ -90,20 +91,26 @@ pub enum ClosureKind { } impl<'tcx> ClosureKind { - // This is the initial value used when doing upvar inference. + /// This is the initial value used when doing upvar inference. pub const LATTICE_BOTTOM: ClosureKind = ClosureKind::Fn; /// Returns `true` if a type that impls this closure kind /// must also implement `other`. pub fn extends(self, other: ty::ClosureKind) -> bool { - matches!( - (self, other), - (ClosureKind::Fn, ClosureKind::Fn) - | (ClosureKind::Fn, ClosureKind::FnMut) - | (ClosureKind::Fn, ClosureKind::FnOnce) - | (ClosureKind::FnMut, ClosureKind::FnMut) - | (ClosureKind::FnMut, ClosureKind::FnOnce) - | (ClosureKind::FnOnce, ClosureKind::FnOnce) + 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, ) } @@ -116,26 +123,6 @@ impl<'tcx> ClosureKind { ClosureKind::FnOnce => tcx.types.i32, } } - - pub fn from_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ClosureKind> { - if Some(def_id) == tcx.lang_items().fn_once_trait() { - Some(ClosureKind::FnOnce) - } else if Some(def_id) == tcx.lang_items().fn_mut_trait() { - Some(ClosureKind::FnMut) - } else if Some(def_id) == tcx.lang_items().fn_trait() { - Some(ClosureKind::Fn) - } else { - None - } - } - - pub fn to_def_id(&self, tcx: TyCtxt<'_>) -> DefId { - match self { - ClosureKind::Fn => tcx.lang_items().fn_once_trait().unwrap(), - ClosureKind::FnMut => tcx.lang_items().fn_mut_trait().unwrap(), - ClosureKind::FnOnce => tcx.lang_items().fn_trait().unwrap(), - } - } } /// A composite describing a `Place` that is captured by a closure. diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 14ec88b7e..75f2d45ea 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -298,7 +298,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<Ty } impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> - for ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>> + for ty::List<ty::PolyExistentialPredicate<'tcx>> { fn decode(decoder: &mut D) -> &'tcx Self { let len = decoder.read_usize(); @@ -310,7 +310,8 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Const<'tcx> { fn decode(decoder: &mut D) -> Self { - decoder.interner().mk_const(Decodable::decode(decoder)) + let consts: ty::ConstS<'tcx> = Decodable::decode(decoder); + decoder.interner().mk_const(consts.kind, consts.ty) } } @@ -344,9 +345,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> } } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> - for [ty::abstract_const::Node<'tcx>] -{ +impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for [(ty::Clause<'tcx>, Span)] { fn decode(decoder: &mut D) -> &'tcx Self { decoder.interner().arena.alloc_from_iter( (0..decoder.read_usize()).map(|_| Decodable::decode(decoder)).collect::<Vec<_>>(), @@ -355,30 +354,29 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> } impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> - for [ty::abstract_const::NodeId] + for ty::List<ty::BoundVariableKind> { fn decode(decoder: &mut D) -> &'tcx Self { - decoder.interner().arena.alloc_from_iter( - (0..decoder.read_usize()).map(|_| Decodable::decode(decoder)).collect::<Vec<_>>(), + let len = decoder.read_usize(); + decoder.interner().mk_bound_variable_kinds( + (0..len).map::<ty::BoundVariableKind, _>(|_| Decodable::decode(decoder)), ) } } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> - for ty::List<ty::BoundVariableKind> -{ +impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<ty::Const<'tcx>> { fn decode(decoder: &mut D) -> &'tcx Self { let len = decoder.read_usize(); - decoder.interner().mk_bound_variable_kinds( - (0..len).map::<ty::BoundVariableKind, _>(|_| Decodable::decode(decoder)), - ) + decoder + .interner() + .mk_const_list((0..len).map::<ty::Const<'tcx>, _>(|_| Decodable::decode(decoder))) } } impl_decodable_via_ref! { &'tcx ty::TypeckResults<'tcx>, &'tcx ty::List<Ty<'tcx>>, - &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>, + &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>, &'tcx traits::ImplSource<'tcx, ()>, &'tcx mir::Body<'tcx>, &'tcx mir::UnsafetyCheckResult, diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index f998e6083..c2be08e49 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -1,8 +1,6 @@ use crate::mir::interpret::LitToConstInput; -use crate::mir::ConstantKind; -use crate::ty::{self, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt}; +use crate::ty::{self, DefIdTree, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt}; use rustc_data_structures::intern::Interned; -use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_macros::HashStable; @@ -77,13 +75,13 @@ impl<'tcx> Const<'tcx> { match Self::try_eval_lit_or_param(tcx, ty, expr) { Some(v) => v, - None => tcx.mk_const(ty::ConstS { - kind: ty::ConstKind::Unevaluated(ty::UnevaluatedConst { + None => tcx.mk_const( + ty::UnevaluatedConst { def: def.to_global(), substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()), - }), + }, ty, - }), + ), } } @@ -132,27 +130,16 @@ impl<'tcx> Const<'tcx> { ExprKind::Path(QPath::Resolved(_, &Path { res: Res::Def(ConstParam, def_id), .. })) => { // Find the name and index of the const parameter by indexing the generics of // the parent item and construct a `ParamConst`. - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); - let item_id = tcx.hir().get_parent_node(hir_id); - let item_def_id = tcx.hir().local_def_id(item_id); - let generics = tcx.generics_of(item_def_id.to_def_id()); + let item_def_id = tcx.parent(def_id); + let generics = tcx.generics_of(item_def_id); let index = generics.param_def_id_to_index[&def_id]; - let name = tcx.hir().name(hir_id); - Some(tcx.mk_const(ty::ConstS { - kind: ty::ConstKind::Param(ty::ParamConst::new(index, name)), - ty, - })) + let name = tcx.item_name(def_id); + Some(tcx.mk_const(ty::ParamConst::new(index, name), ty)) } _ => None, } } - /// Interns the given value as a constant. - #[inline] - pub fn from_value(tcx: TyCtxt<'tcx>, val: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> Self { - tcx.mk_const(ConstS { kind: ConstKind::Value(val), ty }) - } - /// Panics if self.kind != ty::ConstKind::Value pub fn to_valtree(self) -> ty::ValTree<'tcx> { match self.kind() { @@ -161,11 +148,6 @@ impl<'tcx> Const<'tcx> { } } - pub fn from_scalar_int(tcx: TyCtxt<'tcx>, i: ScalarInt, ty: Ty<'tcx>) -> Self { - let valtree = ty::ValTree::from_scalar_int(i); - Self::from_value(tcx, valtree, ty) - } - #[inline] /// Creates a constant with the given integer value and interns it. pub fn from_bits(tcx: TyCtxt<'tcx>, bits: u128, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> Self { @@ -173,14 +155,16 @@ impl<'tcx> Const<'tcx> { .layout_of(ty) .unwrap_or_else(|e| panic!("could not compute layout for {:?}: {:?}", ty, e)) .size; - Self::from_scalar_int(tcx, ScalarInt::try_from_uint(bits, size).unwrap(), ty.value) + tcx.mk_const( + ty::ValTree::from_scalar_int(ScalarInt::try_from_uint(bits, size).unwrap()), + ty.value, + ) } #[inline] /// Creates an interned zst constant. pub fn zero_sized(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self { - let valtree = ty::ValTree::zst(); - Self::from_value(tcx, valtree, ty) + tcx.mk_const(ty::ValTree::zst(), ty) } #[inline] @@ -227,8 +211,8 @@ impl<'tcx> Const<'tcx> { pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Const<'tcx> { if let Some(val) = self.kind().try_eval_for_typeck(tcx, param_env) { match val { - Ok(val) => Const::from_value(tcx, val, self.ty()), - Err(ErrorGuaranteed { .. }) => tcx.const_error(self.ty()), + Ok(val) => tcx.mk_const(val, self.ty()), + Err(guar) => tcx.const_error_with_guaranteed(self.ty(), guar), } } else { // Either the constant isn't evaluatable or ValTree creation failed. @@ -237,20 +221,6 @@ impl<'tcx> Const<'tcx> { } #[inline] - /// Tries to evaluate the constant if it is `Unevaluated` and creates a ConstValue if the - /// evaluation succeeds. If it doesn't succeed, returns the unevaluated constant. - pub fn eval_for_mir(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> ConstantKind<'tcx> { - if let Some(val) = self.kind().try_eval_for_mir(tcx, param_env) { - match val { - Ok(const_val) => ConstantKind::from_value(const_val, self.ty()), - Err(ErrorGuaranteed { .. }) => ConstantKind::Ty(tcx.const_error(self.ty())), - } - } else { - ConstantKind::Ty(self) - } - } - - #[inline] /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type. pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> u128 { self.try_eval_bits(tcx, param_env, ty) @@ -272,9 +242,9 @@ impl<'tcx> Const<'tcx> { pub fn const_param_default<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Const<'tcx> { let default_def_id = match tcx.hir().get_by_def_id(def_id.expect_local()) { hir::Node::GenericParam(hir::GenericParam { - kind: hir::GenericParamKind::Const { ty: _, default: Some(ac) }, + kind: hir::GenericParamKind::Const { default: Some(ac), .. }, .. - }) => tcx.hir().local_def_id(ac.hir_id), + }) => ac.def_id, _ => span_bug!( tcx.def_span(def_id), "`const_param_default` expected a generic parameter with a constant" diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index 7436f0f6f..f3186e1c3 100644 --- a/compiler/rustc_middle/src/ty/consts/int.rs +++ b/compiler/rustc_middle/src/ty/consts/int.rs @@ -245,6 +245,18 @@ impl ScalarInt { self.to_bits(size) } + // Tries to convert the `ScalarInt` to `bool`. Fails if the `size` of the `ScalarInt` + // in not equal to `Size { raw: 1 }` or if the value is not 0 or 1 and returns the `size` + // value of the `ScalarInt` in that case. + #[inline] + pub fn try_to_bool(self) -> Result<bool, Size> { + match self.try_to_u8()? { + 0 => Ok(false), + 1 => Ok(true), + _ => Err(self.size()), + } + } + // Tries to convert the `ScalarInt` to `u8`. Fails if the `size` of the `ScalarInt` // in not equal to `Size { raw: 1 }` and returns the `size` value of the `ScalarInt` in // that case. diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index 4ab761e07..becc2b805 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -1,10 +1,12 @@ use std::convert::TryInto; +use super::Const; use crate::mir; use crate::mir::interpret::{AllocId, ConstValue, Scalar}; +use crate::ty::abstract_const::CastKind; use crate::ty::subst::{InternalSubsts, SubstsRef}; use crate::ty::ParamEnv; -use crate::ty::{self, TyCtxt, TypeVisitable}; +use crate::ty::{self, List, Ty, TyCtxt, TypeVisitable}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::DefId; @@ -47,6 +49,7 @@ impl<'tcx> UnevaluatedConst<'tcx> { /// Represents a constant in Rust. #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)] #[derive(Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(derive_more::From)] pub enum ConstKind<'tcx> { /// A const generic parameter. Param(ty::ParamConst), @@ -69,9 +72,31 @@ pub enum ConstKind<'tcx> { /// A placeholder for a const which could not be computed; this is /// propagated to avoid useless error messages. - Error(ty::DelaySpanBugEmitted), + #[from(ignore)] + Error(ErrorGuaranteed), + + /// Expr which contains an expression which has partially evaluated items. + Expr(Expr<'tcx>), +} + +impl<'tcx> From<ty::ConstVid<'tcx>> for ConstKind<'tcx> { + fn from(const_vid: ty::ConstVid<'tcx>) -> Self { + InferConst::Var(const_vid).into() + } } +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +#[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)] +pub enum Expr<'tcx> { + Binop(mir::BinOp, Const<'tcx>, Const<'tcx>), + UnOp(mir::UnOp, Const<'tcx>), + FunctionCall(Const<'tcx>, &'tcx List<Const<'tcx>>), + Cast(CastKind, Const<'tcx>, Ty<'tcx>), +} + +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] +static_assert_size!(Expr<'_>, 24); + #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(ConstKind<'_>, 32); @@ -226,7 +251,7 @@ impl<'tcx> ConstKind<'tcx> { // (which may be identity substs, see above), // can leak through `val` into the const we return. Ok(val) => Some(Ok(EvalResult::ValTree(val?))), - Err(ErrorHandled::TooGeneric | ErrorHandled::Linted) => None, + Err(ErrorHandled::TooGeneric) => None, Err(ErrorHandled::Reported(e)) => Some(Err(e)), } } @@ -237,7 +262,7 @@ impl<'tcx> ConstKind<'tcx> { // (which may be identity substs, see above), // can leak through `val` into the const we return. Ok(val) => Some(Ok(EvalResult::ConstVal(val))), - Err(ErrorHandled::TooGeneric | ErrorHandled::Linted) => None, + Err(ErrorHandled::TooGeneric) => None, Err(ErrorHandled::Reported(e)) => Some(Err(e)), } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 3d7e2a083..b44bc14ec 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1,5 +1,7 @@ //! Type context book-keeping. +#![allow(rustc::usage_of_ty_tykind)] + use crate::arena::Arena; use crate::dep_graph::{DepGraph, DepKindStruct}; use crate::hir::place::Place as HirPlace; @@ -17,17 +19,17 @@ use crate::traits; use crate::ty::query::{self, TyCtxtAt}; use crate::ty::{ self, AdtDef, AdtDefData, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig, - ClosureSizeProfileData, Const, ConstS, ConstVid, DefIdTree, ExistentialPredicate, FloatTy, - FloatVar, FloatVid, GenericParamDefKind, InferConst, InferTy, IntTy, IntVar, IntVid, List, - ParamConst, ParamTy, PolyFnSig, Predicate, PredicateKind, PredicateS, ProjectionTy, Region, - RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar, TyVid, TypeAndMut, UintTy, + ClosureSizeProfileData, Const, ConstS, DefIdTree, FloatTy, FloatVar, FloatVid, + GenericParamDefKind, InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy, + PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, ProjectionTy, Region, + RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, UintTy, Visibility, }; use crate::ty::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef, UserSubsts}; use rustc_ast as ast; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_data_structures::intern::{Interned, WithStableHash}; +use rustc_data_structures::intern::Interned; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap}; @@ -41,7 +43,7 @@ use rustc_errors::{ }; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, LOCAL_CRATE}; use rustc_hir::definitions::Definitions; use rustc_hir::hir_id::OwnerId; use rustc_hir::intravisit::Visitor; @@ -53,6 +55,7 @@ use rustc_hir::{ use rustc_index::vec::{Idx, IndexVec}; use rustc_macros::HashStable; use rustc_middle::mir::FakeReadCause; +use rustc_query_system::dep_graph::DepNodeIndex; use rustc_query_system::ich::StableHashingContext; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; use rustc_session::config::{CrateType, OutputFilenames}; @@ -67,6 +70,7 @@ use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{Layout, LayoutS, TargetDataLayout, VariantIdx}; use rustc_target::spec::abi; use rustc_type_ir::sty::TyKind::*; +use rustc_type_ir::WithCachedTypeInfo; use rustc_type_ir::{DynKind, InternAs, InternIteratorElement, Interner, TypeFlags}; use std::any::Any; @@ -80,7 +84,7 @@ use std::mem; use std::ops::{Bound, Deref}; use std::sync::Arc; -use super::{ImplPolarity, ResolverOutputs, RvalueScopes}; +use super::{ImplPolarity, RvalueScopes}; pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync { /// Creates a new `OnDiskCache` instance from the serialized data in `data`. @@ -109,7 +113,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type Mutability = hir::Mutability; type Movability = hir::Movability; type PolyFnSig = PolyFnSig<'tcx>; - type ListBinderExistentialPredicate = &'tcx List<Binder<'tcx, ExistentialPredicate<'tcx>>>; + type ListBinderExistentialPredicate = &'tcx List<PolyExistentialPredicate<'tcx>>; type BinderListTy = Binder<'tcx, &'tcx List<Ty<'tcx>>>; type ListTy = &'tcx List<Ty<'tcx>>; type ProjectionTy = ty::ProjectionTy<'tcx>; @@ -117,7 +121,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type BoundTy = ty::BoundTy; type PlaceholderType = ty::PlaceholderType; type InferTy = InferTy; - type DelaySpanBugEmitted = DelaySpanBugEmitted; + type ErrorGuaranteed = ErrorGuaranteed; type PredicateKind = ty::PredicateKind<'tcx>; type AllocId = crate::mir::interpret::AllocId; @@ -128,15 +132,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type PlaceholderRegion = ty::PlaceholderRegion; } -/// A type that is not publicly constructable. This prevents people from making [`TyKind::Error`]s -/// except through the error-reporting functions on a [`tcx`][TyCtxt]. -#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)] -#[derive(TyEncodable, TyDecodable, HashStable)] -pub struct DelaySpanBugEmitted { - pub reported: ErrorGuaranteed, - _priv: (), -} - type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>; pub struct CtxtInterners<'tcx> { @@ -145,20 +140,20 @@ pub struct CtxtInterners<'tcx> { // Specifically use a speedy hash algorithm for these hash sets, since // they're accessed quite often. - type_: InternedSet<'tcx, WithStableHash<TyS<'tcx>>>, + type_: InternedSet<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>, + const_lists: InternedSet<'tcx, List<ty::Const<'tcx>>>, substs: InternedSet<'tcx, InternalSubsts<'tcx>>, canonical_var_infos: InternedSet<'tcx, List<CanonicalVarInfo<'tcx>>>, region: InternedSet<'tcx, RegionKind<'tcx>>, - poly_existential_predicates: - InternedSet<'tcx, List<ty::Binder<'tcx, ExistentialPredicate<'tcx>>>>, - predicate: InternedSet<'tcx, PredicateS<'tcx>>, + poly_existential_predicates: InternedSet<'tcx, List<PolyExistentialPredicate<'tcx>>>, + predicate: InternedSet<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>, predicates: InternedSet<'tcx, List<Predicate<'tcx>>>, projs: InternedSet<'tcx, List<ProjectionKind>>, place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>, const_: InternedSet<'tcx, ConstS<'tcx>>, const_allocation: InternedSet<'tcx, Allocation>, bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>, - layout: InternedSet<'tcx, LayoutS<'tcx>>, + layout: InternedSet<'tcx, LayoutS<VariantIdx>>, adt_def: InternedSet<'tcx, AdtDefData>, } @@ -167,6 +162,7 @@ impl<'tcx> CtxtInterners<'tcx> { CtxtInterners { arena, type_: Default::default(), + const_lists: Default::default(), substs: Default::default(), region: Default::default(), poly_existential_predicates: Default::default(), @@ -198,53 +194,64 @@ impl<'tcx> CtxtInterners<'tcx> { self.type_ .intern(kind, |kind| { let flags = super::flags::FlagComputation::for_kind(&kind); + let stable_hash = + self.stable_hash(&flags, sess, definitions, cstore, source_span, &kind); - // It's impossible to hash inference variables (and will ICE), so we don't need to try to cache them. - // Without incremental, we rarely stable-hash types, so let's not do it proactively. - let stable_hash = if flags.flags.intersects(TypeFlags::NEEDS_INFER) - || sess.opts.incremental.is_none() - { - Fingerprint::ZERO - } else { - let mut hasher = StableHasher::new(); - let mut hcx = StableHashingContext::ignore_spans( - sess, - definitions, - cstore, - source_span, - ); - kind.hash_stable(&mut hcx, &mut hasher); - hasher.finish() - }; - - let ty_struct = TyS { - kind, + InternedInSet(self.arena.alloc(WithCachedTypeInfo { + internee: kind, + stable_hash, flags: flags.flags, outer_exclusive_binder: flags.outer_exclusive_binder, - }; - - InternedInSet( - self.arena.alloc(WithStableHash { internee: ty_struct, stable_hash }), - ) + })) }) .0, )) } + fn stable_hash<'a, T: HashStable<StableHashingContext<'a>>>( + &self, + flags: &ty::flags::FlagComputation, + sess: &'a Session, + definitions: &'a rustc_hir::definitions::Definitions, + cstore: &'a CrateStoreDyn, + source_span: &'a IndexVec<LocalDefId, Span>, + val: &T, + ) -> Fingerprint { + // It's impossible to hash inference variables (and will ICE), so we don't need to try to cache them. + // Without incremental, we rarely stable-hash types, so let's not do it proactively. + if flags.flags.intersects(TypeFlags::NEEDS_INFER) || sess.opts.incremental.is_none() { + Fingerprint::ZERO + } else { + let mut hasher = StableHasher::new(); + let mut hcx = StableHashingContext::new(sess, definitions, cstore, source_span); + val.hash_stable(&mut hcx, &mut hasher); + hasher.finish() + } + } + #[inline(never)] - fn intern_predicate(&self, kind: Binder<'tcx, PredicateKind<'tcx>>) -> Predicate<'tcx> { + fn intern_predicate( + &self, + kind: Binder<'tcx, PredicateKind<'tcx>>, + sess: &Session, + definitions: &rustc_hir::definitions::Definitions, + cstore: &CrateStoreDyn, + source_span: &IndexVec<LocalDefId, Span>, + ) -> Predicate<'tcx> { Predicate(Interned::new_unchecked( self.predicate .intern(kind, |kind| { let flags = super::flags::FlagComputation::for_predicate(kind); - let predicate_struct = PredicateS { - kind, + let stable_hash = + self.stable_hash(&flags, sess, definitions, cstore, source_span, &kind); + + InternedInSet(self.arena.alloc(WithCachedTypeInfo { + internee: kind, + stable_hash, flags: flags.flags, outer_exclusive_binder: flags.outer_exclusive_binder, - }; - - InternedInSet(self.arena.alloc(predicate_struct)) + })) }) .0, )) @@ -456,7 +463,7 @@ pub struct TypeckResults<'tcx> { /// Stores the canonicalized types provided by the user. See also /// `AscribeUserType` statement in MIR. - pub user_provided_sigs: DefIdMap<CanonicalPolyFnSig<'tcx>>, + pub user_provided_sigs: LocalDefIdMap<CanonicalPolyFnSig<'tcx>>, adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>, @@ -660,6 +667,14 @@ impl<'tcx> TypeckResults<'tcx> { LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.field_indices } } + pub fn field_index(&self, id: hir::HirId) -> usize { + self.field_indices().get(id).cloned().expect("no index for a field") + } + + pub fn opt_field_index(&self, id: hir::HirId) -> Option<usize> { + self.field_indices().get(id).cloned() + } + pub fn user_provided_types(&self) -> LocalTableInContext<'_, CanonicalUserType<'tcx>> { LocalTableInContext { hir_owner: self.hir_owner, data: &self.user_provided_types } } @@ -725,22 +740,24 @@ impl<'tcx> TypeckResults<'tcx> { self.node_substs.get(&id.local_id).cloned() } - // Returns the type of a pattern as a monotype. Like @expr_ty, this function - // doesn't provide type parameter substitutions. + /// Returns the type of a pattern as a monotype. Like [`expr_ty`], this function + /// doesn't provide type parameter substitutions. + /// + /// [`expr_ty`]: TypeckResults::expr_ty pub fn pat_ty(&self, pat: &hir::Pat<'_>) -> Ty<'tcx> { self.node_type(pat.hir_id) } - // Returns the type of an expression as a monotype. - // - // NB (1): This is the PRE-ADJUSTMENT TYPE for the expression. That is, in - // some cases, we insert `Adjustment` annotations such as auto-deref or - // auto-ref. The type returned by this function does not consider such - // adjustments. See `expr_ty_adjusted()` instead. - // - // NB (2): This type doesn't provide type parameter substitutions; e.g., if you - // ask for the type of "id" in "id(3)", it will return "fn(&isize) -> isize" - // instead of "fn(ty) -> T with T = isize". + /// Returns the type of an expression as a monotype. + /// + /// NB (1): This is the PRE-ADJUSTMENT TYPE for the expression. That is, in + /// some cases, we insert `Adjustment` annotations such as auto-deref or + /// auto-ref. The type returned by this function does not consider such + /// adjustments. See `expr_ty_adjusted()` instead. + /// + /// NB (2): This type doesn't provide type parameter substitutions; e.g., if you + /// ask for the type of `id` in `id(3)`, it will return `fn(&isize) -> isize` + /// instead of `fn(ty) -> T with T = isize`. pub fn expr_ty(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> { self.node_type(expr.hir_id) } @@ -1007,18 +1024,46 @@ impl<'tcx> CommonConsts<'tcx> { } } -// This struct contains information regarding the `ReFree(FreeRegion)` corresponding to a lifetime -// conflict. +/// This struct contains information regarding the `ReFree(FreeRegion)` corresponding to a lifetime +/// conflict. #[derive(Debug)] pub struct FreeRegionInfo { - // `LocalDefId` corresponding to FreeRegion + /// `LocalDefId` corresponding to FreeRegion pub def_id: LocalDefId, - // the bound region corresponding to FreeRegion + /// the bound region corresponding to FreeRegion pub boundregion: ty::BoundRegionKind, - // checks if bound region is in Impl Item + /// checks if bound region is in Impl Item pub is_impl_item: bool, } +/// This struct should only be created by `create_def`. +#[derive(Copy, Clone)] +pub struct TyCtxtFeed<'tcx, KEY: Copy> { + pub tcx: TyCtxt<'tcx>, + // Do not allow direct access, as downstream code must not mutate this field. + key: KEY, +} + +impl<'tcx> TyCtxt<'tcx> { + pub fn feed_unit_query(self) -> TyCtxtFeed<'tcx, ()> { + TyCtxtFeed { tcx: self, key: () } + } +} + +impl<'tcx, KEY: Copy> TyCtxtFeed<'tcx, KEY> { + #[inline(always)] + pub fn key(&self) -> KEY { + self.key + } +} + +impl<'tcx> TyCtxtFeed<'tcx, LocalDefId> { + #[inline(always)] + pub fn def_id(&self) -> LocalDefId { + self.key + } +} + /// The central data structure of the compiler. It stores references /// to the various **arenas** and also houses the results of the /// various **compiler queries** that have been performed. See the @@ -1071,7 +1116,6 @@ pub struct GlobalCtxt<'tcx> { /// Output of the resolver. pub(crate) untracked_resolutions: ty::ResolverGlobalCtxt, - untracked_resolver_for_lowering: Steal<ty::ResolverAstLowering>, /// The entire crate as AST. This field serves as the input for the hir_crate query, /// which lowers it from AST to HIR. It must not be read or used by anything else. pub untracked_crate: Steal<Lrc<ast::Crate>>, @@ -1201,8 +1245,9 @@ impl<'tcx> TyCtxt<'tcx> { debug!("layout_scalar_valid_range: attr={:?}", attr); if let Some( &[ - ast::NestedMetaItem::Literal(ast::Lit { - kind: ast::LitKind::Int(a, _), .. + ast::NestedMetaItem::Lit(ast::MetaItemLit { + kind: ast::LitKind::Int(a, _), + .. }), ], ) = attr.meta_item_list().as_deref() @@ -1233,21 +1278,17 @@ impl<'tcx> TyCtxt<'tcx> { lint_store: Lrc<dyn Any + sync::Send + sync::Sync>, arena: &'tcx WorkerLocal<Arena<'tcx>>, hir_arena: &'tcx WorkerLocal<hir::Arena<'tcx>>, - resolver_outputs: ResolverOutputs, + definitions: Definitions, + untracked_resolutions: ty::ResolverGlobalCtxt, krate: Lrc<ast::Crate>, dep_graph: DepGraph, on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>, queries: &'tcx dyn query::QueryEngine<'tcx>, query_kinds: &'tcx [DepKindStruct<'tcx>], - crate_name: &str, + crate_name: Symbol, output_filenames: OutputFilenames, ) -> GlobalCtxt<'tcx> { - let ResolverOutputs { - definitions, - global_ctxt: untracked_resolutions, - ast_lowering: untracked_resolver_for_lowering, - } = resolver_outputs; - let data_layout = TargetDataLayout::parse(&s.target).unwrap_or_else(|err| { + let data_layout = s.target.parse_data_layout().unwrap_or_else(|err| { s.emit_fatal(err); }); let interners = CtxtInterners::new(arena); @@ -1275,7 +1316,6 @@ impl<'tcx> TyCtxt<'tcx> { lifetimes: common_lifetimes, consts: common_consts, untracked_resolutions, - untracked_resolver_for_lowering: Steal::new(untracked_resolver_for_lowering), untracked_crate: Steal::new(krate), on_disk_cache, queries, @@ -1285,13 +1325,19 @@ impl<'tcx> TyCtxt<'tcx> { pred_rcache: Default::default(), selection_cache: Default::default(), evaluation_cache: Default::default(), - crate_name: Symbol::intern(crate_name), + crate_name, data_layout, alloc_map: Lock::new(interpret::AllocMap::new()), output_filenames: Arc::new(output_filenames), } } + /// Constructs a `TyKind::Error` type with current `ErrorGuaranteed` + #[track_caller] + pub fn ty_error_with_guaranteed(self, reported: ErrorGuaranteed) -> Ty<'tcx> { + self.mk_ty(Error(reported)) + } + /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used. #[track_caller] pub fn ty_error(self) -> Ty<'tcx> { @@ -1303,7 +1349,17 @@ impl<'tcx> TyCtxt<'tcx> { #[track_caller] pub fn ty_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Ty<'tcx> { let reported = self.sess.delay_span_bug(span, msg); - self.mk_ty(Error(DelaySpanBugEmitted { reported, _priv: () })) + self.mk_ty(Error(reported)) + } + + /// Like [TyCtxt::ty_error] but for constants, with current `ErrorGuaranteed` + #[track_caller] + pub fn const_error_with_guaranteed( + self, + ty: Ty<'tcx>, + reported: ErrorGuaranteed, + ) -> Const<'tcx> { + self.mk_const(ty::ConstKind::Error(reported), ty) } /// Like [TyCtxt::ty_error] but for constants. @@ -1325,10 +1381,7 @@ impl<'tcx> TyCtxt<'tcx> { msg: &str, ) -> Const<'tcx> { let reported = self.sess.delay_span_bug(span, msg); - self.mk_const(ty::ConstS { - kind: ty::ConstKind::Error(DelaySpanBugEmitted { reported, _priv: () }), - ty, - }) + self.mk_const(ty::ConstKind::Error(reported), ty) } pub fn consider_optimizing<T: Fn() -> String>(self, msg: T) -> bool { @@ -1357,6 +1410,11 @@ impl<'tcx> TyCtxt<'tcx> { self.diagnostic_items(did.krate).name_to_id.get(&name) == Some(&did) } + /// Returns `true` if the node pointed to by `def_id` is a generator for an async construct. + pub fn generator_is_async(self, def_id: DefId) -> bool { + matches!(self.generator_kind(def_id), Some(hir::GeneratorKind::Async(_))) + } + pub fn stability(self) -> &'tcx stability::Index { self.stability_index(()) } @@ -1460,14 +1518,19 @@ impl<'tcx> TyCtxt<'tcx> { self.def_path(def_id).to_string_no_crate_verbose() ) } +} +impl<'tcx> TyCtxtAt<'tcx> { /// Create a new definition within the incr. comp. engine. - pub fn create_def(self, parent: LocalDefId, data: hir::definitions::DefPathData) -> LocalDefId { + pub fn create_def( + self, + parent: LocalDefId, + data: hir::definitions::DefPathData, + ) -> 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. // Depending on the forever-red node will tell the graph that the calling query // needs to be re-evaluated. - use rustc_query_system::dep_graph::DepNodeIndex; self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE); // The following call has the side effect of modifying the tables inside `definitions`. @@ -1484,23 +1547,42 @@ impl<'tcx> TyCtxt<'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. - self.definitions.write().create_def(parent, data) + let key = self.definitions.write().create_def(parent, data); + + let feed = TyCtxtFeed { tcx: self.tcx, key }; + feed.def_span(self.span); + feed } +} +impl<'tcx> TyCtxt<'tcx> { pub fn iter_local_def_id(self) -> impl Iterator<Item = LocalDefId> + 'tcx { - // Create a dependency to the crate to be sure we re-execute this when the amount of + // Create a dependency to the red node to be sure we re-execute this when the amount of // definitions change. - self.ensure().hir_crate(()); - // Leak a read lock once we start iterating on definitions, to prevent adding new ones - // while iterating. If some query needs to add definitions, it should be `ensure`d above. - let definitions = self.definitions.leak(); - definitions.iter_local_def_id() + self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE); + + let definitions = &self.definitions; + std::iter::from_generator(|| { + let mut i = 0; + + // Recompute the number of definitions each time, because our caller may be creating + // new ones. + while i < { definitions.read().num_definitions() } { + let local_def_index = rustc_span::def_id::DefIndex::from_usize(i); + yield LocalDefId { local_def_index }; + i += 1; + } + + // Leak a read lock once we finish iterating on definitions, to prevent adding new ones. + definitions.leak(); + }) } pub fn def_path_table(self) -> &'tcx rustc_hir::definitions::DefPathTable { // Create a dependency to the crate to be sure we re-execute this when the amount of // definitions change. - self.ensure().hir_crate(()); + self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE); + // Leak a read lock once we start iterating on definitions, to prevent adding new ones // while iterating. If some query needs to add definitions, it should be `ensure`d above. let definitions = self.definitions.leak(); @@ -1659,7 +1741,7 @@ impl<'tcx> TyCtxt<'tcx> { } } - // Checks if the bound region is in Impl Item. + /// Checks if the bound region is in Impl Item. pub fn is_bound_region_in_impl_item(self, suitable_region_binding_scope: LocalDefId) -> bool { let container_id = self.parent(suitable_region_binding_scope.to_def_id()); if self.impl_trait_ref(container_id).is_some() { @@ -1810,7 +1892,7 @@ nop_lift! {const_; Const<'a> => Const<'tcx>} nop_lift! {const_allocation; ConstAllocation<'a> => ConstAllocation<'tcx>} nop_lift! {predicate; Predicate<'a> => Predicate<'tcx>} -nop_list_lift! {poly_existential_predicates; ty::Binder<'a, ExistentialPredicate<'a>> => ty::Binder<'tcx, ExistentialPredicate<'tcx>>} +nop_list_lift! {poly_existential_predicates; PolyExistentialPredicate<'a> => PolyExistentialPredicate<'tcx>} nop_list_lift! {predicates; Predicate<'a> => Predicate<'tcx>} nop_list_lift! {canonical_var_infos; CanonicalVarInfo<'a> => CanonicalVarInfo<'tcx>} nop_list_lift! {projs; ProjectionKind => ProjectionKind} @@ -2026,7 +2108,7 @@ macro_rules! sty_debug_print { let shards = tcx.interners.type_.lock_shards(); let types = shards.iter().flat_map(|shard| shard.keys()); for &InternedInSet(t) in types { - let variant = match t.kind { + let variant = match t.internee { ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) | ty::Float(..) | ty::Str | ty::Never => continue, ty::Error(_) => /* unimportant */ continue, @@ -2136,49 +2218,26 @@ impl<'tcx, T: 'tcx + ?Sized> IntoPointer for InternedInSet<'tcx, T> { } #[allow(rustc::usage_of_ty_tykind)] -impl<'tcx> Borrow<TyKind<'tcx>> for InternedInSet<'tcx, WithStableHash<TyS<'tcx>>> { - fn borrow<'a>(&'a self) -> &'a TyKind<'tcx> { - &self.0.kind - } -} - -impl<'tcx> PartialEq for InternedInSet<'tcx, WithStableHash<TyS<'tcx>>> { - fn eq(&self, other: &InternedInSet<'tcx, WithStableHash<TyS<'tcx>>>) -> bool { - // The `Borrow` trait requires that `x.borrow() == y.borrow()` equals - // `x == y`. - self.0.kind == other.0.kind - } -} - -impl<'tcx> Eq for InternedInSet<'tcx, WithStableHash<TyS<'tcx>>> {} - -impl<'tcx> Hash for InternedInSet<'tcx, WithStableHash<TyS<'tcx>>> { - fn hash<H: Hasher>(&self, s: &mut H) { - // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`. - self.0.kind.hash(s) - } -} - -impl<'tcx> Borrow<Binder<'tcx, PredicateKind<'tcx>>> for InternedInSet<'tcx, PredicateS<'tcx>> { - fn borrow<'a>(&'a self) -> &'a Binder<'tcx, PredicateKind<'tcx>> { - &self.0.kind +impl<'tcx, T> Borrow<T> for InternedInSet<'tcx, WithCachedTypeInfo<T>> { + fn borrow<'a>(&'a self) -> &'a T { + &self.0.internee } } -impl<'tcx> PartialEq for InternedInSet<'tcx, PredicateS<'tcx>> { - fn eq(&self, other: &InternedInSet<'tcx, PredicateS<'tcx>>) -> bool { +impl<'tcx, T: PartialEq> PartialEq for InternedInSet<'tcx, WithCachedTypeInfo<T>> { + fn eq(&self, other: &InternedInSet<'tcx, WithCachedTypeInfo<T>>) -> bool { // The `Borrow` trait requires that `x.borrow() == y.borrow()` equals // `x == y`. - self.0.kind == other.0.kind + self.0.internee == other.0.internee } } -impl<'tcx> Eq for InternedInSet<'tcx, PredicateS<'tcx>> {} +impl<'tcx, T: Eq> Eq for InternedInSet<'tcx, WithCachedTypeInfo<T>> {} -impl<'tcx> Hash for InternedInSet<'tcx, PredicateS<'tcx>> { +impl<'tcx, T: Hash> Hash for InternedInSet<'tcx, WithCachedTypeInfo<T>> { fn hash<H: Hasher>(&self, s: &mut H) { // The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`. - self.0.kind.hash(s) + self.0.internee.hash(s) } } @@ -2243,9 +2302,9 @@ macro_rules! direct_interners { direct_interners! { region: mk_region(RegionKind<'tcx>): Region -> Region<'tcx>, - const_: mk_const(ConstS<'tcx>): Const -> Const<'tcx>, + const_: mk_const_internal(ConstS<'tcx>): Const -> Const<'tcx>, const_allocation: intern_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>, - layout: intern_layout(LayoutS<'tcx>): Layout -> Layout<'tcx>, + layout: intern_layout(LayoutS<VariantIdx>): Layout -> Layout<'tcx>, adt_def: intern_adt_def(AdtDefData): AdtDef -> AdtDef<'tcx>, } @@ -2262,10 +2321,11 @@ macro_rules! slice_interners { } slice_interners!( + const_lists: _intern_const_list(Const<'tcx>), substs: _intern_substs(GenericArg<'tcx>), canonical_var_infos: _intern_canonical_var_infos(CanonicalVarInfo<'tcx>), poly_existential_predicates: - _intern_poly_existential_predicates(ty::Binder<'tcx, ExistentialPredicate<'tcx>>), + _intern_poly_existential_predicates(PolyExistentialPredicate<'tcx>), predicates: _intern_predicates(Predicate<'tcx>), projs: _intern_projs(ProjectionKind), place_elems: _intern_place_elems(PlaceElem<'tcx>), @@ -2294,10 +2354,10 @@ impl<'tcx> TyCtxt<'tcx> { /// Given a `ty`, return whether it's an `impl Future<...>`. pub fn ty_is_opaque_future(self, ty: Ty<'_>) -> bool { let ty::Opaque(def_id, _) = ty.kind() else { return false }; - let future_trait = self.lang_items().future_trait().unwrap(); + let future_trait = self.require_lang_item(LangItem::Future, None); self.explicit_item_bounds(def_id).iter().any(|(predicate, _)| { - let ty::PredicateKind::Trait(trait_predicate) = predicate.kind().skip_binder() else { + let ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) = predicate.kind().skip_binder() else { return false; }; trait_predicate.trait_ref.def_id == future_trait @@ -2320,7 +2380,9 @@ impl<'tcx> TyCtxt<'tcx> { let generic_predicates = self.super_predicates_of(trait_did); for (predicate, _) in generic_predicates.predicates { - if let ty::PredicateKind::Trait(data) = predicate.kind().skip_binder() { + if let ty::PredicateKind::Clause(ty::Clause::Trait(data)) = + predicate.kind().skip_binder() + { if set.insert(data.def_id()) { stack.push(data.def_id()); } @@ -2374,7 +2436,14 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_predicate(self, binder: Binder<'tcx, PredicateKind<'tcx>>) -> Predicate<'tcx> { - self.interners.intern_predicate(binder) + self.interners.intern_predicate( + binder, + self.sess, + &self.definitions.read(), + &*self.untracked_resolutions.cstore, + // This is only used to create a stable hashing context. + &self.untracked_resolutions.source_span, + ) } #[inline] @@ -2456,7 +2525,7 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_lang_item(self, ty: Ty<'tcx>, item: LangItem) -> Option<Ty<'tcx>> { - let def_id = self.lang_items().require(item).ok()?; + let def_id = self.lang_items().get(item)?; Some(self.mk_generic_adt(def_id, ty)) } @@ -2517,7 +2586,7 @@ impl<'tcx> TyCtxt<'tcx> { self.mk_ty(Tuple(self.intern_type_list(&ts))) } - pub fn mk_tup<I: InternAs<[Ty<'tcx>], Ty<'tcx>>>(self, iter: I) -> I::Output { + pub fn mk_tup<I: InternAs<Ty<'tcx>, Ty<'tcx>>>(self, iter: I) -> I::Output { iter.intern_with(|ts| self.mk_ty(Tuple(self.intern_type_list(&ts)))) } @@ -2533,6 +2602,11 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_fn_def(self, def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> { + debug_assert_eq!( + self.generics_of(def_id).count(), + substs.len(), + "wrong number of generic parameters for {def_id:?}: {substs:?}", + ); self.mk_ty(FnDef(def_id, substs)) } @@ -2544,7 +2618,7 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_dynamic( self, - obj: &'tcx List<ty::Binder<'tcx, ExistentialPredicate<'tcx>>>, + obj: &'tcx List<PolyExistentialPredicate<'tcx>>, reg: ty::Region<'tcx>, repr: DynKind, ) -> Ty<'tcx> { @@ -2553,6 +2627,11 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_projection(self, item_def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> { + debug_assert_eq!( + self.generics_of(item_def_id).count(), + substs.len(), + "wrong number of generic parameters for {item_def_id:?}: {substs:?}", + ); self.mk_ty(Projection(ProjectionTy { item_def_id, substs })) } @@ -2582,8 +2661,8 @@ impl<'tcx> TyCtxt<'tcx> { } #[inline] - pub fn mk_const_var(self, v: ConstVid<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { - self.mk_const(ty::ConstS { kind: ty::ConstKind::Infer(InferConst::Var(v)), ty }) + pub fn mk_const(self, kind: impl Into<ty::ConstKind<'tcx>>, ty: Ty<'tcx>) -> Const<'tcx> { + self.mk_const_internal(ty::ConstS { kind: kind.into(), ty }) } #[inline] @@ -2602,29 +2681,22 @@ impl<'tcx> TyCtxt<'tcx> { } #[inline] - pub fn mk_const_infer(self, ic: InferConst<'tcx>, ty: Ty<'tcx>) -> ty::Const<'tcx> { - self.mk_const(ty::ConstS { kind: ty::ConstKind::Infer(ic), ty }) - } - - #[inline] pub fn mk_ty_param(self, index: u32, name: Symbol) -> Ty<'tcx> { self.mk_ty(Param(ParamTy { index, name })) } - #[inline] - pub fn mk_const_param(self, index: u32, name: Symbol, ty: Ty<'tcx>) -> Const<'tcx> { - self.mk_const(ty::ConstS { kind: ty::ConstKind::Param(ParamConst { index, name }), ty }) - } - pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> GenericArg<'tcx> { match param.kind { GenericParamDefKind::Lifetime => { self.mk_region(ty::ReEarlyBound(param.to_early_bound_region_data())).into() } GenericParamDefKind::Type { .. } => self.mk_ty_param(param.index, param.name).into(), - GenericParamDefKind::Const { .. } => { - self.mk_const_param(param.index, param.name, self.type_of(param.def_id)).into() - } + GenericParamDefKind::Const { .. } => self + .mk_const( + ParamConst { index: param.index, name: param.name }, + self.type_of(param.def_id), + ) + .into(), } } @@ -2677,8 +2749,8 @@ impl<'tcx> TyCtxt<'tcx> { pub fn intern_poly_existential_predicates( self, - eps: &[ty::Binder<'tcx, ExistentialPredicate<'tcx>>], - ) -> &'tcx List<ty::Binder<'tcx, ExistentialPredicate<'tcx>>> { + eps: &[PolyExistentialPredicate<'tcx>], + ) -> &'tcx List<PolyExistentialPredicate<'tcx>> { assert!(!eps.is_empty()); assert!( eps.array_windows() @@ -2700,6 +2772,17 @@ impl<'tcx> TyCtxt<'tcx> { } } + pub fn mk_const_list<I: InternAs<ty::Const<'tcx>, &'tcx List<ty::Const<'tcx>>>>( + self, + iter: I, + ) -> I::Output { + iter.intern_with(|xs| self.intern_const_list(xs)) + } + + pub fn intern_const_list(self, cs: &[ty::Const<'tcx>]) -> &'tcx List<ty::Const<'tcx>> { + if cs.is_empty() { List::empty() } else { self._intern_const_list(cs) } + } + pub fn intern_type_list(self, ts: &[Ty<'tcx>]) -> &'tcx List<Ty<'tcx>> { if ts.is_empty() { List::empty() @@ -2762,10 +2845,7 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn mk_poly_existential_predicates< - I: InternAs< - [ty::Binder<'tcx, ExistentialPredicate<'tcx>>], - &'tcx List<ty::Binder<'tcx, ExistentialPredicate<'tcx>>>, - >, + I: InternAs<PolyExistentialPredicate<'tcx>, &'tcx List<PolyExistentialPredicate<'tcx>>>, >( self, iter: I, @@ -2773,37 +2853,58 @@ impl<'tcx> TyCtxt<'tcx> { iter.intern_with(|xs| self.intern_poly_existential_predicates(xs)) } - pub fn mk_predicates<I: InternAs<[Predicate<'tcx>], &'tcx List<Predicate<'tcx>>>>( + pub fn mk_predicates<I: InternAs<Predicate<'tcx>, &'tcx List<Predicate<'tcx>>>>( self, iter: I, ) -> I::Output { iter.intern_with(|xs| self.intern_predicates(xs)) } - pub fn mk_type_list<I: InternAs<[Ty<'tcx>], &'tcx List<Ty<'tcx>>>>(self, iter: I) -> I::Output { + pub fn mk_type_list<I: InternAs<Ty<'tcx>, &'tcx List<Ty<'tcx>>>>(self, iter: I) -> I::Output { iter.intern_with(|xs| self.intern_type_list(xs)) } - pub fn mk_substs<I: InternAs<[GenericArg<'tcx>], &'tcx List<GenericArg<'tcx>>>>( + pub fn mk_substs<I: InternAs<GenericArg<'tcx>, &'tcx List<GenericArg<'tcx>>>>( self, iter: I, ) -> I::Output { iter.intern_with(|xs| self.intern_substs(xs)) } - pub fn mk_place_elems<I: InternAs<[PlaceElem<'tcx>], &'tcx List<PlaceElem<'tcx>>>>( + pub fn mk_place_elems<I: InternAs<PlaceElem<'tcx>, &'tcx List<PlaceElem<'tcx>>>>( self, iter: I, ) -> I::Output { iter.intern_with(|xs| self.intern_place_elems(xs)) } - pub fn mk_substs_trait(self, self_ty: Ty<'tcx>, rest: &[GenericArg<'tcx>]) -> SubstsRef<'tcx> { - self.mk_substs(iter::once(self_ty.into()).chain(rest.iter().cloned())) + pub fn mk_substs_trait( + self, + self_ty: Ty<'tcx>, + rest: impl IntoIterator<Item = GenericArg<'tcx>>, + ) -> SubstsRef<'tcx> { + self.mk_substs(iter::once(self_ty.into()).chain(rest)) + } + + pub fn mk_trait_ref( + self, + trait_def_id: DefId, + substs: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>, + ) -> ty::TraitRef<'tcx> { + let substs = substs.into_iter().map(Into::into); + let n = self.generics_of(trait_def_id).count(); + debug_assert_eq!( + (n, Some(n)), + substs.size_hint(), + "wrong number of generic parameters for {trait_def_id:?}: {:?} \nDid you accidentally include the self-type in the params list?", + substs.collect::<Vec<_>>(), + ); + let substs = self.mk_substs(substs); + ty::TraitRef::new(trait_def_id, substs) } pub fn mk_bound_variable_kinds< - I: InternAs<[ty::BoundVariableKind], &'tcx List<ty::BoundVariableKind>>, + I: InternAs<ty::BoundVariableKind, &'tcx List<ty::BoundVariableKind>>, >( self, iter: I, @@ -2820,7 +2921,9 @@ impl<'tcx> TyCtxt<'tcx> { span: impl Into<MultiSpan>, decorator: impl for<'a> DecorateLint<'a, ()>, ) { - self.struct_span_lint_hir(lint, hir_id, span, decorator.msg(), |diag| { + 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) }) } @@ -2830,6 +2933,7 @@ impl<'tcx> TyCtxt<'tcx> { /// 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] pub fn struct_span_lint_hir( self, lint: &'static Lint, @@ -2860,6 +2964,7 @@ impl<'tcx> TyCtxt<'tcx> { /// 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] pub fn struct_lint_node( self, lint: &'static Lint, @@ -2954,6 +3059,15 @@ impl<'tcx> TyCtxtAt<'tcx> { pub fn ty_error_with_message(self, msg: &str) -> Ty<'tcx> { self.tcx.ty_error_with_message(self.span, msg) } + + pub fn mk_trait_ref( + self, + trait_lang_item: LangItem, + substs: impl IntoIterator<Item = impl Into<ty::GenericArg<'tcx>>>, + ) -> ty::TraitRef<'tcx> { + let trait_def_id = self.require_lang_item(trait_lang_item, Some(self.span)); + self.tcx.mk_trait_ref(trait_def_id, substs) + } } /// Parameter attributes that can only be determined by examining the body of a function instead @@ -2979,7 +3093,6 @@ fn ptr_eq<T, U>(t: *const T, u: *const U) -> bool { pub fn provide(providers: &mut ty::query::Providers) { providers.resolutions = |tcx, ()| &tcx.untracked_resolutions; - providers.resolver_for_lowering = |tcx, ()| &tcx.untracked_resolver_for_lowering; providers.module_reexports = |tcx, id| tcx.resolutions(()).reexport_map.get(&id).map(|v| &v[..]); providers.crate_name = |tcx, id| { diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index b8fd01e6a..511d51cd6 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -151,7 +151,6 @@ enum SuggestChangingConstraintsMessage<'a> { } fn suggest_removing_unsized_bound( - tcx: TyCtxt<'_>, generics: &hir::Generics<'_>, suggestions: &mut Vec<(Span, String, SuggestChangingConstraintsMessage<'_>)>, param: &hir::GenericParam<'_>, @@ -160,17 +159,16 @@ fn suggest_removing_unsized_bound( // See if there's a `?Sized` bound that can be removed to suggest that. // First look at the `where` clause because we can have `where T: ?Sized`, // then look at params. - let param_def_id = tcx.hir().local_def_id(param.hir_id); for (where_pos, predicate) in generics.predicates.iter().enumerate() { let WherePredicate::BoundPredicate(predicate) = predicate else { continue; }; - if !predicate.is_param_bound(param_def_id.to_def_id()) { + if !predicate.is_param_bound(param.def_id.to_def_id()) { continue; }; for (pos, bound) in predicate.bounds.iter().enumerate() { - let hir::GenericBound::Trait(poly, hir::TraitBoundModifier::Maybe) = bound else { + let hir::GenericBound::Trait(poly, hir::TraitBoundModifier::Maybe) = bound else { continue; }; if poly.trait_ref.trait_def_id() != def_id { @@ -232,7 +230,7 @@ pub fn suggest_constraining_type_params<'a>( param.span, &format!("this type parameter needs to be `{}`", constraint), ); - suggest_removing_unsized_bound(tcx, generics, &mut suggestions, param, def_id); + suggest_removing_unsized_bound(generics, &mut suggestions, param, def_id); } } @@ -283,8 +281,7 @@ pub fn suggest_constraining_type_params<'a>( // -- // | // replace with: `T: Bar +` - let param_def_id = tcx.hir().local_def_id(param.hir_id); - if let Some(span) = generics.bounds_span_for_suggestions(param_def_id) { + if let Some(span) = generics.bounds_span_for_suggestions(param.def_id) { suggest_restrict(span, true); continue; } @@ -358,6 +355,12 @@ pub fn suggest_constraining_type_params<'a>( )); } + // FIXME: remove the suggestions that are from derive, as the span is not correct + suggestions = suggestions + .into_iter() + .filter(|(span, _, _)| !span.in_derive_expansion()) + .collect::<Vec<_>>(); + if suggestions.len() == 1 { let (span, suggestion, msg) = suggestions.pop().unwrap(); @@ -400,7 +403,7 @@ impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> { hir::TyKind::TraitObject( _, hir::Lifetime { - name: + res: hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static, .. }, @@ -424,10 +427,9 @@ pub struct StaticLifetimeVisitor<'tcx>(pub Vec<Span>, pub crate::hir::map::Map<' impl<'v> hir::intravisit::Visitor<'v> for StaticLifetimeVisitor<'v> { fn visit_lifetime(&mut self, lt: &'v hir::Lifetime) { - if let hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static = - lt.name + if let hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static = lt.res { - self.0.push(lt.span); + self.0.push(lt.ident.span); } } } @@ -511,11 +513,3 @@ impl<'tcx> TypeVisitor<'tcx> for IsSuggestableVisitor<'tcx> { c.super_visit_with(self) } } - -#[derive(Diagnostic)] -#[diag(borrowck_const_not_used_in_type_alias)] -pub(super) struct ConstNotUsedTraitAlias { - pub ct: String, - #[primary_span] - pub span: Span, -} diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 4e6cdb786..aa61c39b8 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -12,7 +12,12 @@ use rustc_span::{BytePos, Span}; use rustc_target::spec::abi; use std::borrow::Cow; +use std::collections::hash_map::DefaultHasher; use std::fmt; +use std::hash::{Hash, Hasher}; +use std::path::PathBuf; + +use super::print::PrettyPrinter; #[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable, TypeVisitable, Lift)] pub struct ExpectedFound<T> { @@ -64,10 +69,7 @@ pub enum TypeError<'tcx> { CyclicTy(Ty<'tcx>), CyclicConst(ty::Const<'tcx>), ProjectionMismatched(ExpectedFound<DefId>), - ExistentialMismatch( - ExpectedFound<&'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>>, - ), - ObjectUnsafeCoercion(DefId), + ExistentialMismatch(ExpectedFound<&'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>>), ConstMismatch(ExpectedFound<ty::Const<'tcx>>), IntrinsicCast, @@ -219,7 +221,6 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { f, "cannot coerce functions with `#[target_feature]` to safe function pointers" ), - ObjectUnsafeCoercion(_) => write!(f, "coercion to object-unsafe trait object"), } } } @@ -246,8 +247,7 @@ impl<'tcx> TypeError<'tcx> { | ProjectionMismatched(_) | ExistentialMismatch(_) | ConstMismatch(_) - | IntrinsicCast - | ObjectUnsafeCoercion(_) => true, + | IntrinsicCast => true, } } } @@ -430,7 +430,9 @@ impl<'tcx> TyCtxt<'tcx> { (ty::Projection(_), ty::Projection(_)) => { diag.note("an associated type was expected, but a different one was found"); } - (ty::Param(p), ty::Projection(proj)) | (ty::Projection(proj), ty::Param(p)) => { + (ty::Param(p), ty::Projection(proj)) | (ty::Projection(proj), ty::Param(p)) + if self.def_kind(proj.item_def_id) != DefKind::ImplTraitPlaceholder => + { let generics = self.generics_of(body_owner_def_id); let p_span = self.def_span(generics.type_param(p, self).def_id); if !sp.contains(p_span) { @@ -983,6 +985,47 @@ fn foo(&self) -> Self::T { String::new() } false } + pub fn short_ty_string(self, ty: Ty<'tcx>) -> (String, Option<PathBuf>) { + let width = self.sess.diagnostic_width(); + let length_limit = width.saturating_sub(30); + let mut type_limit = 50; + let regular = FmtPrinter::new(self, hir::def::Namespace::TypeNS) + .pretty_print_type(ty) + .expect("could not write to `String`") + .into_buffer(); + if regular.len() <= width { + return (regular, None); + } + let mut short; + loop { + // Look for the longest properly trimmed path that still fits in lenght_limit. + short = FmtPrinter::new_with_limit( + self, + hir::def::Namespace::TypeNS, + rustc_session::Limit(type_limit), + ) + .pretty_print_type(ty) + .expect("could not write to `String`") + .into_buffer(); + if short.len() <= length_limit || type_limit == 0 { + break; + } + type_limit -= 1; + } + if regular == short { + return (regular, None); + } + // Multiple types might be shortened in a single error, ensure we create a file for each. + 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), + } + } + fn format_generic_args(self, args: &[ty::GenericArg<'tcx>]) -> String { FmtPrinter::new(self, hir::def::Namespace::TypeNS) .path_generic_args(Ok, args) diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index 3be0bc4de..c9c09c93a 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -42,7 +42,6 @@ where ClosureSimplifiedType(D), GeneratorSimplifiedType(D), GeneratorWitnessSimplifiedType(usize), - OpaqueSimplifiedType(D), FunctionSimplifiedType(usize), PlaceholderSimplifiedType, } @@ -127,7 +126,7 @@ pub fn simplify_type<'tcx>( TreatParams::AsPlaceholder => Some(PlaceholderSimplifiedType), TreatParams::AsInfer => None, }, - ty::Projection(_) => match treat_params { + ty::Opaque(..) | ty::Projection(_) => match treat_params { // When treating `ty::Param` as a placeholder, projections also // don't unify with anything else as long as they are fully normalized. // @@ -138,7 +137,6 @@ pub fn simplify_type<'tcx>( } TreatParams::AsPlaceholder | TreatParams::AsInfer => None, }, - ty::Opaque(def_id, _) => Some(OpaqueSimplifiedType(def_id)), ty::Foreign(def_id) => Some(ForeignSimplifiedType(def_id)), ty::Bound(..) | ty::Infer(_) | ty::Error(_) => None, } @@ -151,8 +149,7 @@ impl<D: Copy + Debug + Eq> SimplifiedTypeGen<D> { | ForeignSimplifiedType(d) | TraitSimplifiedType(d) | ClosureSimplifiedType(d) - | GeneratorSimplifiedType(d) - | OpaqueSimplifiedType(d) => Some(d), + | GeneratorSimplifiedType(d) => Some(d), _ => None, } } @@ -182,7 +179,6 @@ impl<D: Copy + Debug + Eq> SimplifiedTypeGen<D> { ClosureSimplifiedType(d) => ClosureSimplifiedType(map(d)), GeneratorSimplifiedType(d) => GeneratorSimplifiedType(map(d)), GeneratorWitnessSimplifiedType(n) => GeneratorWitnessSimplifiedType(n), - OpaqueSimplifiedType(d) => OpaqueSimplifiedType(map(d)), FunctionSimplifiedType(n) => FunctionSimplifiedType(n), PlaceholderSimplifiedType => PlaceholderSimplifiedType, } @@ -229,7 +225,7 @@ impl DeepRejectCtxt { match impl_ty.kind() { // Start by checking whether the type in the impl may unify with // pretty much everything. Just return `true` in that case. - ty::Param(_) | ty::Projection(_) | ty::Error(_) => return true, + ty::Param(_) | ty::Projection(_) | ty::Error(_) | ty::Opaque(..) => return true, // These types only unify with inference variables or their own // variant. ty::Bool @@ -247,8 +243,7 @@ impl DeepRejectCtxt { | ty::Never | ty::Tuple(..) | ty::FnPtr(..) - | ty::Foreign(..) - | ty::Opaque(..) => {} + | ty::Foreign(..) => {} ty::FnDef(..) | ty::Closure(..) | ty::Generator(..) @@ -328,10 +323,7 @@ impl DeepRejectCtxt { _ => false, }, - // Opaque types in impls should be forbidden, but that doesn't - // stop compilation. So this match arm should never return true - // if compilation succeeds. - ty::Opaque(..) => matches!(k, ty::Opaque(..)), + ty::Opaque(..) => true, // Impls cannot contain these types as these cannot be named directly. ty::FnDef(..) | ty::Closure(..) | ty::Generator(..) => false, @@ -364,7 +356,10 @@ impl DeepRejectCtxt { pub fn consts_may_unify(self, obligation_ct: ty::Const<'_>, impl_ct: ty::Const<'_>) -> bool { match impl_ct.kind() { - ty::ConstKind::Param(_) | ty::ConstKind::Unevaluated(_) | ty::ConstKind::Error(_) => { + ty::ConstKind::Expr(_) + | ty::ConstKind::Param(_) + | ty::ConstKind::Unevaluated(_) + | ty::ConstKind::Error(_) => { return true; } ty::ConstKind::Value(_) => {} @@ -382,7 +377,9 @@ impl DeepRejectCtxt { // As we don't necessarily eagerly evaluate constants, // they might unify with any value. - ty::ConstKind::Unevaluated(_) | ty::ConstKind::Error(_) => true, + ty::ConstKind::Expr(_) | ty::ConstKind::Unevaluated(_) | ty::ConstKind::Error(_) => { + true + } ty::ConstKind::Value(obl) => match k { ty::ConstKind::Value(imp) => obl == imp, _ => true, diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 7201737be..046a2660a 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -6,7 +6,7 @@ use std::slice; pub struct FlagComputation { pub flags: TypeFlags, - // see `Ty::outer_exclusive_binder` for details + /// see `Ty::outer_exclusive_binder` for details pub outer_exclusive_binder: ty::DebruijnIndex, } @@ -216,14 +216,17 @@ impl FlagComputation { fn add_predicate_atom(&mut self, atom: ty::PredicateKind<'_>) { match atom { - ty::PredicateKind::Trait(trait_pred) => { + ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => { self.add_substs(trait_pred.trait_ref.substs); } - ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => { + ty::PredicateKind::Clause(ty::Clause::RegionOutlives(ty::OutlivesPredicate(a, b))) => { self.add_region(a); self.add_region(b); } - ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty, region)) => { + ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate( + ty, + region, + ))) => { self.add_ty(ty); self.add_region(region); } @@ -235,7 +238,10 @@ impl FlagComputation { self.add_ty(a); self.add_ty(b); } - ty::PredicateKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => { + ty::PredicateKind::Clause(ty::Clause::Projection(ty::ProjectionPredicate { + projection_ty, + term, + })) => { self.add_projection_ty(projection_ty); match term.unpack() { ty::TermKind::Ty(ty) => self.add_ty(ty), @@ -259,6 +265,7 @@ impl FlagComputation { ty::PredicateKind::TypeWellFormedFromEnv(ty) => { self.add_ty(ty); } + ty::PredicateKind::Ambiguous => {} } } @@ -306,6 +313,26 @@ impl FlagComputation { self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); } ty::ConstKind::Value(_) => {} + ty::ConstKind::Expr(e) => { + use ty::Expr; + match e { + Expr::Binop(_, l, r) => { + self.add_const(l); + self.add_const(r); + } + Expr::UnOp(_, v) => self.add_const(v), + Expr::FunctionCall(f, args) => { + self.add_const(f); + for arg in args { + self.add_const(arg); + } + } + Expr::Cast(_, c, t) => { + self.add_ty(t); + self.add_const(c); + } + } + } ty::ConstKind::Error(_) => self.add_flags(TypeFlags::HAS_ERROR), } } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 54f1499eb..d431d008d 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -407,6 +407,7 @@ where match *t.kind() { ty::Bound(debruijn, bound_ty) if debruijn == self.current_index => { let ty = self.delegate.replace_ty(bound_ty); + debug_assert!(!ty.has_vars_bound_above(ty::INNERMOST)); ty::fold::shift_vars(self.tcx, ty, self.current_index.as_u32()) } _ if t.has_vars_bound_at_or_above(self.current_index) => t.super_fold_with(self), @@ -437,6 +438,7 @@ where match ct.kind() { ty::ConstKind::Bound(debruijn, bound_const) if debruijn == self.current_index => { let ct = self.delegate.replace_const(bound_const, ct.ty()); + debug_assert!(!ct.has_vars_bound_above(ty::INNERMOST)); ty::fold::shift_vars(self.tcx, ct, self.current_index.as_u32()) } _ => ct.super_fold_with(self), @@ -566,10 +568,7 @@ impl<'tcx> TyCtxt<'tcx> { )) }, consts: &mut |c, ty: Ty<'tcx>| { - self.mk_const(ty::ConstS { - kind: ty::ConstKind::Bound(ty::INNERMOST, shift_bv(c)), - ty, - }) + self.mk_const(ty::ConstKind::Bound(ty::INNERMOST, shift_bv(c)), ty) }, }, ) @@ -601,7 +600,7 @@ impl<'tcx> TyCtxt<'tcx> { .replace_late_bound_regions(sig, |_| { let br = ty::BoundRegion { var: ty::BoundVar::from_u32(counter), - kind: ty::BrAnon(counter), + kind: ty::BrAnon(counter, None), }; let r = self.mk_region(ty::ReLateBound(ty::INNERMOST, br)); counter += 1; @@ -609,7 +608,7 @@ impl<'tcx> TyCtxt<'tcx> { }) .0; let bound_vars = self.mk_bound_variable_kinds( - (0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i))), + (0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i, None))), ); Binder::bind_with_vars(inner, bound_vars) } @@ -629,7 +628,9 @@ impl<'tcx> TyCtxt<'tcx> { let index = entry.index(); let var = ty::BoundVar::from_usize(index); let kind = entry - .or_insert_with(|| ty::BoundVariableKind::Region(ty::BrAnon(index as u32))) + .or_insert_with(|| { + ty::BoundVariableKind::Region(ty::BrAnon(index as u32, None)) + }) .expect_region(); let br = ty::BoundRegion { var, kind }; self.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)) @@ -648,7 +649,7 @@ impl<'tcx> TyCtxt<'tcx> { let index = entry.index(); let var = ty::BoundVar::from_usize(index); let () = entry.or_insert_with(|| ty::BoundVariableKind::Const).expect_const(); - self.tcx.mk_const(ty::ConstS { ty, kind: ty::ConstKind::Bound(ty::INNERMOST, var) }) + self.tcx.mk_const(ty::ConstKind::Bound(ty::INNERMOST, var), ty) } } @@ -698,14 +699,10 @@ impl<'tcx> TypeFolder<'tcx> for Shifter<'tcx> { fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { match *r { - ty::ReLateBound(debruijn, br) => { - if self.amount == 0 || debruijn < self.current_index { - r - } else { - let debruijn = debruijn.shifted_in(self.amount); - let shifted = ty::ReLateBound(debruijn, br); - self.tcx.mk_region(shifted) - } + ty::ReLateBound(debruijn, br) if debruijn >= self.current_index => { + let debruijn = debruijn.shifted_in(self.amount); + let shifted = ty::ReLateBound(debruijn, br); + self.tcx.mk_region(shifted) } _ => r, } @@ -713,34 +710,30 @@ impl<'tcx> TypeFolder<'tcx> for Shifter<'tcx> { fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { match *ty.kind() { - ty::Bound(debruijn, bound_ty) => { - if self.amount == 0 || debruijn < self.current_index { - ty - } else { - let debruijn = debruijn.shifted_in(self.amount); - self.tcx.mk_ty(ty::Bound(debruijn, bound_ty)) - } + ty::Bound(debruijn, bound_ty) if debruijn >= self.current_index => { + let debruijn = debruijn.shifted_in(self.amount); + self.tcx.mk_ty(ty::Bound(debruijn, bound_ty)) } - _ => ty.super_fold_with(self), + _ if ty.has_vars_bound_at_or_above(self.current_index) => ty.super_fold_with(self), + _ => ty, } } fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { - if let ty::ConstKind::Bound(debruijn, bound_ct) = ct.kind() { - if self.amount == 0 || debruijn < self.current_index { - ct - } else { - let debruijn = debruijn.shifted_in(self.amount); - self.tcx.mk_const(ty::ConstS { - kind: ty::ConstKind::Bound(debruijn, bound_ct), - ty: ct.ty(), - }) - } + if let ty::ConstKind::Bound(debruijn, bound_ct) = ct.kind() + && debruijn >= self.current_index + { + let debruijn = debruijn.shifted_in(self.amount); + self.tcx.mk_const(ty::ConstKind::Bound(debruijn, bound_ct), ct.ty()) } else { ct.super_fold_with(self) } } + + fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> { + if p.has_vars_bound_at_or_above(self.current_index) { p.super_fold_with(self) } else { p } + } } pub fn shift_region<'tcx>( @@ -762,5 +755,9 @@ where { debug!("shift_vars(value={:?}, amount={})", value, amount); + if amount == 0 || !value.has_escaping_bound_vars() { + return value; + } + value.fold_with(&mut Shifter::new(tcx, amount)) } diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 19754d145..48329da3e 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -3,7 +3,7 @@ use crate::ty::{EarlyBinder, SubstsRef}; use rustc_ast as ast; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::DefId; -use rustc_span::symbol::Symbol; +use rustc_span::symbol::{kw, Symbol}; use rustc_span::Span; use super::{EarlyBoundRegion, InstantiatedPredicates, ParamConst, ParamTy, Predicate, TyCtxt}; @@ -78,6 +78,15 @@ impl GenericParamDef { } } + pub fn is_anonymous_lifetime(&self) -> bool { + match self.kind { + GenericParamDefKind::Lifetime => { + self.name == kw::UnderscoreLifetime || self.name == kw::Empty + } + _ => false, + } + } + pub fn default_value<'tcx>( &self, tcx: TyCtxt<'tcx>, @@ -92,6 +101,20 @@ impl GenericParamDef { _ => None, } } + + pub fn to_error<'tcx>( + &self, + tcx: TyCtxt<'tcx>, + preceding_substs: &[ty::GenericArg<'tcx>], + ) -> ty::GenericArg<'tcx> { + match &self.kind { + ty::GenericParamDefKind::Lifetime => tcx.lifetimes.re_static.into(), + ty::GenericParamDefKind::Type { .. } => tcx.ty_error().into(), + ty::GenericParamDefKind::Const { .. } => { + tcx.const_error(tcx.bound_type_of(self.def_id).subst(tcx, preceding_substs)).into() + } + } + } } #[derive(Default)] diff --git a/compiler/rustc_middle/src/ty/impls_ty.rs b/compiler/rustc_middle/src/ty/impls_ty.rs index d1c0d62ac..3e59c0b96 100644 --- a/compiler/rustc_middle/src/ty/impls_ty.rs +++ b/compiler/rustc_middle/src/ty/impls_ty.rs @@ -112,19 +112,6 @@ impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::AllocId { } } -// `Relocations` with default type parameters is a sorted map. -impl<'a, Prov> HashStable<StableHashingContext<'a>> for mir::interpret::ProvenanceMap<Prov> -where - Prov: HashStable<StableHashingContext<'a>>, -{ - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - self.len().hash_stable(hcx, hasher); - for reloc in self.iter() { - reloc.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 b7aa45572..33f727297 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs @@ -41,6 +41,13 @@ impl<'tcx> InhabitedPredicate<'tcx> { self.apply_inner(tcx, param_env, &|_| 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)); + result + } + fn apply_inner<E>( self, tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs index 279a728ea..ace81bc4f 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs @@ -5,7 +5,7 @@ //! //! # Example //! ```rust -//! enum Void {} +//! #![feature(never_type)] //! mod a { //! pub mod b { //! pub struct SecretlyUninhabited { @@ -15,6 +15,7 @@ //! } //! //! mod c { +//! enum Void {} //! pub struct AlsoSecretlyUninhabited { //! _priv: Void, //! } @@ -28,14 +29,14 @@ //! } //! ``` //! In this code, the type `Foo` will only be visibly uninhabited inside the -//! modules `b`, `c` and `d`. Calling `uninhabited_predicate` on `Foo` will +//! modules `b`, `c` and `d`. Calling `inhabited_predicate` on `Foo` will //! return `NotInModule(b) AND NotInModule(c)`. //! //! We need this information for pattern-matching on `Foo` or types that contain //! `Foo`. //! //! # Example -//! ```rust +//! ```ignore(illustrative) //! let foo_result: Result<T, Foo> = ... ; //! let Ok(t) = foo_result; //! ``` @@ -56,57 +57,6 @@ pub(crate) fn provide(providers: &mut ty::query::Providers) { ty::query::Providers { inhabited_predicate_adt, inhabited_predicate_type, ..*providers }; } -impl<'tcx> TyCtxt<'tcx> { - /// Checks whether a type is visibly uninhabited from a particular module. - /// - /// # Example - /// ``` - /// #![feature(never_type)] - /// # fn main() {} - /// enum Void {} - /// mod a { - /// pub mod b { - /// pub struct SecretlyUninhabited { - /// _priv: !, - /// } - /// } - /// } - /// - /// mod c { - /// use super::Void; - /// pub struct AlsoSecretlyUninhabited { - /// _priv: Void, - /// } - /// mod d { - /// } - /// } - /// - /// struct Foo { - /// x: a::b::SecretlyUninhabited, - /// y: c::AlsoSecretlyUninhabited, - /// } - /// ``` - /// In this code, the type `Foo` will only be visibly uninhabited inside the - /// modules b, c and d. This effects pattern-matching on `Foo` or types that - /// contain `Foo`. - /// - /// # Example - /// ```ignore (illustrative) - /// let foo_result: Result<T, Foo> = ... ; - /// let Ok(t) = foo_result; - /// ``` - /// This code should only compile in modules where the uninhabitedness of Foo is - /// visible. - pub fn is_ty_uninhabited_from( - self, - module: DefId, - ty: Ty<'tcx>, - param_env: ty::ParamEnv<'tcx>, - ) -> bool { - !ty.inhabited_predicate(self).apply(self, param_env, module) - } -} - /// Returns an `InhabitedPredicate` that is generic over type parameters and /// requires calling [`InhabitedPredicate::subst`] fn inhabited_predicate_adt(tcx: TyCtxt<'_>, def_id: DefId) -> InhabitedPredicate<'_> { @@ -170,6 +120,64 @@ impl<'tcx> Ty<'tcx> { _ => InhabitedPredicate::True, } } + + /// Checks whether a type is visibly uninhabited from a particular module. + /// + /// # Example + /// ``` + /// #![feature(never_type)] + /// # fn main() {} + /// enum Void {} + /// mod a { + /// pub mod b { + /// pub struct SecretlyUninhabited { + /// _priv: !, + /// } + /// } + /// } + /// + /// mod c { + /// use super::Void; + /// pub struct AlsoSecretlyUninhabited { + /// _priv: Void, + /// } + /// mod d { + /// } + /// } + /// + /// struct Foo { + /// x: a::b::SecretlyUninhabited, + /// y: c::AlsoSecretlyUninhabited, + /// } + /// ``` + /// In this code, the type `Foo` will only be visibly uninhabited inside the + /// modules b, c and d. This effects pattern-matching on `Foo` or types that + /// contain `Foo`. + /// + /// # Example + /// ```ignore (illustrative) + /// let foo_result: Result<T, Foo> = ... ; + /// let Ok(t) = foo_result; + /// ``` + /// This code should only compile in modules where the uninhabitedness of Foo is + /// visible. + pub fn is_inhabited_from( + self, + tcx: TyCtxt<'tcx>, + module: DefId, + param_env: ty::ParamEnv<'tcx>, + ) -> bool { + self.inhabited_predicate(tcx).apply(tcx, param_env, module) + } + + /// Returns true if the type is uninhabited without regard to visibility + pub fn is_privately_uninhabited( + self, + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ) -> bool { + !self.inhabited_predicate(tcx).apply_ignore_module(tcx, param_env) + } } /// N.B. this query should only be called through `Ty::inhabited_predicate` diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 6c1414f7b..586460986 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -276,28 +276,45 @@ impl<'tcx> InstanceDef<'tcx> { } } -impl<'tcx> fmt::Display for Instance<'tcx> { +fn fmt_instance( + f: &mut fmt::Formatter<'_>, + instance: &Instance<'_>, + type_length: rustc_session::Limit, +) -> fmt::Result { + ty::tls::with(|tcx| { + let substs = tcx.lift(instance.substs).expect("could not lift for printing"); + + let s = FmtPrinter::new_with_limit(tcx, Namespace::ValueNS, type_length) + .print_def_path(instance.def_id(), substs)? + .into_buffer(); + f.write_str(&s) + })?; + + match instance.def { + InstanceDef::Item(_) => Ok(()), + InstanceDef::VTableShim(_) => write!(f, " - shim(vtable)"), + InstanceDef::ReifyShim(_) => write!(f, " - shim(reify)"), + InstanceDef::Intrinsic(_) => write!(f, " - intrinsic"), + InstanceDef::Virtual(_, num) => write!(f, " - virtual#{}", num), + InstanceDef::FnPtrShim(_, ty) => write!(f, " - shim({})", ty), + InstanceDef::ClosureOnceShim { .. } => write!(f, " - shim"), + InstanceDef::DropGlue(_, None) => write!(f, " - shim(None)"), + InstanceDef::DropGlue(_, Some(ty)) => write!(f, " - shim(Some({}))", ty), + InstanceDef::CloneShim(_, ty) => write!(f, " - shim({})", ty), + } +} + +pub struct ShortInstance<'a, 'tcx>(pub &'a Instance<'tcx>, pub usize); + +impl<'a, 'tcx> fmt::Display for ShortInstance<'a, 'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - ty::tls::with(|tcx| { - let substs = tcx.lift(self.substs).expect("could not lift for printing"); - let s = FmtPrinter::new(tcx, Namespace::ValueNS) - .print_def_path(self.def_id(), substs)? - .into_buffer(); - f.write_str(&s) - })?; + fmt_instance(f, self.0, rustc_session::Limit(self.1)) + } +} - match self.def { - InstanceDef::Item(_) => Ok(()), - InstanceDef::VTableShim(_) => write!(f, " - shim(vtable)"), - InstanceDef::ReifyShim(_) => write!(f, " - shim(reify)"), - InstanceDef::Intrinsic(_) => write!(f, " - intrinsic"), - InstanceDef::Virtual(_, num) => write!(f, " - virtual#{}", num), - InstanceDef::FnPtrShim(_, ty) => write!(f, " - shim({})", ty), - InstanceDef::ClosureOnceShim { .. } => write!(f, " - shim"), - InstanceDef::DropGlue(_, None) => write!(f, " - shim(None)"), - InstanceDef::DropGlue(_, Some(ty)) => write!(f, " - shim(Some({}))", ty), - InstanceDef::CloneShim(_, ty) => write!(f, " - shim({})", ty), - } +impl<'tcx> fmt::Display for Instance<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + ty::tls::with(|tcx| fmt_instance(f, self, tcx.type_length_limit())) } } @@ -511,12 +528,12 @@ impl<'tcx> Instance<'tcx> { Instance::resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap().unwrap() } + #[instrument(level = "debug", skip(tcx), ret)] pub fn fn_once_adapter_instance( tcx: TyCtxt<'tcx>, closure_did: DefId, substs: ty::SubstsRef<'tcx>, ) -> Option<Instance<'tcx>> { - debug!("fn_once_adapter_shim({:?}, {:?})", closure_did, substs); let fn_once = tcx.require_lang_item(LangItem::FnOnce, None); let call_once = tcx .associated_items(fn_once) @@ -534,9 +551,9 @@ impl<'tcx> Instance<'tcx> { let sig = tcx.try_normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig).ok()?; assert_eq!(sig.inputs().len(), 1); - let substs = tcx.mk_substs_trait(self_ty, &[sig.inputs()[0].into()]); + let substs = tcx.mk_substs_trait(self_ty, [sig.inputs()[0].into()]); - debug!("fn_once_adapter_shim: self_ty={:?} sig={:?}", self_ty, sig); + debug!(?self_ty, ?sig); Some(Instance { def, substs }) } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 3312f44c6..488fd5678 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1,8 +1,6 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::ty::normalize_erasing_regions::NormalizationError; use crate::ty::{self, ReprOptions, Ty, TyCtxt, TypeVisitable}; -use rustc_ast as ast; -use rustc_attr as attr; use rustc_errors::{DiagnosticBuilder, Handler, IntoDiagnostic}; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -20,7 +18,6 @@ use std::ops::Bound; pub trait IntegerExt { fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool) -> Ty<'tcx>; - fn from_attr<C: HasDataLayout>(cx: &C, ity: attr::IntType) -> Integer; fn from_int_ty<C: HasDataLayout>(cx: &C, ity: ty::IntTy) -> Integer; fn from_uint_ty<C: HasDataLayout>(cx: &C, uty: ty::UintTy) -> Integer; fn repr_discr<'tcx>( @@ -49,22 +46,6 @@ impl IntegerExt for Integer { } } - /// Gets the Integer type from an attr::IntType. - fn from_attr<C: HasDataLayout>(cx: &C, ity: attr::IntType) -> Integer { - let dl = cx.data_layout(); - - match ity { - attr::SignedInt(ast::IntTy::I8) | attr::UnsignedInt(ast::UintTy::U8) => I8, - attr::SignedInt(ast::IntTy::I16) | attr::UnsignedInt(ast::UintTy::U16) => I16, - attr::SignedInt(ast::IntTy::I32) | attr::UnsignedInt(ast::UintTy::U32) => I32, - attr::SignedInt(ast::IntTy::I64) | attr::UnsignedInt(ast::UintTy::U64) => I64, - attr::SignedInt(ast::IntTy::I128) | attr::UnsignedInt(ast::UintTy::U128) => I128, - attr::SignedInt(ast::IntTy::Isize) | attr::UnsignedInt(ast::UintTy::Usize) => { - dl.ptr_sized_integer() - } - } - } - fn from_int_ty<C: HasDataLayout>(cx: &C, ity: ty::IntTy) -> Integer { match ity { ty::IntTy::I8 => I8, @@ -189,8 +170,8 @@ pub enum LayoutError<'tcx> { NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>), } -impl<'a> IntoDiagnostic<'a, !> for LayoutError<'a> { - fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, !> { +impl IntoDiagnostic<'_, !> for LayoutError<'_> { + fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, !> { let mut diag = handler.struct_fatal(""); match self { @@ -237,6 +218,18 @@ pub struct LayoutCx<'tcx, C> { pub param_env: ty::ParamEnv<'tcx>, } +impl<'tcx> LayoutCalculator for LayoutCx<'tcx, TyCtxt<'tcx>> { + type TargetDataLayoutRef = &'tcx TargetDataLayout; + + fn delay_bug(&self, txt: &str) { + self.tcx.sess.delay_span_bug(DUMMY_SP, txt); + } + + fn current_data_layout(&self) -> Self::TargetDataLayoutRef { + &self.tcx.data_layout + } +} + /// Type size "skeleton", i.e., the only information determining a type's size. /// While this is conservative, (aside from constant sizes, only pointers, /// newtypes thereof and null pointer optimized enums are allowed), it is @@ -610,7 +603,7 @@ where }) } - Variants::Multiple { ref variants, .. } => variants[variant_index], + Variants::Multiple { ref variants, .. } => cx.tcx().intern_layout(variants[variant_index].clone()), }; assert_eq!(*layout.variants(), Variants::Single { index: variant_index }); @@ -1126,8 +1119,8 @@ impl<'tcx> fmt::Display for FnAbiError<'tcx> { } } -impl<'tcx> IntoDiagnostic<'tcx, !> for FnAbiError<'tcx> { - fn into_diagnostic(self, handler: &'tcx Handler) -> DiagnosticBuilder<'tcx, !> { +impl IntoDiagnostic<'_, !> for FnAbiError<'_> { + fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, !> { handler.struct_fatal(self.to_string()) } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index a42d05706..3f99efd25 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -9,6 +9,8 @@ //! //! ["The `ty` module: representing types"]: https://rustc-dev-guide.rust-lang.org/ty.html +#![allow(rustc::usage_of_ty_tykind)] + pub use self::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable}; pub use self::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; pub use self::AssocItemContainer::*; @@ -26,13 +28,12 @@ use crate::ty::util::Discr; pub use adt::*; pub use assoc::*; pub use generics::*; -use hir::OpaqueTyOrigin; use rustc_ast as ast; use rustc_ast::node_id::NodeMap; use rustc_attr as attr; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; -use rustc_data_structures::intern::{Interned, WithStableHash}; +use rustc_data_structures::intern::Interned; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::tagged_ptr::CopyTaggedPtr; use rustc_hir as hir; @@ -48,7 +49,9 @@ use rustc_session::cstore::CrateStoreDyn; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{ExpnId, Span}; -use rustc_target::abi::{Align, VariantIdx}; +use rustc_target::abi::{Align, Integer, IntegerType, VariantIdx}; +pub use rustc_target::abi::{ReprFlags, ReprOptions}; +use rustc_type_ir::WithCachedTypeInfo; pub use subst::*; pub use vtable::*; @@ -76,15 +79,15 @@ pub use self::closure::{ CAPTURE_STRUCT_LOCAL, }; pub use self::consts::{ - Const, ConstInt, ConstKind, ConstS, InferConst, ScalarInt, UnevaluatedConst, ValTree, + Const, ConstInt, ConstKind, ConstS, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree, }; pub use self::context::{ tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, - CtxtInterners, DeducedParamAttrs, DelaySpanBugEmitted, FreeRegionInfo, GeneratorDiagnosticData, - GeneratorInteriorTypeCause, GlobalCtxt, Lift, OnDiskCache, TyCtxt, TypeckResults, UserType, - UserTypeAnnotationIndex, + CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GeneratorDiagnosticData, + GeneratorInteriorTypeCause, GlobalCtxt, Lift, OnDiskCache, TyCtxt, TyCtxtFeed, TypeckResults, + UserType, UserTypeAnnotationIndex, }; -pub use self::instance::{Instance, InstanceDef}; +pub use self::instance::{Instance, InstanceDef, ShortInstance}; pub use self::list::List; pub use self::parameterized::ParameterizedOverTcx; pub use self::rvalue_scopes::RvalueScopes; @@ -94,9 +97,10 @@ pub use self::sty::{ BoundVariableKind, CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstVid, EarlyBoundRegion, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig, FreeRegion, GenSig, GeneratorSubsts, GeneratorSubstsParts, InlineConstSubsts, - InlineConstSubstsParts, ParamConst, ParamTy, PolyExistentialProjection, - PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef, ProjectionTy, Region, RegionKind, - RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts, VarianceDiagInfo, + InlineConstSubstsParts, ParamConst, ParamTy, PolyExistentialPredicate, + PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef, + ProjectionTy, Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts, + VarianceDiagInfo, }; pub use self::trait_def::TraitDef; @@ -206,6 +210,8 @@ pub struct ResolverAstLowering { /// 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>, } #[derive(Clone, Copy, Debug)] @@ -410,7 +416,7 @@ impl Visibility<DefId> { self.map_id(|id| id.expect_local()) } - // Returns `true` if this item is visible anywhere in the local crate. + /// Returns `true` if this item is visible anywhere in the local crate. pub fn is_visible_locally(self) -> bool { match self { Visibility::Public => true, @@ -441,118 +447,44 @@ pub struct CReaderCacheKey { pub pos: usize, } -/// Represents a type. -/// -/// IMPORTANT: -/// - This is a very "dumb" struct (with no derives and no `impls`). -/// - Values of this type are always interned and thus unique, and are stored -/// as an `Interned<TyS>`. -/// - `Ty` (which contains a reference to a `Interned<TyS>`) or `Interned<TyS>` -/// should be used everywhere instead of `TyS`. In particular, `Ty` has most -/// of the relevant methods. -#[derive(PartialEq, Eq, PartialOrd, Ord)] -#[allow(rustc::usage_of_ty_tykind)] -pub(crate) struct TyS<'tcx> { - /// This field shouldn't be used directly and may be removed in the future. - /// Use `Ty::kind()` instead. - kind: TyKind<'tcx>, - - /// This field provides fast access to information that is also contained - /// in `kind`. - /// - /// This field shouldn't be used directly and may be removed in the future. - /// Use `Ty::flags()` instead. - flags: TypeFlags, - - /// This field provides fast access to information that is also contained - /// in `kind`. - /// - /// This is a kind of confusing thing: it stores the smallest - /// binder such that - /// - /// (a) the binder itself captures nothing but - /// (b) all the late-bound things within the type are captured - /// by some sub-binder. - /// - /// So, for a type without any late-bound things, like `u32`, this - /// will be *innermost*, because that is the innermost binder that - /// captures nothing. But for a type `&'D u32`, where `'D` is a - /// late-bound region with De Bruijn index `D`, this would be `D + 1` - /// -- the binder itself does not capture `D`, but `D` is captured - /// by an inner binder. - /// - /// We call this concept an "exclusive" binder `D` because all - /// De Bruijn indices within the type are contained within `0..D` - /// (exclusive). - outer_exclusive_binder: ty::DebruijnIndex, -} - -/// Use this rather than `TyS`, whenever possible. +/// Use this rather than `TyKind`, whenever possible. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)] #[rustc_diagnostic_item = "Ty"] #[rustc_pass_by_value] -pub struct Ty<'tcx>(Interned<'tcx, WithStableHash<TyS<'tcx>>>); +pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>); impl<'tcx> TyCtxt<'tcx> { /// A "bool" type used in rustc_mir_transform unit tests when we /// have not spun up a TyCtxt. - pub const BOOL_TY_FOR_UNIT_TESTING: Ty<'tcx> = Ty(Interned::new_unchecked(&WithStableHash { - internee: TyS { - kind: ty::Bool, + pub const BOOL_TY_FOR_UNIT_TESTING: Ty<'tcx> = + Ty(Interned::new_unchecked(&WithCachedTypeInfo { + internee: ty::Bool, + stable_hash: Fingerprint::ZERO, flags: TypeFlags::empty(), outer_exclusive_binder: DebruijnIndex::from_usize(0), - }, - stable_hash: Fingerprint::ZERO, - })); -} - -impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TyS<'tcx> { - #[inline] - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - let TyS { - kind, - - // The other fields just provide fast access to information that is - // also contained in `kind`, so no need to hash them. - flags: _, - - outer_exclusive_binder: _, - } = self; - - kind.hash_stable(hcx, hasher) - } + })); } impl ty::EarlyBoundRegion { /// 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 { - self.name != kw::UnderscoreLifetime + self.name != kw::UnderscoreLifetime && self.name != kw::Empty } } -/// Represents a predicate. -/// -/// See comments on `TyS`, which apply here too (albeit for -/// `PredicateS`/`Predicate` rather than `TyS`/`Ty`). -#[derive(Debug)] -pub(crate) struct PredicateS<'tcx> { - kind: Binder<'tcx, PredicateKind<'tcx>>, - flags: TypeFlags, - /// See the comment for the corresponding field of [TyS]. - outer_exclusive_binder: ty::DebruijnIndex, -} - -/// Use this rather than `PredicateS`, whenever possible. -#[derive(Clone, Copy, PartialEq, Eq, Hash)] +/// Use this rather than `PredicateKind`, whenever possible. +#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)] #[rustc_pass_by_value] -pub struct Predicate<'tcx>(Interned<'tcx, PredicateS<'tcx>>); +pub struct Predicate<'tcx>( + Interned<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>, +); impl<'tcx> Predicate<'tcx> { /// Gets the inner `Binder<'tcx, PredicateKind<'tcx>>`. #[inline] pub fn kind(self) -> Binder<'tcx, PredicateKind<'tcx>> { - self.0.kind + self.0.internee } #[inline(always)] @@ -572,13 +504,15 @@ impl<'tcx> Predicate<'tcx> { let kind = self .kind() .map_bound(|kind| match kind { - PredicateKind::Trait(TraitPredicate { trait_ref, constness, polarity }) => { - Some(PredicateKind::Trait(TraitPredicate { - trait_ref, - constness, - polarity: polarity.flip()?, - })) - } + PredicateKind::Clause(Clause::Trait(TraitPredicate { + trait_ref, + constness, + polarity, + })) => Some(PredicateKind::Clause(Clause::Trait(TraitPredicate { + trait_ref, + constness, + polarity: polarity.flip()?, + }))), _ => None, }) @@ -588,14 +522,14 @@ impl<'tcx> Predicate<'tcx> { } pub fn without_const(mut self, tcx: TyCtxt<'tcx>) -> Self { - if let PredicateKind::Trait(TraitPredicate { trait_ref, constness, polarity }) = self.kind().skip_binder() + if let PredicateKind::Clause(Clause::Trait(TraitPredicate { trait_ref, constness, polarity })) = self.kind().skip_binder() && constness != BoundConstness::NotConst { - self = tcx.mk_predicate(self.kind().rebind(PredicateKind::Trait(TraitPredicate { + self = tcx.mk_predicate(self.kind().rebind(PredicateKind::Clause(Clause::Trait(TraitPredicate { trait_ref, constness: BoundConstness::NotConst, polarity, - }))); + })))); } self } @@ -609,36 +543,22 @@ impl<'tcx> Predicate<'tcx> { pub fn allow_normalization(self) -> bool { match self.kind().skip_binder() { PredicateKind::WellFormed(_) => false, - PredicateKind::Trait(_) - | PredicateKind::RegionOutlives(_) - | PredicateKind::TypeOutlives(_) - | PredicateKind::Projection(_) + PredicateKind::Clause(Clause::Trait(_)) + | PredicateKind::Clause(Clause::RegionOutlives(_)) + | PredicateKind::Clause(Clause::TypeOutlives(_)) + | PredicateKind::Clause(Clause::Projection(_)) | PredicateKind::ObjectSafe(_) | PredicateKind::ClosureKind(_, _, _) | PredicateKind::Subtype(_) | PredicateKind::Coerce(_) | PredicateKind::ConstEvaluatable(_) | PredicateKind::ConstEquate(_, _) + | PredicateKind::Ambiguous | PredicateKind::TypeWellFormedFromEnv(_) => true, } } } -impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Predicate<'tcx> { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - let PredicateS { - ref kind, - - // The other fields just provide fast access to information that is - // also contained in `kind`, so no need to hash them. - flags: _, - outer_exclusive_binder: _, - } = self.0.0; - - kind.hash_stable(hcx, hasher); - } -} - impl rustc_errors::IntoDiagnosticArg for Predicate<'_> { fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { rustc_errors::DiagnosticArgValue::Str(std::borrow::Cow::Owned(self.to_string())) @@ -647,7 +567,9 @@ impl rustc_errors::IntoDiagnosticArg for Predicate<'_> { #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub enum PredicateKind<'tcx> { +/// A clause is something that can appear in where bounds or be inferred +/// by implied bounds. +pub enum Clause<'tcx> { /// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be /// the `Self` type of the trait reference and `A`, `B`, and `C` /// would be the type parameters. @@ -662,6 +584,13 @@ pub enum PredicateKind<'tcx> { /// `where <T as TraitRef>::Name == X`, approximately. /// See the `ProjectionPredicate` struct for details. Projection(ProjectionPredicate<'tcx>), +} + +#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +pub enum PredicateKind<'tcx> { + /// Prove a clause + Clause(Clause<'tcx>), /// No syntax: `T` well-formed. WellFormed(GenericArg<'tcx>), @@ -701,6 +630,10 @@ pub enum PredicateKind<'tcx> { /// /// Only used for Chalk. TypeWellFormedFromEnv(Ty<'tcx>), + + /// A marker predicate that is always ambiguous. + /// Used for coherence to mark opaque types as possibly equal to each other but ambiguous. + Ambiguous, } /// The crate outlives map is computed during typeck and contains the @@ -714,7 +647,7 @@ pub struct CratePredicatesMap<'tcx> { /// For each struct with outlive bounds, maps to a vector of the /// predicate of its outlive bounds. If an item has no outlives /// bounds, it will have no entry. - pub predicates: FxHashMap<DefId, &'tcx [(Predicate<'tcx>, Span)]>, + pub predicates: FxHashMap<DefId, &'tcx [(Clause<'tcx>, Span)]>, } impl<'tcx> Predicate<'tcx> { @@ -851,6 +784,10 @@ impl<'tcx> TraitPredicate<'tcx> { } } + pub fn with_self_type(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { + Self { trait_ref: self.trait_ref.with_self_type(tcx, self_ty), ..self } + } + pub fn def_id(self) -> DefId { self.trait_ref.def_id } @@ -902,9 +839,10 @@ impl<'tcx> PolyTraitPredicate<'tcx> { } } +/// `A: B` #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct OutlivesPredicate<A, B>(pub A, pub B); // `A: B` +pub struct OutlivesPredicate<A, B>(pub A, pub B); pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>; pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>; pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder<'tcx, RegionOutlivesPredicate<'tcx>>; @@ -1003,7 +941,7 @@ impl<'tcx> Term<'tcx> { unsafe { match ptr & TAG_MASK { TYPE_TAG => TermKind::Ty(Ty(Interned::new_unchecked( - &*((ptr & !TAG_MASK) as *const WithStableHash<ty::TyS<'tcx>>), + &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::TyKind<'tcx>>), ))), CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked( &*((ptr & !TAG_MASK) as *const ty::ConstS<'tcx>), @@ -1047,7 +985,7 @@ impl<'tcx> TermKind<'tcx> { TermKind::Ty(ty) => { // Ensure we can use the tag bits. assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0); - (TYPE_TAG, ty.0.0 as *const WithStableHash<ty::TyS<'tcx>> as usize) + (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo<ty::TyKind<'tcx>> as usize) } TermKind::Const(ct) => { // Ensure we can use the tag bits. @@ -1125,12 +1063,12 @@ impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> { } } -pub trait ToPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx>; +pub trait ToPredicate<'tcx, P = Predicate<'tcx>> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> P; } -impl<'tcx> ToPredicate<'tcx> for Predicate<'tcx> { - fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { +impl<'tcx, T> ToPredicate<'tcx, T> for T { + fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> T { self } } @@ -1142,27 +1080,53 @@ impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> { } } +impl<'tcx> ToPredicate<'tcx> for Clause<'tcx> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + tcx.mk_predicate(ty::Binder::dummy(ty::PredicateKind::Clause(self))) + } +} + +impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + let pred: PolyTraitPredicate<'tcx> = self.to_predicate(tcx); + pred.to_predicate(tcx) + } +} + +impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for Binder<'tcx, TraitRef<'tcx>> { + #[inline(always)] + fn to_predicate(self, _: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> { + self.map_bound(|trait_ref| TraitPredicate { + trait_ref, + constness: ty::BoundConstness::NotConst, + polarity: ty::ImplPolarity::Positive, + }) + } +} + impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - self.map_bound(PredicateKind::Trait).to_predicate(tcx) + self.map_bound(|p| PredicateKind::Clause(Clause::Trait(p))).to_predicate(tcx) } } impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - self.map_bound(PredicateKind::RegionOutlives).to_predicate(tcx) + self.map_bound(|p| PredicateKind::Clause(Clause::RegionOutlives(p))).to_predicate(tcx) } } impl<'tcx> ToPredicate<'tcx> for PolyTypeOutlivesPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - self.map_bound(PredicateKind::TypeOutlives).to_predicate(tcx) + self.map_bound(|p| PredicateKind::Clause(Clause::TypeOutlives(p))).to_predicate(tcx) } } impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - self.map_bound(PredicateKind::Projection).to_predicate(tcx) + self.map_bound(|p| PredicateKind::Clause(Clause::Projection(p))).to_predicate(tcx) } } @@ -1170,17 +1134,18 @@ impl<'tcx> Predicate<'tcx> { pub fn to_opt_poly_trait_pred(self) -> Option<PolyTraitPredicate<'tcx>> { let predicate = self.kind(); match predicate.skip_binder() { - PredicateKind::Trait(t) => Some(predicate.rebind(t)), - PredicateKind::Projection(..) + PredicateKind::Clause(Clause::Trait(t)) => Some(predicate.rebind(t)), + PredicateKind::Clause(Clause::Projection(..)) | PredicateKind::Subtype(..) | PredicateKind::Coerce(..) - | PredicateKind::RegionOutlives(..) + | PredicateKind::Clause(Clause::RegionOutlives(..)) | PredicateKind::WellFormed(..) | PredicateKind::ObjectSafe(..) | PredicateKind::ClosureKind(..) - | PredicateKind::TypeOutlives(..) + | PredicateKind::Clause(Clause::TypeOutlives(..)) | PredicateKind::ConstEvaluatable(..) | PredicateKind::ConstEquate(..) + | PredicateKind::Ambiguous | PredicateKind::TypeWellFormedFromEnv(..) => None, } } @@ -1188,17 +1153,18 @@ impl<'tcx> Predicate<'tcx> { pub fn to_opt_poly_projection_pred(self) -> Option<PolyProjectionPredicate<'tcx>> { let predicate = self.kind(); match predicate.skip_binder() { - PredicateKind::Projection(t) => Some(predicate.rebind(t)), - PredicateKind::Trait(..) + PredicateKind::Clause(Clause::Projection(t)) => Some(predicate.rebind(t)), + PredicateKind::Clause(Clause::Trait(..)) | PredicateKind::Subtype(..) | PredicateKind::Coerce(..) - | PredicateKind::RegionOutlives(..) + | PredicateKind::Clause(Clause::RegionOutlives(..)) | PredicateKind::WellFormed(..) | PredicateKind::ObjectSafe(..) | PredicateKind::ClosureKind(..) - | PredicateKind::TypeOutlives(..) + | PredicateKind::Clause(Clause::TypeOutlives(..)) | PredicateKind::ConstEvaluatable(..) | PredicateKind::ConstEquate(..) + | PredicateKind::Ambiguous | PredicateKind::TypeWellFormedFromEnv(..) => None, } } @@ -1206,17 +1172,18 @@ impl<'tcx> Predicate<'tcx> { pub fn to_opt_type_outlives(self) -> Option<PolyTypeOutlivesPredicate<'tcx>> { let predicate = self.kind(); match predicate.skip_binder() { - PredicateKind::TypeOutlives(data) => Some(predicate.rebind(data)), - PredicateKind::Trait(..) - | PredicateKind::Projection(..) + PredicateKind::Clause(Clause::TypeOutlives(data)) => Some(predicate.rebind(data)), + PredicateKind::Clause(Clause::Trait(..)) + | PredicateKind::Clause(Clause::Projection(..)) | PredicateKind::Subtype(..) | PredicateKind::Coerce(..) - | PredicateKind::RegionOutlives(..) + | PredicateKind::Clause(Clause::RegionOutlives(..)) | PredicateKind::WellFormed(..) | PredicateKind::ObjectSafe(..) | PredicateKind::ClosureKind(..) | PredicateKind::ConstEvaluatable(..) | PredicateKind::ConstEquate(..) + | PredicateKind::Ambiguous | PredicateKind::TypeWellFormedFromEnv(..) => None, } } @@ -1257,7 +1224,7 @@ impl<'tcx> InstantiatedPredicates<'tcx> { } } -#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable, Lift)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable, Lift)] #[derive(TypeFoldable, TypeVisitable)] pub struct OpaqueTypeKey<'tcx> { pub def_id: LocalDefId, @@ -1319,7 +1286,6 @@ impl<'tcx> OpaqueHiddenType<'tcx> { tcx: TyCtxt<'tcx>, // typeck errors have subpar spans for opaque types, so delay error reporting until borrowck. ignore_errors: bool, - origin: OpaqueTyOrigin, ) -> Self { let OpaqueTypeKey { def_id, substs } = opaque_type_key; @@ -1332,78 +1298,10 @@ impl<'tcx> OpaqueHiddenType<'tcx> { let id_substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); debug!(?id_substs); - let map = substs.iter().zip(id_substs); - - let map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>> = match origin { - // HACK: The HIR lowering for async fn does not generate - // any `+ Captures<'x>` bounds for the `impl Future<...>`, so all async fns with lifetimes - // would now fail to compile. We should probably just make hir lowering fill this in properly. - OpaqueTyOrigin::AsyncFn(_) => map.collect(), - OpaqueTyOrigin::FnReturn(_) | OpaqueTyOrigin::TyAlias => { - // Opaque types may only use regions that are bound. So for - // ```rust - // type Foo<'a, 'b, 'c> = impl Trait<'a> + 'b; - // ``` - // we may not use `'c` in the hidden type. - struct OpaqueTypeLifetimeCollector<'tcx> { - lifetimes: FxHashSet<ty::Region<'tcx>>, - } - - impl<'tcx> ty::TypeVisitor<'tcx> for OpaqueTypeLifetimeCollector<'tcx> { - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { - self.lifetimes.insert(r); - r.super_visit_with(self) - } - } - - let mut collector = OpaqueTypeLifetimeCollector { lifetimes: Default::default() }; - - for pred in tcx.bound_explicit_item_bounds(def_id.to_def_id()).transpose_iter() { - let pred = pred.map_bound(|(pred, _)| *pred).subst(tcx, id_substs); - - trace!(pred=?pred.kind()); - - // We only ignore opaque type substs if the opaque type is the outermost type. - // The opaque type may be nested within itself via recursion in e.g. - // type Foo<'a> = impl PartialEq<Foo<'a>>; - // which thus mentions `'a` and should thus accept hidden types that borrow 'a - // instead of requiring an additional `+ 'a`. - match pred.kind().skip_binder() { - ty::PredicateKind::Trait(TraitPredicate { - trait_ref: ty::TraitRef { def_id: _, substs }, - constness: _, - polarity: _, - }) => { - trace!(?substs); - for subst in &substs[1..] { - subst.visit_with(&mut collector); - } - } - ty::PredicateKind::Projection(ty::ProjectionPredicate { - projection_ty: ty::ProjectionTy { substs, item_def_id: _ }, - term, - }) => { - for subst in &substs[1..] { - subst.visit_with(&mut collector); - } - term.visit_with(&mut collector); - } - _ => { - pred.visit_with(&mut collector); - } - } - } - let lifetimes = collector.lifetimes; - trace!(?lifetimes); - map.filter(|(_, v)| { - let ty::GenericArgKind::Lifetime(lt) = v.unpack() else { - return true; - }; - lifetimes.contains(<) - }) - .collect() - } - }; + // This zip may have several times the same lifetime in `substs` paired with a different + // lifetime from `id_substs`. Simply `collect`ing the iterator is the correct behaviour: + // it will pick the last one, which is the one we introduced in the impl-trait desugaring. + let map = substs.iter().zip(id_substs).collect(); debug!("map = {:#?}", map); // Convert the type from the function into a type valid outside @@ -1748,7 +1646,7 @@ impl<'tcx> ParamEnv<'tcx> { } ParamEnv::new( - tcx.normalize_opaque_types(self.caller_bounds()), + tcx.reveal_opaque_types_in_bounds(self.caller_bounds()), Reveal::All, self.constness(), ) @@ -1852,15 +1750,13 @@ pub struct VariantDef { pub def_id: DefId, /// `DefId` that identifies the variant's constructor. /// If this variant is a struct variant, then this is `None`. - pub ctor_def_id: Option<DefId>, + pub ctor: Option<(CtorKind, DefId)>, /// Variant or struct name. pub name: Symbol, /// Discriminant of this variant. pub discr: VariantDiscr, /// Fields of this variant. pub fields: Vec<FieldDef>, - /// Type of constructor of variant. - pub ctor_kind: CtorKind, /// Flags of the variant (e.g. is field list non-exhaustive)? flags: VariantFlags, } @@ -1885,19 +1781,18 @@ impl VariantDef { pub fn new( name: Symbol, variant_did: Option<DefId>, - ctor_def_id: Option<DefId>, + ctor: Option<(CtorKind, DefId)>, discr: VariantDiscr, fields: Vec<FieldDef>, - ctor_kind: CtorKind, adt_kind: AdtKind, parent_did: DefId, recovered: bool, is_field_list_non_exhaustive: bool, ) -> Self { debug!( - "VariantDef::new(name = {:?}, variant_did = {:?}, ctor_def_id = {:?}, discr = {:?}, - fields = {:?}, ctor_kind = {:?}, adt_kind = {:?}, parent_did = {:?})", - name, variant_did, ctor_def_id, discr, fields, ctor_kind, adt_kind, parent_did, + "VariantDef::new(name = {:?}, variant_did = {:?}, ctor = {:?}, discr = {:?}, + fields = {:?}, adt_kind = {:?}, parent_did = {:?})", + name, variant_did, ctor, discr, fields, adt_kind, parent_did, ); let mut flags = VariantFlags::NO_VARIANT_FLAGS; @@ -1909,15 +1804,7 @@ impl VariantDef { flags |= VariantFlags::IS_RECOVERED; } - VariantDef { - def_id: variant_did.unwrap_or(parent_did), - ctor_def_id, - name, - discr, - fields, - ctor_kind, - flags, - } + VariantDef { def_id: variant_did.unwrap_or(parent_did), ctor, name, discr, fields, flags } } /// Is this field list non-exhaustive? @@ -1936,6 +1823,16 @@ impl VariantDef { pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident { Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap()) } + + #[inline] + pub fn ctor_kind(&self) -> Option<CtorKind> { + self.ctor.map(|(kind, _)| kind) + } + + #[inline] + pub fn ctor_def_id(&self) -> Option<DefId> { + self.ctor.map(|(_, def_id)| def_id) + } } impl PartialEq for VariantDef { @@ -1948,26 +1845,8 @@ impl PartialEq for VariantDef { // definition of `VariantDef` changes, a compile-error will be produced, // reminding us to revisit this assumption. - let Self { - def_id: lhs_def_id, - ctor_def_id: _, - name: _, - discr: _, - fields: _, - ctor_kind: _, - flags: _, - } = &self; - - let Self { - def_id: rhs_def_id, - ctor_def_id: _, - name: _, - discr: _, - fields: _, - ctor_kind: _, - flags: _, - } = other; - + let Self { def_id: lhs_def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = &self; + let Self { def_id: rhs_def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = other; lhs_def_id == rhs_def_id } } @@ -1984,9 +1863,7 @@ impl Hash for VariantDef { // of `VariantDef` changes, a compile-error will be produced, reminding // us to revisit this assumption. - let Self { def_id, ctor_def_id: _, name: _, discr: _, fields: _, ctor_kind: _, flags: _ } = - &self; - + let Self { def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = &self; def_id.hash(s) } } @@ -2047,163 +1924,6 @@ impl Hash for FieldDef { } } -bitflags! { - #[derive(TyEncodable, TyDecodable, Default, HashStable)] - pub struct ReprFlags: u8 { - const IS_C = 1 << 0; - const IS_SIMD = 1 << 1; - const IS_TRANSPARENT = 1 << 2; - // Internal only for now. If true, don't reorder fields. - const IS_LINEAR = 1 << 3; - // If true, the type's layout can be randomized using - // the seed stored in `ReprOptions.layout_seed` - const RANDOMIZE_LAYOUT = 1 << 4; - // Any of these flags being set prevent field reordering optimisation. - const IS_UNOPTIMISABLE = ReprFlags::IS_C.bits - | ReprFlags::IS_SIMD.bits - | ReprFlags::IS_LINEAR.bits; - } -} - -/// Represents the repr options provided by the user, -#[derive(Copy, Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable, Default, HashStable)] -pub struct ReprOptions { - pub int: Option<attr::IntType>, - pub align: Option<Align>, - pub pack: Option<Align>, - pub flags: ReprFlags, - /// The seed to be used for randomizing a type's layout - /// - /// Note: This could technically be a `[u8; 16]` (a `u128`) which would - /// be the "most accurate" hash as it'd encompass the item and crate - /// hash without loss, but it does pay the price of being larger. - /// Everything's a tradeoff, a `u64` seed should be sufficient for our - /// purposes (primarily `-Z randomize-layout`) - pub field_shuffle_seed: u64, -} - -impl ReprOptions { - pub fn new(tcx: TyCtxt<'_>, did: DefId) -> ReprOptions { - let mut flags = ReprFlags::empty(); - let mut size = None; - let mut max_align: Option<Align> = None; - let mut min_pack: Option<Align> = None; - - // Generate a deterministically-derived seed from the item's path hash - // to allow for cross-crate compilation to actually work - let mut field_shuffle_seed = tcx.def_path_hash(did).0.to_smaller_hash(); - - // If the user defined a custom seed for layout randomization, xor the item's - // path hash with the user defined seed, this will allowing determinism while - // still allowing users to further randomize layout generation for e.g. fuzzing - if let Some(user_seed) = tcx.sess.opts.unstable_opts.layout_seed { - field_shuffle_seed ^= user_seed; - } - - for attr in tcx.get_attrs(did, sym::repr) { - for r in attr::parse_repr_attr(&tcx.sess, attr) { - flags.insert(match r { - attr::ReprC => ReprFlags::IS_C, - attr::ReprPacked(pack) => { - let pack = Align::from_bytes(pack as u64).unwrap(); - min_pack = Some(if let Some(min_pack) = min_pack { - min_pack.min(pack) - } else { - pack - }); - ReprFlags::empty() - } - attr::ReprTransparent => ReprFlags::IS_TRANSPARENT, - attr::ReprSimd => ReprFlags::IS_SIMD, - attr::ReprInt(i) => { - size = Some(i); - ReprFlags::empty() - } - attr::ReprAlign(align) => { - max_align = max_align.max(Some(Align::from_bytes(align as u64).unwrap())); - ReprFlags::empty() - } - }); - } - } - - // If `-Z randomize-layout` was enabled for the type definition then we can - // consider performing layout randomization - if tcx.sess.opts.unstable_opts.randomize_layout { - flags.insert(ReprFlags::RANDOMIZE_LAYOUT); - } - - // This is here instead of layout because the choice must make it into metadata. - if !tcx.consider_optimizing(|| format!("Reorder fields of {:?}", tcx.def_path_str(did))) { - flags.insert(ReprFlags::IS_LINEAR); - } - - Self { int: size, align: max_align, pack: min_pack, flags, field_shuffle_seed } - } - - #[inline] - pub fn simd(&self) -> bool { - self.flags.contains(ReprFlags::IS_SIMD) - } - - #[inline] - pub fn c(&self) -> bool { - self.flags.contains(ReprFlags::IS_C) - } - - #[inline] - pub fn packed(&self) -> bool { - self.pack.is_some() - } - - #[inline] - pub fn transparent(&self) -> bool { - self.flags.contains(ReprFlags::IS_TRANSPARENT) - } - - #[inline] - pub fn linear(&self) -> bool { - self.flags.contains(ReprFlags::IS_LINEAR) - } - - /// Returns the discriminant type, given these `repr` options. - /// This must only be called on enums! - pub fn discr_type(&self) -> attr::IntType { - self.int.unwrap_or(attr::SignedInt(ast::IntTy::Isize)) - } - - /// Returns `true` if this `#[repr()]` should inhabit "smart enum - /// layout" optimizations, such as representing `Foo<&T>` as a - /// single pointer. - pub fn inhibit_enum_layout_opt(&self) -> bool { - self.c() || self.int.is_some() - } - - /// Returns `true` if this `#[repr()]` should inhibit struct field reordering - /// optimizations, such as with `repr(C)`, `repr(packed(1))`, or `repr(<int>)`. - pub fn inhibit_struct_field_reordering_opt(&self) -> bool { - if let Some(pack) = self.pack { - if pack.bytes() == 1 { - return true; - } - } - - self.flags.intersects(ReprFlags::IS_UNOPTIMISABLE) || self.int.is_some() - } - - /// Returns `true` if this type is valid for reordering and `-Z randomize-layout` - /// was enabled for its declaration crate - pub fn can_randomize_type_layout(&self) -> bool { - !self.inhibit_struct_field_reordering_opt() - && self.flags.contains(ReprFlags::RANDOMIZE_LAYOUT) - } - - /// Returns `true` if this `#[repr()]` should inhibit union ABI optimisations. - pub fn inhibit_union_abi_opt(&self) -> bool { - self.c() - } -} - impl<'tcx> FieldDef { /// Returns the type of this field. The resulting type is not normalized. The `subst` is /// typically obtained via the second field of [`TyKind::Adt`]. @@ -2271,6 +1991,81 @@ impl<'tcx> TyCtxt<'tcx> { .filter(move |item| item.kind == AssocKind::Fn && item.defaultness(self).has_value()) } + pub fn repr_options_of_def(self, did: DefId) -> ReprOptions { + let mut flags = ReprFlags::empty(); + let mut size = None; + let mut max_align: Option<Align> = None; + let mut min_pack: Option<Align> = None; + + // Generate a deterministically-derived seed from the item's path hash + // to allow for cross-crate compilation to actually work + let mut field_shuffle_seed = self.def_path_hash(did).0.to_smaller_hash(); + + // If the user defined a custom seed for layout randomization, xor the item's + // path hash with the user defined seed, this will allowing determinism while + // still allowing users to further randomize layout generation for e.g. fuzzing + if let Some(user_seed) = self.sess.opts.unstable_opts.layout_seed { + field_shuffle_seed ^= user_seed; + } + + for attr in self.get_attrs(did, sym::repr) { + for r in attr::parse_repr_attr(&self.sess, attr) { + flags.insert(match r { + attr::ReprC => ReprFlags::IS_C, + attr::ReprPacked(pack) => { + let pack = Align::from_bytes(pack as u64).unwrap(); + min_pack = Some(if let Some(min_pack) = min_pack { + min_pack.min(pack) + } else { + pack + }); + ReprFlags::empty() + } + attr::ReprTransparent => ReprFlags::IS_TRANSPARENT, + attr::ReprSimd => ReprFlags::IS_SIMD, + attr::ReprInt(i) => { + size = Some(match i { + attr::IntType::SignedInt(x) => match x { + ast::IntTy::Isize => IntegerType::Pointer(true), + ast::IntTy::I8 => IntegerType::Fixed(Integer::I8, true), + ast::IntTy::I16 => IntegerType::Fixed(Integer::I16, true), + ast::IntTy::I32 => IntegerType::Fixed(Integer::I32, true), + ast::IntTy::I64 => IntegerType::Fixed(Integer::I64, true), + ast::IntTy::I128 => IntegerType::Fixed(Integer::I128, true), + }, + attr::IntType::UnsignedInt(x) => match x { + ast::UintTy::Usize => IntegerType::Pointer(false), + ast::UintTy::U8 => IntegerType::Fixed(Integer::I8, false), + ast::UintTy::U16 => IntegerType::Fixed(Integer::I16, false), + ast::UintTy::U32 => IntegerType::Fixed(Integer::I32, false), + ast::UintTy::U64 => IntegerType::Fixed(Integer::I64, false), + ast::UintTy::U128 => IntegerType::Fixed(Integer::I128, false), + }, + }); + ReprFlags::empty() + } + attr::ReprAlign(align) => { + max_align = max_align.max(Some(Align::from_bytes(align as u64).unwrap())); + ReprFlags::empty() + } + }); + } + } + + // If `-Z randomize-layout` was enabled for the type definition then we can + // consider performing layout randomization + if self.sess.opts.unstable_opts.randomize_layout { + flags.insert(ReprFlags::RANDOMIZE_LAYOUT); + } + + // This is here instead of layout because the choice must make it into metadata. + if !self.consider_optimizing(|| format!("Reorder fields of {:?}", self.def_path_str(did))) { + flags.insert(ReprFlags::IS_LINEAR); + } + + ReprOptions { int: size, align: max_align, pack: min_pack, flags, field_shuffle_seed } + } + /// Look up the name of a definition across crates. This does not look at HIR. pub fn opt_item_name(self, def_id: DefId) -> Option<Symbol> { if let Some(cnum) = def_id.as_crate_root() { @@ -2322,10 +2117,6 @@ impl<'tcx> TyCtxt<'tcx> { } } - pub fn field_index(self, hir_id: hir::HirId, typeck_results: &TypeckResults<'_>) -> usize { - typeck_results.field_indices().get(hir_id).cloned().expect("no index for a field") - } - pub fn find_field_index(self, ident: Ident, variant: &VariantDef) -> Option<usize> { variant .fields @@ -2506,6 +2297,10 @@ impl<'tcx> TyCtxt<'tcx> { self.trait_def(trait_def_id).has_auto_impl } + pub fn trait_is_coinductive(self, trait_def_id: DefId) -> bool { + self.trait_is_auto(trait_def_id) || self.lang_items().sized_trait() == Some(trait_def_id) + } + /// Returns layout of a generator. Layout might be unavailable if the /// generator is tainted by errors. pub fn generator_layout(self, def_id: DefId) -> Option<&'tcx GeneratorLayout<'tcx>> { @@ -2550,11 +2345,11 @@ impl<'tcx> TyCtxt<'tcx> { /// Looks up the span of `impl_did` if the impl is local; otherwise returns `Err` /// with the name of the crate containing the impl. - pub fn span_of_impl(self, impl_did: DefId) -> Result<Span, Symbol> { - if let Some(impl_did) = impl_did.as_local() { - Ok(self.def_span(impl_did)) + pub fn span_of_impl(self, impl_def_id: DefId) -> Result<Span, Symbol> { + if let Some(impl_def_id) = impl_def_id.as_local() { + Ok(self.def_span(impl_def_id)) } else { - Err(self.crate_name(impl_did.krate)) + Err(self.crate_name(impl_def_id.krate)) } } @@ -2782,8 +2577,7 @@ mod size_asserts { use super::*; use rustc_data_structures::static_assert_size; // tidy-alphabetical-start - static_assert_size!(PredicateS<'_>, 48); - static_assert_size!(TyS<'_>, 40); - static_assert_size!(WithStableHash<TyS<'_>>, 56); + static_assert_size!(PredicateKind<'_>, 32); + static_assert_size!(WithCachedTypeInfo<TyKind<'_>>, 56); // tidy-alphabetical-end } diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs index b05c63109..98cd92007 100644 --- a/compiler/rustc_middle/src/ty/opaque_types.rs +++ b/compiler/rustc_middle/src/ty/opaque_types.rs @@ -1,7 +1,8 @@ +use crate::error::ConstNotUsedTraitAlias; +use crate::ty::fold::{TypeFolder, TypeSuperFoldable}; +use crate::ty::subst::{GenericArg, GenericArgKind}; +use crate::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_data_structures::fx::FxHashMap; -use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable}; -use rustc_middle::ty::subst::{GenericArg, GenericArgKind}; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_span::Span; /// Converts generic params of a TypeFoldable from one @@ -201,7 +202,7 @@ impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> { Some(u) => panic!("const mapped to unexpected kind: {:?}", u), None => { if !self.ignore_errors { - self.tcx.sess.emit_err(ty::ConstNotUsedTraitAlias { + self.tcx.sess.emit_err(ConstNotUsedTraitAlias { ct: ct.to_string(), span: self.span, }); diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index e1e705a92..9e69544d2 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -4,9 +4,8 @@ use rustc_index::vec::{Idx, IndexVec}; use crate::middle::exported_symbols::ExportedSymbol; use crate::mir::Body; -use crate::ty::abstract_const::Node; use crate::ty::{ - self, Const, FnSig, GeneratorDiagnosticData, GenericPredicates, Predicate, TraitRef, Ty, + self, Clause, Const, FnSig, GeneratorDiagnosticData, GenericPredicates, Predicate, TraitRef, Ty, }; pub trait ParameterizedOverTcx: 'static { @@ -54,6 +53,7 @@ trivially_parameterized_over_tcx! { usize, (), u32, + bool, std::string::String, crate::metadata::ModChild, crate::middle::codegen_fn_attrs::CodegenFnAttrs, @@ -70,7 +70,7 @@ trivially_parameterized_over_tcx! { ty::adjustment::CoerceUnsizedInfo, ty::fast_reject::SimplifiedTypeGen<DefId>, rustc_ast::Attribute, - rustc_ast::MacArgs, + rustc_ast::DelimArgs, rustc_attr::ConstStability, rustc_attr::DefaultBodyStability, rustc_attr::Deprecation, @@ -122,8 +122,8 @@ parameterized_over_tcx! { TraitRef, Const, Predicate, + Clause, GeneratorDiagnosticData, Body, - Node, ExportedSymbol, } diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 44b9548db..667298b9b 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -63,7 +63,7 @@ pub trait Printer<'tcx>: Sized { fn print_dyn_existential( self, - predicates: &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>, + predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>, ) -> Result<Self::DynExistential, Self::Error>; fn print_const(self, ct: ty::Const<'tcx>) -> Result<Self::Const, Self::Error>; @@ -308,9 +308,7 @@ impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for Ty<'tcx> { } } -impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> - for &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>> -{ +impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> { type Output = P::DynExistential; type Error = P::Error; fn print(&self, cx: P) -> Result<Self::Output, Self::Error> { diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index ef9aa236b..5303341ba 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -11,8 +11,10 @@ use rustc_hir as hir; use rustc_hir::def::{self, CtorKind, DefKind, Namespace}; use rustc_hir::def_id::{DefId, DefIdSet, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData}; +use rustc_hir::LangItem; use rustc_session::config::TrimmedDefPaths; use rustc_session::cstore::{ExternCrate, ExternCrateSource}; +use rustc_session::Limit; use rustc_span::symbol::{kw, Ident, Symbol}; use rustc_target::abi::Size; use rustc_target::spec::abi::Abi; @@ -63,7 +65,6 @@ thread_local! { static NO_TRIMMED_PATH: Cell<bool> = const { Cell::new(false) }; static NO_QUERIES: Cell<bool> = const { Cell::new(false) }; static NO_VISIBLE_PATH: Cell<bool> = const { Cell::new(false) }; - static NO_VERBOSE_CONSTANTS: Cell<bool> = const { Cell::new(false) }; } macro_rules! define_helper { @@ -118,9 +119,6 @@ define_helper!( /// Prevent selection of visible paths. `Display` impl of DefId will prefer /// visible (public) reexports of types as paths. fn with_no_visible_paths(NoVisibleGuard, NO_VISIBLE_PATH); - /// Prevent verbose printing of constants. Verbose printing of constants is - /// never desirable in some contexts like `std::any::type_name`. - fn with_no_verbose_constants(NoVerboseConstantsGuard, NO_VERBOSE_CONSTANTS); ); /// The "region highlights" are used to control region printing during @@ -600,7 +598,7 @@ pub trait PrettyPrinter<'tcx>: } ty::FnPtr(ref bare_fn) => p!(print(bare_fn)), ty::Infer(infer_ty) => { - let verbose = self.tcx().sess.verbose(); + let verbose = self.should_print_verbose(); if let ty::TyVar(ty_vid) = infer_ty { if let Some(name) = self.ty_infer_name(ty_vid) { p!(write("{}", name)) @@ -642,7 +640,7 @@ pub trait PrettyPrinter<'tcx>: p!(print_def_path(def_id, &[])); } ty::Projection(ref data) => { - if !(self.tcx().sess.verbose() || NO_QUERIES.with(|q| q.get())) + if !(self.should_print_verbose() || NO_QUERIES.with(|q| q.get())) && self.tcx().def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder { return self.pretty_print_opaque_impl_type(data.item_def_id, data.substs); @@ -658,7 +656,7 @@ pub trait PrettyPrinter<'tcx>: // only affect certain debug messages (e.g. messages printed // from `rustc_middle::ty` during the computation of `tcx.predicates_of`), // and should have no effect on any compiler output. - if self.tcx().sess.verbose() || NO_QUERIES.with(|q| q.get()) { + if self.should_print_verbose() || NO_QUERIES.with(|q| q.get()) { p!(write("Opaque({:?}, {:?})", def_id, substs)); return Ok(self); } @@ -684,13 +682,19 @@ pub trait PrettyPrinter<'tcx>: ty::Str => p!("str"), ty::Generator(did, substs, movability) => { p!(write("[")); - match movability { - hir::Movability::Movable => {} - hir::Movability::Static => p!("static "), + let generator_kind = self.tcx().generator_kind(did).unwrap(); + let should_print_movability = + self.should_print_verbose() || generator_kind == hir::GeneratorKind::Gen; + + if should_print_movability { + match movability { + hir::Movability::Movable => {} + hir::Movability::Static => p!("static "), + } } - if !self.tcx().sess.verbose() { - p!("generator"); + if !self.should_print_verbose() { + p!(write("{}", generator_kind)); // FIXME(eddyb) should use `def_span`. if let Some(did) = did.as_local() { let span = self.tcx().def_span(did); @@ -725,7 +729,7 @@ pub trait PrettyPrinter<'tcx>: } ty::Closure(did, substs) => { p!(write("[")); - if !self.tcx().sess.verbose() { + if !self.should_print_verbose() { p!(write("closure")); // FIXME(eddyb) should use `def_span`. if let Some(did) = did.as_local() { @@ -763,7 +767,7 @@ pub trait PrettyPrinter<'tcx>: } ty::Array(ty, sz) => { p!("[", print(ty), "; "); - if !NO_VERBOSE_CONSTANTS.with(|flag| flag.get()) && self.tcx().sess.verbose() { + if self.should_print_verbose() { p!(write("{:?}", sz)); } else if let ty::ConstKind::Unevaluated(..) = sz.kind() { // Do not try to evaluate unevaluated constants. If we are const evaluating an @@ -805,7 +809,7 @@ pub trait PrettyPrinter<'tcx>: let bound_predicate = predicate.kind(); match bound_predicate.skip_binder() { - ty::PredicateKind::Trait(pred) => { + ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => { let trait_ref = bound_predicate.rebind(pred.trait_ref); // Don't print + Sized, but rather + ?Sized if absent. @@ -816,7 +820,7 @@ pub trait PrettyPrinter<'tcx>: self.insert_trait_and_projection(trait_ref, None, &mut traits, &mut fn_traits); } - ty::PredicateKind::Projection(pred) => { + ty::PredicateKind::Clause(ty::Clause::Projection(pred)) => { let proj_ref = bound_predicate.rebind(pred); let trait_ref = proj_ref.required_poly_trait_ref(tcx); @@ -830,7 +834,7 @@ pub trait PrettyPrinter<'tcx>: &mut fn_traits, ); } - ty::PredicateKind::TypeOutlives(outlives) => { + ty::PredicateKind::Clause(ty::Clause::TypeOutlives(outlives)) => { lifetimes.push(outlives.1); } _ => {} @@ -892,7 +896,7 @@ pub trait PrettyPrinter<'tcx>: // Group the return ty with its def id, if we had one. entry .return_ty - .map(|ty| (tcx.lang_items().fn_once_output().unwrap(), ty)), + .map(|ty| (tcx.require_lang_item(LangItem::FnOnce, None), ty)), ); } if let Some(trait_ref) = entry.fn_mut_trait_ref { @@ -1063,7 +1067,7 @@ pub trait PrettyPrinter<'tcx>: fn pretty_print_dyn_existential( mut self, - predicates: &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>, + predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>, ) -> Result<Self::DynExistential, Self::Error> { // Generate the main trait ref, including associated types. let mut first = true; @@ -1076,8 +1080,8 @@ pub trait PrettyPrinter<'tcx>: let mut resugared = false; // Special-case `Fn(...) -> ...` and re-sugar it. - let fn_trait_kind = cx.tcx().fn_trait_kind_from_lang_item(principal.def_id); - if !cx.tcx().sess.verbose() && fn_trait_kind.is_some() { + let fn_trait_kind = cx.tcx().fn_trait_kind_from_def_id(principal.def_id); + if !cx.should_print_verbose() && fn_trait_kind.is_some() { if let ty::Tuple(tys) = principal.substs.type_at(0).kind() { let mut projections = predicates.projection_bounds(); if let (Some(proj), None) = (projections.next(), projections.next()) { @@ -1141,7 +1145,7 @@ pub trait PrettyPrinter<'tcx>: // // To avoid causing instabilities in compiletest // output, sort the auto-traits alphabetically. - auto_traits.sort_by_cached_key(|did| self.tcx().def_path_str(*did)); + auto_traits.sort_by_cached_key(|did| with_no_trimmed_paths!(self.tcx().def_path_str(*did))); for def_id in auto_traits { if !first { @@ -1185,7 +1189,7 @@ pub trait PrettyPrinter<'tcx>: ) -> Result<Self::Const, Self::Error> { define_scoped_cx!(self); - if !NO_VERBOSE_CONSTANTS.with(|flag| flag.get()) && self.tcx().sess.verbose() { + if self.should_print_verbose() { p!(write("Const({:?}: {:?})", ct.kind(), ct.ty())); return Ok(self); } @@ -1244,6 +1248,9 @@ pub trait PrettyPrinter<'tcx>: self.pretty_print_bound_var(debruijn, bound_var)? } ty::ConstKind::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)), + // FIXME(generic_const_exprs): + // write out some legible representation of an abstract const? + ty::ConstKind::Expr(_) => p!("[Const Expr]"), ty::ConstKind::Error(_) => p!("[const error]"), }; Ok(self) @@ -1420,7 +1427,7 @@ pub trait PrettyPrinter<'tcx>: ) -> Result<Self::Const, Self::Error> { define_scoped_cx!(self); - if !NO_VERBOSE_CONSTANTS.with(|flag| flag.get()) && self.tcx().sess.verbose() { + if self.should_print_verbose() { p!(write("ValTree({:?}: ", valtree), print(ty), ")"); return Ok(self); } @@ -1461,8 +1468,7 @@ pub trait PrettyPrinter<'tcx>: } // Aggregates, printed as array/tuple/struct/variant construction syntax. (ty::ValTree::Branch(_), ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) => { - let contents = - self.tcx().destructure_const(ty::Const::from_value(self.tcx(), valtree, ty)); + let contents = self.tcx().destructure_const(self.tcx().mk_const(valtree, ty)); let fields = contents.fields.iter().copied(); match *ty.kind() { ty::Array(..) => { @@ -1490,12 +1496,12 @@ pub trait PrettyPrinter<'tcx>: contents.variant.expect("destructed const of adt without variant idx"); let variant_def = &def.variant(variant_idx); p!(print_value_path(variant_def.def_id, substs)); - match variant_def.ctor_kind { - CtorKind::Const => {} - CtorKind::Fn => { + match variant_def.ctor_kind() { + Some(CtorKind::Const) => {} + Some(CtorKind::Fn) => { p!("(", comma_sep(fields), ")"); } - CtorKind::Fictive => { + None => { p!(" {{ "); let mut first = true; for (field_def, field) in iter::zip(&variant_def.fields, fields) { @@ -1564,6 +1570,10 @@ pub trait PrettyPrinter<'tcx>: Ok(cx) }) } + + fn should_print_verbose(&self) -> bool { + self.tcx().sess.verbose() + } } // HACK(eddyb) boxed to avoid moving around a large struct by-value. @@ -1583,6 +1593,8 @@ pub struct FmtPrinterData<'a, 'tcx> { region_index: usize, binder_depth: usize, printed_type_count: usize, + type_length_limit: Limit, + truncated: bool, pub region_highlight_mode: RegionHighlightMode<'tcx>, @@ -1605,6 +1617,10 @@ impl DerefMut for FmtPrinter<'_, '_> { impl<'a, 'tcx> FmtPrinter<'a, 'tcx> { pub fn new(tcx: TyCtxt<'tcx>, ns: Namespace) -> Self { + Self::new_with_limit(tcx, ns, tcx.type_length_limit()) + } + + pub fn new_with_limit(tcx: TyCtxt<'tcx>, ns: Namespace, type_length_limit: Limit) -> Self { FmtPrinter(Box::new(FmtPrinterData { tcx, // Estimated reasonable capacity to allocate upfront based on a few @@ -1617,6 +1633,8 @@ impl<'a, 'tcx> FmtPrinter<'a, 'tcx> { region_index: 0, binder_depth: 0, printed_type_count: 0, + type_length_limit, + truncated: false, region_highlight_mode: RegionHighlightMode::new(tcx), ty_infer_name_resolver: None, const_infer_name_resolver: None, @@ -1659,6 +1677,12 @@ impl<'t> TyCtxt<'t> { debug!("def_path_str: def_id={:?}, ns={:?}", def_id, ns); FmtPrinter::new(self, ns).print_def_path(def_id, substs).unwrap().into_buffer() } + + pub fn value_path_str_with_substs(self, def_id: DefId, substs: &'t [GenericArg<'t>]) -> String { + let ns = guess_def_namespace(self, def_id); + debug!("value_path_str: def_id={:?}, ns={:?}", def_id, ns); + FmtPrinter::new(self, ns).print_value_path(def_id, substs).unwrap().into_buffer() + } } impl fmt::Write for FmtPrinter<'_, '_> { @@ -1745,11 +1769,11 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { } fn print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> { - let type_length_limit = self.tcx.type_length_limit(); - if type_length_limit.value_within_limit(self.printed_type_count) { + if self.type_length_limit.value_within_limit(self.printed_type_count) { self.printed_type_count += 1; self.pretty_print_type(ty) } else { + self.truncated = true; write!(self, "...")?; Ok(self) } @@ -1757,7 +1781,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { fn print_dyn_existential( self, - predicates: &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>, + predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>, ) -> Result<Self::DynExistential, Self::Error> { self.pretty_print_dyn_existential(predicates) } @@ -1839,7 +1863,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { } } - let verbose = self.tcx.sess.verbose(); + let verbose = self.should_print_verbose(); disambiguated_data.fmt_maybe_verbose(&mut self, verbose)?; self.empty_path = false; @@ -1940,24 +1964,20 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { return true; } - if self.tcx.sess.verbose() { + if self.should_print_verbose() { return true; } let identify_regions = self.tcx.sess.opts.unstable_opts.identify_regions; match *region { - ty::ReEarlyBound(ref data) => { - data.name != kw::Empty && data.name != kw::UnderscoreLifetime - } + ty::ReEarlyBound(ref data) => data.has_name(), ty::ReLateBound(_, ty::BoundRegion { kind: br, .. }) | ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { - if let ty::BrNamed(_, name) = br { - if name != kw::Empty && name != kw::UnderscoreLifetime { - return true; - } + if br.is_named() { + return true; } if let Some((region, _)) = highlight.highlight_bound_region { @@ -2012,7 +2032,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { return Ok(self); } - if self.tcx.sess.verbose() { + if self.should_print_verbose() { p!(write("{:?}", region)); return Ok(self); } @@ -2033,11 +2053,9 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { ty::ReLateBound(_, ty::BoundRegion { kind: br, .. }) | ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { - if let ty::BrNamed(_, name) = br { - if name != kw::Empty && name != kw::UnderscoreLifetime { - p!(write("{}", name)); - return Ok(self); - } + if let ty::BrNamed(_, name) = br && br.is_named() { + p!(write("{}", name)); + return Ok(self); } if let Some((region, counter)) = highlight.highlight_bound_region { @@ -2115,7 +2133,7 @@ impl<'a, 'tcx> ty::TypeFolder<'tcx> for RegionFolder<'a, 'tcx> { // If this is an anonymous placeholder, don't rename. Otherwise, in some // async fns, we get a `for<'r> Send` bound match kind { - ty::BrAnon(_) | ty::BrEnv => r, + ty::BrAnon(..) | ty::BrEnv => r, _ => { // Index doesn't matter, since this is just for naming and these never get bound let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind }; @@ -2188,11 +2206,9 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { define_scoped_cx!(self); - let possible_names = - ('a'..='z').rev().map(|s| Symbol::intern(&format!("'{s}"))).collect::<Vec<_>>(); + let possible_names = ('a'..='z').rev().map(|s| Symbol::intern(&format!("'{s}"))); let mut available_names = possible_names - .into_iter() .filter(|name| !self.used_region_names.contains(&name)) .collect::<Vec<_>>(); debug!(?available_names); @@ -2218,47 +2234,13 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { // aren't named. Eventually, we might just want this as the default, but // this is not *quite* right and changes the ordering of some output // anyways. - let (new_value, map) = if self.tcx().sess.verbose() { - let regions: Vec<_> = value - .bound_vars() - .into_iter() - .map(|var| { - let ty::BoundVariableKind::Region(var) = var else { - // This doesn't really matter because it doesn't get used, - // it's just an empty value - return ty::BrAnon(0); - }; - match var { - ty::BrAnon(_) | ty::BrEnv => { - start_or_continue(&mut self, "for<", ", "); - let name = next_name(&self); - debug!(?name); - do_continue(&mut self, name); - ty::BrNamed(CRATE_DEF_ID.to_def_id(), name) - } - ty::BrNamed(def_id, kw::UnderscoreLifetime) => { - start_or_continue(&mut self, "for<", ", "); - let name = next_name(&self); - do_continue(&mut self, name); - ty::BrNamed(def_id, name) - } - ty::BrNamed(def_id, name) => { - start_or_continue(&mut self, "for<", ", "); - do_continue(&mut self, name); - ty::BrNamed(def_id, name) - } - } - }) - .collect(); + let (new_value, map) = if self.should_print_verbose() { + for var in value.bound_vars().iter() { + start_or_continue(&mut self, "for<", ", "); + write!(self, "{:?}", var)?; + } start_or_continue(&mut self, "", "> "); - - self.tcx.replace_late_bound_regions(value.clone(), |br| { - let kind = regions[br.var.as_usize()]; - self.tcx.mk_region(ty::ReLateBound( - ty::INNERMOST, - ty::BoundRegion { var: br.var, kind }, - )) - }) + (value.clone().skip_binder(), BTreeMap::default()) } else { let tcx = self.tcx; @@ -2271,7 +2253,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { binder_level_idx: ty::DebruijnIndex, br: ty::BoundRegion| { let (name, kind) = match br.kind { - ty::BrAnon(_) | ty::BrEnv => { + ty::BrAnon(..) | ty::BrEnv => { let name = next_name(&self); if let Some(lt_idx) = lifetime_idx { @@ -2286,7 +2268,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { (name, ty::BrNamed(CRATE_DEF_ID.to_def_id(), name)) } - ty::BrNamed(def_id, kw::UnderscoreLifetime) => { + ty::BrNamed(def_id, kw::UnderscoreLifetime | kw::Empty) => { let name = next_name(&self); if let Some(lt_idx) = lifetime_idx { @@ -2551,12 +2533,12 @@ pub struct PrintClosureAsImpl<'tcx> { forward_display_to_print! { ty::Region<'tcx>, Ty<'tcx>, - &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>, + &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>, ty::Const<'tcx>, // HACK(eddyb) these are exhaustive instead of generic, // because `for<'tcx>` isn't possible yet. - ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>, + ty::PolyExistentialPredicate<'tcx>, ty::Binder<'tcx, ty::TraitRef<'tcx>>, ty::Binder<'tcx, ty::ExistentialTraitRef<'tcx>>, ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, @@ -2698,14 +2680,14 @@ define_print_and_forward_display! { ty::PredicateKind<'tcx> { match *self { - ty::PredicateKind::Trait(ref data) => { + ty::PredicateKind::Clause(ty::Clause::Trait(ref data)) => { p!(print(data)) } ty::PredicateKind::Subtype(predicate) => p!(print(predicate)), ty::PredicateKind::Coerce(predicate) => p!(print(predicate)), - ty::PredicateKind::RegionOutlives(predicate) => p!(print(predicate)), - ty::PredicateKind::TypeOutlives(predicate) => p!(print(predicate)), - ty::PredicateKind::Projection(predicate) => p!(print(predicate)), + ty::PredicateKind::Clause(ty::Clause::RegionOutlives(predicate)) => p!(print(predicate)), + ty::PredicateKind::Clause(ty::Clause::TypeOutlives(predicate)) => p!(print(predicate)), + ty::PredicateKind::Clause(ty::Clause::Projection(predicate)) => p!(print(predicate)), ty::PredicateKind::WellFormed(arg) => p!(print(arg), " well-formed"), ty::PredicateKind::ObjectSafe(trait_def_id) => { p!("the trait `", print_def_path(trait_def_id, &[]), "` is object-safe") @@ -2724,6 +2706,7 @@ define_print_and_forward_display! { ty::PredicateKind::TypeWellFormedFromEnv(ty) => { p!("the type `", print(ty), "` is found in the environment") } + ty::PredicateKind::Ambiguous => p!("ambiguous"), } } diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs index ec90590ad..642900d3a 100644 --- a/compiler/rustc_middle/src/ty/query.rs +++ b/compiler/rustc_middle/src/ty/query.rs @@ -15,6 +15,7 @@ use crate::mir::interpret::{ }; use crate::mir::interpret::{LitToConstError, LitToConstInput}; use crate::mir::mono::CodegenUnit; +use crate::query::Key; use crate::thir; use crate::traits::query::{ CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal, @@ -27,6 +28,7 @@ use crate::traits::query::{ }; use crate::traits::specialization_graph; use crate::traits::{self, ImplSource}; +use crate::ty::context::TyCtxtFeed; use crate::ty::fast_reject::SimplifiedType; use crate::ty::layout::TyAndLayout; use crate::ty::subst::{GenericArg, SubstsRef}; @@ -121,10 +123,10 @@ macro_rules! query_helper_param_ty { macro_rules! query_storage { ([][$K:ty, $V:ty]) => { - <DefaultCacheSelector as CacheSelector<$K, $V>>::Cache + <<$K as Key>::CacheSelector as CacheSelector<'tcx, $V>>::Cache }; ([(arena_cache) $($rest:tt)*][$K:ty, $V:ty]) => { - <ArenaCacheSelector<'tcx> as CacheSelector<$K, $V>>::Cache + <<$K as Key>::CacheSelector as CacheSelector<'tcx, $V>>::ArenaCache }; ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => { query_storage!([$($modifiers)*][$($args)*]) @@ -275,13 +277,16 @@ macro_rules! define_callbacks { impl Default for Providers { fn default() -> Self { + use crate::query::Key; + Providers { $($name: |_, key| bug!( - "`tcx.{}({:?})` is not supported for external or local crate;\n - hint: Queries can be either made to the local crate, or the external crate. This error means you tried to use it for one that's not supported (likely the local crate).\n + "`tcx.{}({:?})` is not supported for {} crate;\n + hint: Queries can be either made to the local crate, or the external crate. This error means you tried to use it for one that's not supported.\n If that's not the case, {} was likely never assigned to a provider function.\n", stringify!($name), key, + if key.query_crate_is_local() { "local" } else { "external" }, stringify!($name), ),)* } @@ -323,6 +328,56 @@ macro_rules! define_callbacks { }; } +macro_rules! hash_result { + ([]) => {{ + Some(dep_graph::hash_result) + }}; + ([(no_hash) $($rest:tt)*]) => {{ + None + }}; + ([$other:tt $($modifiers:tt)*]) => { + hash_result!([$($modifiers)*]) + }; +} + +macro_rules! define_feedable { + ($($(#[$attr:meta])* [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => { + $(impl<'tcx, K: IntoQueryParam<$($K)*> + Copy> TyCtxtFeed<'tcx, K> { + $(#[$attr])* + #[inline(always)] + pub fn $name(self, value: $V) -> query_stored::$name<'tcx> { + let key = self.key().into_query_param(); + opt_remap_env_constness!([$($modifiers)*][key]); + + let tcx = self.tcx; + let cache = &tcx.query_caches.$name; + + let cached = try_get_cached(tcx, cache, &key, copy); + + match cached { + Ok(old) => { + bug!( + "Trying to feed an already recorded value for query {} key={key:?}:\nold value: {old:?}\nnew value: {value:?}", + stringify!($name), + ); + } + Err(()) => (), + } + + let dep_node = dep_graph::DepNode::construct(tcx, dep_graph::DepKind::$name, &key); + let dep_node_index = tcx.dep_graph.with_feed_task( + dep_node, + tcx, + key, + &value, + hash_result!([$($modifiers)*]), + ); + cache.complete(key, value, dep_node_index) + } + })* + } +} + // Each of these queries corresponds to a function pointer field in the // `Providers` struct for requesting a value of that type, and a method // on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way @@ -336,6 +391,7 @@ macro_rules! define_callbacks { // as they will raise an fatal error on query cycles instead. rustc_query_append! { define_callbacks! } +rustc_feedable_queries! { define_feedable! } mod sealed { use super::{DefId, LocalDefId, OwnerId}; diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index b25b4bd4f..c759fb6d5 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -5,7 +5,7 @@ //! subtyping, type equality, etc. use crate::ty::error::{ExpectedFound, TypeError}; -use crate::ty::{self, ImplSubject, Term, TermKind, Ty, TyCtxt, TypeFoldable}; +use crate::ty::{self, Expr, ImplSubject, Term, TermKind, Ty, TyCtxt, TypeFoldable}; use crate::ty::{GenericArg, GenericArgKind, SubstsRef}; use rustc_hir as ast; use rustc_hir::def_id::DefId; @@ -23,6 +23,8 @@ pub enum Cause { pub trait TypeRelation<'tcx>: Sized { fn tcx(&self) -> TyCtxt<'tcx>; + fn intercrate(&self) -> bool; + fn param_env(&self) -> ty::ParamEnv<'tcx>; /// Returns a static string we can use for printouts. @@ -32,6 +34,9 @@ pub trait TypeRelation<'tcx>: Sized { /// relation. Just affects error messages. fn a_is_expected(&self) -> bool; + /// Used during coherence. If called, must emit an always-ambiguous obligation. + fn mark_ambiguous(&mut self); + fn with_cause<F, R>(&mut self, _cause: Cause, f: F) -> R where F: FnOnce(&mut Self) -> R, @@ -60,7 +65,7 @@ pub trait TypeRelation<'tcx>: Sized { let tcx = self.tcx(); let opt_variances = tcx.variances_of(item_def_id); - relate_substs_with_variances(self, item_def_id, opt_variances, a_subst, b_subst) + relate_substs_with_variances(self, item_def_id, opt_variances, a_subst, b_subst, true) } /// Switch variance for the purpose of relating `a` and `b`. @@ -151,13 +156,14 @@ pub fn relate_substs_with_variances<'tcx, R: TypeRelation<'tcx>>( variances: &[ty::Variance], a_subst: SubstsRef<'tcx>, b_subst: SubstsRef<'tcx>, + fetch_ty_for_diag: bool, ) -> RelateResult<'tcx, SubstsRef<'tcx>> { let tcx = relation.tcx(); let mut cached_ty = None; let params = iter::zip(a_subst, b_subst).enumerate().map(|(i, (a, b))| { let variance = variances[i]; - let variance_info = if variance == ty::Invariant { + let variance_info = if variance == ty::Invariant && fetch_ty_for_diag { let ty = *cached_ty.get_or_insert_with(|| tcx.bound_type_of(ty_def_id).subst(tcx, a_subst)); ty::VarianceDiagInfo::Invariant { ty, param_index: i.try_into().unwrap() } @@ -561,8 +567,23 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>( (&ty::Opaque(a_def_id, a_substs), &ty::Opaque(b_def_id, b_substs)) if a_def_id == b_def_id => { - let substs = relate_substs(relation, a_substs, b_substs)?; - Ok(tcx.mk_opaque(a_def_id, substs)) + if relation.intercrate() { + // During coherence, opaque types should be treated as equal to each other, even if their generic params + // differ, as they could resolve to the same hidden type, even for different generic params. + relation.mark_ambiguous(); + Ok(a) + } else { + let opt_variances = tcx.variances_of(a_def_id); + let substs = relate_substs_with_variances( + relation, + a_def_id, + opt_variances, + a_substs, + b_substs, + false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle + )?; + Ok(tcx.mk_opaque(a_def_id, substs)) + } } _ => Err(TypeError::Sorts(expected_found(relation, a, b))), @@ -592,7 +613,10 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>( if a_ty != b_ty { relation.tcx().sess.delay_span_bug( DUMMY_SP, - &format!("cannot relate constants of different types: {} != {}", a_ty, b_ty), + &format!( + "cannot relate constants ({:?}, {:?}) of different types: {} != {}", + a, b, a_ty, b_ty + ), ); } @@ -602,11 +626,16 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>( // an unnormalized (i.e. unevaluated) const in the param-env. // FIXME(generic_const_exprs): Once we always lazily unify unevaluated constants // these `eval` calls can be removed. - if !relation.tcx().features().generic_const_exprs { + if !tcx.features().generic_const_exprs { a = a.eval(tcx, relation.param_env()); b = b.eval(tcx, relation.param_env()); } + if tcx.features().generic_const_exprs { + a = tcx.expand_abstract_consts(a); + b = tcx.expand_abstract_consts(b); + } + // Currently, the values that can be unified are primitive types, // and those that derive both `PartialEq` and `Eq`, corresponding // to structural-match types. @@ -623,33 +652,69 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>( (ty::ConstKind::Placeholder(p1), ty::ConstKind::Placeholder(p2)) => p1 == p2, (ty::ConstKind::Value(a_val), ty::ConstKind::Value(b_val)) => a_val == b_val, - (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) - if tcx.features().generic_const_exprs => - { - tcx.try_unify_abstract_consts(relation.param_env().and((au, bu))) - } - // While this is slightly incorrect, it shouldn't matter for `min_const_generics` // and is the better alternative to waiting until `generic_const_exprs` can // be stabilized. (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) if au.def == bu.def => { + assert_eq!(a.ty(), b.ty()); let substs = relation.relate_with_variance( ty::Variance::Invariant, ty::VarianceDiagInfo::default(), au.substs, bu.substs, )?; - return Ok(tcx.mk_const(ty::ConstS { - kind: ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def: au.def, substs }), - ty: a.ty(), - })); + return Ok(tcx.mk_const(ty::UnevaluatedConst { def: au.def, substs }, a.ty())); + } + // Before calling relate on exprs, it is necessary to ensure that the nested consts + // have identical types. + (ty::ConstKind::Expr(ae), ty::ConstKind::Expr(be)) => { + let r = relation; + + // FIXME(generic_const_exprs): is it possible to relate two consts which are not identical + // exprs? Should we care about that? + let expr = match (ae, be) { + (Expr::Binop(a_op, al, ar), Expr::Binop(b_op, bl, br)) + if a_op == b_op && al.ty() == bl.ty() && ar.ty() == br.ty() => + { + Expr::Binop(a_op, r.consts(al, bl)?, r.consts(ar, br)?) + } + (Expr::UnOp(a_op, av), Expr::UnOp(b_op, bv)) + if a_op == b_op && av.ty() == bv.ty() => + { + Expr::UnOp(a_op, r.consts(av, bv)?) + } + (Expr::Cast(ak, av, at), Expr::Cast(bk, bv, bt)) + if ak == bk && av.ty() == bv.ty() => + { + Expr::Cast(ak, r.consts(av, bv)?, r.tys(at, bt)?) + } + (Expr::FunctionCall(af, aa), Expr::FunctionCall(bf, ba)) + if aa.len() == ba.len() + && af.ty() == bf.ty() + && aa + .iter() + .zip(ba.iter()) + .all(|(a_arg, b_arg)| a_arg.ty() == b_arg.ty()) => + { + let func = r.consts(af, bf)?; + let mut related_args = Vec::with_capacity(aa.len()); + for (a_arg, b_arg) in aa.iter().zip(ba.iter()) { + related_args.push(r.consts(a_arg, b_arg)?); + } + let related_args = tcx.mk_const_list(related_args.iter()); + Expr::FunctionCall(func, related_args) + } + _ => return Err(TypeError::ConstMismatch(expected_found(r, a, b))), + }; + let kind = ty::ConstKind::Expr(expr); + return Ok(tcx.mk_const(kind, a.ty())); } _ => false, }; if is_match { Ok(a) } else { Err(TypeError::ConstMismatch(expected_found(relation, a, b))) } } -impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>> { +impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> { fn relate<R: TypeRelation<'tcx>>( relation: &mut R, a: Self, diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 2cad333e3..9f70b4f1f 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -68,7 +68,7 @@ impl<'tcx> fmt::Debug for ty::adjustment::Adjustment<'tcx> { impl fmt::Debug for ty::BoundRegionKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { - ty::BrAnon(n) => write!(f, "BrAnon({:?})", n), + ty::BrAnon(n, span) => write!(f, "BrAnon({n:?}, {span:?})"), ty::BrNamed(did, name) => { if did.is_crate_root() { write!(f, "BrNamed({})", name) @@ -150,15 +150,23 @@ impl<'tcx> fmt::Debug for ty::Predicate<'tcx> { } } +impl<'tcx> fmt::Debug for ty::Clause<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + ty::Clause::Trait(ref a) => a.fmt(f), + ty::Clause::RegionOutlives(ref pair) => pair.fmt(f), + ty::Clause::TypeOutlives(ref pair) => pair.fmt(f), + ty::Clause::Projection(ref pair) => pair.fmt(f), + } + } +} + impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { - ty::PredicateKind::Trait(ref a) => a.fmt(f), + ty::PredicateKind::Clause(ref a) => a.fmt(f), ty::PredicateKind::Subtype(ref pair) => pair.fmt(f), ty::PredicateKind::Coerce(ref pair) => pair.fmt(f), - ty::PredicateKind::RegionOutlives(ref pair) => pair.fmt(f), - ty::PredicateKind::TypeOutlives(ref pair) => pair.fmt(f), - ty::PredicateKind::Projection(ref pair) => pair.fmt(f), ty::PredicateKind::WellFormed(data) => write!(f, "WellFormed({:?})", data), ty::PredicateKind::ObjectSafe(trait_def_id) => { write!(f, "ObjectSafe({:?})", trait_def_id) @@ -173,6 +181,7 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> { ty::PredicateKind::TypeWellFormedFromEnv(ty) => { write!(f, "TypeWellFormedFromEnv({:?})", ty) } + ty::PredicateKind::Ambiguous => write!(f, "Ambiguous"), } } } @@ -240,7 +249,6 @@ TrivialTypeTraversalAndLiftImpls! { Field, interpret::Scalar, rustc_target::abi::Size, - ty::DelaySpanBugEmitted, rustc_type_ir::DebruijnIndex, ty::BoundVar, ty::Placeholder<ty::BoundVar>, @@ -587,12 +595,18 @@ impl<'tcx, T: TypeVisitable<'tcx>> TypeSuperVisitable<'tcx> for ty::Binder<'tcx, } } -impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>> { +impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> { fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { ty::util::fold_list(self, folder, |tcx, v| tcx.intern_poly_existential_predicates(v)) } } +impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::Const<'tcx>> { + fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { + ty::util::fold_list(self, folder, |tcx, v| tcx.mk_const_list(v.iter())) + } +} + impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ProjectionKind> { fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { ty::util::fold_list(self, folder, |tcx, v| tcx.intern_projs(v)) @@ -806,7 +820,7 @@ impl<'tcx> TypeSuperFoldable<'tcx> for ty::Const<'tcx> { let ty = self.ty().try_fold_with(folder)?; let kind = self.kind().try_fold_with(folder)?; if ty != self.ty() || kind != self.kind() { - Ok(folder.tcx().mk_const(ty::ConstS { ty, kind })) + Ok(folder.tcx().mk_const(kind, ty)) } else { Ok(self) } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index cf420bafe..9cbda95a4 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -17,9 +17,11 @@ use rustc_data_structures::captures::Captures; use rustc_data_structures::intern::Interned; use rustc_hir as hir; use rustc_hir::def_id::DefId; +use rustc_hir::LangItem; use rustc_index::vec::Idx; use rustc_macros::HashStable; use rustc_span::symbol::{kw, sym, Symbol}; +use rustc_span::Span; use rustc_target::abi::VariantIdx; use rustc_target::spec::abi; use std::borrow::Cow; @@ -58,7 +60,7 @@ pub struct FreeRegion { #[derive(HashStable)] pub enum BoundRegionKind { /// An anonymous region parameter for a given fn (&T) - BrAnon(u32), + BrAnon(u32, Option<Span>), /// Named region parameters for functions (a in &'a T) /// @@ -81,7 +83,9 @@ pub struct BoundRegion { impl BoundRegionKind { pub fn is_named(&self) -> bool { match *self { - BoundRegionKind::BrNamed(_, name) => name != kw::UnderscoreLifetime, + BoundRegionKind::BrNamed(_, name) => { + name != kw::UnderscoreLifetime && name != kw::Empty + } _ => false, } } @@ -702,7 +706,9 @@ impl<'tcx> ExistentialPredicate<'tcx> { } } -impl<'tcx> Binder<'tcx, ExistentialPredicate<'tcx>> { +pub type PolyExistentialPredicate<'tcx> = Binder<'tcx, ExistentialPredicate<'tcx>>; + +impl<'tcx> PolyExistentialPredicate<'tcx> { /// Given an existential predicate like `?Self: PartialEq<u32>` (e.g., derived from `dyn PartialEq<u32>`), /// and a concrete type `self_ty`, returns a full predicate where the existentially quantified variable `?Self` /// has been replaced with `self_ty` (e.g., `self_ty: PartialEq<u32>`, in our example). @@ -716,17 +722,23 @@ impl<'tcx> Binder<'tcx, ExistentialPredicate<'tcx>> { self.rebind(p.with_self_ty(tcx, self_ty)).to_predicate(tcx) } ExistentialPredicate::AutoTrait(did) => { - let trait_ref = self.rebind(ty::TraitRef { - def_id: did, - substs: tcx.mk_substs_trait(self_ty, &[]), - }); - trait_ref.without_const().to_predicate(tcx) + let generics = tcx.generics_of(did); + let trait_ref = if generics.params.len() == 1 { + tcx.mk_trait_ref(did, [self_ty]) + } else { + // If this is an ill-formed auto trait, then synthesize + // new error substs for the missing generics. + let err_substs = + ty::InternalSubsts::extend_with_error(tcx, did, &[self_ty.into()]); + tcx.mk_trait_ref(did, err_substs) + }; + self.rebind(trait_ref).without_const().to_predicate(tcx) } } } } -impl<'tcx> List<ty::Binder<'tcx, ExistentialPredicate<'tcx>>> { +impl<'tcx> List<ty::PolyExistentialPredicate<'tcx>> { /// Returns the "principal `DefId`" of this set of existential predicates. /// /// A Rust trait object type consists (in addition to a lifetime bound) @@ -811,6 +823,13 @@ impl<'tcx> TraitRef<'tcx> { TraitRef { def_id, substs } } + pub fn with_self_type(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { + tcx.mk_trait_ref( + self.def_id, + [self_ty.into()].into_iter().chain(self.substs.iter().skip(1)), + ) + } + /// Returns a `TraitRef` of the form `P0: Foo<P1..Pn>` where `Pi` /// are the parameters defined on trait. pub fn identity(tcx: TyCtxt<'tcx>, def_id: DefId) -> Binder<'tcx, TraitRef<'tcx>> { @@ -845,23 +864,6 @@ impl<'tcx> PolyTraitRef<'tcx> { pub fn def_id(&self) -> DefId { self.skip_binder().def_id } - - pub fn to_poly_trait_predicate(&self) -> ty::PolyTraitPredicate<'tcx> { - self.map_bound(|trait_ref| ty::TraitPredicate { - trait_ref, - constness: ty::BoundConstness::NotConst, - polarity: ty::ImplPolarity::Positive, - }) - } - - /// Same as [`PolyTraitRef::to_poly_trait_predicate`] but sets a negative polarity instead. - pub fn to_poly_trait_predicate_negative_polarity(&self) -> ty::PolyTraitPredicate<'tcx> { - self.map_bound(|trait_ref| ty::TraitPredicate { - trait_ref, - constness: ty::BoundConstness::NotConst, - polarity: ty::ImplPolarity::Negative, - }) - } } impl rustc_errors::IntoDiagnosticArg for PolyTraitRef<'_> { @@ -906,7 +908,7 @@ impl<'tcx> ExistentialTraitRef<'tcx> { // otherwise the escaping vars would be captured by the binder // debug_assert!(!self_ty.has_escaping_bound_vars()); - ty::TraitRef { def_id: self.def_id, substs: tcx.mk_substs_trait(self_ty, self.substs) } + tcx.mk_trait_ref(self.def_id, [self_ty.into()].into_iter().chain(self.substs.iter())) } } @@ -1282,6 +1284,12 @@ impl<'tcx> ParamTy { pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { tcx.mk_ty_param(self.index, self.name) } + + pub fn span_from_generics(&self, tcx: TyCtxt<'tcx>, item_with_generics: DefId) -> Span { + let generics = tcx.generics_of(item_with_generics); + let type_param = generics.type_param(self, tcx); + tcx.def_span(type_param.def_id) + } } #[derive(Copy, Clone, Hash, TyEncodable, TyDecodable, Eq, PartialEq, Ord, PartialOrd)] @@ -1603,7 +1611,7 @@ impl<'tcx> Region<'tcx> { impl<'tcx> Ty<'tcx> { #[inline(always)] pub fn kind(self) -> &'tcx TyKind<'tcx> { - &self.0.0.kind + &self.0.0 } #[inline(always)] @@ -2095,7 +2103,7 @@ impl<'tcx> Ty<'tcx> { ty::Str | ty::Slice(_) => (tcx.types.usize, false), ty::Dynamic(..) => { - let dyn_metadata = tcx.lang_items().dyn_metadata().unwrap(); + let dyn_metadata = tcx.require_lang_item(LangItem::DynMetadata, None); (tcx.bound_type_of(dyn_metadata).subst(tcx, &[tail.into()]), false) }, @@ -2117,8 +2125,7 @@ impl<'tcx> Ty<'tcx> { /// parameter. This is kind of a phantom type, except that the /// most convenient thing for us to are the integral types. This /// function converts such a special type into the closure - /// kind. To go the other way, use - /// `tcx.closure_kind_ty(closure_kind)`. + /// kind. To go the other way, use `closure_kind.to_ty(tcx)`. /// /// Note that during type checking, we use an inference variable /// to represent the closure kind, because it has not yet been @@ -2244,7 +2251,7 @@ impl<'tcx> Ty<'tcx> { } } - // If `self` is a primitive, return its [`Symbol`]. + /// If `self` is a primitive, return its [`Symbol`]. pub fn primitive_symbol(self) -> Option<Symbol> { match self.kind() { ty::Bool => Some(sym::bool), diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 0660e9b79..a1b084a5e 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -6,11 +6,11 @@ use crate::ty::sty::{ClosureSubsts, GeneratorSubsts, InlineConstSubsts}; use crate::ty::visit::{TypeVisitable, TypeVisitor}; use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt}; -use rustc_data_structures::captures::Captures; -use rustc_data_structures::intern::{Interned, WithStableHash}; +use rustc_data_structures::intern::Interned; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; use rustc_serialize::{self, Decodable, Encodable}; +use rustc_type_ir::WithCachedTypeInfo; use smallvec::SmallVec; use core::intrinsics; @@ -19,7 +19,7 @@ use std::fmt; use std::marker::PhantomData; use std::mem; use std::num::NonZeroUsize; -use std::ops::ControlFlow; +use std::ops::{ControlFlow, Deref}; use std::slice; /// An entity in the Rust type system, which can be one of @@ -85,7 +85,7 @@ impl<'tcx> GenericArgKind<'tcx> { GenericArgKind::Type(ty) => { // Ensure we can use the tag bits. assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0); - (TYPE_TAG, ty.0.0 as *const WithStableHash<ty::TyS<'tcx>> as usize) + (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo<ty::TyKind<'tcx>> as usize) } GenericArgKind::Const(ct) => { // Ensure we can use the tag bits. @@ -141,6 +141,15 @@ impl<'tcx> From<ty::Const<'tcx>> for GenericArg<'tcx> { } } +impl<'tcx> From<ty::Term<'tcx>> for GenericArg<'tcx> { + fn from(value: ty::Term<'tcx>) -> Self { + match value.unpack() { + ty::TermKind::Ty(t) => t.into(), + ty::TermKind::Const(c) => c.into(), + } + } +} + impl<'tcx> GenericArg<'tcx> { #[inline] pub fn unpack(self) -> GenericArgKind<'tcx> { @@ -154,7 +163,7 @@ impl<'tcx> GenericArg<'tcx> { &*((ptr & !TAG_MASK) as *const ty::RegionKind<'tcx>), ))), TYPE_TAG => GenericArgKind::Type(Ty(Interned::new_unchecked( - &*((ptr & !TAG_MASK) as *const WithStableHash<ty::TyS<'tcx>>), + &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::TyKind<'tcx>>), ))), CONST_TAG => GenericArgKind::Const(ty::Const(Interned::new_unchecked( &*((ptr & !TAG_MASK) as *const ty::ConstS<'tcx>), @@ -344,6 +353,22 @@ impl<'tcx> InternalSubsts<'tcx> { } } + // Extend an `original_substs` list to the full number of substs expected by `def_id`, + // filling in the missing parameters with error ty/ct or 'static regions. + pub fn extend_with_error( + tcx: TyCtxt<'tcx>, + def_id: DefId, + original_substs: &[GenericArg<'tcx>], + ) -> SubstsRef<'tcx> { + ty::InternalSubsts::for_item(tcx, def_id, |def, substs| { + if let Some(subst) = original_substs.get(def.index as usize) { + *subst + } else { + def.to_error(tcx, substs) + } + }) + } + #[inline] pub fn types(&'tcx self) -> impl DoubleEndedIterator<Item = Ty<'tcx>> + 'tcx { self.iter() @@ -506,6 +531,9 @@ impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for &'tcx ty::List<T> { } } +/// Similar to [`super::Binder`] except that it tracks early bound generics, i.e. `struct Foo<T>(T)` +/// needs `T` substituted immediately. This type primarily exists to avoid forgetting to call +/// `subst`. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[derive(Encodable, Decodable, HashStable)] pub struct EarlyBinder<T>(pub T); @@ -559,25 +587,94 @@ impl<T, U> EarlyBinder<(T, U)> { } } -impl<'tcx, 's, T: IntoIterator<Item = I>, I: TypeFoldable<'tcx>> EarlyBinder<T> { +impl<'tcx, 's, I: IntoIterator> EarlyBinder<I> +where + I::Item: TypeFoldable<'tcx>, +{ pub fn subst_iter( self, tcx: TyCtxt<'tcx>, substs: &'s [GenericArg<'tcx>], - ) -> impl Iterator<Item = I> + Captures<'s> + Captures<'tcx> { - self.0.into_iter().map(move |t| EarlyBinder(t).subst(tcx, substs)) + ) -> SubstIter<'s, 'tcx, I> { + SubstIter { it: self.0.into_iter(), tcx, substs } + } +} + +pub struct SubstIter<'s, 'tcx, I: IntoIterator> { + it: I::IntoIter, + tcx: TyCtxt<'tcx>, + substs: &'s [GenericArg<'tcx>], +} + +impl<'tcx, I: IntoIterator> Iterator for SubstIter<'_, 'tcx, I> +where + I::Item: TypeFoldable<'tcx>, +{ + type Item = I::Item; + + fn next(&mut self) -> Option<Self::Item> { + Some(EarlyBinder(self.it.next()?).subst(self.tcx, self.substs)) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + self.it.size_hint() } } -impl<'tcx, 's, 'a, T: IntoIterator<Item = &'a I>, I: Copy + TypeFoldable<'tcx> + 'a> - EarlyBinder<T> +impl<'tcx, I: IntoIterator> DoubleEndedIterator for SubstIter<'_, 'tcx, I> +where + I::IntoIter: DoubleEndedIterator, + I::Item: TypeFoldable<'tcx>, +{ + fn next_back(&mut self) -> Option<Self::Item> { + Some(EarlyBinder(self.it.next_back()?).subst(self.tcx, self.substs)) + } +} + +impl<'tcx, 's, I: IntoIterator> EarlyBinder<I> +where + I::Item: Deref, + <I::Item as Deref>::Target: Copy + TypeFoldable<'tcx>, { pub fn subst_iter_copied( self, tcx: TyCtxt<'tcx>, substs: &'s [GenericArg<'tcx>], - ) -> impl Iterator<Item = I> + Captures<'s> + Captures<'tcx> + Captures<'a> { - self.0.into_iter().map(move |t| EarlyBinder(*t).subst(tcx, substs)) + ) -> SubstIterCopied<'s, 'tcx, I> { + SubstIterCopied { it: self.0.into_iter(), tcx, substs } + } +} + +pub struct SubstIterCopied<'a, 'tcx, I: IntoIterator> { + it: I::IntoIter, + tcx: TyCtxt<'tcx>, + substs: &'a [GenericArg<'tcx>], +} + +impl<'tcx, I: IntoIterator> Iterator for SubstIterCopied<'_, 'tcx, I> +where + I::Item: Deref, + <I::Item as Deref>::Target: Copy + TypeFoldable<'tcx>, +{ + type Item = <I::Item as Deref>::Target; + + fn next(&mut self) -> Option<Self::Item> { + Some(EarlyBinder(*self.it.next()?).subst(self.tcx, self.substs)) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + self.it.size_hint() + } +} + +impl<'tcx, I: IntoIterator> DoubleEndedIterator for SubstIterCopied<'_, 'tcx, I> +where + I::IntoIter: DoubleEndedIterator, + I::Item: Deref, + <I::Item as Deref>::Target: Copy + TypeFoldable<'tcx>, +{ + fn next_back(&mut self) -> Option<Self::Item> { + Some(EarlyBinder(*self.it.next_back()?).subst(self.tcx, self.substs)) } } @@ -597,6 +694,10 @@ impl<T: Iterator> Iterator for EarlyBinderIter<T> { fn next(&mut self) -> Option<Self::Item> { self.t.next().map(|i| EarlyBinder(i)) } + + fn size_hint(&self) -> (usize, Option<usize>) { + self.t.size_hint() + } } impl<'tcx, T: TypeFoldable<'tcx>> ty::EarlyBinder<T> { diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index ac79949fc..b38a5fbf2 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -211,7 +211,7 @@ impl<'tcx> TyCtxt<'tcx> { } } -// Query provider for `trait_impls_of`. +/// Query provider for `trait_impls_of`. pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> TraitImpls { let mut impls = TraitImpls::default(); @@ -255,7 +255,7 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait impls } -// Query provider for `incoherent_impls`. +/// Query provider for `incoherent_impls`. pub(super) fn incoherent_impls_provider(tcx: TyCtxt<'_>, simp: SimplifiedType) -> &[DefId] { let mut impls = Vec::new(); diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index f72e236ed..47c1ce807 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -8,8 +8,6 @@ use crate::ty::{ }; use crate::ty::{GenericArgKind, SubstsRef}; use rustc_apfloat::Float as _; -use rustc_ast as ast; -use rustc_attr::{self as attr, SignedInt, UnsignedInt}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_errors::ErrorGuaranteed; @@ -19,7 +17,7 @@ use rustc_hir::def_id::DefId; use rustc_index::bit_set::GrowableBitSet; use rustc_macros::HashStable; use rustc_span::{sym, DUMMY_SP}; -use rustc_target::abi::{Integer, Size, TargetDataLayout}; +use rustc_target::abi::{Integer, IntegerType, Size, TargetDataLayout}; use rustc_target::spec::abi::Abi; use smallvec::SmallVec; use std::{fmt, iter}; @@ -104,21 +102,12 @@ pub trait IntTypeExt { fn initial_discriminant<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Discr<'tcx>; } -impl IntTypeExt for attr::IntType { +impl IntTypeExt for IntegerType { fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { - match *self { - SignedInt(ast::IntTy::I8) => tcx.types.i8, - SignedInt(ast::IntTy::I16) => tcx.types.i16, - SignedInt(ast::IntTy::I32) => tcx.types.i32, - SignedInt(ast::IntTy::I64) => tcx.types.i64, - SignedInt(ast::IntTy::I128) => tcx.types.i128, - SignedInt(ast::IntTy::Isize) => tcx.types.isize, - UnsignedInt(ast::UintTy::U8) => tcx.types.u8, - UnsignedInt(ast::UintTy::U16) => tcx.types.u16, - UnsignedInt(ast::UintTy::U32) => tcx.types.u32, - UnsignedInt(ast::UintTy::U64) => tcx.types.u64, - UnsignedInt(ast::UintTy::U128) => tcx.types.u128, - UnsignedInt(ast::UintTy::Usize) => tcx.types.usize, + match self { + IntegerType::Pointer(true) => tcx.types.isize, + IntegerType::Pointer(false) => tcx.types.usize, + IntegerType::Fixed(i, s) => i.to_ty(tcx, *s), } } @@ -1219,11 +1208,11 @@ pub fn is_trivially_const_drop<'tcx>(ty: Ty<'tcx>) -> bool { } } -// Does the equivalent of -// ``` -// let v = self.iter().map(|p| p.fold_with(folder)).collect::<SmallVec<[_; 8]>>(); -// folder.tcx().intern_*(&v) -// ``` +/// Does the equivalent of +/// ```ignore (ilustrative) +/// let v = self.iter().map(|p| p.fold_with(folder)).collect::<SmallVec<[_; 8]>>(); +/// folder.tcx().intern_*(&v) +/// ``` pub fn fold_list<'tcx, F, T>( list: &'tcx ty::List<T>, folder: &mut F, @@ -1259,9 +1248,9 @@ where #[derive(Copy, Clone, Debug, HashStable, TyEncodable, TyDecodable)] pub struct AlwaysRequiresDrop; -/// Normalizes all opaque types in the given value, replacing them +/// Reveals all opaque types in the given value, replacing them /// with their underlying types. -pub fn normalize_opaque_types<'tcx>( +pub fn reveal_opaque_types_in_bounds<'tcx>( tcx: TyCtxt<'tcx>, val: &'tcx ty::List<ty::Predicate<'tcx>>, ) -> &'tcx ty::List<ty::Predicate<'tcx>> { @@ -1298,7 +1287,7 @@ pub fn is_intrinsic(tcx: TyCtxt<'_>, def_id: DefId) -> bool { pub fn provide(providers: &mut ty::query::Providers) { *providers = ty::query::Providers { - normalize_opaque_types, + reveal_opaque_types_in_bounds, is_doc_hidden, is_doc_notable_trait, is_intrinsic, diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index c09f71f9a..4cdfd9e59 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -72,12 +72,18 @@ pub trait TypeVisitable<'tcx>: fmt::Debug + Clone { self.visit_with(&mut HasEscapingVarsVisitor { outer_index: binder }).is_break() } - /// Returns `true` if this `self` has any regions that escape `binder` (and + /// Returns `true` if this type has any regions that escape `binder` (and /// hence are not bound by it). fn has_vars_bound_above(&self, binder: ty::DebruijnIndex) -> bool { self.has_vars_bound_at_or_above(binder.shifted_in(1)) } + /// Return `true` if this type has regions that are not a part of the type. + /// For example, `for<'a> fn(&'a i32)` return `false`, while `fn(&'a i32)` + /// would return `true`. The latter can occur when traversing through the + /// former. + /// + /// See [`HasEscapingVarsVisitor`] for more information. fn has_escaping_bound_vars(&self) -> bool { self.has_vars_bound_at_or_above(ty::INNERMOST) } @@ -95,11 +101,15 @@ pub trait TypeVisitable<'tcx>: fmt::Debug + Clone { fn references_error(&self) -> bool { self.has_type_flags(TypeFlags::HAS_ERROR) } - fn error_reported(&self) -> Option<ErrorGuaranteed> { + fn error_reported(&self) -> Result<(), ErrorGuaranteed> { if self.references_error() { - Some(ErrorGuaranteed::unchecked_claim_error_was_emitted()) + if let Some(reported) = ty::tls::with(|tcx| tcx.sess.is_compilation_going_to_fail()) { + Err(reported) + } else { + bug!("expect tcx.sess.is_compilation_going_to_fail return `Some`"); + } } else { - None + Ok(()) } } fn has_non_region_param(&self) -> bool { diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs index 5ca51c25a..6eae94511 100644 --- a/compiler/rustc_middle/src/ty/vtable.rs +++ b/compiler/rustc_middle/src/ty/vtable.rs @@ -66,7 +66,7 @@ pub(super) fn vtable_allocation_provider<'tcx>( let layout = tcx .layout_of(ty::ParamEnv::reveal_all().and(ty)) .expect("failed to build vtable representation"); - assert!(!layout.is_unsized(), "can't create a vtable for an unsized type"); + assert!(layout.is_sized(), "can't create a vtable for an unsized type"); let size = layout.size.bytes(); let align = layout.align.abi.bytes(); diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index 91db9698c..4fab5abe9 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -214,6 +214,24 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) | ty::ConstKind::Value(_) | ty::ConstKind::Error(_) => {} + ty::ConstKind::Expr(expr) => match expr { + ty::Expr::UnOp(_, v) => push_inner(stack, v.into()), + ty::Expr::Binop(_, l, r) => { + push_inner(stack, r.into()); + push_inner(stack, l.into()) + } + ty::Expr::FunctionCall(func, args) => { + for a in args.iter().rev() { + push_inner(stack, a.into()); + } + push_inner(stack, func.into()); + } + ty::Expr::Cast(_, c, t) => { + push_inner(stack, t.into()); + push_inner(stack, c.into()); + } + }, + ty::ConstKind::Unevaluated(ct) => { stack.extend(ct.substs.iter().rev()); } |