1
Fork 0

Auto merge of #109517 - matthiaskrgr:rollup-m3orqzd, r=matthiaskrgr

Rollup of 7 pull requests

Successful merges:

 - #108541 (Suppress `opaque_hidden_inferred_bound` for nested RPITs)
 - #109137 (resolve: Querify most cstore access methods (subset 2))
 - #109380 (add `known-bug` test for unsoundness issue)
 - #109462 (Make alias-eq have a relation direction (and rename it to alias-relate))
 - #109475 (Simpler checked shifts in MIR building)
 - #109504 (Stabilize `arc_into_inner` and `rc_into_inner`.)
 - #109506 (make param bound vars visibly bound vars with -Zverbose)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-03-23 12:35:05 +00:00
commit 99c49d95cd
54 changed files with 729 additions and 245 deletions

View file

@ -1336,7 +1336,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
ty::Clause::RegionOutlives(_) | ty::Clause::ConstArgHasType(..) => bug!(),
},
ty::PredicateKind::WellFormed(_)
| ty::PredicateKind::AliasEq(..)
| ty::PredicateKind::AliasRelate(..)
| ty::PredicateKind::ObjectSafe(_)
| ty::PredicateKind::ClosureKind(_, _, _)
| ty::PredicateKind::Subtype(_)

View file

@ -528,7 +528,7 @@ fn trait_predicate_kind<'tcx>(
| ty::PredicateKind::Clause(ty::Clause::TypeOutlives(_))
| ty::PredicateKind::Clause(ty::Clause::Projection(_))
| ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
| ty::PredicateKind::AliasEq(..)
| ty::PredicateKind::AliasRelate(..)
| ty::PredicateKind::WellFormed(_)
| ty::PredicateKind::Subtype(_)
| ty::PredicateKind::Coerce(_)

View file

@ -56,7 +56,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> {
| ty::PredicateKind::Clause(ty::Clause::Projection(..))
| ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
| ty::PredicateKind::WellFormed(..)
| ty::PredicateKind::AliasEq(..)
| ty::PredicateKind::AliasRelate(..)
| ty::PredicateKind::ObjectSafe(..)
| ty::PredicateKind::ClosureKind(..)
| ty::PredicateKind::Subtype(..)

View file

@ -666,7 +666,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
| ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..))
| ty::PredicateKind::WellFormed(..)
| ty::PredicateKind::ObjectSafe(..)
| ty::PredicateKind::AliasEq(..)
| ty::PredicateKind::AliasRelate(..)
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::ConstEquate(..)
// N.B., this predicate is created by breaking down a

View file

@ -838,7 +838,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::ConstEquate(..)
| ty::PredicateKind::Ambiguous
| ty::PredicateKind::AliasEq(..)
| ty::PredicateKind::AliasRelate(..)
| ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
}
});

View file

@ -128,7 +128,7 @@ impl<'tcx> InferCtxt<'tcx> {
(_, ty::Alias(AliasKind::Projection, _)) | (ty::Alias(AliasKind::Projection, _), _)
if self.tcx.trait_solver_next() =>
{
relation.register_type_equate_obligation(a, b);
relation.register_type_relate_obligation(a, b);
Ok(a)
}
@ -842,23 +842,25 @@ pub trait ObligationEmittingRelation<'tcx>: TypeRelation<'tcx> {
let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) };
self.register_predicates([ty::Binder::dummy(if self.tcx().trait_solver_next() {
ty::PredicateKind::AliasEq(a.into(), b.into())
ty::PredicateKind::AliasRelate(a.into(), b.into(), ty::AliasRelationDirection::Equate)
} else {
ty::PredicateKind::ConstEquate(a, b)
})]);
}
/// Register an obligation that both types must be equal to each other.
///
/// If they aren't equal then the relation doesn't hold.
fn register_type_equate_obligation(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) {
let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) };
self.register_predicates([ty::Binder::dummy(ty::PredicateKind::AliasEq(
/// Register an obligation that both types must be related to each other according to
/// the [`ty::AliasRelationDirection`] given by [`ObligationEmittingRelation::alias_relate_direction`]
fn register_type_relate_obligation(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) {
self.register_predicates([ty::Binder::dummy(ty::PredicateKind::AliasRelate(
a.into(),
b.into(),
self.alias_relate_direction(),
))]);
}
/// Relation direction emitted for `AliasRelate` predicates, corresponding to the direction
/// of the relation.
fn alias_relate_direction(&self) -> ty::AliasRelationDirection;
}
fn int_unification_error<'tcx>(

View file

@ -210,4 +210,8 @@ impl<'tcx> ObligationEmittingRelation<'tcx> for Equate<'_, '_, 'tcx> {
fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
self.fields.register_obligations(obligations);
}
fn alias_relate_direction(&self) -> ty::AliasRelationDirection {
ty::AliasRelationDirection::Equate
}
}

View file

@ -155,4 +155,9 @@ impl<'tcx> ObligationEmittingRelation<'tcx> for Glb<'_, '_, 'tcx> {
fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
self.fields.register_obligations(obligations);
}
fn alias_relate_direction(&self) -> ty::AliasRelationDirection {
// FIXME(deferred_projection_equality): This isn't right, I think?
ty::AliasRelationDirection::Equate
}
}

View file

@ -155,4 +155,9 @@ impl<'tcx> ObligationEmittingRelation<'tcx> for Lub<'_, '_, 'tcx> {
fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
self.fields.register_obligations(obligations)
}
fn alias_relate_direction(&self) -> ty::AliasRelationDirection {
// FIXME(deferred_projection_equality): This isn't right, I think?
ty::AliasRelationDirection::Equate
}
}

View file

@ -711,6 +711,34 @@ where
fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
self.delegate.register_obligations(obligations);
}
fn alias_relate_direction(&self) -> ty::AliasRelationDirection {
unreachable!("manually overridden to handle ty::Variance::Contravariant ambient variance")
}
fn register_type_relate_obligation(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) {
self.register_predicates([ty::Binder::dummy(match self.ambient_variance {
ty::Variance::Covariant => ty::PredicateKind::AliasRelate(
a.into(),
b.into(),
ty::AliasRelationDirection::Subtype,
),
// a :> b is b <: a
ty::Variance::Contravariant => ty::PredicateKind::AliasRelate(
b.into(),
a.into(),
ty::AliasRelationDirection::Subtype,
),
ty::Variance::Invariant => ty::PredicateKind::AliasRelate(
a.into(),
b.into(),
ty::AliasRelationDirection::Equate,
),
// FIXME(deferred_projection_equality): Implement this when we trigger it.
// Probably just need to do nothing here.
ty::Variance::Bivariant => unreachable!(),
})]);
}
}
/// When we encounter a binder like `for<..> fn(..)`, we actually have

View file

@ -22,7 +22,7 @@ pub fn explicit_outlives_bounds<'tcx>(
ty::PredicateKind::Clause(ty::Clause::Projection(..))
| ty::PredicateKind::Clause(ty::Clause::Trait(..))
| ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
| ty::PredicateKind::AliasEq(..)
| ty::PredicateKind::AliasRelate(..)
| ty::PredicateKind::Coerce(..)
| ty::PredicateKind::Subtype(..)
| ty::PredicateKind::WellFormed(..)

View file

@ -26,7 +26,7 @@ impl<'tcx> InferCtxt<'tcx> {
// completely change the normalization routine with the new solver.
//
// The new solver correctly handles projection equality so this hack
// is not necessary. if re-enabled it should emit `PredicateKind::AliasEq`
// is not necessary. if re-enabled it should emit `PredicateKind::AliasRelate`
// not `PredicateKind::Clause(Clause::Projection(..))` as in the new solver
// `Projection` is used as `normalizes-to` which will fail for `<T as Trait>::Assoc eq ?0`.
return projection_ty.to_ty(self.tcx);

View file

@ -236,4 +236,8 @@ impl<'tcx> ObligationEmittingRelation<'tcx> for Sub<'_, '_, 'tcx> {
fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
self.fields.register_obligations(obligations);
}
fn alias_relate_direction(&self) -> ty::AliasRelationDirection {
ty::AliasRelationDirection::Subtype
}
}

View file

@ -293,7 +293,7 @@ impl<'tcx> Elaborator<'tcx> {
// Nothing to elaborate
}
ty::PredicateKind::Ambiguous => {}
ty::PredicateKind::AliasEq(..) => {
ty::PredicateKind::AliasRelate(..) => {
// No
}
ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => {

View file

@ -1600,7 +1600,7 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
// Ignore projections, as they can only be global
// if the trait bound is global
Clause(Clause::Projection(..)) |
AliasEq(..) |
AliasRelate(..) |
// Ignore bounds that a user can't type
WellFormed(..) |
ObjectSafe(..) |

View file

@ -27,6 +27,8 @@ declare_lint! {
/// ### Example
///
/// ```rust
/// #![feature(type_alias_impl_trait)]
///
/// trait Duh {}
///
/// impl Duh for i32 {}
@ -41,7 +43,9 @@ declare_lint! {
/// type Assoc = F;
/// }
///
/// fn test() -> impl Trait<Assoc = impl Sized> {
/// type Tait = impl Sized;
///
/// fn test() -> impl Trait<Assoc = Tait> {
/// 42
/// }
/// ```
@ -54,7 +58,7 @@ declare_lint! {
///
/// Although the hidden type, `i32` does satisfy this bound, we do not
/// consider the return type to be well-formed with this lint. It can be
/// fixed by changing `impl Sized` into `impl Sized + Send`.
/// fixed by changing `Tait = impl Sized` into `Tait = impl Sized + Send`.
pub OPAQUE_HIDDEN_INFERRED_BOUND,
Warn,
"detects the use of nested `impl Trait` types in associated type bounds that are not general enough"
@ -64,7 +68,7 @@ declare_lint_pass!(OpaqueHiddenInferredBound => [OPAQUE_HIDDEN_INFERRED_BOUND]);
impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
let hir::ItemKind::OpaqueTy(_) = &item.kind else { return; };
let hir::ItemKind::OpaqueTy(opaque) = &item.kind else { return; };
let def_id = item.owner_id.def_id.to_def_id();
let infcx = &cx.tcx.infer_ctxt().build();
// For every projection predicate in the opaque type's explicit bounds,
@ -81,6 +85,17 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
// have opaques in them anyways.
let Some(proj_term) = proj.term.ty() else { continue };
// HACK: `impl Trait<Assoc = impl Trait2>` from an RPIT is "ok"...
if let ty::Alias(ty::Opaque, opaque_ty) = *proj_term.kind()
&& cx.tcx.parent(opaque_ty.def_id) == def_id
&& matches!(
opaque.origin,
hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_)
)
{
continue;
}
let proj_ty =
cx.tcx.mk_projection(proj.projection_ty.def_id, proj.projection_ty.substs);
// For every instance of the projection type in the bounds,

View file

@ -925,10 +925,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
tcx.mk_adt_def(did, adt_kind, variants, repr)
}
fn get_generics(self, item_id: DefIndex, sess: &Session) -> ty::Generics {
self.root.tables.generics_of.get(self, item_id).unwrap().decode((self, sess))
}
fn get_visibility(self, id: DefIndex) -> Visibility<DefId> {
self.root
.tables

View file

@ -545,10 +545,6 @@ impl CStore {
self.get_crate_data(def.krate).def_kind(def.index)
}
pub fn item_generics_num_lifetimes(&self, def_id: DefId, sess: &Session) -> usize {
self.get_crate_data(def_id.krate).get_generics(def_id.index, sess).own_counts().lifetimes
}
pub fn module_expansion_untracked(&self, def_id: DefId, sess: &Session) -> ExpnId {
self.get_crate_data(def_id.krate).module_expansion(def_id.index, sess)
}
@ -560,14 +556,6 @@ impl CStore {
self.get_crate_data(cnum).num_def_ids()
}
pub fn item_attrs_untracked<'a>(
&'a self,
def_id: DefId,
sess: &'a Session,
) -> impl Iterator<Item = ast::Attribute> + 'a {
self.get_crate_data(def_id.krate).get_item_attrs(def_id.index, sess)
}
pub fn get_proc_macro_quoted_span_untracked(
&self,
cnum: CrateNum,

View file

@ -288,7 +288,7 @@ impl FlagComputation {
self.add_ty(ty);
}
ty::PredicateKind::Ambiguous => {}
ty::PredicateKind::AliasEq(t1, t2) => {
ty::PredicateKind::AliasRelate(t1, t2, _) => {
self.add_term(t1);
self.add_term(t2);
}

View file

@ -543,7 +543,7 @@ impl<'tcx> Predicate<'tcx> {
| PredicateKind::Clause(Clause::TypeOutlives(_))
| PredicateKind::Clause(Clause::Projection(_))
| PredicateKind::Clause(Clause::ConstArgHasType(..))
| PredicateKind::AliasEq(..)
| PredicateKind::AliasRelate(..)
| PredicateKind::ObjectSafe(_)
| PredicateKind::ClosureKind(_, _, _)
| PredicateKind::Subtype(_)
@ -640,7 +640,23 @@ pub enum PredicateKind<'tcx> {
/// This predicate requires two terms to be equal to eachother.
///
/// Only used for new solver
AliasEq(Term<'tcx>, Term<'tcx>),
AliasRelate(Term<'tcx>, Term<'tcx>, AliasRelationDirection),
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, Debug)]
pub enum AliasRelationDirection {
Equate,
Subtype,
}
impl std::fmt::Display for AliasRelationDirection {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
AliasRelationDirection::Equate => write!(f, " == "),
AliasRelationDirection::Subtype => write!(f, " <: "),
}
}
}
/// The crate outlives map is computed during typeck and contains the
@ -976,11 +992,11 @@ impl<'tcx> Term<'tcx> {
}
}
/// This function returns `None` for `AliasKind::Opaque`.
/// This function returns the inner `AliasTy` if this term is a projection.
///
/// FIXME: rename `AliasTy` to `AliasTerm` and make sure we correctly
/// deal with constants.
pub fn to_alias_term_no_opaque(&self, tcx: TyCtxt<'tcx>) -> Option<AliasTy<'tcx>> {
pub fn to_projection_term(&self, tcx: TyCtxt<'tcx>) -> Option<AliasTy<'tcx>> {
match self.unpack() {
TermKind::Ty(ty) => match ty.kind() {
ty::Alias(kind, alias_ty) => match kind {
@ -1206,7 +1222,7 @@ impl<'tcx> Predicate<'tcx> {
PredicateKind::Clause(Clause::Trait(t)) => Some(predicate.rebind(t)),
PredicateKind::Clause(Clause::Projection(..))
| PredicateKind::Clause(Clause::ConstArgHasType(..))
| PredicateKind::AliasEq(..)
| PredicateKind::AliasRelate(..)
| PredicateKind::Subtype(..)
| PredicateKind::Coerce(..)
| PredicateKind::Clause(Clause::RegionOutlives(..))
@ -1227,7 +1243,7 @@ impl<'tcx> Predicate<'tcx> {
PredicateKind::Clause(Clause::Projection(t)) => Some(predicate.rebind(t)),
PredicateKind::Clause(Clause::Trait(..))
| PredicateKind::Clause(Clause::ConstArgHasType(..))
| PredicateKind::AliasEq(..)
| PredicateKind::AliasRelate(..)
| PredicateKind::Subtype(..)
| PredicateKind::Coerce(..)
| PredicateKind::Clause(Clause::RegionOutlives(..))
@ -1249,7 +1265,7 @@ impl<'tcx> Predicate<'tcx> {
PredicateKind::Clause(Clause::Trait(..))
| PredicateKind::Clause(Clause::ConstArgHasType(..))
| PredicateKind::Clause(Clause::Projection(..))
| PredicateKind::AliasEq(..)
| PredicateKind::AliasRelate(..)
| PredicateKind::Subtype(..)
| PredicateKind::Coerce(..)
| PredicateKind::Clause(Clause::RegionOutlives(..))

View file

@ -704,7 +704,11 @@ pub trait PrettyPrinter<'tcx>:
ty::BoundTyKind::Anon(bv) => {
self.pretty_print_bound_var(debruijn, ty::BoundVar::from_u32(bv))?
}
ty::BoundTyKind::Param(_, s) => p!(write("{}", s)),
ty::BoundTyKind::Param(_, s) => match self.should_print_verbose() {
true if debruijn == ty::INNERMOST => p!(write("^{}", s)),
true => p!(write("^{}_{}", debruijn.index(), s)),
false => p!(write("{}", s)),
},
},
ty::Adt(def, substs) => {
p!(print_def_path(def.did(), substs));
@ -2847,7 +2851,7 @@ define_print_and_forward_display! {
p!("the type `", print(ty), "` is found in the environment")
}
ty::PredicateKind::Ambiguous => p!("ambiguous"),
ty::PredicateKind::AliasEq(t1, t2) => p!(print(t1), " == ", print(t2)),
ty::PredicateKind::AliasRelate(t1, t2, dir) => p!(print(t1), write(" {} ", dir), print(t2)),
}
}

View file

@ -177,7 +177,9 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> {
write!(f, "TypeWellFormedFromEnv({:?})", ty)
}
ty::PredicateKind::Ambiguous => write!(f, "Ambiguous"),
ty::PredicateKind::AliasEq(t1, t2) => write!(f, "AliasEq({t1:?}, {t2:?})"),
ty::PredicateKind::AliasRelate(t1, t2, dir) => {
write!(f, "AliasRelate({t1:?}, {dir:?}, {t2:?})")
}
}
}
}
@ -250,6 +252,7 @@ TrivialTypeTraversalAndLiftImpls! {
crate::ty::AssocItem,
crate::ty::AssocKind,
crate::ty::AliasKind,
crate::ty::AliasRelationDirection,
crate::ty::Placeholder<crate::ty::BoundRegionKind>,
crate::ty::Placeholder<crate::ty::BoundTyKind>,
crate::ty::ClosureKind,

View file

@ -566,41 +566,51 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
Rvalue::Use(Operand::Move(val))
}
BinOp::Shl | BinOp::Shr if self.check_overflow && ty.is_integral() => {
// Consider that the shift overflows if `rhs < 0` or `rhs >= bits`.
// This can be encoded as a single operation as `(rhs & -bits) != 0`.
let (size, _) = ty.int_size_and_signed(self.tcx);
let bits = size.bits();
debug_assert!(bits.is_power_of_two());
let mask = !((bits - 1) as u128);
// For an unsigned RHS, the shift is in-range for `rhs < bits`.
// For a signed RHS, `IntToInt` cast to the equivalent unsigned
// type and do that same comparison. Because the type is the
// same size, there's no negative shift amount that ends up
// overlapping with valid ones, thus it catches negatives too.
let (lhs_size, _) = ty.int_size_and_signed(self.tcx);
let rhs_ty = rhs.ty(&self.local_decls, self.tcx);
let (rhs_size, _) = rhs_ty.int_size_and_signed(self.tcx);
let mask = Operand::const_from_scalar(
let (unsigned_rhs, unsigned_ty) = match rhs_ty.kind() {
ty::Uint(_) => (rhs.to_copy(), rhs_ty),
ty::Int(int_width) => {
let uint_ty = self.tcx.mk_mach_uint(int_width.to_unsigned());
let rhs_temp = self.temp(uint_ty, span);
self.cfg.push_assign(
block,
source_info,
rhs_temp,
Rvalue::Cast(CastKind::IntToInt, rhs.to_copy(), uint_ty),
);
(Operand::Move(rhs_temp), uint_ty)
}
_ => unreachable!("only integers are shiftable"),
};
// This can't overflow because the largest shiftable types are 128-bit,
// which fits in `u8`, the smallest possible `unsigned_ty`.
// (And `from_uint` will `bug!` if that's ever no longer true.)
let lhs_bits = Operand::const_from_scalar(
self.tcx,
rhs_ty,
Scalar::from_uint(rhs_size.truncate(mask), rhs_size),
unsigned_ty,
Scalar::from_uint(lhs_size.bits(), rhs_size),
span,
);
let outer_bits = self.temp(rhs_ty, span);
let inbounds = self.temp(bool_ty, span);
self.cfg.push_assign(
block,
source_info,
outer_bits,
Rvalue::BinaryOp(BinOp::BitAnd, Box::new((rhs.to_copy(), mask))),
);
let overflows = self.temp(bool_ty, span);
let zero = self.zero_literal(span, rhs_ty);
self.cfg.push_assign(
block,
source_info,
overflows,
Rvalue::BinaryOp(BinOp::Ne, Box::new((Operand::Move(outer_bits), zero))),
inbounds,
Rvalue::BinaryOp(BinOp::Lt, Box::new((unsigned_rhs, lhs_bits))),
);
let overflow_err = AssertKind::Overflow(op, lhs.to_copy(), rhs.to_copy());
block = self.assert(block, Operand::Move(overflows), false, overflow_err, span);
block = self.assert(block, Operand::Move(inbounds), true, overflow_err, span);
Rvalue::BinaryOp(op, Box::new((lhs, rhs)))
}
BinOp::Div | BinOp::Rem if ty.is_integral() => {

View file

@ -180,7 +180,7 @@ where
| ty::PredicateKind::ConstEquate(_, _)
| ty::PredicateKind::TypeWellFormedFromEnv(_)
| ty::PredicateKind::Ambiguous
| ty::PredicateKind::AliasEq(_, _) => bug!("unexpected predicate: {:?}", predicate),
| ty::PredicateKind::AliasRelate(..) => bug!("unexpected predicate: {:?}", predicate),
}
}

View file

@ -27,7 +27,6 @@ use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
use rustc_metadata::creader::LoadedMacro;
use rustc_middle::metadata::ModChild;
use rustc_middle::{bug, ty};
use rustc_session::cstore::CrateStore;
use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span;
@ -116,33 +115,24 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
if !def_id.is_local() {
let def_kind = self.cstore().def_kind(def_id);
match def_kind {
DefKind::Mod | DefKind::Enum | DefKind::Trait => {
let def_key = self.cstore().def_key(def_id);
let parent = def_key.parent.map(|index| {
self.get_nearest_non_block_module(DefId { index, krate: def_id.krate })
});
let name = if let Some(cnum) = def_id.as_crate_root() {
self.cstore().crate_name(cnum)
} else {
def_key.disambiguated_data.data.get_opt_name().expect("module without name")
};
let expn_id = self.cstore().module_expansion_untracked(def_id, &self.tcx.sess);
Some(self.new_module(
parent,
ModuleKind::Def(def_kind, def_id, name),
expn_id,
self.def_span(def_id),
// FIXME: Account for `#[no_implicit_prelude]` attributes.
parent.map_or(false, |module| module.no_implicit_prelude),
))
}
_ => None,
if let DefKind::Mod | DefKind::Enum | DefKind::Trait = def_kind {
let parent = self
.tcx
.opt_parent(def_id)
.map(|parent_id| self.get_nearest_non_block_module(parent_id));
let expn_id = self.cstore().module_expansion_untracked(def_id, &self.tcx.sess);
return Some(self.new_module(
parent,
ModuleKind::Def(def_kind, def_id, self.tcx.item_name(def_id)),
expn_id,
self.def_span(def_id),
// FIXME: Account for `#[no_implicit_prelude]` attributes.
parent.map_or(false, |module| module.no_implicit_prelude),
));
}
} else {
None
}
None
}
pub(crate) fn expn_def_scope(&mut self, expn_id: ExpnId) -> Module<'a> {

View file

@ -1168,7 +1168,7 @@ impl<'tcx> Resolver<'_, 'tcx> {
if let Some(def_id) = def_id.as_local() {
self.item_generics_num_lifetimes[&def_id]
} else {
self.cstore().item_generics_num_lifetimes(def_id, self.tcx.sess)
self.tcx.generics_of(def_id).own_counts().lifetimes
}
}
@ -1906,10 +1906,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
return v.clone();
}
let attr = self
.cstore()
.item_attrs_untracked(def_id, self.tcx.sess)
.find(|a| a.has_name(sym::rustc_legacy_const_generics))?;
let attr = self.tcx.get_attr(def_id, sym::rustc_legacy_const_generics)?;
let mut ret = Vec::new();
for meta in attr.meta_item_list()? {
match meta.lit()?.kind {

View file

@ -236,9 +236,11 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
ty::PredicateKind::TypeWellFormedFromEnv(..) => {
bug!("TypeWellFormedFromEnv is only used for Chalk")
}
ty::PredicateKind::AliasEq(lhs, rhs) => {
self.compute_alias_eq_goal(Goal { param_env, predicate: (lhs, rhs) })
}
ty::PredicateKind::AliasRelate(lhs, rhs, direction) => self
.compute_alias_relate_goal(Goal {
param_env,
predicate: (lhs, rhs, direction),
}),
}
} else {
let kind = self.infcx.instantiate_binder_with_placeholders(kind);
@ -470,6 +472,25 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
})
}
#[instrument(level = "debug", skip(self, param_env), ret)]
pub(super) fn sub<T: ToTrace<'tcx>>(
&mut self,
param_env: ty::ParamEnv<'tcx>,
sub: T,
sup: T,
) -> Result<(), NoSolution> {
self.infcx
.at(&ObligationCause::dummy(), param_env)
.sub(DefineOpaqueTypes::No, sub, sup)
.map(|InferOk { value: (), obligations }| {
self.add_goals(obligations.into_iter().map(|o| o.into()));
})
.map_err(|e| {
debug!(?e, "failed to subtype");
NoSolution
})
}
/// Equates two values returning the nested goals without adding them
/// to the nested goals of the `EvalCtxt`.
///

View file

@ -73,7 +73,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
MismatchedProjectionTypes { err: TypeError::Mismatch },
)
}
ty::PredicateKind::AliasEq(_, _) => {
ty::PredicateKind::AliasRelate(_, _, _) => {
FulfillmentErrorCode::CodeProjectionError(
MismatchedProjectionTypes { err: TypeError::Mismatch },
)

View file

@ -13,7 +13,6 @@
use rustc_hir::def_id::DefId;
use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues};
use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
use rustc_infer::traits::query::NoSolution;
use rustc_middle::traits::solve::{
CanonicalGoal, CanonicalResponse, Certainty, ExternalConstraints, ExternalConstraintsData,
@ -110,11 +109,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
// That won't actually reflect in the query response, so it seems moot.
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
} else {
let InferOk { value: (), obligations } = self
.infcx
.at(&ObligationCause::dummy(), goal.param_env)
.sub(DefineOpaqueTypes::No, goal.predicate.a, goal.predicate.b)?;
self.add_goals(obligations.into_iter().map(|pred| pred.into()));
self.sub(goal.param_env, goal.predicate.a, goal.predicate.b)?;
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}
}
@ -165,55 +160,94 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
}
#[instrument(level = "debug", skip(self), ret)]
fn compute_alias_eq_goal(
fn compute_alias_relate_goal(
&mut self,
goal: Goal<'tcx, (ty::Term<'tcx>, ty::Term<'tcx>)>,
goal: Goal<'tcx, (ty::Term<'tcx>, ty::Term<'tcx>, ty::AliasRelationDirection)>,
) -> QueryResult<'tcx> {
let tcx = self.tcx();
// We may need to invert the alias relation direction if dealing an alias on the RHS.
enum Invert {
No,
Yes,
}
let evaluate_normalizes_to =
|ecx: &mut EvalCtxt<'_, 'tcx>, alias, other, direction, invert| {
debug!("evaluate_normalizes_to(alias={:?}, other={:?})", alias, other);
let result = ecx.probe(|ecx| {
let other = match direction {
// This is purely an optimization.
ty::AliasRelationDirection::Equate => other,
let evaluate_normalizes_to = |ecx: &mut EvalCtxt<'_, 'tcx>, alias, other| {
debug!("evaluate_normalizes_to(alias={:?}, other={:?})", alias, other);
let r = ecx.probe(|ecx| {
ecx.add_goal(goal.with(
tcx,
ty::Binder::dummy(ty::ProjectionPredicate {
projection_ty: alias,
term: other,
}),
));
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
});
debug!("evaluate_normalizes_to(..) -> {:?}", r);
r
};
ty::AliasRelationDirection::Subtype => {
let fresh = ecx.next_term_infer_of_kind(other);
let (sub, sup) = match invert {
Invert::No => (fresh, other),
Invert::Yes => (other, fresh),
};
ecx.sub(goal.param_env, sub, sup)?;
fresh
}
};
ecx.add_goal(goal.with(
tcx,
ty::Binder::dummy(ty::ProjectionPredicate {
projection_ty: alias,
term: other,
}),
));
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
});
debug!("evaluate_normalizes_to({alias}, {other}, {direction:?}) -> {result:?}");
result
};
if goal.predicate.0.is_infer() || goal.predicate.1.is_infer() {
let (lhs, rhs, direction) = goal.predicate;
if lhs.is_infer() || rhs.is_infer() {
bug!(
"`AliasEq` goal with an infer var on lhs or rhs which should have been instantiated"
"`AliasRelate` goal with an infer var on lhs or rhs which should have been instantiated"
);
}
match (
goal.predicate.0.to_alias_term_no_opaque(tcx),
goal.predicate.1.to_alias_term_no_opaque(tcx),
) {
(None, None) => bug!("`AliasEq` goal without an alias on either lhs or rhs"),
(Some(alias), None) => evaluate_normalizes_to(self, alias, goal.predicate.1),
(None, Some(alias)) => evaluate_normalizes_to(self, alias, goal.predicate.0),
match (lhs.to_projection_term(tcx), rhs.to_projection_term(tcx)) {
(None, None) => bug!("`AliasRelate` goal without an alias on either lhs or rhs"),
// RHS is not a projection, only way this is true is if LHS normalizes-to RHS
(Some(alias_lhs), None) => {
evaluate_normalizes_to(self, alias_lhs, rhs, direction, Invert::No)
}
// LHS is not a projection, only way this is true is if RHS normalizes-to LHS
(None, Some(alias_rhs)) => {
evaluate_normalizes_to(self, alias_rhs, lhs, direction, Invert::Yes)
}
(Some(alias_lhs), Some(alias_rhs)) => {
debug!("compute_alias_eq_goal: both sides are aliases");
debug!("compute_alias_relate_goal: both sides are aliases");
let mut candidates = Vec::with_capacity(3);
let candidates = vec![
// LHS normalizes-to RHS
evaluate_normalizes_to(self, alias_lhs, rhs, direction, Invert::No),
// RHS normalizes-to RHS
evaluate_normalizes_to(self, alias_rhs, lhs, direction, Invert::Yes),
// Relate via substs
self.probe(|ecx| {
debug!(
"compute_alias_relate_goal: alias defids are equal, equating substs"
);
// Evaluate all 3 potential candidates for the alias' being equal
candidates.push(evaluate_normalizes_to(self, alias_lhs, goal.predicate.1));
candidates.push(evaluate_normalizes_to(self, alias_rhs, goal.predicate.0));
candidates.push(self.probe(|ecx| {
debug!("compute_alias_eq_goal: alias defids are equal, equating substs");
ecx.eq(goal.param_env, alias_lhs, alias_rhs)?;
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}));
match direction {
ty::AliasRelationDirection::Equate => {
ecx.eq(goal.param_env, alias_lhs, alias_rhs)?;
}
ty::AliasRelationDirection::Subtype => {
ecx.sub(goal.param_env, alias_lhs, alias_rhs)?;
}
}
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}),
];
debug!(?candidates);
self.try_merge_responses(candidates.into_iter())

View file

@ -832,7 +832,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
// the `ParamEnv`.
ty::PredicateKind::WellFormed(..)
| ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
| ty::PredicateKind::AliasEq(..)
| ty::PredicateKind::AliasRelate(..)
| ty::PredicateKind::ObjectSafe(..)
| ty::PredicateKind::ClosureKind(..)
| ty::PredicateKind::Subtype(..)

View file

@ -92,6 +92,11 @@ impl<'a, 'tcx> TypeRelation<'tcx> for CollectAllMismatches<'a, 'tcx> {
}
impl<'tcx> ObligationEmittingRelation<'tcx> for CollectAllMismatches<'_, 'tcx> {
fn alias_relate_direction(&self) -> ty::AliasRelationDirection {
// FIXME(deferred_projection_equality): We really should get rid of this relation.
ty::AliasRelationDirection::Equate
}
fn register_obligations(&mut self, _obligations: PredicateObligations<'tcx>) {
// FIXME(deferred_projection_equality)
}

View file

@ -1276,9 +1276,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
"TypeWellFormedFromEnv predicate should only exist in the environment"
),
ty::PredicateKind::AliasEq(..) => span_bug!(
ty::PredicateKind::AliasRelate(..) => span_bug!(
span,
"AliasEq predicate should never be the predicate cause of a SelectionError"
"AliasRelate predicate should never be the predicate cause of a SelectionError"
),
ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {

View file

@ -361,8 +361,8 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
ty::PredicateKind::TypeWellFormedFromEnv(..) => {
bug!("TypeWellFormedFromEnv is only used for Chalk")
}
ty::PredicateKind::AliasEq(..) => {
bug!("AliasEq is only used for new solver")
ty::PredicateKind::AliasRelate(..) => {
bug!("AliasRelate is only used for new solver")
}
},
Some(pred) => match pred {
@ -630,8 +630,8 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
ty::PredicateKind::TypeWellFormedFromEnv(..) => {
bug!("TypeWellFormedFromEnv is only used for Chalk")
}
ty::PredicateKind::AliasEq(..) => {
bug!("AliasEq is only used for new solver")
ty::PredicateKind::AliasRelate(..) => {
bug!("AliasRelate is only used for new solver")
}
ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
match self.selcx.infcx.at(&obligation.cause, obligation.param_env).eq(

View file

@ -335,7 +335,7 @@ fn predicate_references_self<'tcx>(
has_self_ty(&ty.into()).then_some(sp)
}
ty::PredicateKind::AliasEq(..) => bug!("`AliasEq` not allowed as assumption"),
ty::PredicateKind::AliasRelate(..) => bug!("`AliasRelate` not allowed as assumption"),
ty::PredicateKind::WellFormed(..)
| ty::PredicateKind::ObjectSafe(..)
@ -395,7 +395,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
| ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..))
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::ConstEquate(..)
| ty::PredicateKind::AliasEq(..)
| ty::PredicateKind::AliasRelate(..)
| ty::PredicateKind::Ambiguous
| ty::PredicateKind::TypeWellFormedFromEnv(..) => false,
}

View file

@ -977,8 +977,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ty::PredicateKind::TypeWellFormedFromEnv(..) => {
bug!("TypeWellFormedFromEnv is only used for chalk")
}
ty::PredicateKind::AliasEq(..) => {
bug!("AliasEq is only used for new solver")
ty::PredicateKind::AliasRelate(..) => {
bug!("AliasRelate is only used for new solver")
}
ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig),
ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {

View file

@ -191,8 +191,8 @@ pub fn predicate_obligations<'tcx>(
ty::PredicateKind::TypeWellFormedFromEnv(..) => {
bug!("TypeWellFormedFromEnv is only used for Chalk")
}
ty::PredicateKind::AliasEq(..) => {
bug!("We should only wf check where clauses and `AliasEq` is not a `Clause`")
ty::PredicateKind::AliasRelate(..) => {
bug!("We should only wf check where clauses and `AliasRelate` is not a `Clause`")
}
}
@ -936,7 +936,7 @@ pub(crate) fn required_region_bounds<'tcx>(
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::ConstEquate(..)
| ty::PredicateKind::Ambiguous
| ty::PredicateKind::AliasEq(..)
| ty::PredicateKind::AliasRelate(..)
| ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate(
ref t,

View file

@ -119,7 +119,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment<chalk_ir::Goal<RustInterner<'
},
ty::PredicateKind::ObjectSafe(..)
| ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
| ty::PredicateKind::AliasEq(..)
| ty::PredicateKind::AliasRelate(..)
| ty::PredicateKind::ClosureKind(..)
| ty::PredicateKind::Subtype(..)
| ty::PredicateKind::Coerce(..)
@ -215,7 +215,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData<RustInterner<'tcx>>> for ty::Predi
// some of these in terms of chalk operations.
ty::PredicateKind::ClosureKind(..)
| ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
| ty::PredicateKind::AliasEq(..)
| ty::PredicateKind::AliasRelate(..)
| ty::PredicateKind::Coerce(..)
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::Ambiguous
@ -652,7 +652,7 @@ impl<'tcx> LowerInto<'tcx, Option<chalk_ir::QuantifiedWhereClause<RustInterner<'
ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => None,
ty::PredicateKind::ObjectSafe(..)
| ty::PredicateKind::AliasEq(..)
| ty::PredicateKind::AliasRelate(..)
| ty::PredicateKind::ClosureKind(..)
| ty::PredicateKind::Subtype(..)
| ty::PredicateKind::Coerce(..)
@ -787,7 +787,7 @@ impl<'tcx> LowerInto<'tcx, Option<chalk_solve::rust_ir::QuantifiedInlineBound<Ru
ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => None,
ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..))
| ty::PredicateKind::AliasEq(..)
| ty::PredicateKind::AliasRelate(..)
| ty::PredicateKind::ObjectSafe(..)
| ty::PredicateKind::ClosureKind(..)
| ty::PredicateKind::Subtype(..)

View file

@ -86,7 +86,7 @@ fn compute_implied_outlives_bounds<'tcx>(
if obligation.predicate.has_non_region_infer() {
match obligation.predicate.kind().skip_binder() {
ty::PredicateKind::Clause(ty::Clause::Projection(..))
| ty::PredicateKind::AliasEq(..) => {
| ty::PredicateKind::AliasRelate(..) => {
ocx.register_obligation(obligation.clone());
}
_ => {}
@ -110,7 +110,7 @@ fn compute_implied_outlives_bounds<'tcx>(
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::ConstEquate(..)
| ty::PredicateKind::Ambiguous
| ty::PredicateKind::AliasEq(..)
| ty::PredicateKind::AliasRelate(..)
| ty::PredicateKind::TypeWellFormedFromEnv(..) => {}
// We need to search through *all* WellFormed predicates

View file

@ -61,7 +61,7 @@ fn not_outlives_predicate(p: ty::Predicate<'_>) -> bool {
ty::PredicateKind::Clause(ty::Clause::Trait(..))
| ty::PredicateKind::Clause(ty::Clause::Projection(..))
| ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
| ty::PredicateKind::AliasEq(..)
| ty::PredicateKind::AliasRelate(..)
| ty::PredicateKind::WellFormed(..)
| ty::PredicateKind::ObjectSafe(..)
| ty::PredicateKind::ClosureKind(..)

View file

@ -432,6 +432,17 @@ impl IntTy {
_ => *self,
}
}
pub fn to_unsigned(self) -> UintTy {
match self {
IntTy::Isize => UintTy::Usize,
IntTy::I8 => UintTy::U8,
IntTy::I16 => UintTy::U16,
IntTy::I32 => UintTy::U32,
IntTy::I64 => UintTy::U64,
IntTy::I128 => UintTy::U128,
}
}
}
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Debug)]
@ -479,6 +490,17 @@ impl UintTy {
_ => *self,
}
}
pub fn to_signed(self) -> IntTy {
match self {
UintTy::Usize => IntTy::Isize,
UintTy::U8 => IntTy::I8,
UintTy::U16 => IntTy::I16,
UintTy::U32 => IntTy::I32,
UintTy::U64 => IntTy::I64,
UintTy::U128 => IntTy::I128,
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]