Dejargnonize subst
This commit is contained in:
parent
084ce5bdb5
commit
3856df059e
128 changed files with 574 additions and 541 deletions
|
@ -336,12 +336,12 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
|||
|
||||
let projection_ty = if let ty::AssocKind::Fn = assoc_kind {
|
||||
let mut emitted_bad_param_err = None;
|
||||
// If we have an method return type bound, then we need to substitute
|
||||
// If we have an method return type bound, then we need to instantiate
|
||||
// the method's early bound params with suitable late-bound params.
|
||||
let mut num_bound_vars = candidate.bound_vars().len();
|
||||
let args =
|
||||
candidate.skip_binder().args.extend_to(tcx, assoc_item.def_id, |param, _| {
|
||||
let subst = match param.kind {
|
||||
let arg = match param.kind {
|
||||
ty::GenericParamDefKind::Lifetime => ty::Region::new_bound(
|
||||
tcx,
|
||||
ty::INNERMOST,
|
||||
|
@ -379,7 +379,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
|||
}
|
||||
};
|
||||
num_bound_vars += 1;
|
||||
subst
|
||||
arg
|
||||
});
|
||||
|
||||
// Next, we need to check that the return-type notation is being used on
|
||||
|
@ -402,12 +402,13 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
|||
|
||||
// Finally, move the fn return type's bound vars over to account for the early bound
|
||||
// params (and trait ref's late bound params). This logic is very similar to
|
||||
// `Predicate::subst_supertrait`, and it's no coincidence why.
|
||||
// `rustc_middle::ty::predicate::Clause::instantiate_supertrait`
|
||||
// and it's no coincidence why.
|
||||
let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output);
|
||||
let subst_output = ty::EarlyBinder::bind(shifted_output).instantiate(tcx, args);
|
||||
let instantiation_output = ty::EarlyBinder::bind(shifted_output).instantiate(tcx, args);
|
||||
|
||||
let bound_vars = tcx.late_bound_vars(binding.hir_id);
|
||||
ty::Binder::bind_with_vars(subst_output, bound_vars)
|
||||
ty::Binder::bind_with_vars(instantiation_output, bound_vars)
|
||||
} else {
|
||||
// Append the generic arguments of the associated type to the `trait_ref`.
|
||||
candidate.map_bound(|trait_ref| {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use super::IsMethodCall;
|
||||
use crate::astconv::{
|
||||
errors::prohibit_assoc_ty_binding, CreateSubstsForGenericArgsCtxt, ExplicitLateBound,
|
||||
errors::prohibit_assoc_ty_binding, CreateInstantiationsForGenericArgsCtxt, ExplicitLateBound,
|
||||
GenericArgCountMismatch, GenericArgCountResult, GenericArgPosition,
|
||||
};
|
||||
use crate::structured_errors::{GenericArgsInfo, StructuredDiagnostic, WrongNumberOfGenericArgs};
|
||||
|
@ -177,9 +177,9 @@ pub fn create_args_for_parent_generic_args<'tcx: 'a, 'a>(
|
|||
has_self: bool,
|
||||
self_ty: Option<Ty<'tcx>>,
|
||||
arg_count: &GenericArgCountResult,
|
||||
ctx: &mut impl CreateSubstsForGenericArgsCtxt<'a, 'tcx>,
|
||||
ctx: &mut impl CreateInstantiationsForGenericArgsCtxt<'a, 'tcx>,
|
||||
) -> GenericArgsRef<'tcx> {
|
||||
// Collect the segments of the path; we need to substitute arguments
|
||||
// Collect the segments of the path; we need to instantiate arguments
|
||||
// for parameters throughout the entire path (wherever there are
|
||||
// generic parameters).
|
||||
let mut parent_defs = tcx.generics_of(def_id);
|
||||
|
@ -191,7 +191,7 @@ pub fn create_args_for_parent_generic_args<'tcx: 'a, 'a>(
|
|||
}
|
||||
|
||||
// We manually build up the generic arguments, rather than using convenience
|
||||
// methods in `subst.rs`, so that we can iterate over the arguments and
|
||||
// methods in `rustc_middle/src/ty/generic_args.rs`, so that we can iterate over the arguments and
|
||||
// parameters in lock-step linearly, instead of trying to match each pair.
|
||||
let mut args: SmallVec<[ty::GenericArg<'tcx>; 8]> = SmallVec::with_capacity(count);
|
||||
// Iterate over each segment of the path.
|
||||
|
|
|
@ -214,7 +214,7 @@ pub struct GenericArgCountResult {
|
|||
pub correct: Result<(), GenericArgCountMismatch>,
|
||||
}
|
||||
|
||||
pub trait CreateSubstsForGenericArgsCtxt<'a, 'tcx> {
|
||||
pub trait CreateInstantiationsForGenericArgsCtxt<'a, 'tcx> {
|
||||
fn args_for_def_id(&mut self, def_id: DefId) -> (Option<&'a GenericArgs<'tcx>>, bool);
|
||||
|
||||
fn provided_kind(
|
||||
|
@ -366,8 +366,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
|
||||
if generics.has_self {
|
||||
if generics.parent.is_some() {
|
||||
// The parent is a trait so it should have at least one subst
|
||||
// for the `Self` type.
|
||||
// The parent is a trait so it should have at least one
|
||||
// generic parameter for the `Self` type.
|
||||
assert!(!parent_args.is_empty())
|
||||
} else {
|
||||
// This item (presumably a trait) needs a self-type.
|
||||
|
@ -402,7 +402,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
return (tcx.mk_args(parent_args), arg_count);
|
||||
}
|
||||
|
||||
struct SubstsForAstPathCtxt<'a, 'tcx> {
|
||||
struct InstantiationsForAstPathCtxt<'a, 'tcx> {
|
||||
astconv: &'a (dyn AstConv<'tcx> + 'a),
|
||||
def_id: DefId,
|
||||
generic_args: &'a GenericArgs<'tcx>,
|
||||
|
@ -411,7 +411,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
infer_args: bool,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> CreateSubstsForGenericArgsCtxt<'a, 'tcx> for SubstsForAstPathCtxt<'a, 'tcx> {
|
||||
impl<'a, 'tcx> CreateInstantiationsForGenericArgsCtxt<'a, 'tcx>
|
||||
for InstantiationsForAstPathCtxt<'a, 'tcx>
|
||||
{
|
||||
fn args_for_def_id(&mut self, did: DefId) -> (Option<&'a GenericArgs<'tcx>>, bool) {
|
||||
if did == self.def_id {
|
||||
(Some(self.generic_args), self.infer_args)
|
||||
|
@ -556,7 +558,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
}
|
||||
}
|
||||
|
||||
let mut args_ctx = SubstsForAstPathCtxt {
|
||||
let mut args_ctx = InstantiationsForAstPathCtxt {
|
||||
astconv: self,
|
||||
def_id,
|
||||
span,
|
||||
|
@ -2412,8 +2414,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
|
||||
let self_ty = self.tcx().type_of(parent).instantiate_identity();
|
||||
let generic_self_ty = ty::GenericArg::from(self_ty);
|
||||
let substs = self.tcx().mk_args_from_iter(std::iter::once(generic_self_ty));
|
||||
sig.instantiate(self.tcx(), substs)
|
||||
let args = self.tcx().mk_args_from_iter(std::iter::once(generic_self_ty));
|
||||
sig.instantiate(self.tcx(), args)
|
||||
} else {
|
||||
sig.instantiate_identity()
|
||||
};
|
||||
|
|
|
@ -175,7 +175,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
}
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => {
|
||||
let pred = bound_predicate.rebind(pred);
|
||||
// A `Self` within the original bound will be substituted with a
|
||||
// A `Self` within the original bound will be instantiated with a
|
||||
// `trait_object_dummy_self`, so check for that.
|
||||
let references_self = match pred.skip_binder().term.unpack() {
|
||||
ty::TermKind::Ty(ty) => ty.walk().any(|arg| arg == dummy_self.into()),
|
||||
|
|
|
@ -1030,7 +1030,7 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
|
|||
match t.kind() {
|
||||
ty::Tuple(list) => list.iter().try_for_each(|t| check_non_exhaustive(tcx, t)),
|
||||
ty::Array(ty, _) => check_non_exhaustive(tcx, *ty),
|
||||
ty::Adt(def, subst) => {
|
||||
ty::Adt(def, args) => {
|
||||
if !def.did().is_local() {
|
||||
let non_exhaustive = def.is_variant_list_non_exhaustive()
|
||||
|| def
|
||||
|
@ -1042,13 +1042,13 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
|
|||
return ControlFlow::Break((
|
||||
def.descr(),
|
||||
def.did(),
|
||||
subst,
|
||||
args,
|
||||
non_exhaustive,
|
||||
));
|
||||
}
|
||||
}
|
||||
def.all_fields()
|
||||
.map(|field| field.ty(tcx, subst))
|
||||
.map(|field| field.ty(tcx, args))
|
||||
.try_for_each(|t| check_non_exhaustive(tcx, t))
|
||||
}
|
||||
_ => ControlFlow::Continue(()),
|
||||
|
|
|
@ -125,9 +125,9 @@ fn check_method_is_structurally_compatible<'tcx>(
|
|||
/// <'b> fn(t: &'i0 U0, m: &'b N0) -> Foo
|
||||
/// ```
|
||||
///
|
||||
/// We now want to extract and substitute the type of the *trait*
|
||||
/// We now want to extract and instantiate the type of the *trait*
|
||||
/// method and compare it. To do so, we must create a compound
|
||||
/// substitution by combining `trait_to_impl_args` and
|
||||
/// instantiation by combining `trait_to_impl_args` and
|
||||
/// `impl_to_placeholder_args`, and also adding a mapping for the method
|
||||
/// type parameters. We extend the mapping to also include
|
||||
/// the method parameters.
|
||||
|
@ -146,11 +146,11 @@ fn check_method_is_structurally_compatible<'tcx>(
|
|||
/// vs `'b`). However, the normal subtyping rules on fn types handle
|
||||
/// this kind of equivalency just fine.
|
||||
///
|
||||
/// We now use these substitutions to ensure that all declared bounds are
|
||||
/// satisfied by the implementation's method.
|
||||
/// We now use these generic parameters to ensure that all declared bounds
|
||||
/// are satisfied by the implementation's method.
|
||||
///
|
||||
/// We do this by creating a parameter environment which contains a
|
||||
/// substitution corresponding to `impl_to_placeholder_args`. We then build
|
||||
/// generic parameter corresponding to `impl_to_placeholder_args`. We then build
|
||||
/// `trait_to_placeholder_args` and use it to convert the predicates contained
|
||||
/// in the `trait_m` generics to the placeholder form.
|
||||
///
|
||||
|
@ -454,7 +454,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
|||
let impl_trait_ref =
|
||||
tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap().instantiate_identity();
|
||||
// First, check a few of the same things as `compare_impl_method`,
|
||||
// just so we don't ICE during substitution later.
|
||||
// just so we don't ICE during instantiation later.
|
||||
check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, true)?;
|
||||
|
||||
let trait_to_impl_args = impl_trait_ref.args;
|
||||
|
@ -543,7 +543,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
|||
// }
|
||||
// ```
|
||||
// .. to compile. However, since we use both the normalized and unnormalized
|
||||
// inputs and outputs from the substituted trait signature, we will end up
|
||||
// inputs and outputs from the instantiated trait signature, we will end up
|
||||
// seeing the hidden type of an RPIT in the signature itself. Naively, this
|
||||
// means that we will use the hidden type to imply the hidden type's own
|
||||
// well-formedness.
|
||||
|
@ -699,7 +699,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
|||
// NOTE(compiler-errors): RPITITs, like all other RPITs, have early-bound
|
||||
// region args that are synthesized during AST lowering. These are args
|
||||
// that are appended to the parent args (trait and trait method). However,
|
||||
// we're trying to infer the unsubstituted type value of the RPITIT inside
|
||||
// we're trying to infer the uninstantiated type value of the RPITIT inside
|
||||
// the *impl*, so we can later use the impl's method args to normalize
|
||||
// an RPITIT to a concrete type (`confirm_impl_trait_in_trait_candidate`).
|
||||
//
|
||||
|
@ -711,7 +711,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
|||
// guarantee that the indices from the trait args and impl args line up.
|
||||
// So to fix this, we subtract the number of trait args and add the number of
|
||||
// impl args to *renumber* these early-bound regions to their corresponding
|
||||
// indices in the impl's substitutions list.
|
||||
// indices in the impl's generic parameters list.
|
||||
//
|
||||
// Also, we only need to account for a difference in trait and impl args,
|
||||
// since we previously enforce that the trait method and impl method have the
|
||||
|
|
|
@ -124,14 +124,14 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
|
|||
let infcx = tcx.infer_ctxt().build();
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
|
||||
// Take the param-env of the adt and substitute the args that show up in
|
||||
// Take the param-env of the adt and instantiate the args that show up in
|
||||
// the implementation's self type. This gives us the assumptions that the
|
||||
// self ty of the implementation is allowed to know just from it being a
|
||||
// well-formed adt, since that's all we're allowed to assume while proving
|
||||
// the Drop implementation is not specialized.
|
||||
//
|
||||
// We don't need to normalize this param-env or anything, since we're only
|
||||
// substituting it with free params, so no additional param-env normalization
|
||||
// instantiating it with free params, so no additional param-env normalization
|
||||
// can occur on top of what has been done in the param_env query itself.
|
||||
let param_env =
|
||||
ty::EarlyBinder::bind(tcx.param_env(adt_def_id)).instantiate(tcx, adt_to_impl_args);
|
||||
|
|
|
@ -56,7 +56,7 @@ type variable is an instance of a type parameter. That is,
|
|||
given a generic function `fn foo<T>(t: T)`, while checking the
|
||||
function `foo`, the type `ty_param(0)` refers to the type `T`, which
|
||||
is treated in abstract. However, when `foo()` is called, `T` will be
|
||||
substituted for a fresh type variable `N`. This variable will
|
||||
instantiated with a fresh type variable `N`. This variable will
|
||||
eventually be resolved to some concrete type (which might itself be
|
||||
a type parameter).
|
||||
|
||||
|
|
|
@ -618,7 +618,7 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
|
|||
// The bounds we that we would require from `to_check`
|
||||
let mut bounds = FxHashSet::default();
|
||||
|
||||
let (regions, types) = GATSubstCollector::visit(gat_def_id.to_def_id(), to_check);
|
||||
let (regions, types) = GATArgsCollector::visit(gat_def_id.to_def_id(), to_check);
|
||||
|
||||
// If both regions and types are empty, then this GAT isn't in the
|
||||
// set of types we are checking, and we shouldn't try to do clause analysis
|
||||
|
@ -787,34 +787,34 @@ fn test_region_obligations<'tcx>(
|
|||
/// `<P0 as Trait<P1..Pn>>::GAT<Pn..Pm>` and adds the arguments `P0..Pm` into
|
||||
/// the two vectors, `regions` and `types` (depending on their kind). For each
|
||||
/// parameter `Pi` also track the index `i`.
|
||||
struct GATSubstCollector<'tcx> {
|
||||
struct GATArgsCollector<'tcx> {
|
||||
gat: DefId,
|
||||
// Which region appears and which parameter index its substituted for
|
||||
// Which region appears and which parameter index its instantiated with
|
||||
regions: FxHashSet<(ty::Region<'tcx>, usize)>,
|
||||
// Which params appears and which parameter index its substituted for
|
||||
// Which params appears and which parameter index its instantiated with
|
||||
types: FxHashSet<(Ty<'tcx>, usize)>,
|
||||
}
|
||||
|
||||
impl<'tcx> GATSubstCollector<'tcx> {
|
||||
impl<'tcx> GATArgsCollector<'tcx> {
|
||||
fn visit<T: TypeFoldable<TyCtxt<'tcx>>>(
|
||||
gat: DefId,
|
||||
t: T,
|
||||
) -> (FxHashSet<(ty::Region<'tcx>, usize)>, FxHashSet<(Ty<'tcx>, usize)>) {
|
||||
let mut visitor =
|
||||
GATSubstCollector { gat, regions: FxHashSet::default(), types: FxHashSet::default() };
|
||||
GATArgsCollector { gat, regions: FxHashSet::default(), types: FxHashSet::default() };
|
||||
t.visit_with(&mut visitor);
|
||||
(visitor.regions, visitor.types)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GATSubstCollector<'tcx> {
|
||||
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GATArgsCollector<'tcx> {
|
||||
type BreakTy = !;
|
||||
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
match t.kind() {
|
||||
ty::Alias(ty::Projection, p) if p.def_id == self.gat => {
|
||||
for (idx, subst) in p.args.iter().enumerate() {
|
||||
match subst.unpack() {
|
||||
for (idx, arg) in p.args.iter().enumerate() {
|
||||
match arg.unpack() {
|
||||
GenericArgKind::Lifetime(lt) if !lt.is_bound() => {
|
||||
self.regions.insert((lt, idx));
|
||||
}
|
||||
|
@ -1407,14 +1407,14 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
|
|||
}
|
||||
}
|
||||
|
||||
// Check that trait predicates are WF when params are substituted by their defaults.
|
||||
// Check that trait predicates are WF when params are instantiated with their defaults.
|
||||
// We don't want to overly constrain the predicates that may be written but we want to
|
||||
// catch cases where a default my never be applied such as `struct Foo<T: Copy = String>`.
|
||||
// Therefore we check if a predicate which contains a single type param
|
||||
// with a concrete default is WF with that default substituted.
|
||||
// with a concrete default is WF with that default instantiated.
|
||||
// For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`.
|
||||
//
|
||||
// First we build the defaulted substitution.
|
||||
// First we build the defaulted generic parameters.
|
||||
let args = GenericArgs::for_item(tcx, def_id.to_def_id(), |param, _| {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => {
|
||||
|
@ -1428,7 +1428,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
|
|||
let default_ty = tcx.type_of(param.def_id).instantiate_identity();
|
||||
// ... and it's not a dependent default, ...
|
||||
if !default_ty.has_param() {
|
||||
// ... then substitute it with the default.
|
||||
// ... then instantiate it with the default.
|
||||
return default_ty.into();
|
||||
}
|
||||
}
|
||||
|
@ -1441,7 +1441,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
|
|||
let default_ct = tcx.const_param_default(param.def_id).instantiate_identity();
|
||||
// ... and it's not a dependent default, ...
|
||||
if !default_ct.has_param() {
|
||||
// ... then substitute it with the default.
|
||||
// ... then instantiate it with the default.
|
||||
return default_ct.into();
|
||||
}
|
||||
}
|
||||
|
@ -1451,7 +1451,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
|
|||
}
|
||||
});
|
||||
|
||||
// Now we build the substituted predicates.
|
||||
// Now we build the instantiated predicates.
|
||||
let default_obligations = predicates
|
||||
.predicates
|
||||
.iter()
|
||||
|
@ -1483,23 +1483,25 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
|
|||
}
|
||||
let mut param_count = CountParams::default();
|
||||
let has_region = pred.visit_with(&mut param_count).is_break();
|
||||
let substituted_pred = ty::EarlyBinder::bind(pred).instantiate(tcx, args);
|
||||
let instantiated_pred = ty::EarlyBinder::bind(pred).instantiate(tcx, args);
|
||||
// Don't check non-defaulted params, dependent defaults (including lifetimes)
|
||||
// or preds with multiple params.
|
||||
if substituted_pred.has_non_region_param() || param_count.params.len() > 1 || has_region
|
||||
if instantiated_pred.has_non_region_param()
|
||||
|| param_count.params.len() > 1
|
||||
|| has_region
|
||||
{
|
||||
None
|
||||
} else if predicates.predicates.iter().any(|&(p, _)| p == substituted_pred) {
|
||||
} else if predicates.predicates.iter().any(|&(p, _)| p == instantiated_pred) {
|
||||
// Avoid duplication of predicates that contain no parameters, for example.
|
||||
None
|
||||
} else {
|
||||
Some((substituted_pred, sp))
|
||||
Some((instantiated_pred, sp))
|
||||
}
|
||||
})
|
||||
.map(|(pred, sp)| {
|
||||
// Convert each of those into an obligation. So if you have
|
||||
// something like `struct Foo<T: Copy = String>`, we would
|
||||
// take that predicate `T: Copy`, substitute to `String: Copy`
|
||||
// take that predicate `T: Copy`, instantiated with `String: Copy`
|
||||
// (actually that happens in the previous `flat_map` call),
|
||||
// and then try to prove it (in this case, we'll fail).
|
||||
//
|
||||
|
|
|
@ -396,7 +396,7 @@ pub fn coerce_unsized_info<'tcx>(
|
|||
//
|
||||
// To check if this impl is legal, we would walk down
|
||||
// the fields of `Foo` and consider their types with
|
||||
// both substitutes. We are looking to find that
|
||||
// both generic parameters. We are looking to find that
|
||||
// exactly one (non-phantom) field has changed its
|
||||
// type, which we will expect to be the pointer that
|
||||
// is becoming fat (we could probably generalize this
|
||||
|
|
|
@ -71,7 +71,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
|||
// end up with that const looking like: `ty::ConstKind::Unevaluated(def_id, args: [N#0])`.
|
||||
//
|
||||
// This causes ICEs (#86580) when building the args for Foo in `fn foo() -> Foo { .. }` as
|
||||
// we substitute the defaults with the partially built args when we build the args. Subst'ing
|
||||
// we instantiate the defaults with the partially built args when we build the args. Instantiating
|
||||
// the `N#0` on the unevaluated const indexes into the empty args we're in the process of building.
|
||||
//
|
||||
// We fix this by having this function return the parent's generics ourselves and truncating the
|
||||
|
|
|
@ -1786,7 +1786,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
|||
let bound_predicate = pred.kind();
|
||||
match bound_predicate.skip_binder() {
|
||||
ty::ClauseKind::Trait(data) => {
|
||||
// The order here needs to match what we would get from `subst_supertrait`
|
||||
// The order here needs to match what we would get from
|
||||
// `rustc_middle::ty::predicate::Clause::instantiate_supertrait`
|
||||
let pred_bound_vars = bound_predicate.bound_vars();
|
||||
let mut all_bound_vars = bound_vars.clone();
|
||||
all_bound_vars.extend(pred_bound_vars.iter());
|
||||
|
|
|
@ -119,7 +119,7 @@ pub fn identify_constrained_generic_params<'tcx>(
|
|||
/// * `<U as Iterator>::Item = T` -- a desugared ProjectionPredicate
|
||||
///
|
||||
/// When we, for example, try to go over the trait-reference
|
||||
/// `IntoIter<u32> as Trait`, we substitute the impl parameters with fresh
|
||||
/// `IntoIter<u32> as Trait`, we instantiate the impl parameters with fresh
|
||||
/// variables and match them with the impl trait-ref, so we know that
|
||||
/// `$U = IntoIter<u32>`.
|
||||
///
|
||||
|
|
|
@ -372,8 +372,8 @@ pub struct ManualImplementation {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_substs_on_overridden_impl)]
|
||||
pub struct SubstsOnOverriddenImpl {
|
||||
#[diag(hir_analysis_generic_args_on_overridden_impl)]
|
||||
pub struct GenericArgsOnOverriddenImpl {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
|
|
@ -34,8 +34,8 @@
|
|||
//! impl<T, I: Iterator<Item=T>> SpecExtend<T> for I { /* default impl */ }
|
||||
//! ```
|
||||
//!
|
||||
//! We get that the subst for `impl2` are `[T, std::vec::IntoIter<T>]`. `T` is
|
||||
//! constrained to be `<I as Iterator>::Item`, so we check only
|
||||
//! We get that the generic pamameters for `impl2` are `[T, std::vec::IntoIter<T>]`.
|
||||
//! `T` is constrained to be `<I as Iterator>::Item`, so we check only
|
||||
//! `std::vec::IntoIter<T>` for repeated parameters, which it doesn't have. The
|
||||
//! predicates of `impl1` are only `T: Sized`, which is also a predicate of
|
||||
//! `impl2`. So this specialization is sound.
|
||||
|
@ -65,7 +65,7 @@
|
|||
//! cause use after frees with purely safe code in the same way as specializing
|
||||
//! on traits with methods can.
|
||||
|
||||
use crate::errors::SubstsOnOverriddenImpl;
|
||||
use crate::errors::GenericArgsOnOverriddenImpl;
|
||||
use crate::{constrained_generic_params as cgp, errors};
|
||||
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
|
@ -179,8 +179,8 @@ fn check_constness(
|
|||
}
|
||||
|
||||
/// Given a specializing impl `impl1`, and the base impl `impl2`, returns two
|
||||
/// substitutions `(S1, S2)` that equate their trait references. The returned
|
||||
/// types are expressed in terms of the generics of `impl1`.
|
||||
/// generic parameters `(S1, S2)` that equate their trait references.
|
||||
/// The returned types are expressed in terms of the generics of `impl1`.
|
||||
///
|
||||
/// Example
|
||||
///
|
||||
|
@ -228,13 +228,13 @@ fn get_impl_args(
|
|||
let _ = ocx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env);
|
||||
let Ok(impl2_args) = infcx.fully_resolve(impl2_args) else {
|
||||
let span = tcx.def_span(impl1_def_id);
|
||||
let guar = tcx.dcx().emit_err(SubstsOnOverriddenImpl { span });
|
||||
let guar = tcx.dcx().emit_err(GenericArgsOnOverriddenImpl { span });
|
||||
return Err(guar);
|
||||
};
|
||||
Ok((impl1_args, impl2_args))
|
||||
}
|
||||
|
||||
/// Returns a list of all of the unconstrained subst of the given impl.
|
||||
/// Returns a list of all of the unconstrained generic parameters of the given impl.
|
||||
///
|
||||
/// For example given the impl:
|
||||
///
|
||||
|
|
|
@ -229,7 +229,7 @@ fn insert_required_predicates_to_be_wf<'tcx>(
|
|||
/// Here, we should fetch the explicit predicates, which
|
||||
/// will give us `U: 'static` and `U: Outer`. The latter we
|
||||
/// can ignore, but we will want to process `U: 'static`,
|
||||
/// applying the substitution as above.
|
||||
/// applying the instantiation as above.
|
||||
fn check_explicit_predicates<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
|
@ -316,7 +316,7 @@ fn check_explicit_predicates<'tcx>(
|
|||
/// Here, when processing the type of field `outer`, we would request the
|
||||
/// set of implicit predicates computed for `Inner` thus far. This will
|
||||
/// initially come back empty, but in next round we will get `U: 'b`.
|
||||
/// We then apply the substitution `['b => 'a, U => T]` and thus get the
|
||||
/// We then apply the instantiation `['b => 'a, U => T]` and thus get the
|
||||
/// requirement that `T: 'a` holds for `Outer`.
|
||||
fn check_inferred_predicates<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
|
@ -334,7 +334,7 @@ fn check_inferred_predicates<'tcx>(
|
|||
|
||||
for (&predicate, &span) in predicates.as_ref().skip_binder() {
|
||||
// `predicate` is `U: 'b` in the example above.
|
||||
// So apply the substitution to get `T: 'a`.
|
||||
// So apply the instantiation to get `T: 'a`.
|
||||
let ty::OutlivesPredicate(arg, region) =
|
||||
predicates.rebind(predicate).instantiate(tcx, args);
|
||||
insert_outlives_predicate(tcx, arg, region, span, required_predicates);
|
||||
|
|
|
@ -172,16 +172,16 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
|
|||
trait_ref: ty::TraitRef { def_id: _, args, .. },
|
||||
polarity: _,
|
||||
}) => {
|
||||
for subst in &args[1..] {
|
||||
subst.visit_with(&mut collector);
|
||||
for arg in &args[1..] {
|
||||
arg.visit_with(&mut collector);
|
||||
}
|
||||
}
|
||||
ty::ClauseKind::Projection(ty::ProjectionPredicate {
|
||||
projection_ty: ty::AliasTy { args, .. },
|
||||
term,
|
||||
}) => {
|
||||
for subst in &args[1..] {
|
||||
subst.visit_with(&mut collector);
|
||||
for arg in &args[1..] {
|
||||
arg.visit_with(&mut collector);
|
||||
}
|
||||
term.visit_with(&mut collector);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue