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:
commit
99c49d95cd
@ -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(_)
|
||||
|
@ -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(_)
|
||||
|
@ -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(..)
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
}
|
||||
});
|
||||
|
@ -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>(
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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(..)
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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(..)) => {
|
||||
|
@ -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(..) |
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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(..))
|
||||
|
@ -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)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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() => {
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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> {
|
||||
|
@ -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 {
|
||||
|
@ -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`.
|
||||
///
|
||||
|
@ -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 },
|
||||
)
|
||||
|
@ -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())
|
||||
|
@ -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(..)
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)) => {
|
||||
|
@ -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(
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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)) => {
|
||||
|
@ -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,
|
||||
|
@ -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(..)
|
||||
|
@ -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
|
||||
|
@ -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(..)
|
||||
|
@ -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)]
|
||||
|
@ -692,10 +692,10 @@ impl<T> Rc<T> {
|
||||
/// it is guaranteed that exactly one of the calls returns the inner value.
|
||||
/// This means in particular that the inner value is not dropped.
|
||||
///
|
||||
/// This is equivalent to `Rc::try_unwrap(...).ok()`. (Note that these are not equivalent for
|
||||
/// `Arc`, due to race conditions that do not apply to `Rc`.)
|
||||
/// This is equivalent to `Rc::try_unwrap(this).ok()`. (Note that these are not equivalent for
|
||||
/// [`Arc`](crate::sync::Arc), due to race conditions that do not apply to `Rc`.)
|
||||
#[inline]
|
||||
#[unstable(feature = "rc_into_inner", issue = "106894")]
|
||||
#[stable(feature = "rc_into_inner", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub fn into_inner(this: Self) -> Option<T> {
|
||||
Rc::try_unwrap(this).ok()
|
||||
}
|
||||
|
@ -662,20 +662,17 @@ impl<T> Arc<T> {
|
||||
///
|
||||
/// This will succeed even if there are outstanding weak references.
|
||||
///
|
||||
// FIXME: when `Arc::into_inner` is stabilized, add this paragraph:
|
||||
/*
|
||||
/// It is strongly recommended to use [`Arc::into_inner`] instead if you don't
|
||||
/// want to keep the `Arc` in the [`Err`] case.
|
||||
/// Immediately dropping the [`Err`] payload, like in the expression
|
||||
/// `Arc::try_unwrap(this).ok()`, can still cause the strong count to
|
||||
/// drop to zero and the inner value of the `Arc` to be dropped:
|
||||
/// For instance if two threads execute this expression in parallel, then
|
||||
/// For instance if two threads each execute this expression in parallel, then
|
||||
/// there is a race condition. The threads could first both check whether they
|
||||
/// have the last clone of their `Arc` via `Arc::try_unwrap`, and then
|
||||
/// both drop their `Arc` in the call to [`ok`][`Result::ok`],
|
||||
/// taking the strong count from two down to zero.
|
||||
///
|
||||
*/
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
@ -719,20 +716,13 @@ impl<T> Arc<T> {
|
||||
/// This means in particular that the inner value is not dropped.
|
||||
///
|
||||
/// The similar expression `Arc::try_unwrap(this).ok()` does not
|
||||
/// offer such a guarantee. See the last example below.
|
||||
//
|
||||
// FIXME: when `Arc::into_inner` is stabilized, add this to end
|
||||
// of the previous sentence:
|
||||
/*
|
||||
/// offer such a guarantee. See the last example below
|
||||
/// and the documentation of [`Arc::try_unwrap`].
|
||||
*/
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Minimal example demonstrating the guarantee that `Arc::into_inner` gives.
|
||||
/// ```
|
||||
/// #![feature(arc_into_inner)]
|
||||
///
|
||||
/// use std::sync::Arc;
|
||||
///
|
||||
/// let x = Arc::new(3);
|
||||
@ -756,8 +746,6 @@ impl<T> Arc<T> {
|
||||
///
|
||||
/// A more practical example demonstrating the need for `Arc::into_inner`:
|
||||
/// ```
|
||||
/// #![feature(arc_into_inner)]
|
||||
///
|
||||
/// use std::sync::Arc;
|
||||
///
|
||||
/// // Definition of a simple singly linked list using `Arc`:
|
||||
@ -807,13 +795,8 @@ impl<T> Arc<T> {
|
||||
/// x_thread.join().unwrap();
|
||||
/// y_thread.join().unwrap();
|
||||
/// ```
|
||||
|
||||
// FIXME: when `Arc::into_inner` is stabilized, adjust above documentation
|
||||
// and the documentation of `Arc::try_unwrap` according to the `FIXME`s. Also
|
||||
// open an issue on rust-lang/rust-clippy, asking for a lint against
|
||||
// `Arc::try_unwrap(...).ok()`.
|
||||
#[inline]
|
||||
#[unstable(feature = "arc_into_inner", issue = "106894")]
|
||||
#[stable(feature = "arc_into_inner", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub fn into_inner(this: Self) -> Option<T> {
|
||||
// Make sure that the ordinary `Drop` implementation isn’t called as well
|
||||
let mut this = mem::ManuallyDrop::new(this);
|
||||
|
@ -324,7 +324,7 @@ pub(crate) fn clean_predicate<'tcx>(
|
||||
ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => None,
|
||||
|
||||
ty::PredicateKind::Subtype(..)
|
||||
| ty::PredicateKind::AliasEq(..)
|
||||
| ty::PredicateKind::AliasRelate(..)
|
||||
| ty::PredicateKind::Coerce(..)
|
||||
| ty::PredicateKind::ObjectSafe(..)
|
||||
| ty::PredicateKind::ClosureKind(..)
|
||||
|
@ -37,7 +37,7 @@ pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv)
|
||||
| ty::PredicateKind::ConstEvaluatable(..)
|
||||
| ty::PredicateKind::ConstEquate(..)
|
||||
| ty::PredicateKind::TypeWellFormedFromEnv(..) => continue,
|
||||
ty::PredicateKind::AliasEq(..) => panic!("alias eq predicate on function: {predicate:#?}"),
|
||||
ty::PredicateKind::AliasRelate(..) => panic!("alias relate predicate on function: {predicate:#?}"),
|
||||
ty::PredicateKind::ObjectSafe(_) => panic!("object safe predicate on function: {predicate:#?}"),
|
||||
ty::PredicateKind::ClosureKind(..) => panic!("closure kind predicate on function: {predicate:#?}"),
|
||||
ty::PredicateKind::Subtype(_) => panic!("subtype predicate on function: {predicate:#?}"),
|
||||
|
20
tests/mir-opt/building/shifts.rs
Normal file
20
tests/mir-opt/building/shifts.rs
Normal file
@ -0,0 +1,20 @@
|
||||
// compile-flags: -C debug-assertions=yes
|
||||
|
||||
// EMIT_MIR shifts.shift_signed.built.after.mir
|
||||
fn shift_signed(small: i8, big: u128, a: i8, b: i32, c: i128) -> ([i8; 3], [u128; 3]) {
|
||||
(
|
||||
[small >> a, small >> b, small >> c],
|
||||
[big << a, big << b, big << c],
|
||||
)
|
||||
}
|
||||
|
||||
// EMIT_MIR shifts.shift_unsigned.built.after.mir
|
||||
fn shift_unsigned(small: u8, big: i128, a: u8, b: u32, c: u128) -> ([u8; 3], [i128; 3]) {
|
||||
(
|
||||
[small >> a, small >> b, small >> c],
|
||||
[big << a, big << b, big << c],
|
||||
)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
147
tests/mir-opt/building/shifts.shift_signed.built.after.mir
Normal file
147
tests/mir-opt/building/shifts.shift_signed.built.after.mir
Normal file
@ -0,0 +1,147 @@
|
||||
// MIR for `shift_signed` after built
|
||||
|
||||
fn shift_signed(_1: i8, _2: u128, _3: i8, _4: i32, _5: i128) -> ([i8; 3], [u128; 3]) {
|
||||
debug small => _1; // in scope 0 at $DIR/shifts.rs:+0:17: +0:22
|
||||
debug big => _2; // in scope 0 at $DIR/shifts.rs:+0:28: +0:31
|
||||
debug a => _3; // in scope 0 at $DIR/shifts.rs:+0:39: +0:40
|
||||
debug b => _4; // in scope 0 at $DIR/shifts.rs:+0:46: +0:47
|
||||
debug c => _5; // in scope 0 at $DIR/shifts.rs:+0:54: +0:55
|
||||
let mut _0: ([i8; 3], [u128; 3]); // return place in scope 0 at $DIR/shifts.rs:+0:66: +0:86
|
||||
let mut _6: [i8; 3]; // in scope 0 at $DIR/shifts.rs:+2:9: +2:45
|
||||
let mut _7: i8; // in scope 0 at $DIR/shifts.rs:+2:10: +2:20
|
||||
let mut _8: i8; // in scope 0 at $DIR/shifts.rs:+2:10: +2:15
|
||||
let mut _9: i8; // in scope 0 at $DIR/shifts.rs:+2:19: +2:20
|
||||
let mut _10: u8; // in scope 0 at $DIR/shifts.rs:+2:10: +2:20
|
||||
let mut _11: bool; // in scope 0 at $DIR/shifts.rs:+2:10: +2:20
|
||||
let mut _12: i8; // in scope 0 at $DIR/shifts.rs:+2:22: +2:32
|
||||
let mut _13: i8; // in scope 0 at $DIR/shifts.rs:+2:22: +2:27
|
||||
let mut _14: i32; // in scope 0 at $DIR/shifts.rs:+2:31: +2:32
|
||||
let mut _15: u32; // in scope 0 at $DIR/shifts.rs:+2:22: +2:32
|
||||
let mut _16: bool; // in scope 0 at $DIR/shifts.rs:+2:22: +2:32
|
||||
let mut _17: i8; // in scope 0 at $DIR/shifts.rs:+2:34: +2:44
|
||||
let mut _18: i8; // in scope 0 at $DIR/shifts.rs:+2:34: +2:39
|
||||
let mut _19: i128; // in scope 0 at $DIR/shifts.rs:+2:43: +2:44
|
||||
let mut _20: u128; // in scope 0 at $DIR/shifts.rs:+2:34: +2:44
|
||||
let mut _21: bool; // in scope 0 at $DIR/shifts.rs:+2:34: +2:44
|
||||
let mut _22: [u128; 3]; // in scope 0 at $DIR/shifts.rs:+3:9: +3:39
|
||||
let mut _23: u128; // in scope 0 at $DIR/shifts.rs:+3:10: +3:18
|
||||
let mut _24: u128; // in scope 0 at $DIR/shifts.rs:+3:10: +3:13
|
||||
let mut _25: i8; // in scope 0 at $DIR/shifts.rs:+3:17: +3:18
|
||||
let mut _26: u8; // in scope 0 at $DIR/shifts.rs:+3:10: +3:18
|
||||
let mut _27: bool; // in scope 0 at $DIR/shifts.rs:+3:10: +3:18
|
||||
let mut _28: u128; // in scope 0 at $DIR/shifts.rs:+3:20: +3:28
|
||||
let mut _29: u128; // in scope 0 at $DIR/shifts.rs:+3:20: +3:23
|
||||
let mut _30: i32; // in scope 0 at $DIR/shifts.rs:+3:27: +3:28
|
||||
let mut _31: u32; // in scope 0 at $DIR/shifts.rs:+3:20: +3:28
|
||||
let mut _32: bool; // in scope 0 at $DIR/shifts.rs:+3:20: +3:28
|
||||
let mut _33: u128; // in scope 0 at $DIR/shifts.rs:+3:30: +3:38
|
||||
let mut _34: u128; // in scope 0 at $DIR/shifts.rs:+3:30: +3:33
|
||||
let mut _35: i128; // in scope 0 at $DIR/shifts.rs:+3:37: +3:38
|
||||
let mut _36: u128; // in scope 0 at $DIR/shifts.rs:+3:30: +3:38
|
||||
let mut _37: bool; // in scope 0 at $DIR/shifts.rs:+3:30: +3:38
|
||||
|
||||
bb0: {
|
||||
StorageLive(_6); // scope 0 at $DIR/shifts.rs:+2:9: +2:45
|
||||
StorageLive(_7); // scope 0 at $DIR/shifts.rs:+2:10: +2:20
|
||||
StorageLive(_8); // scope 0 at $DIR/shifts.rs:+2:10: +2:15
|
||||
_8 = _1; // scope 0 at $DIR/shifts.rs:+2:10: +2:15
|
||||
StorageLive(_9); // scope 0 at $DIR/shifts.rs:+2:19: +2:20
|
||||
_9 = _3; // scope 0 at $DIR/shifts.rs:+2:19: +2:20
|
||||
_10 = _9 as u8 (IntToInt); // scope 0 at $DIR/shifts.rs:+2:10: +2:20
|
||||
_11 = Lt(move _10, const 8_u8); // scope 0 at $DIR/shifts.rs:+2:10: +2:20
|
||||
assert(move _11, "attempt to shift right by `{}`, which would overflow", _9) -> [success: bb1, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:10: +2:20
|
||||
}
|
||||
|
||||
bb1: {
|
||||
_7 = Shr(move _8, move _9); // scope 0 at $DIR/shifts.rs:+2:10: +2:20
|
||||
StorageDead(_9); // scope 0 at $DIR/shifts.rs:+2:19: +2:20
|
||||
StorageDead(_8); // scope 0 at $DIR/shifts.rs:+2:19: +2:20
|
||||
StorageLive(_12); // scope 0 at $DIR/shifts.rs:+2:22: +2:32
|
||||
StorageLive(_13); // scope 0 at $DIR/shifts.rs:+2:22: +2:27
|
||||
_13 = _1; // scope 0 at $DIR/shifts.rs:+2:22: +2:27
|
||||
StorageLive(_14); // scope 0 at $DIR/shifts.rs:+2:31: +2:32
|
||||
_14 = _4; // scope 0 at $DIR/shifts.rs:+2:31: +2:32
|
||||
_15 = _14 as u32 (IntToInt); // scope 0 at $DIR/shifts.rs:+2:22: +2:32
|
||||
_16 = Lt(move _15, const 8_u32); // scope 0 at $DIR/shifts.rs:+2:22: +2:32
|
||||
assert(move _16, "attempt to shift right by `{}`, which would overflow", _14) -> [success: bb2, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:22: +2:32
|
||||
}
|
||||
|
||||
bb2: {
|
||||
_12 = Shr(move _13, move _14); // scope 0 at $DIR/shifts.rs:+2:22: +2:32
|
||||
StorageDead(_14); // scope 0 at $DIR/shifts.rs:+2:31: +2:32
|
||||
StorageDead(_13); // scope 0 at $DIR/shifts.rs:+2:31: +2:32
|
||||
StorageLive(_17); // scope 0 at $DIR/shifts.rs:+2:34: +2:44
|
||||
StorageLive(_18); // scope 0 at $DIR/shifts.rs:+2:34: +2:39
|
||||
_18 = _1; // scope 0 at $DIR/shifts.rs:+2:34: +2:39
|
||||
StorageLive(_19); // scope 0 at $DIR/shifts.rs:+2:43: +2:44
|
||||
_19 = _5; // scope 0 at $DIR/shifts.rs:+2:43: +2:44
|
||||
_20 = _19 as u128 (IntToInt); // scope 0 at $DIR/shifts.rs:+2:34: +2:44
|
||||
_21 = Lt(move _20, const 8_u128); // scope 0 at $DIR/shifts.rs:+2:34: +2:44
|
||||
assert(move _21, "attempt to shift right by `{}`, which would overflow", _19) -> [success: bb3, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:34: +2:44
|
||||
}
|
||||
|
||||
bb3: {
|
||||
_17 = Shr(move _18, move _19); // scope 0 at $DIR/shifts.rs:+2:34: +2:44
|
||||
StorageDead(_19); // scope 0 at $DIR/shifts.rs:+2:43: +2:44
|
||||
StorageDead(_18); // scope 0 at $DIR/shifts.rs:+2:43: +2:44
|
||||
_6 = [move _7, move _12, move _17]; // scope 0 at $DIR/shifts.rs:+2:9: +2:45
|
||||
StorageDead(_17); // scope 0 at $DIR/shifts.rs:+2:44: +2:45
|
||||
StorageDead(_12); // scope 0 at $DIR/shifts.rs:+2:44: +2:45
|
||||
StorageDead(_7); // scope 0 at $DIR/shifts.rs:+2:44: +2:45
|
||||
StorageLive(_22); // scope 0 at $DIR/shifts.rs:+3:9: +3:39
|
||||
StorageLive(_23); // scope 0 at $DIR/shifts.rs:+3:10: +3:18
|
||||
StorageLive(_24); // scope 0 at $DIR/shifts.rs:+3:10: +3:13
|
||||
_24 = _2; // scope 0 at $DIR/shifts.rs:+3:10: +3:13
|
||||
StorageLive(_25); // scope 0 at $DIR/shifts.rs:+3:17: +3:18
|
||||
_25 = _3; // scope 0 at $DIR/shifts.rs:+3:17: +3:18
|
||||
_26 = _25 as u8 (IntToInt); // scope 0 at $DIR/shifts.rs:+3:10: +3:18
|
||||
_27 = Lt(move _26, const 128_u8); // scope 0 at $DIR/shifts.rs:+3:10: +3:18
|
||||
assert(move _27, "attempt to shift left by `{}`, which would overflow", _25) -> [success: bb4, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:10: +3:18
|
||||
}
|
||||
|
||||
bb4: {
|
||||
_23 = Shl(move _24, move _25); // scope 0 at $DIR/shifts.rs:+3:10: +3:18
|
||||
StorageDead(_25); // scope 0 at $DIR/shifts.rs:+3:17: +3:18
|
||||
StorageDead(_24); // scope 0 at $DIR/shifts.rs:+3:17: +3:18
|
||||
StorageLive(_28); // scope 0 at $DIR/shifts.rs:+3:20: +3:28
|
||||
StorageLive(_29); // scope 0 at $DIR/shifts.rs:+3:20: +3:23
|
||||
_29 = _2; // scope 0 at $DIR/shifts.rs:+3:20: +3:23
|
||||
StorageLive(_30); // scope 0 at $DIR/shifts.rs:+3:27: +3:28
|
||||
_30 = _4; // scope 0 at $DIR/shifts.rs:+3:27: +3:28
|
||||
_31 = _30 as u32 (IntToInt); // scope 0 at $DIR/shifts.rs:+3:20: +3:28
|
||||
_32 = Lt(move _31, const 128_u32); // scope 0 at $DIR/shifts.rs:+3:20: +3:28
|
||||
assert(move _32, "attempt to shift left by `{}`, which would overflow", _30) -> [success: bb5, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:20: +3:28
|
||||
}
|
||||
|
||||
bb5: {
|
||||
_28 = Shl(move _29, move _30); // scope 0 at $DIR/shifts.rs:+3:20: +3:28
|
||||
StorageDead(_30); // scope 0 at $DIR/shifts.rs:+3:27: +3:28
|
||||
StorageDead(_29); // scope 0 at $DIR/shifts.rs:+3:27: +3:28
|
||||
StorageLive(_33); // scope 0 at $DIR/shifts.rs:+3:30: +3:38
|
||||
StorageLive(_34); // scope 0 at $DIR/shifts.rs:+3:30: +3:33
|
||||
_34 = _2; // scope 0 at $DIR/shifts.rs:+3:30: +3:33
|
||||
StorageLive(_35); // scope 0 at $DIR/shifts.rs:+3:37: +3:38
|
||||
_35 = _5; // scope 0 at $DIR/shifts.rs:+3:37: +3:38
|
||||
_36 = _35 as u128 (IntToInt); // scope 0 at $DIR/shifts.rs:+3:30: +3:38
|
||||
_37 = Lt(move _36, const 128_u128); // scope 0 at $DIR/shifts.rs:+3:30: +3:38
|
||||
assert(move _37, "attempt to shift left by `{}`, which would overflow", _35) -> [success: bb6, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:30: +3:38
|
||||
}
|
||||
|
||||
bb6: {
|
||||
_33 = Shl(move _34, move _35); // scope 0 at $DIR/shifts.rs:+3:30: +3:38
|
||||
StorageDead(_35); // scope 0 at $DIR/shifts.rs:+3:37: +3:38
|
||||
StorageDead(_34); // scope 0 at $DIR/shifts.rs:+3:37: +3:38
|
||||
_22 = [move _23, move _28, move _33]; // scope 0 at $DIR/shifts.rs:+3:9: +3:39
|
||||
StorageDead(_33); // scope 0 at $DIR/shifts.rs:+3:38: +3:39
|
||||
StorageDead(_28); // scope 0 at $DIR/shifts.rs:+3:38: +3:39
|
||||
StorageDead(_23); // scope 0 at $DIR/shifts.rs:+3:38: +3:39
|
||||
_0 = (move _6, move _22); // scope 0 at $DIR/shifts.rs:+1:5: +4:6
|
||||
StorageDead(_22); // scope 0 at $DIR/shifts.rs:+4:5: +4:6
|
||||
StorageDead(_6); // scope 0 at $DIR/shifts.rs:+4:5: +4:6
|
||||
return; // scope 0 at $DIR/shifts.rs:+5:2: +5:2
|
||||
}
|
||||
|
||||
bb7 (cleanup): {
|
||||
resume; // scope 0 at $DIR/shifts.rs:+0:1: +5:2
|
||||
}
|
||||
}
|
135
tests/mir-opt/building/shifts.shift_unsigned.built.after.mir
Normal file
135
tests/mir-opt/building/shifts.shift_unsigned.built.after.mir
Normal file
@ -0,0 +1,135 @@
|
||||
// MIR for `shift_unsigned` after built
|
||||
|
||||
fn shift_unsigned(_1: u8, _2: i128, _3: u8, _4: u32, _5: u128) -> ([u8; 3], [i128; 3]) {
|
||||
debug small => _1; // in scope 0 at $DIR/shifts.rs:+0:19: +0:24
|
||||
debug big => _2; // in scope 0 at $DIR/shifts.rs:+0:30: +0:33
|
||||
debug a => _3; // in scope 0 at $DIR/shifts.rs:+0:41: +0:42
|
||||
debug b => _4; // in scope 0 at $DIR/shifts.rs:+0:48: +0:49
|
||||
debug c => _5; // in scope 0 at $DIR/shifts.rs:+0:56: +0:57
|
||||
let mut _0: ([u8; 3], [i128; 3]); // return place in scope 0 at $DIR/shifts.rs:+0:68: +0:88
|
||||
let mut _6: [u8; 3]; // in scope 0 at $DIR/shifts.rs:+2:9: +2:45
|
||||
let mut _7: u8; // in scope 0 at $DIR/shifts.rs:+2:10: +2:20
|
||||
let mut _8: u8; // in scope 0 at $DIR/shifts.rs:+2:10: +2:15
|
||||
let mut _9: u8; // in scope 0 at $DIR/shifts.rs:+2:19: +2:20
|
||||
let mut _10: bool; // in scope 0 at $DIR/shifts.rs:+2:10: +2:20
|
||||
let mut _11: u8; // in scope 0 at $DIR/shifts.rs:+2:22: +2:32
|
||||
let mut _12: u8; // in scope 0 at $DIR/shifts.rs:+2:22: +2:27
|
||||
let mut _13: u32; // in scope 0 at $DIR/shifts.rs:+2:31: +2:32
|
||||
let mut _14: bool; // in scope 0 at $DIR/shifts.rs:+2:22: +2:32
|
||||
let mut _15: u8; // in scope 0 at $DIR/shifts.rs:+2:34: +2:44
|
||||
let mut _16: u8; // in scope 0 at $DIR/shifts.rs:+2:34: +2:39
|
||||
let mut _17: u128; // in scope 0 at $DIR/shifts.rs:+2:43: +2:44
|
||||
let mut _18: bool; // in scope 0 at $DIR/shifts.rs:+2:34: +2:44
|
||||
let mut _19: [i128; 3]; // in scope 0 at $DIR/shifts.rs:+3:9: +3:39
|
||||
let mut _20: i128; // in scope 0 at $DIR/shifts.rs:+3:10: +3:18
|
||||
let mut _21: i128; // in scope 0 at $DIR/shifts.rs:+3:10: +3:13
|
||||
let mut _22: u8; // in scope 0 at $DIR/shifts.rs:+3:17: +3:18
|
||||
let mut _23: bool; // in scope 0 at $DIR/shifts.rs:+3:10: +3:18
|
||||
let mut _24: i128; // in scope 0 at $DIR/shifts.rs:+3:20: +3:28
|
||||
let mut _25: i128; // in scope 0 at $DIR/shifts.rs:+3:20: +3:23
|
||||
let mut _26: u32; // in scope 0 at $DIR/shifts.rs:+3:27: +3:28
|
||||
let mut _27: bool; // in scope 0 at $DIR/shifts.rs:+3:20: +3:28
|
||||
let mut _28: i128; // in scope 0 at $DIR/shifts.rs:+3:30: +3:38
|
||||
let mut _29: i128; // in scope 0 at $DIR/shifts.rs:+3:30: +3:33
|
||||
let mut _30: u128; // in scope 0 at $DIR/shifts.rs:+3:37: +3:38
|
||||
let mut _31: bool; // in scope 0 at $DIR/shifts.rs:+3:30: +3:38
|
||||
|
||||
bb0: {
|
||||
StorageLive(_6); // scope 0 at $DIR/shifts.rs:+2:9: +2:45
|
||||
StorageLive(_7); // scope 0 at $DIR/shifts.rs:+2:10: +2:20
|
||||
StorageLive(_8); // scope 0 at $DIR/shifts.rs:+2:10: +2:15
|
||||
_8 = _1; // scope 0 at $DIR/shifts.rs:+2:10: +2:15
|
||||
StorageLive(_9); // scope 0 at $DIR/shifts.rs:+2:19: +2:20
|
||||
_9 = _3; // scope 0 at $DIR/shifts.rs:+2:19: +2:20
|
||||
_10 = Lt(_9, const 8_u8); // scope 0 at $DIR/shifts.rs:+2:10: +2:20
|
||||
assert(move _10, "attempt to shift right by `{}`, which would overflow", _9) -> [success: bb1, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:10: +2:20
|
||||
}
|
||||
|
||||
bb1: {
|
||||
_7 = Shr(move _8, move _9); // scope 0 at $DIR/shifts.rs:+2:10: +2:20
|
||||
StorageDead(_9); // scope 0 at $DIR/shifts.rs:+2:19: +2:20
|
||||
StorageDead(_8); // scope 0 at $DIR/shifts.rs:+2:19: +2:20
|
||||
StorageLive(_11); // scope 0 at $DIR/shifts.rs:+2:22: +2:32
|
||||
StorageLive(_12); // scope 0 at $DIR/shifts.rs:+2:22: +2:27
|
||||
_12 = _1; // scope 0 at $DIR/shifts.rs:+2:22: +2:27
|
||||
StorageLive(_13); // scope 0 at $DIR/shifts.rs:+2:31: +2:32
|
||||
_13 = _4; // scope 0 at $DIR/shifts.rs:+2:31: +2:32
|
||||
_14 = Lt(_13, const 8_u32); // scope 0 at $DIR/shifts.rs:+2:22: +2:32
|
||||
assert(move _14, "attempt to shift right by `{}`, which would overflow", _13) -> [success: bb2, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:22: +2:32
|
||||
}
|
||||
|
||||
bb2: {
|
||||
_11 = Shr(move _12, move _13); // scope 0 at $DIR/shifts.rs:+2:22: +2:32
|
||||
StorageDead(_13); // scope 0 at $DIR/shifts.rs:+2:31: +2:32
|
||||
StorageDead(_12); // scope 0 at $DIR/shifts.rs:+2:31: +2:32
|
||||
StorageLive(_15); // scope 0 at $DIR/shifts.rs:+2:34: +2:44
|
||||
StorageLive(_16); // scope 0 at $DIR/shifts.rs:+2:34: +2:39
|
||||
_16 = _1; // scope 0 at $DIR/shifts.rs:+2:34: +2:39
|
||||
StorageLive(_17); // scope 0 at $DIR/shifts.rs:+2:43: +2:44
|
||||
_17 = _5; // scope 0 at $DIR/shifts.rs:+2:43: +2:44
|
||||
_18 = Lt(_17, const 8_u128); // scope 0 at $DIR/shifts.rs:+2:34: +2:44
|
||||
assert(move _18, "attempt to shift right by `{}`, which would overflow", _17) -> [success: bb3, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+2:34: +2:44
|
||||
}
|
||||
|
||||
bb3: {
|
||||
_15 = Shr(move _16, move _17); // scope 0 at $DIR/shifts.rs:+2:34: +2:44
|
||||
StorageDead(_17); // scope 0 at $DIR/shifts.rs:+2:43: +2:44
|
||||
StorageDead(_16); // scope 0 at $DIR/shifts.rs:+2:43: +2:44
|
||||
_6 = [move _7, move _11, move _15]; // scope 0 at $DIR/shifts.rs:+2:9: +2:45
|
||||
StorageDead(_15); // scope 0 at $DIR/shifts.rs:+2:44: +2:45
|
||||
StorageDead(_11); // scope 0 at $DIR/shifts.rs:+2:44: +2:45
|
||||
StorageDead(_7); // scope 0 at $DIR/shifts.rs:+2:44: +2:45
|
||||
StorageLive(_19); // scope 0 at $DIR/shifts.rs:+3:9: +3:39
|
||||
StorageLive(_20); // scope 0 at $DIR/shifts.rs:+3:10: +3:18
|
||||
StorageLive(_21); // scope 0 at $DIR/shifts.rs:+3:10: +3:13
|
||||
_21 = _2; // scope 0 at $DIR/shifts.rs:+3:10: +3:13
|
||||
StorageLive(_22); // scope 0 at $DIR/shifts.rs:+3:17: +3:18
|
||||
_22 = _3; // scope 0 at $DIR/shifts.rs:+3:17: +3:18
|
||||
_23 = Lt(_22, const 128_u8); // scope 0 at $DIR/shifts.rs:+3:10: +3:18
|
||||
assert(move _23, "attempt to shift left by `{}`, which would overflow", _22) -> [success: bb4, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:10: +3:18
|
||||
}
|
||||
|
||||
bb4: {
|
||||
_20 = Shl(move _21, move _22); // scope 0 at $DIR/shifts.rs:+3:10: +3:18
|
||||
StorageDead(_22); // scope 0 at $DIR/shifts.rs:+3:17: +3:18
|
||||
StorageDead(_21); // scope 0 at $DIR/shifts.rs:+3:17: +3:18
|
||||
StorageLive(_24); // scope 0 at $DIR/shifts.rs:+3:20: +3:28
|
||||
StorageLive(_25); // scope 0 at $DIR/shifts.rs:+3:20: +3:23
|
||||
_25 = _2; // scope 0 at $DIR/shifts.rs:+3:20: +3:23
|
||||
StorageLive(_26); // scope 0 at $DIR/shifts.rs:+3:27: +3:28
|
||||
_26 = _4; // scope 0 at $DIR/shifts.rs:+3:27: +3:28
|
||||
_27 = Lt(_26, const 128_u32); // scope 0 at $DIR/shifts.rs:+3:20: +3:28
|
||||
assert(move _27, "attempt to shift left by `{}`, which would overflow", _26) -> [success: bb5, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:20: +3:28
|
||||
}
|
||||
|
||||
bb5: {
|
||||
_24 = Shl(move _25, move _26); // scope 0 at $DIR/shifts.rs:+3:20: +3:28
|
||||
StorageDead(_26); // scope 0 at $DIR/shifts.rs:+3:27: +3:28
|
||||
StorageDead(_25); // scope 0 at $DIR/shifts.rs:+3:27: +3:28
|
||||
StorageLive(_28); // scope 0 at $DIR/shifts.rs:+3:30: +3:38
|
||||
StorageLive(_29); // scope 0 at $DIR/shifts.rs:+3:30: +3:33
|
||||
_29 = _2; // scope 0 at $DIR/shifts.rs:+3:30: +3:33
|
||||
StorageLive(_30); // scope 0 at $DIR/shifts.rs:+3:37: +3:38
|
||||
_30 = _5; // scope 0 at $DIR/shifts.rs:+3:37: +3:38
|
||||
_31 = Lt(_30, const 128_u128); // scope 0 at $DIR/shifts.rs:+3:30: +3:38
|
||||
assert(move _31, "attempt to shift left by `{}`, which would overflow", _30) -> [success: bb6, unwind: bb7]; // scope 0 at $DIR/shifts.rs:+3:30: +3:38
|
||||
}
|
||||
|
||||
bb6: {
|
||||
_28 = Shl(move _29, move _30); // scope 0 at $DIR/shifts.rs:+3:30: +3:38
|
||||
StorageDead(_30); // scope 0 at $DIR/shifts.rs:+3:37: +3:38
|
||||
StorageDead(_29); // scope 0 at $DIR/shifts.rs:+3:37: +3:38
|
||||
_19 = [move _20, move _24, move _28]; // scope 0 at $DIR/shifts.rs:+3:9: +3:39
|
||||
StorageDead(_28); // scope 0 at $DIR/shifts.rs:+3:38: +3:39
|
||||
StorageDead(_24); // scope 0 at $DIR/shifts.rs:+3:38: +3:39
|
||||
StorageDead(_20); // scope 0 at $DIR/shifts.rs:+3:38: +3:39
|
||||
_0 = (move _6, move _19); // scope 0 at $DIR/shifts.rs:+1:5: +4:6
|
||||
StorageDead(_19); // scope 0 at $DIR/shifts.rs:+4:5: +4:6
|
||||
StorageDead(_6); // scope 0 at $DIR/shifts.rs:+4:5: +4:6
|
||||
return; // scope 0 at $DIR/shifts.rs:+5:2: +5:2
|
||||
}
|
||||
|
||||
bb7 (cleanup): {
|
||||
resume; // scope 0 at $DIR/shifts.rs:+0:1: +5:2
|
||||
}
|
||||
}
|
@ -12,9 +12,9 @@
|
||||
let mut _7: u32; // in scope 0 at $DIR/issue_101973.rs:+1:31: +1:52
|
||||
let mut _8: u32; // in scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
|
||||
let mut _9: u32; // in scope 0 at $DIR/issue_101973.rs:+1:33: +1:39
|
||||
let mut _10: i32; // in scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
|
||||
let mut _10: u32; // in scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
|
||||
let mut _11: bool; // in scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
|
||||
let mut _12: i32; // in scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
|
||||
let mut _12: u32; // in scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
|
||||
let mut _13: bool; // in scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
|
||||
scope 1 (inlined imm8) { // at $DIR/issue_101973.rs:14:5: 14:17
|
||||
debug x => _1; // in scope 1 at $DIR/issue_101973.rs:5:13: 5:14
|
||||
@ -43,24 +43,24 @@
|
||||
StorageLive(_6); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
|
||||
StorageLive(_7); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:52
|
||||
StorageLive(_8); // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
|
||||
- _10 = BitAnd(const 8_i32, const -32_i32); // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
|
||||
- _11 = Ne(move _10, const 0_i32); // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
|
||||
- assert(!move _11, "attempt to shift right by `{}`, which would overflow", const 8_i32) -> bb1; // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
|
||||
+ _10 = const 0_i32; // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
|
||||
+ _11 = const false; // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
|
||||
+ assert(!const false, "attempt to shift right by `{}`, which would overflow", const 8_i32) -> bb1; // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
|
||||
- _10 = const 8_i32 as u32 (IntToInt); // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
|
||||
- _11 = Lt(move _10, const 32_u32); // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
|
||||
- assert(move _11, "attempt to shift right by `{}`, which would overflow", const 8_i32) -> bb1; // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
|
||||
+ _10 = const 8_u32; // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
|
||||
+ _11 = const true; // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
|
||||
+ assert(const true, "attempt to shift right by `{}`, which would overflow", const 8_i32) -> bb1; // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
|
||||
}
|
||||
|
||||
bb1: {
|
||||
_8 = Shr(_1, const 8_i32); // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
|
||||
_7 = BitAnd(move _8, const 15_u32); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:52
|
||||
StorageDead(_8); // scope 0 at $DIR/issue_101973.rs:+1:51: +1:52
|
||||
- _12 = BitAnd(const 1_i32, const -32_i32); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
|
||||
- _13 = Ne(move _12, const 0_i32); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
|
||||
- assert(!move _13, "attempt to shift left by `{}`, which would overflow", const 1_i32) -> bb2; // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
|
||||
+ _12 = const 0_i32; // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
|
||||
+ _13 = const false; // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
|
||||
+ assert(!const false, "attempt to shift left by `{}`, which would overflow", const 1_i32) -> bb2; // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
|
||||
- _12 = const 1_i32 as u32 (IntToInt); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
|
||||
- _13 = Lt(move _12, const 32_u32); // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
|
||||
- assert(move _13, "attempt to shift left by `{}`, which would overflow", const 1_i32) -> bb2; // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
|
||||
+ _12 = const 1_u32; // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
|
||||
+ _13 = const true; // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
|
||||
+ assert(const true, "attempt to shift left by `{}`, which would overflow", const 1_i32) -> bb2; // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
|
||||
}
|
||||
|
||||
bb2: {
|
||||
|
@ -0,0 +1,52 @@
|
||||
// check-pass
|
||||
// known-bug: #97156
|
||||
|
||||
#![feature(const_type_id, generic_const_exprs)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
use std::any::TypeId;
|
||||
// `One` and `Two` are currently considered equal types, as both
|
||||
// `One <: Two` and `One :> Two` holds.
|
||||
type One = for<'a> fn(&'a (), &'a ());
|
||||
type Two = for<'a, 'b> fn(&'a (), &'b ());
|
||||
trait AssocCt {
|
||||
const ASSOC: usize;
|
||||
}
|
||||
const fn to_usize<T: 'static>() -> usize {
|
||||
const WHAT_A_TYPE: TypeId = TypeId::of::<One>();
|
||||
match TypeId::of::<T>() {
|
||||
WHAT_A_TYPE => 0,
|
||||
_ => 1000,
|
||||
}
|
||||
}
|
||||
impl<T: 'static> AssocCt for T {
|
||||
const ASSOC: usize = to_usize::<T>();
|
||||
}
|
||||
|
||||
trait WithAssoc<U> {
|
||||
type Assoc;
|
||||
}
|
||||
impl<T: 'static> WithAssoc<()> for T where [(); <T as AssocCt>::ASSOC]: {
|
||||
type Assoc = [u8; <T as AssocCt>::ASSOC];
|
||||
}
|
||||
|
||||
fn generic<T: 'static, U>(x: <T as WithAssoc<U>>::Assoc) -> <T as WithAssoc<U>>::Assoc
|
||||
where
|
||||
[(); <T as AssocCt>::ASSOC]:,
|
||||
T: WithAssoc<U>,
|
||||
{
|
||||
x
|
||||
}
|
||||
|
||||
|
||||
fn unsound<T>(x: <One as WithAssoc<T>>::Assoc) -> <Two as WithAssoc<T>>::Assoc
|
||||
where
|
||||
One: WithAssoc<T>,
|
||||
{
|
||||
let x: <Two as WithAssoc<T>>::Assoc = generic::<One, T>(x);
|
||||
x
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("{:?}", unsound::<()>([]));
|
||||
}
|
@ -26,7 +26,6 @@ impl<R: Duh, F: FnMut() -> R> Trait for F {
|
||||
// Lazy TAIT would error out, but we inserted a hack to make it work again,
|
||||
// keeping backwards compatibility.
|
||||
fn foo() -> impl Trait<Assoc = impl Send> {
|
||||
//~^ WARN opaque type `impl Trait<Assoc = impl Send>` does not satisfy its associated type bounds
|
||||
|| 42
|
||||
}
|
||||
|
||||
|
@ -1,17 +0,0 @@
|
||||
warning: opaque type `impl Trait<Assoc = impl Send>` does not satisfy its associated type bounds
|
||||
--> $DIR/nested-return-type2.rs:28:24
|
||||
|
|
||||
LL | type Assoc: Duh;
|
||||
| --- this associated type bound is unsatisfied for `impl Send`
|
||||
...
|
||||
LL | fn foo() -> impl Trait<Assoc = impl Send> {
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(opaque_hidden_inferred_bound)]` on by default
|
||||
help: add this bound
|
||||
|
|
||||
LL | fn foo() -> impl Trait<Assoc = impl Send + Duh> {
|
||||
| +++++
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
@ -13,7 +13,6 @@ impl<F: Duh> Trait for F {
|
||||
}
|
||||
|
||||
fn foo() -> impl Trait<Assoc = impl Send> {
|
||||
//~^ WARN opaque type `impl Trait<Assoc = impl Send>` does not satisfy its associated type bounds
|
||||
42
|
||||
}
|
||||
|
||||
|
@ -1,17 +0,0 @@
|
||||
warning: opaque type `impl Trait<Assoc = impl Send>` does not satisfy its associated type bounds
|
||||
--> $DIR/nested-return-type3.rs:15:24
|
||||
|
|
||||
LL | type Assoc: Duh;
|
||||
| --- this associated type bound is unsatisfied for `impl Send`
|
||||
...
|
||||
LL | fn foo() -> impl Trait<Assoc = impl Send> {
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(opaque_hidden_inferred_bound)]` on by default
|
||||
help: add this bound
|
||||
|
|
||||
LL | fn foo() -> impl Trait<Assoc = impl Send + Duh> {
|
||||
| +++++
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
34
tests/ui/traits/new-solver/alias-sub.rs
Normal file
34
tests/ui/traits/new-solver/alias-sub.rs
Normal file
@ -0,0 +1,34 @@
|
||||
// compile-flags: -Ztrait-solver=next
|
||||
// check-pass
|
||||
|
||||
trait Trait {
|
||||
type Assoc: Sized;
|
||||
}
|
||||
|
||||
impl Trait for &'static str {
|
||||
type Assoc = &'static str;
|
||||
}
|
||||
|
||||
// Wrapper is just here to get around stupid `Sized` obligations in mir typeck
|
||||
struct Wrapper<T: ?Sized>(std::marker::PhantomData<T>);
|
||||
fn mk<T: Trait>(x: T) -> Wrapper<<T as Trait>::Assoc> { todo!() }
|
||||
|
||||
|
||||
trait IsStaticStr {}
|
||||
impl IsStaticStr for (&'static str,) {}
|
||||
fn define<T: IsStaticStr>(_: T) {}
|
||||
|
||||
fn foo<'a, T: Trait>() {
|
||||
let y = Default::default();
|
||||
|
||||
// `<?0 as Trait>::Assoc <: &'a str`
|
||||
// In the old solver, this would *equate* the LHS and RHS.
|
||||
let _: Wrapper<&'a str> = mk(y);
|
||||
|
||||
// ... then later on, we constrain `?0 = &'static str`
|
||||
// but that should not mean that `'a = 'static`, because
|
||||
// we should use *sub* above.
|
||||
define((y,));
|
||||
}
|
||||
|
||||
fn main() {}
|
Loading…
x
Reference in New Issue
Block a user