Add AliasKind::Weak
for type aliases.
Only use it when the type alias contains an opaque type. Also does wf-checking on such type aliases.
This commit is contained in:
parent
4fdd07fe88
commit
f3b7dd6388
86 changed files with 474 additions and 199 deletions
|
@ -508,10 +508,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||
| ty::Placeholder(..)
|
||||
| ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
|
||||
| ty::Alias(ty::Inherent, _)
|
||||
| ty::Alias(ty::Weak, _)
|
||||
| ty::Error(_) => return,
|
||||
ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
|
||||
| ty::Bound(..) => bug!("unexpected self type for `{goal:?}`"),
|
||||
// Excluding IATs here as they don't have meaningful item bounds.
|
||||
// Excluding IATs and type aliases here as they don't have meaningful item bounds.
|
||||
ty::Alias(ty::Projection | ty::Opaque, alias_ty) => alias_ty,
|
||||
};
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
|
|||
ty::Dynamic(..)
|
||||
| ty::Param(..)
|
||||
| ty::Foreign(..)
|
||||
| ty::Alias(ty::Projection | ty::Inherent, ..)
|
||||
| ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..)
|
||||
| ty::Placeholder(..)
|
||||
| ty::Bound(..)
|
||||
| ty::Infer(_) => {
|
||||
|
|
|
@ -29,6 +29,7 @@ mod opaques;
|
|||
mod project_goals;
|
||||
mod search_graph;
|
||||
mod trait_goals;
|
||||
mod weak_types;
|
||||
|
||||
pub use eval_ctxt::{EvalCtxt, InferCtxtEvalExt};
|
||||
pub use fulfill::FulfillmentCtxt;
|
||||
|
|
|
@ -57,6 +57,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||
}
|
||||
DefKind::AnonConst => self.normalize_anon_const(goal),
|
||||
DefKind::OpaqueTy => self.normalize_opaque_type(goal),
|
||||
DefKind::TyAlias => self.normalize_weak_type(goal),
|
||||
kind => bug!("unknown DefKind {} in projection goal: {goal:#?}", kind.descr(def_id)),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -618,7 +618,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||
ty::Dynamic(..)
|
||||
| ty::Param(..)
|
||||
| ty::Foreign(..)
|
||||
| ty::Alias(ty::Projection | ty::Inherent, ..)
|
||||
| ty::Alias(ty::Projection | ty::Weak | ty::Inherent, ..)
|
||||
| ty::Placeholder(..) => Some(Err(NoSolution)),
|
||||
|
||||
ty::Infer(_) | ty::Bound(_, _) => bug!("unexpected type `{self_ty}`"),
|
||||
|
|
19
compiler/rustc_trait_selection/src/solve/weak_types.rs
Normal file
19
compiler/rustc_trait_selection/src/solve/weak_types.rs
Normal file
|
@ -0,0 +1,19 @@
|
|||
use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
|
||||
use rustc_middle::ty;
|
||||
|
||||
use super::EvalCtxt;
|
||||
|
||||
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
pub(super) fn normalize_weak_type(
|
||||
&mut self,
|
||||
goal: Goal<'tcx, ty::ProjectionPredicate<'tcx>>,
|
||||
) -> QueryResult<'tcx> {
|
||||
let tcx = self.tcx();
|
||||
let weak_ty = goal.predicate.projection_ty;
|
||||
let expected = goal.predicate.term.ty().expect("no such thing as a const alias");
|
||||
|
||||
let actual = tcx.type_of(weak_ty.def_id).subst(tcx, weak_ty.substs);
|
||||
self.eq(goal.param_env, expected, actual)?;
|
||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
}
|
||||
}
|
|
@ -695,7 +695,9 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OrphanChecker<'tcx> {
|
|||
| ty::RawPtr(..)
|
||||
| ty::Never
|
||||
| ty::Tuple(..)
|
||||
| ty::Alias(ty::Projection | ty::Inherent, ..) => self.found_non_local_ty(ty),
|
||||
| ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..) => {
|
||||
self.found_non_local_ty(ty)
|
||||
}
|
||||
|
||||
ty::Param(..) => self.found_param_ty(ty),
|
||||
|
||||
|
|
|
@ -1824,12 +1824,13 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
ty::Alias(ty::Projection, ..) => Some(12),
|
||||
ty::Alias(ty::Inherent, ..) => Some(13),
|
||||
ty::Alias(ty::Opaque, ..) => Some(14),
|
||||
ty::Never => Some(15),
|
||||
ty::Adt(..) => Some(16),
|
||||
ty::Generator(..) => Some(17),
|
||||
ty::Foreign(..) => Some(18),
|
||||
ty::GeneratorWitness(..) => Some(19),
|
||||
ty::GeneratorWitnessMIR(..) => Some(20),
|
||||
ty::Alias(ty::Weak, ..) => Some(15),
|
||||
ty::Never => Some(16),
|
||||
ty::Adt(..) => Some(17),
|
||||
ty::Generator(..) => Some(18),
|
||||
ty::Foreign(..) => Some(19),
|
||||
ty::GeneratorWitness(..) => Some(20),
|
||||
ty::GeneratorWitnessMIR(..) => Some(21),
|
||||
ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3198,6 +3198,29 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
)
|
||||
});
|
||||
}
|
||||
ObligationCauseCode::TypeAlias(ref nested, span, def_id) => {
|
||||
// #74711: avoid a stack overflow
|
||||
ensure_sufficient_stack(|| {
|
||||
self.note_obligation_cause_code(
|
||||
body_id,
|
||||
err,
|
||||
predicate,
|
||||
param_env,
|
||||
nested,
|
||||
obligated_types,
|
||||
seen_requirements,
|
||||
)
|
||||
});
|
||||
let mut multispan = MultiSpan::from(span);
|
||||
multispan.push_span_label(span, "required by this bound");
|
||||
err.span_note(
|
||||
multispan,
|
||||
format!(
|
||||
"required by a bound on the type alias `{}`",
|
||||
self.infcx.tcx.item_name(def_id)
|
||||
),
|
||||
);
|
||||
}
|
||||
ObligationCauseCode::FunctionArgumentObligation {
|
||||
arg_hir_id,
|
||||
call_hir_id,
|
||||
|
|
|
@ -9,7 +9,7 @@ use rustc_span::def_id::LocalDefId;
|
|||
|
||||
pub use rustc_middle::traits::query::OutlivesBound;
|
||||
|
||||
type Bounds<'a, 'tcx: 'a> = impl Iterator<Item = OutlivesBound<'tcx>> + 'a;
|
||||
pub type Bounds<'a, 'tcx: 'a> = impl Iterator<Item = OutlivesBound<'tcx>> + 'a;
|
||||
pub trait InferCtxtExt<'a, 'tcx> {
|
||||
fn implied_outlives_bounds(
|
||||
&self,
|
||||
|
|
|
@ -31,6 +31,7 @@ use rustc_infer::infer::at::At;
|
|||
use rustc_infer::infer::resolve::OpportunisticRegionResolver;
|
||||
use rustc_infer::infer::DefineOpaqueTypes;
|
||||
use rustc_infer::traits::ImplSourceBuiltinData;
|
||||
use rustc_infer::traits::ObligationCauseCode;
|
||||
use rustc_middle::traits::select::OverflowError;
|
||||
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
|
||||
use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable, TypeVisitableExt};
|
||||
|
@ -621,6 +622,30 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
|
|||
);
|
||||
normalized_ty
|
||||
}
|
||||
ty::Weak => {
|
||||
let infcx = self.selcx.infcx;
|
||||
self.obligations.extend(
|
||||
infcx
|
||||
.tcx
|
||||
.predicates_of(data.def_id)
|
||||
.instantiate_own(infcx.tcx, data.substs)
|
||||
.map(|(mut predicate, span)| {
|
||||
if data.has_escaping_bound_vars() {
|
||||
(predicate, ..) = BoundVarReplacer::replace_bound_vars(
|
||||
infcx,
|
||||
&mut self.universes,
|
||||
predicate,
|
||||
);
|
||||
}
|
||||
let mut cause = self.cause.clone();
|
||||
cause.map_code(|code| {
|
||||
ObligationCauseCode::TypeAlias(code, span, data.def_id)
|
||||
});
|
||||
Obligation::new(infcx.tcx, cause, self.param_env, predicate)
|
||||
}),
|
||||
);
|
||||
infcx.tcx.type_of(data.def_id).subst(infcx.tcx, data.substs).fold_with(self)
|
||||
}
|
||||
|
||||
ty::Inherent if !data.has_escaping_bound_vars() => {
|
||||
// This branch is *mostly* just an optimization: when we don't
|
||||
|
@ -1545,7 +1570,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
|
|||
// Check whether the self-type is itself a projection.
|
||||
// If so, extract what we know from the trait and try to come up with a good answer.
|
||||
let bounds = match *obligation.predicate.self_ty().kind() {
|
||||
// Excluding IATs here as they don't have meaningful item bounds.
|
||||
// Excluding IATs and type aliases here as they don't have meaningful item bounds.
|
||||
ty::Alias(ty::Projection | ty::Opaque, ref data) => {
|
||||
tcx.item_bounds(data.def_id).subst(tcx, data.substs)
|
||||
}
|
||||
|
|
|
@ -257,7 +257,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
|
|||
|
||||
ty::Opaque => ty.try_super_fold_with(self)?,
|
||||
|
||||
ty::Projection | ty::Inherent => {
|
||||
ty::Projection | ty::Inherent | ty::Weak => {
|
||||
// See note in `rustc_trait_selection::traits::project`
|
||||
|
||||
let infcx = self.infcx;
|
||||
|
@ -282,6 +282,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
|
|||
debug!("QueryNormalizer: orig_values = {:#?}", orig_values);
|
||||
let result = match kind {
|
||||
ty::Projection => tcx.normalize_projection_ty(c_data),
|
||||
ty::Weak => tcx.normalize_weak_ty(c_data),
|
||||
ty::Inherent => tcx.normalize_inherent_projection_ty(c_data),
|
||||
_ => unreachable!(),
|
||||
}?;
|
||||
|
|
|
@ -143,7 +143,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
// Before we go into the whole placeholder thing, just
|
||||
// quickly check if the self-type is a projection at all.
|
||||
match obligation.predicate.skip_binder().trait_ref.self_ty().kind() {
|
||||
// Excluding IATs here as they don't have meaningful item bounds.
|
||||
// Excluding IATs and type aliases here as they don't have meaningful item bounds.
|
||||
ty::Alias(ty::Projection | ty::Opaque, _) => {}
|
||||
ty::Infer(ty::TyVar(_)) => {
|
||||
span_bug!(
|
||||
|
|
|
@ -163,7 +163,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
let placeholder_self_ty = placeholder_trait_predicate.self_ty();
|
||||
let placeholder_trait_predicate = ty::Binder::dummy(placeholder_trait_predicate);
|
||||
let (def_id, substs) = match *placeholder_self_ty.kind() {
|
||||
// Excluding IATs here as they don't have meaningful item bounds.
|
||||
// Excluding IATs and type aliases here as they don't have meaningful item bounds.
|
||||
ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
|
||||
(def_id, substs)
|
||||
}
|
||||
|
|
|
@ -2314,7 +2314,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
|||
| ty::Dynamic(..)
|
||||
| ty::Param(..)
|
||||
| ty::Foreign(..)
|
||||
| ty::Alias(ty::Projection | ty::Inherent, ..)
|
||||
| ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..)
|
||||
| ty::Bound(..)
|
||||
| ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
|
||||
bug!("asked to assemble constituent types of unexpected type: {:?}", t);
|
||||
|
|
|
@ -731,6 +731,11 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
ty::Alias(ty::Weak, ty::AliasTy { def_id, substs, .. }) => {
|
||||
let obligations = self.nominal_obligations(def_id, substs);
|
||||
self.out.extend(obligations);
|
||||
}
|
||||
|
||||
ty::Dynamic(data, r, _) => {
|
||||
// WfObject
|
||||
//
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue