summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_trait_selection/src/traits
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_trait_selection/src/traits')
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs41
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs240
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/engine.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs250
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs62
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs528
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs73
-rw-r--r--compiler/rustc_trait_selection/src/traits/misc.rs20
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs64
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs35
-rw-r--r--compiler/rustc_trait_selection/src/traits/outlives_bounds.rs3
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs319
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs33
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs13
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/normalize.rs53
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs23
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs5
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs10
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs134
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs452
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs360
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/mod.rs90
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/structural_match.rs10
-rw-r--r--compiler/rustc_trait_selection/src/traits/structural_normalize.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/util.rs48
-rw-r--r--compiler/rustc_trait_selection/src/traits/vtable.rs184
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs95
30 files changed, 1566 insertions, 1597 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index cb38d0ac8..ba5000da6 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -97,7 +97,6 @@ impl<'tcx> AutoTraitFinder<'tcx> {
orig_env,
ty::TraitPredicate {
trait_ref,
- constness: ty::BoundConstness::NotConst,
polarity: if polarity {
ImplPolarity::Positive
} else {
@@ -152,21 +151,16 @@ impl<'tcx> AutoTraitFinder<'tcx> {
// traits::project will see that 'T: SomeTrait' is in our ParamEnv, allowing
// SelectionContext to return it back to us.
- let Some((new_env, user_env)) = self.evaluate_predicates(
- &infcx,
- trait_did,
- ty,
- orig_env,
- orig_env,
- &mut fresh_preds,
- ) else {
+ let Some((new_env, user_env)) =
+ self.evaluate_predicates(&infcx, trait_did, ty, orig_env, orig_env, &mut fresh_preds)
+ else {
return AutoTraitResult::NegativeImpl;
};
let (full_env, full_user_env) = self
.evaluate_predicates(&infcx, trait_did, ty, new_env, user_env, &mut fresh_preds)
.unwrap_or_else(|| {
- panic!("Failed to fully process: {:?} {:?} {:?}", ty, trait_did, orig_env)
+ panic!("Failed to fully process: {ty:?} {trait_did:?} {orig_env:?}")
});
debug!(
@@ -183,7 +177,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
ocx.register_bound(ObligationCause::dummy(), full_env, ty, trait_did);
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
- panic!("Unable to fulfill trait {:?} for '{:?}': {:?}", trait_did, ty, errors);
+ panic!("Unable to fulfill trait {trait_did:?} for '{ty:?}': {errors:?}");
}
let outlives_env = OutlivesEnvironment::new(full_env);
@@ -265,7 +259,6 @@ impl<'tcx> AutoTraitFinder<'tcx> {
predicates.push_back(ty::Binder::dummy(ty::TraitPredicate {
trait_ref: ty::TraitRef::new(infcx.tcx, trait_did, [ty]),
- constness: ty::BoundConstness::NotConst,
// Auto traits are positive
polarity: ty::ImplPolarity::Positive,
}));
@@ -329,7 +322,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
}
Ok(None) => {}
Err(SelectionError::Unimplemented) => {
- if self.is_param_no_infer(pred.skip_binder().trait_ref.substs) {
+ if self.is_param_no_infer(pred.skip_binder().trait_ref.args) {
already_visited.remove(&pred);
self.add_user_pred(&mut user_computed_preds, pred.to_predicate(self.tcx));
predicates.push_back(pred);
@@ -339,12 +332,12 @@ impl<'tcx> AutoTraitFinder<'tcx> {
{:?} {:?} {:?}",
ty,
pred,
- pred.skip_binder().trait_ref.substs
+ pred.skip_binder().trait_ref.args
);
return None;
}
}
- _ => panic!("Unexpected error for '{:?}': {:?}", ty, result),
+ _ => panic!("Unexpected error for '{ty:?}': {result:?}"),
};
let normalized_preds =
@@ -352,14 +345,12 @@ impl<'tcx> AutoTraitFinder<'tcx> {
new_env = ty::ParamEnv::new(
tcx.mk_clauses_from_iter(normalized_preds.filter_map(|p| p.as_clause())),
param_env.reveal(),
- param_env.constness(),
);
}
let final_user_env = ty::ParamEnv::new(
tcx.mk_clauses_from_iter(user_computed_preds.into_iter().filter_map(|p| p.as_clause())),
user_env.reveal(),
- user_env.constness(),
);
debug!(
"evaluate_nested_obligations(ty={:?}, trait_did={:?}): succeeded with '{:?}' \
@@ -406,17 +397,17 @@ impl<'tcx> AutoTraitFinder<'tcx> {
) = (new_pred.kind().skip_binder(), old_pred.kind().skip_binder())
{
if new_trait.def_id() == old_trait.def_id() {
- let new_substs = new_trait.trait_ref.substs;
- let old_substs = old_trait.trait_ref.substs;
+ let new_args = new_trait.trait_ref.args;
+ let old_args = old_trait.trait_ref.args;
- if !new_substs.types().eq(old_substs.types()) {
+ if !new_args.types().eq(old_args.types()) {
// We can't compare lifetimes if the types are different,
// so skip checking `old_pred`.
return true;
}
for (new_region, old_region) in
- iter::zip(new_substs.regions(), old_substs.regions())
+ iter::zip(new_args.regions(), old_args.regions())
{
match (*new_region, *old_region) {
// If both predicates have an `ReLateBound` (a HRTB) in the
@@ -569,8 +560,8 @@ impl<'tcx> AutoTraitFinder<'tcx> {
finished_map
}
- fn is_param_no_infer(&self, substs: SubstsRef<'_>) -> bool {
- self.is_of_param(substs.type_at(0)) && !substs.types().any(|t| t.has_infer_types())
+ fn is_param_no_infer(&self, args: GenericArgsRef<'_>) -> bool {
+ self.is_of_param(args.type_at(0)) && !args.types().any(|t| t.has_infer_types())
}
pub fn is_of_param(&self, ty: Ty<'_>) -> bool {
@@ -641,7 +632,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
// an inference variable.
// Additionally, we check if we've seen this predicate before,
// to avoid rendering duplicate bounds to the user.
- if self.is_param_no_infer(p.skip_binder().projection_ty.substs)
+ if self.is_param_no_infer(p.skip_binder().projection_ty.args)
&& !p.term().skip_binder().has_infer_types()
&& is_new_pred
{
@@ -754,7 +745,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
// subobligations or getting an error) when we started off with
// inference variables
if p.term().skip_binder().has_infer_types() {
- panic!("Unexpected result when selecting {:?} {:?}", ty, obligation)
+ panic!("Unexpected result when selecting {ty:?} {obligation:?}")
}
}
}
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index 1b1285e1b..5746781ae 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -7,7 +7,7 @@
use crate::infer::outlives::env::OutlivesEnvironment;
use crate::infer::InferOk;
use crate::traits::outlives_bounds::InferCtxtExt as _;
-use crate::traits::select::IntercrateAmbiguityCause;
+use crate::traits::select::{IntercrateAmbiguityCause, TreatInductiveCycleAs};
use crate::traits::util::impl_subject_and_oblig;
use crate::traits::SkipLeakCheck;
use crate::traits::{
@@ -24,6 +24,7 @@ use rustc_middle::traits::DefiningAnchor;
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor};
+use rustc_session::lint::builtin::COINDUCTIVE_OVERLAP_IN_COHERENCE;
use rustc_span::symbol::sym;
use rustc_span::DUMMY_SP;
use std::fmt::Debug;
@@ -96,9 +97,7 @@ pub fn overlapping_impls(
let impl1_ref = tcx.impl_trait_ref(impl1_def_id);
let impl2_ref = tcx.impl_trait_ref(impl2_def_id);
let may_overlap = match (impl1_ref, impl2_ref) {
- (Some(a), Some(b)) => {
- drcx.substs_refs_may_unify(a.skip_binder().substs, b.skip_binder().substs)
- }
+ (Some(a), Some(b)) => drcx.args_refs_may_unify(a.skip_binder().args, b.skip_binder().args),
(None, None) => {
let self_ty1 = tcx.type_of(impl1_def_id).skip_binder();
let self_ty2 = tcx.type_of(impl2_def_id).skip_binder();
@@ -143,24 +142,26 @@ fn with_fresh_ty_vars<'cx, 'tcx>(
impl_def_id: DefId,
) -> ty::ImplHeader<'tcx> {
let tcx = selcx.tcx();
- let impl_substs = selcx.infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
+ let impl_args = selcx.infcx.fresh_args_for_item(DUMMY_SP, impl_def_id);
let header = ty::ImplHeader {
impl_def_id,
- self_ty: tcx.type_of(impl_def_id).subst(tcx, impl_substs),
- trait_ref: tcx.impl_trait_ref(impl_def_id).map(|i| i.subst(tcx, impl_substs)),
+ self_ty: tcx.type_of(impl_def_id).instantiate(tcx, impl_args),
+ trait_ref: tcx.impl_trait_ref(impl_def_id).map(|i| i.instantiate(tcx, impl_args)),
predicates: tcx
.predicates_of(impl_def_id)
- .instantiate(tcx, impl_substs)
+ .instantiate(tcx, impl_args)
.iter()
- .map(|(c, _)| c.as_predicate())
+ .map(|(c, s)| (c.as_predicate(), s))
.collect(),
};
- let InferOk { value: mut header, obligations } =
- selcx.infcx.at(&ObligationCause::dummy(), param_env).normalize(header);
+ let InferOk { value: mut header, obligations } = selcx
+ .infcx
+ .at(&ObligationCause::dummy_with_span(tcx.def_span(impl_def_id)), param_env)
+ .normalize(header);
- header.predicates.extend(obligations.into_iter().map(|o| o.predicate));
+ header.predicates.extend(obligations.into_iter().map(|o| (o.predicate, o.cause.span)));
header
}
@@ -209,16 +210,76 @@ fn overlap<'tcx>(
let equate_obligations = equate_impl_headers(selcx.infcx, &impl1_header, &impl2_header)?;
debug!("overlap: unification check succeeded");
- if overlap_mode.use_implicit_negative()
- && impl_intersection_has_impossible_obligation(
- selcx,
- param_env,
- &impl1_header,
- impl2_header,
- equate_obligations,
- )
- {
- return None;
+ if overlap_mode.use_implicit_negative() {
+ for mode in [TreatInductiveCycleAs::Ambig, TreatInductiveCycleAs::Recur] {
+ if let Some(failing_obligation) = selcx.with_treat_inductive_cycle_as(mode, |selcx| {
+ impl_intersection_has_impossible_obligation(
+ selcx,
+ param_env,
+ &impl1_header,
+ &impl2_header,
+ &equate_obligations,
+ )
+ }) {
+ if matches!(mode, TreatInductiveCycleAs::Recur) {
+ let first_local_impl = impl1_header
+ .impl_def_id
+ .as_local()
+ .or(impl2_header.impl_def_id.as_local())
+ .expect("expected one of the impls to be local");
+ infcx.tcx.struct_span_lint_hir(
+ COINDUCTIVE_OVERLAP_IN_COHERENCE,
+ infcx.tcx.local_def_id_to_hir_id(first_local_impl),
+ infcx.tcx.def_span(first_local_impl),
+ format!(
+ "implementations {} will conflict in the future",
+ match impl1_header.trait_ref {
+ Some(trait_ref) => {
+ let trait_ref = infcx.resolve_vars_if_possible(trait_ref);
+ format!(
+ "of `{}` for `{}`",
+ trait_ref.print_only_trait_path(),
+ trait_ref.self_ty()
+ )
+ }
+ None => format!(
+ "for `{}`",
+ infcx.resolve_vars_if_possible(impl1_header.self_ty)
+ ),
+ },
+ ),
+ |lint| {
+ lint.note(
+ "impls that are not considered to overlap may be considered to \
+ overlap in the future",
+ )
+ .span_label(
+ infcx.tcx.def_span(impl1_header.impl_def_id),
+ "the first impl is here",
+ )
+ .span_label(
+ infcx.tcx.def_span(impl2_header.impl_def_id),
+ "the second impl is here",
+ );
+ if !failing_obligation.cause.span.is_dummy() {
+ lint.span_label(
+ failing_obligation.cause.span,
+ format!(
+ "`{}` may be considered to hold in future releases, \
+ causing the impls to overlap",
+ infcx
+ .resolve_vars_if_possible(failing_obligation.predicate)
+ ),
+ );
+ }
+ lint
+ },
+ );
+ }
+
+ return None;
+ }
+ }
}
// We toggle the `leak_check` by using `skip_leak_check` when constructing the
@@ -286,40 +347,30 @@ fn impl_intersection_has_impossible_obligation<'cx, 'tcx>(
selcx: &mut SelectionContext<'cx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
impl1_header: &ty::ImplHeader<'tcx>,
- impl2_header: ty::ImplHeader<'tcx>,
- obligations: PredicateObligations<'tcx>,
-) -> bool {
+ impl2_header: &ty::ImplHeader<'tcx>,
+ obligations: &PredicateObligations<'tcx>,
+) -> Option<PredicateObligation<'tcx>> {
let infcx = selcx.infcx;
- let obligation_guaranteed_to_fail = move |obligation: &PredicateObligation<'tcx>| {
- if infcx.next_trait_solver() {
- infcx.evaluate_obligation(obligation).map_or(false, |result| !result.may_apply())
- } else {
- // We use `evaluate_root_obligation` to correctly track
- // intercrate ambiguity clauses. We do not need this in the
- // new solver.
- selcx.evaluate_root_obligation(obligation).map_or(
- false, // Overflow has occurred, and treat the obligation as possibly holding.
- |result| !result.may_apply(),
- )
- }
- };
-
- let opt_failing_obligation = [&impl1_header.predicates, &impl2_header.predicates]
+ [&impl1_header.predicates, &impl2_header.predicates]
.into_iter()
.flatten()
- .map(|&predicate| {
- Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, predicate)
+ .map(|&(predicate, span)| {
+ Obligation::new(infcx.tcx, ObligationCause::dummy_with_span(span), param_env, predicate)
+ })
+ .chain(obligations.into_iter().cloned())
+ .find(|obligation: &PredicateObligation<'tcx>| {
+ if infcx.next_trait_solver() {
+ infcx.evaluate_obligation(obligation).map_or(false, |result| !result.may_apply())
+ } else {
+ // We use `evaluate_root_obligation` to correctly track intercrate
+ // ambiguity clauses. We cannot use this in the new solver.
+ selcx.evaluate_root_obligation(obligation).map_or(
+ false, // Overflow has occurred, and treat the obligation as possibly holding.
+ |result| !result.may_apply(),
+ )
+ }
})
- .chain(obligations)
- .find(obligation_guaranteed_to_fail);
-
- if let Some(failing_obligation) = opt_failing_obligation {
- debug!("overlap: obligation unsatisfiable {:?}", failing_obligation);
- true
- } else {
- false
- }
}
/// Check if both impls can be satisfied by a common type by considering whether
@@ -353,13 +404,13 @@ fn impl_intersection_has_negative_obligation(
&infcx,
ObligationCause::dummy(),
impl_env,
- tcx.impl_subject(impl1_def_id).subst_identity(),
+ tcx.impl_subject(impl1_def_id).instantiate_identity(),
) {
Ok(s) => s,
Err(err) => {
tcx.sess.delay_span_bug(
tcx.def_span(impl1_def_id),
- format!("failed to fully normalize {:?}: {:?}", impl1_def_id, err),
+ format!("failed to fully normalize {impl1_def_id:?}: {err:?}"),
);
return false;
}
@@ -367,16 +418,16 @@ fn impl_intersection_has_negative_obligation(
// Attempt to prove that impl2 applies, given all of the above.
let selcx = &mut SelectionContext::new(&infcx);
- let impl2_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl2_def_id);
+ let impl2_args = infcx.fresh_args_for_item(DUMMY_SP, impl2_def_id);
let (subject2, normalization_obligations) =
- impl_subject_and_oblig(selcx, impl_env, impl2_def_id, impl2_substs, |_, _| {
+ impl_subject_and_oblig(selcx, impl_env, impl2_def_id, impl2_args, |_, _| {
ObligationCause::dummy()
});
// do the impls unify? If not, then it's not currently possible to prove any
// obligations about their intersection.
let Ok(InferOk { obligations: equate_obligations, .. }) =
- infcx.at(&ObligationCause::dummy(), impl_env).eq(DefineOpaqueTypes::No,subject1, subject2)
+ infcx.at(&ObligationCause::dummy(), impl_env).eq(DefineOpaqueTypes::No, subject1, subject2)
else {
debug!("explicit_disjoint: {:?} does not unify with {:?}", subject1, subject2);
return false;
@@ -437,8 +488,7 @@ fn prove_negated_obligation<'tcx>(
let body_def_id = body_def_id.as_local().unwrap_or(CRATE_DEF_ID);
let ocx = ObligationCtxt::new(&infcx);
- let Ok(wf_tys) = ocx.assumed_wf_types(param_env, body_def_id)
- else {
+ let Ok(wf_tys) = ocx.assumed_wf_types(param_env, body_def_id) else {
return false;
};
@@ -455,22 +505,23 @@ fn prove_negated_obligation<'tcx>(
/// This both checks whether any downstream or sibling crates could
/// implement it and whether an upstream crate can add this impl
/// without breaking backwards compatibility.
-#[instrument(level = "debug", skip(tcx), ret)]
-pub fn trait_ref_is_knowable<'tcx>(
+#[instrument(level = "debug", skip(tcx, lazily_normalize_ty), ret)]
+pub fn trait_ref_is_knowable<'tcx, E: Debug>(
tcx: TyCtxt<'tcx>,
trait_ref: ty::TraitRef<'tcx>,
-) -> Result<(), Conflict> {
+ mut lazily_normalize_ty: impl FnMut(Ty<'tcx>) -> Result<Ty<'tcx>, E>,
+) -> Result<Result<(), Conflict>, E> {
if Some(trait_ref.def_id) == tcx.lang_items().fn_ptr_trait() {
// The only types implementing `FnPtr` are function pointers,
// so if there's no impl of `FnPtr` in the current crate,
// then such an impl will never be added in the future.
- return Ok(());
+ return Ok(Ok(()));
}
- if orphan_check_trait_ref(trait_ref, InCrate::Remote).is_ok() {
+ if orphan_check_trait_ref(trait_ref, InCrate::Remote, &mut lazily_normalize_ty)?.is_ok() {
// A downstream or cousin crate is allowed to implement some
// substitution of this trait-ref.
- return Err(Conflict::Downstream);
+ return Ok(Err(Conflict::Downstream));
}
if trait_ref_is_local_or_fundamental(tcx, trait_ref) {
@@ -479,7 +530,7 @@ pub fn trait_ref_is_knowable<'tcx>(
// allowed to implement a substitution of this trait ref, which
// means impls could only come from dependencies of this crate,
// which we already know about.
- return Ok(());
+ return Ok(Ok(()));
}
// This is a remote non-fundamental trait, so if another crate
@@ -490,10 +541,10 @@ pub fn trait_ref_is_knowable<'tcx>(
// and if we are an intermediate owner, then we don't care
// about future-compatibility, which means that we're OK if
// we are an owner.
- if orphan_check_trait_ref(trait_ref, InCrate::Local).is_ok() {
- Ok(())
+ if orphan_check_trait_ref(trait_ref, InCrate::Local, &mut lazily_normalize_ty)?.is_ok() {
+ Ok(Ok(()))
} else {
- Err(Conflict::Upstream)
+ Ok(Err(Conflict::Upstream))
}
}
@@ -520,7 +571,7 @@ pub enum OrphanCheckErr<'tcx> {
pub fn orphan_check(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Result<(), OrphanCheckErr<'_>> {
// We only except this routine to be invoked on implementations
// of a trait, not inherent implementations.
- let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity();
+ let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity();
debug!(?trait_ref);
// If the *trait* is local to the crate, ok.
@@ -529,7 +580,7 @@ pub fn orphan_check(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Result<(), OrphanChe
return Ok(());
}
- orphan_check_trait_ref(trait_ref, InCrate::Local)
+ orphan_check_trait_ref::<!>(trait_ref, InCrate::Local, |ty| Ok(ty)).unwrap()
}
/// Checks whether a trait-ref is potentially implementable by a crate.
@@ -618,11 +669,12 @@ pub fn orphan_check(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Result<(), OrphanChe
///
/// Note that this function is never called for types that have both type
/// parameters and inference variables.
-#[instrument(level = "trace", ret)]
-fn orphan_check_trait_ref<'tcx>(
+#[instrument(level = "trace", skip(lazily_normalize_ty), ret)]
+fn orphan_check_trait_ref<'tcx, E: Debug>(
trait_ref: ty::TraitRef<'tcx>,
in_crate: InCrate,
-) -> Result<(), OrphanCheckErr<'tcx>> {
+ lazily_normalize_ty: impl FnMut(Ty<'tcx>) -> Result<Ty<'tcx>, E>,
+) -> Result<Result<(), OrphanCheckErr<'tcx>>, E> {
if trait_ref.has_infer() && trait_ref.has_param() {
bug!(
"can't orphan check a trait ref with both params and inference variables {:?}",
@@ -630,9 +682,10 @@ fn orphan_check_trait_ref<'tcx>(
);
}
- let mut checker = OrphanChecker::new(in_crate);
- match trait_ref.visit_with(&mut checker) {
+ let mut checker = OrphanChecker::new(in_crate, lazily_normalize_ty);
+ Ok(match trait_ref.visit_with(&mut checker) {
ControlFlow::Continue(()) => Err(OrphanCheckErr::NonLocalInputType(checker.non_local_tys)),
+ ControlFlow::Break(OrphanCheckEarlyExit::NormalizationFailure(err)) => return Err(err),
ControlFlow::Break(OrphanCheckEarlyExit::ParamTy(ty)) => {
// Does there exist some local type after the `ParamTy`.
checker.search_first_local_ty = true;
@@ -645,34 +698,39 @@ fn orphan_check_trait_ref<'tcx>(
}
}
ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(_)) => Ok(()),
- }
+ })
}
-struct OrphanChecker<'tcx> {
+struct OrphanChecker<'tcx, F> {
in_crate: InCrate,
in_self_ty: bool,
+ lazily_normalize_ty: F,
/// Ignore orphan check failures and exclusively search for the first
/// local type.
search_first_local_ty: bool,
non_local_tys: Vec<(Ty<'tcx>, bool)>,
}
-impl<'tcx> OrphanChecker<'tcx> {
- fn new(in_crate: InCrate) -> Self {
+impl<'tcx, F, E> OrphanChecker<'tcx, F>
+where
+ F: FnOnce(Ty<'tcx>) -> Result<Ty<'tcx>, E>,
+{
+ fn new(in_crate: InCrate, lazily_normalize_ty: F) -> Self {
OrphanChecker {
in_crate,
in_self_ty: true,
+ lazily_normalize_ty,
search_first_local_ty: false,
non_local_tys: Vec::new(),
}
}
- fn found_non_local_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<OrphanCheckEarlyExit<'tcx>> {
+ fn found_non_local_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<OrphanCheckEarlyExit<'tcx, E>> {
self.non_local_tys.push((t, self.in_self_ty));
ControlFlow::Continue(())
}
- fn found_param_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<OrphanCheckEarlyExit<'tcx>> {
+ fn found_param_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<OrphanCheckEarlyExit<'tcx, E>> {
if self.search_first_local_ty {
ControlFlow::Continue(())
} else {
@@ -688,18 +746,28 @@ impl<'tcx> OrphanChecker<'tcx> {
}
}
-enum OrphanCheckEarlyExit<'tcx> {
+enum OrphanCheckEarlyExit<'tcx, E> {
+ NormalizationFailure(E),
ParamTy(Ty<'tcx>),
LocalTy(Ty<'tcx>),
}
-impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OrphanChecker<'tcx> {
- type BreakTy = OrphanCheckEarlyExit<'tcx>;
+impl<'tcx, F, E> TypeVisitor<TyCtxt<'tcx>> for OrphanChecker<'tcx, F>
+where
+ F: FnMut(Ty<'tcx>) -> Result<Ty<'tcx>, E>,
+{
+ type BreakTy = OrphanCheckEarlyExit<'tcx, E>;
fn visit_region(&mut self, _r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
ControlFlow::Continue(())
}
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+ // Need to lazily normalize here in with `-Ztrait-solver=next-coherence`.
+ let ty = match (self.lazily_normalize_ty)(ty) {
+ Ok(ty) => ty,
+ Err(err) => return ControlFlow::Break(OrphanCheckEarlyExit::NormalizationFailure(err)),
+ };
+
let result = match *ty.kind() {
ty::Bool
| ty::Char
@@ -729,11 +797,11 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OrphanChecker<'tcx> {
// For fundamental types, we just look inside of them.
ty::Ref(_, ty, _) => ty.visit_with(self),
- ty::Adt(def, substs) => {
+ ty::Adt(def, args) => {
if self.def_id_is_local(def.did()) {
ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty))
} else if def.is_fundamental() {
- substs.visit_with(self)
+ args.visit_with(self)
} else {
self.found_non_local_ty(ty)
}
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index 8dc13b827..3d0d3812d 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -191,7 +191,7 @@ fn satisfied_from_param_env<'tcx>(
if let ty::ConstKind::Expr(e) = c.kind() {
e.visit_with(self)
} else {
- // FIXME(generic_const_exprs): This doesn't recurse into `<T as Trait<U>>::ASSOC`'s substs.
+ // FIXME(generic_const_exprs): This doesn't recurse into `<T as Trait<U>>::ASSOC`'s args.
// This is currently unobservable as `<T as Trait<{ U + 1 }>>::ASSOC` creates an anon const
// with its own `ConstEvaluatable` bound in the param env which we will visit separately.
//
diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs
index 61f693e1b..820973dc0 100644
--- a/compiler/rustc_trait_selection/src/traits/engine.rs
+++ b/compiler/rustc_trait_selection/src/traits/engine.rs
@@ -97,7 +97,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
cause,
recursion_depth: 0,
param_env,
- predicate: ty::Binder::dummy(trait_ref).without_const().to_predicate(tcx),
+ predicate: ty::Binder::dummy(trait_ref).to_predicate(tcx),
});
}
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
index f785c4eaf..fd813ca4e 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
@@ -26,8 +26,8 @@ pub fn recompute_applicable_impls<'tcx>(
let obligation_trait_ref =
ocx.normalize(&ObligationCause::dummy(), param_env, placeholder_obligation.trait_ref);
- let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
- let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().subst(tcx, impl_substs);
+ let impl_args = infcx.fresh_args_for_item(DUMMY_SP, impl_def_id);
+ let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(tcx, impl_args);
let impl_trait_ref = ocx.normalize(&ObligationCause::dummy(), param_env, impl_trait_ref);
if let Err(_) =
@@ -36,7 +36,7 @@ pub fn recompute_applicable_impls<'tcx>(
return false;
}
- let impl_predicates = tcx.predicates_of(impl_def_id).instantiate(tcx, impl_substs);
+ let impl_predicates = tcx.predicates_of(impl_def_id).instantiate(tcx, impl_args);
ocx.register_obligations(impl_predicates.predicates.iter().map(|&predicate| {
Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate)
}));
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index f34218059..457d5420c 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -7,6 +7,7 @@ use super::{
ObligationCauseCode, ObligationCtxt, OutputTypeParameterMismatch, Overflow,
PredicateObligation, SelectionError, TraitNotObjectSafe,
};
+use crate::errors::{ClosureFnMutLabel, ClosureFnOnceLabel, ClosureKindMismatch};
use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use crate::infer::{self, InferCtxt};
@@ -100,7 +101,6 @@ pub trait InferCtxtExt<'tcx> {
&self,
param_env: ty::ParamEnv<'tcx>,
ty: ty::Binder<'tcx, Ty<'tcx>>,
- constness: ty::BoundConstness,
polarity: ty::ImplPolarity,
) -> Result<(ty::ClosureKind, ty::Binder<'tcx, Ty<'tcx>>), ()>;
}
@@ -226,7 +226,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
let span = variant_data.ctor_hir_id().map_or(DUMMY_SP, |id| hir.span(id));
(span, None, vec![ArgKind::empty(); variant_data.fields().len()])
}
- _ => panic!("non-FnLike node found: {:?}", node),
+ _ => panic!("non-FnLike node found: {node:?}"),
})
}
@@ -273,10 +273,10 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
found_str,
);
- err.span_label(span, format!("expected {} that takes {}", kind, expected_str));
+ err.span_label(span, format!("expected {kind} that takes {expected_str}"));
if let Some(found_span) = found_span {
- err.span_label(found_span, format!("takes {}", found_str));
+ err.span_label(found_span, format!("takes {found_str}"));
// Suggest to take and ignore the arguments with expected_args_length `_`s if
// found arguments is empty (assume the user just wants to ignore args in this case).
@@ -289,7 +289,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
"consider changing the closure to take and ignore the expected argument{}",
pluralize!(expected_args.len())
),
- format!("|{}|", underscores),
+ format!("|{underscores}|"),
Applicability::MachineApplicable,
);
}
@@ -304,7 +304,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
err.span_suggestion_verbose(
found_span,
"change the closure to take multiple arguments instead of a single tuple",
- format!("|{}|", sugg),
+ format!("|{sugg}|"),
Applicability::MachineApplicable,
);
}
@@ -356,7 +356,6 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
&self,
param_env: ty::ParamEnv<'tcx>,
ty: ty::Binder<'tcx, Ty<'tcx>>,
- constness: ty::BoundConstness,
polarity: ty::ImplPolarity,
) -> Result<(ty::ClosureKind, ty::Binder<'tcx, Ty<'tcx>>), ()> {
self.commit_if_ok(|_| {
@@ -372,12 +371,13 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
span: DUMMY_SP,
kind: TypeVariableOriginKind::MiscVariable,
});
+ // FIXME(effects)
let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, [ty.skip_binder(), var]);
let obligation = Obligation::new(
self.tcx,
ObligationCause::dummy(),
param_env,
- ty.rebind(ty::TraitPredicate { trait_ref, constness, polarity }),
+ ty.rebind(ty::TraitPredicate { trait_ref, polarity }),
);
let ocx = ObligationCtxt::new(self);
ocx.register_obligation(obligation);
@@ -687,11 +687,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
match bound_predicate.skip_binder() {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => {
let trait_predicate = bound_predicate.rebind(trait_predicate);
- let mut trait_predicate = self.resolve_vars_if_possible(trait_predicate);
+ let trait_predicate = self.resolve_vars_if_possible(trait_predicate);
- trait_predicate.remap_constness_diag(obligation.param_env);
- let predicate_is_const = ty::BoundConstness::ConstIfConst
- == trait_predicate.skip_binder().constness;
+ // FIXME(effects)
+ let predicate_is_const = false;
if self.tcx.sess.has_errors().is_some()
&& trait_predicate.references_error()
@@ -704,9 +703,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
.get_parent_trait_ref(obligation.cause.code())
.map(|(t, s)| {
(
- format!(" in `{}`", t),
- format!("within `{}`, ", t),
- s.map(|s| (format!("within this `{}`", t), s)),
+ format!(" in `{t}`"),
+ format!("within `{t}`, "),
+ s.map(|s| (format!("within this `{t}`"), s)),
)
})
.unwrap_or_default();
@@ -1050,8 +1049,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
report_object_safety_error(self.tcx, span, trait_def_id, violations)
}
- ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind) => {
- let found_kind = self.closure_kind(closure_substs).unwrap();
+ ty::PredicateKind::ClosureKind(closure_def_id, closure_args, kind) => {
+ let found_kind = self.closure_kind(closure_args).unwrap();
self.report_closure_error(&obligation, closure_def_id, found_kind, kind)
}
@@ -1071,7 +1070,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// which bounds actually failed to hold.
self.tcx.sess.struct_span_err(
span,
- format!("the type `{}` is not well-formed", ty),
+ format!("the type `{ty}` is not well-formed"),
)
}
}
@@ -1109,7 +1108,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
let mut diag = self.tcx.sess.struct_span_err(
span,
- format!("the constant `{}` is not of type `{}`", ct, ty),
+ format!("the constant `{ct}` is not of type `{ty}`"),
);
self.note_type_err(
&mut diag,
@@ -1627,19 +1626,21 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
ty::TermKind::Ty(_) => Ty::new_projection(
self.tcx,
data.projection_ty.def_id,
- data.projection_ty.substs,
+ data.projection_ty.args,
)
.into(),
ty::TermKind::Const(ct) => ty::Const::new_unevaluated(
self.tcx,
ty::UnevaluatedConst {
def: data.projection_ty.def_id,
- substs: data.projection_ty.substs,
+ args: data.projection_ty.args,
},
ct.ty(),
)
.into(),
};
+ // FIXME(-Ztrait-solver=next): For diagnostic purposes, it would be nice
+ // to deeply normalize this type.
let normalized_term =
ocx.normalize(&obligation.cause, obligation.param_env, unnormalized_term);
@@ -1908,9 +1909,6 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
.all_impls(trait_pred.def_id())
.filter_map(|def_id| {
if self.tcx.impl_polarity(def_id) == ty::ImplPolarity::Negative
- || !trait_pred
- .skip_binder()
- .is_constness_satisfied_by(self.tcx.constness(def_id))
|| !self.tcx.is_user_visible_dep(def_id.krate)
{
return None;
@@ -1970,7 +1968,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
traits.sort();
traits.dedup();
// FIXME: this could use a better heuristic, like just checking
- // that substs[1..] is the same.
+ // that args[1..] is the same.
let all_traits_equal = traits.len() == 1;
let candidates: Vec<String> = candidates
@@ -1979,7 +1977,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
if all_traits_equal {
format!("\n {}", c.self_ty())
} else {
- format!("\n {}", c)
+ format!("\n {c}")
}
})
.collect();
@@ -2016,7 +2014,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|| self.tcx.is_automatically_derived(def_id)
})
.filter_map(|def_id| self.tcx.impl_trait_ref(def_id))
- .map(ty::EarlyBinder::subst_identity)
+ .map(ty::EarlyBinder::instantiate_identity)
.filter(|trait_ref| {
let self_ty = trait_ref.self_ty();
// Avoid mentioning type parameters.
@@ -2177,10 +2175,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
format!("trait impl{} with same name found", pluralize!(trait_impls.len())),
);
let trait_crate = self.tcx.crate_name(trait_with_same_path.krate);
- let crate_msg = format!(
- "perhaps two different versions of crate `{}` are being used?",
- trait_crate
- );
+ let crate_msg =
+ format!("perhaps two different versions of crate `{trait_crate}` are being used?");
err.note(crate_msg);
suggested = true;
}
@@ -2265,7 +2261,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// Pick the first substitution that still contains inference variables as the one
// we're going to emit an error for. If there are none (see above), fall back to
// a more general error.
- let subst = data.trait_ref.substs.iter().find(|s| s.has_non_region_infer());
+ let subst = data.trait_ref.args.iter().find(|s| s.has_non_region_infer());
let mut err = if let Some(subst) = subst {
self.emit_inference_failure_err(
@@ -2290,7 +2286,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
&obligation.with(self.tcx, trait_ref),
);
let has_non_region_infer =
- trait_ref.skip_binder().substs.types().any(|t| !t.is_ty_or_numeric_infer());
+ trait_ref.skip_binder().args.types().any(|t| !t.is_ty_or_numeric_infer());
// It doesn't make sense to talk about applicable impls if there are more
// than a handful of them.
if ambiguities.len() > 1 && ambiguities.len() < 10 && has_non_region_infer {
@@ -2308,7 +2304,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
err.cancel();
return;
}
- err.note(format!("cannot satisfy `{}`", predicate));
+ err.note(format!("cannot satisfy `{predicate}`"));
let impl_candidates = self
.find_similar_impl_candidates(predicate.to_opt_poly_trait_pred().unwrap());
if impl_candidates.len() < 10 {
@@ -2328,7 +2324,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
}
- if let Some(ty::subst::GenericArgKind::Type(_)) = subst.map(|subst| subst.unpack())
+ if let Some(ty::GenericArgKind::Type(_)) = subst.map(|subst| subst.unpack())
&& let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id)
{
let mut expr_finder = FindExprBySpan::new(span);
@@ -2372,7 +2368,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
if let Some(local_def_id) = data.trait_ref.def_id.as_local()
&& let Some(hir::Node::Item(hir::Item { ident: trait_name, kind: hir::ItemKind::Trait(_, _, _, _, trait_item_refs), .. })) = self.tcx.hir().find_by_def_id(local_def_id)
&& let Some(method_ref) = trait_item_refs.iter().find(|item_ref| item_ref.ident == *assoc_item_name) {
- err.span_label(method_ref.span, format!("`{}::{}` defined here", trait_name, assoc_item_name));
+ err.span_label(method_ref.span, format!("`{trait_name}::{assoc_item_name}` defined here"));
}
err.span_label(span, format!("cannot {verb} associated {noun} of trait"));
@@ -2386,14 +2382,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// If there is only one implementation of the trait, suggest using it.
// Otherwise, use a placeholder comment for the implementation.
let (message, impl_suggestion) = if non_blanket_impl_count == 1 {(
- "use the fully-qualified path to the only available implementation".to_string(),
- format!("<{} as ", self.tcx.type_of(impl_def_id).subst_identity())
- )} else {(
- format!(
- "use a fully-qualified path to a specific available implementation ({} found)",
- non_blanket_impl_count
- ),
- "</* self type */ as ".to_string()
+ "use the fully-qualified path to the only available implementation",
+ format!("<{} as ", self.tcx.type_of(impl_def_id).instantiate_identity())
+ )} else {
+ ("use a fully-qualified path to a specific available implementation",
+ "</* self type */ as ".to_string()
)};
let mut suggestions = vec![(
path.span.shrink_to_lo(),
@@ -2464,7 +2457,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
let subst = data
.projection_ty
- .substs
+ .args
.iter()
.chain(Some(data.term.into_arg()))
.find(|g| g.has_non_region_infer());
@@ -2476,7 +2469,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
ErrorCode::E0284,
true,
);
- err.note(format!("cannot satisfy `{}`", predicate));
+ err.note(format!("cannot satisfy `{predicate}`"));
err
} else {
// If we can't find a substitution, just print a generic error
@@ -2487,7 +2480,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
"type annotations needed: cannot satisfy `{}`",
predicate,
);
- err.span_label(span, format!("cannot satisfy `{}`", predicate));
+ err.span_label(span, format!("cannot satisfy `{predicate}`"));
err
}
}
@@ -2515,7 +2508,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
"type annotations needed: cannot satisfy `{}`",
predicate,
);
- err.span_label(span, format!("cannot satisfy `{}`", predicate));
+ err.span_label(span, format!("cannot satisfy `{predicate}`"));
err
}
}
@@ -2530,7 +2523,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
"type annotations needed: cannot satisfy `{}`",
predicate,
);
- err.span_label(span, format!("cannot satisfy `{}`", predicate));
+ err.span_label(span, format!("cannot satisfy `{predicate}`"));
err
}
};
@@ -2567,7 +2560,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
}
}
- let mut crate_names: Vec<_> = crates.iter().map(|n| format!("`{}`", n)).collect();
+ let mut crate_names: Vec<_> = crates.iter().map(|n| format!("`{n}`")).collect();
crate_names.sort();
crate_names.dedup();
post.sort();
@@ -2594,7 +2587,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
predicate
);
let post = if post.len() > 1 || (post.len() == 1 && post[0].contains('\n')) {
- format!(":\n{}", post.iter().map(|p| format!("- {}", p)).collect::<Vec<_>>().join("\n"),)
+ format!(":\n{}", post.iter().map(|p| format!("- {p}")).collect::<Vec<_>>().join("\n"),)
} else if post.len() == 1 {
format!(": `{}`", post[0])
} else {
@@ -2603,7 +2596,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
match (spans.len(), crates.len(), crate_names.len()) {
(0, 0, 0) => {
- err.note(format!("cannot satisfy `{}`", predicate));
+ err.note(format!("cannot satisfy `{predicate}`"));
}
(0, _, 1) => {
err.note(format!("{} in the `{}` crate{}", msg, crates[0], post,));
@@ -2706,10 +2699,17 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
err: &mut Diagnostic,
obligation: &PredicateObligation<'tcx>,
) {
- let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) = obligation.predicate.kind().skip_binder() else { return; };
+ let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) =
+ obligation.predicate.kind().skip_binder()
+ else {
+ return;
+ };
let (ObligationCauseCode::BindingObligation(item_def_id, span)
- | ObligationCauseCode::ExprBindingObligation(item_def_id, span, ..))
- = *obligation.cause.code().peel_derives() else { return; };
+ | ObligationCauseCode::ExprBindingObligation(item_def_id, span, ..)) =
+ *obligation.cause.code().peel_derives()
+ else {
+ return;
+ };
debug!(?pred, ?item_def_id, ?span);
let (Some(node), true) = (
@@ -2767,7 +2767,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
err.span_suggestion_verbose(
span,
"consider relaxing the implicit `Sized` restriction",
- format!("{} ?Sized", separator),
+ format!("{separator} ?Sized"),
Applicability::MachineApplicable,
);
}
@@ -2820,9 +2820,9 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
if obligated_types.iter().any(|ot| ot == &self_ty) {
return true;
}
- if let ty::Adt(def, substs) = self_ty.kind()
- && let [arg] = &substs[..]
- && let ty::subst::GenericArgKind::Type(ty) = arg.unpack()
+ if let ty::Adt(def, args) = self_ty.kind()
+ && let [arg] = &args[..]
+ && let ty::GenericArgKind::Type(ty) = arg.unpack()
&& let ty::Adt(inner_def, _) = ty.kind()
&& inner_def == def
{
@@ -2858,7 +2858,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
})
.unwrap_or_else(|| {
- format!("the trait bound `{}` is not satisfied{}", trait_predicate, post_message)
+ format!("the trait bound `{trait_predicate}` is not satisfied{post_message}")
})
}
@@ -2874,14 +2874,20 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let trait_ref = self.tcx.erase_regions(self.tcx.erase_late_bound_regions(trait_ref));
let src_and_dst = rustc_transmute::Types {
- dst: trait_ref.substs.type_at(0),
- src: trait_ref.substs.type_at(1),
+ dst: trait_ref.args.type_at(0),
+ src: trait_ref.args.type_at(1),
+ };
+ let scope = trait_ref.args.type_at(2);
+ let Some(assume) = rustc_transmute::Assume::from_const(
+ self.infcx.tcx,
+ obligation.param_env,
+ trait_ref.args.const_at(3),
+ ) else {
+ span_bug!(
+ span,
+ "Unable to construct rustc_transmute::Assume where it was previously possible"
+ );
};
- let scope = trait_ref.substs.type_at(2);
- let Some(assume) =
- rustc_transmute::Assume::from_const(self.infcx.tcx, obligation.param_env, trait_ref.substs.const_at(3)) else {
- span_bug!(span, "Unable to construct rustc_transmute::Assume where it was previously possible");
- };
match rustc_transmute::TransmuteTypeEnv::new(self.infcx).is_transmutable(
obligation.cause,
@@ -2890,8 +2896,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
assume,
) {
Answer::No(reason) => {
- let dst = trait_ref.substs.type_at(0);
- let src = trait_ref.substs.type_at(1);
+ let dst = trait_ref.args.type_at(0);
+ let src = trait_ref.args.type_at(1);
let err_msg = format!(
"`{src}` cannot be safely transmuted into `{dst}` in the defining scope of `{scope}`"
);
@@ -2982,12 +2988,19 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
unsatisfied_const: bool,
) {
let body_def_id = obligation.cause.body_id;
+ let span = if let ObligationCauseCode::BinOp { rhs_span: Some(rhs_span), .. } =
+ obligation.cause.code()
+ {
+ *rhs_span
+ } else {
+ span
+ };
+
// Try to report a help message
if is_fn_trait
&& let Ok((implemented_kind, params)) = self.type_implements_fn_trait(
obligation.param_env,
trait_ref.self_ty(),
- trait_predicate.skip_binder().constness,
trait_predicate.skip_binder().polarity,
)
{
@@ -3021,8 +3034,9 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
self.report_similar_impl_candidates_for_root_obligation(&obligation, *trait_predicate, body_def_id, err);
}
- self.maybe_suggest_convert_to_slice(
+ self.suggest_convert_to_slice(
err,
+ obligation,
trait_ref,
impl_candidates.as_slice(),
span,
@@ -3058,7 +3072,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// Note any argument mismatches
let given_ty = params.skip_binder();
- let expected_ty = trait_ref.skip_binder().substs.type_at(1);
+ let expected_ty = trait_ref.skip_binder().args.type_at(1);
if let ty::Tuple(given) = given_ty.kind()
&& let ty::Tuple(expected) = expected_ty.kind()
{
@@ -3089,34 +3103,14 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
fn maybe_add_note_for_unsatisfied_const(
&self,
- obligation: &PredicateObligation<'tcx>,
- trait_ref: ty::PolyTraitRef<'tcx>,
- trait_predicate: &ty::PolyTraitPredicate<'tcx>,
- err: &mut Diagnostic,
- span: Span,
+ _obligation: &PredicateObligation<'tcx>,
+ _trait_ref: ty::PolyTraitRef<'tcx>,
+ _trait_predicate: &ty::PolyTraitPredicate<'tcx>,
+ _err: &mut Diagnostic,
+ _span: Span,
) -> UnsatisfiedConst {
- let mut unsatisfied_const = UnsatisfiedConst(false);
- if trait_predicate.is_const_if_const() && obligation.param_env.is_const() {
- let non_const_predicate = trait_ref.without_const();
- let non_const_obligation = Obligation {
- cause: obligation.cause.clone(),
- param_env: obligation.param_env.without_const(),
- predicate: non_const_predicate.to_predicate(self.tcx),
- recursion_depth: obligation.recursion_depth,
- };
- if self.predicate_may_hold(&non_const_obligation) {
- unsatisfied_const = UnsatisfiedConst(true);
- err.span_note(
- span,
- format!(
- "the trait `{}` is implemented for `{}`, \
- but that implementation is not `const`",
- non_const_predicate.print_modifiers_and_trait_path(),
- trait_ref.skip_binder().self_ty(),
- ),
- );
- }
- }
+ let unsatisfied_const = UnsatisfiedConst(false);
+ // FIXME(effects)
unsatisfied_const
}
@@ -3128,24 +3122,15 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
kind: ty::ClosureKind,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
let closure_span = self.tcx.def_span(closure_def_id);
- let mut err = struct_span_err!(
- self.tcx.sess,
- closure_span,
- E0525,
- "expected a closure that implements the `{}` trait, \
- but this closure only implements `{}`",
- kind,
- found_kind
- );
- err.span_label(
+ let mut err = ClosureKindMismatch {
closure_span,
- format!("this closure implements `{}`, not `{}`", found_kind, kind),
- );
- err.span_label(
- obligation.cause.span,
- format!("the requirement to implement `{}` derives from here", kind),
- );
+ expected: kind,
+ found: found_kind,
+ cause_span: obligation.cause.span,
+ fn_once_label: None,
+ fn_mut_label: None,
+ };
// Additional context information explaining why the closure only implements
// a particular trait.
@@ -3153,30 +3138,22 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let hir_id = self.tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local());
match (found_kind, typeck_results.closure_kind_origins().get(hir_id)) {
(ty::ClosureKind::FnOnce, Some((span, place))) => {
- err.span_label(
- *span,
- format!(
- "closure is `FnOnce` because it moves the \
- variable `{}` out of its environment",
- ty::place_to_string_for_capture(self.tcx, place)
- ),
- );
+ err.fn_once_label = Some(ClosureFnOnceLabel {
+ span: *span,
+ place: ty::place_to_string_for_capture(self.tcx, &place),
+ })
}
(ty::ClosureKind::FnMut, Some((span, place))) => {
- err.span_label(
- *span,
- format!(
- "closure is `FnMut` because it mutates the \
- variable `{}` here",
- ty::place_to_string_for_capture(self.tcx, place)
- ),
- );
+ err.fn_mut_label = Some(ClosureFnMutLabel {
+ span: *span,
+ place: ty::place_to_string_for_capture(self.tcx, &place),
+ })
}
_ => {}
}
}
- err
+ self.tcx.sess.create_err(err)
}
fn report_type_parameter_mismatch_cyclic_type_error(
@@ -3273,7 +3250,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let mut not_tupled = false;
- let found = match found_trait_ref.skip_binder().substs.type_at(1).kind() {
+ let found = match found_trait_ref.skip_binder().args.type_at(1).kind() {
ty::Tuple(ref tys) => vec![ArgKind::empty(); tys.len()],
_ => {
not_tupled = true;
@@ -3281,7 +3258,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
};
- let expected_ty = expected_trait_ref.skip_binder().substs.type_at(1);
+ let expected_ty = expected_trait_ref.skip_binder().args.type_at(1);
let expected = match expected_ty.kind() {
ty::Tuple(ref tys) => {
tys.iter().map(|t| ArgKind::from_expected_ty(t, Some(span))).collect()
@@ -3371,8 +3348,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let const_span = self.tcx.def_span(uv.def);
match self.tcx.sess.source_map().span_to_snippet(const_span) {
Ok(snippet) => err.help(format!(
- "try adding a `where` bound using this expression: `where [(); {}]:`",
- snippet
+ "try adding a `where` bound using this expression: `where [(); {snippet}]:`"
)),
_ => err.help("consider adding a `where` bound using this expression"),
};
@@ -3554,7 +3530,7 @@ pub fn dump_proof_tree<'tcx>(o: &Obligation<'tcx, ty::Predicate<'tcx>>, infcx: &
.1
.expect("proof tree should have been generated");
let mut lock = std::io::stdout().lock();
- let _ = lock.write_fmt(format_args!("{tree:?}"));
+ let _ = lock.write_fmt(format_args!("{tree:?}\n"));
let _ = lock.flush();
});
}
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
index b16d2eb5f..0e73bad19 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
@@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{struct_span_err, ErrorGuaranteed};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
-use rustc_middle::ty::SubstsRef;
+use rustc_middle::ty::GenericArgsRef;
use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt};
use rustc_parse_format::{ParseMode, Parser, Piece, Position};
use rustc_span::symbol::{kw, sym, Symbol};
@@ -25,7 +25,7 @@ pub trait TypeErrCtxtExt<'tcx> {
&self,
trait_ref: ty::PolyTraitRef<'tcx>,
obligation: &PredicateObligation<'tcx>,
- ) -> Option<(DefId, SubstsRef<'tcx>)>;
+ ) -> Option<(DefId, GenericArgsRef<'tcx>)>;
/*private*/
fn describe_enclosure(&self, hir_id: hir::HirId) -> Option<&'static str>;
@@ -56,7 +56,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
&self,
trait_ref: ty::PolyTraitRef<'tcx>,
obligation: &PredicateObligation<'tcx>,
- ) -> Option<(DefId, SubstsRef<'tcx>)> {
+ ) -> Option<(DefId, GenericArgsRef<'tcx>)> {
let tcx = self.tcx;
let param_env = obligation.param_env;
let trait_ref = self.instantiate_binder_with_placeholders(trait_ref);
@@ -66,26 +66,23 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let mut fuzzy_match_impls = vec![];
self.tcx.for_each_relevant_impl(trait_ref.def_id, trait_self_ty, |def_id| {
- let impl_substs = self.fresh_substs_for_item(obligation.cause.span, def_id);
- let impl_trait_ref = tcx.impl_trait_ref(def_id).unwrap().subst(tcx, impl_substs);
+ let impl_args = self.fresh_args_for_item(obligation.cause.span, def_id);
+ let impl_trait_ref = tcx.impl_trait_ref(def_id).unwrap().instantiate(tcx, impl_args);
let impl_self_ty = impl_trait_ref.self_ty();
if self.can_eq(param_env, trait_self_ty, impl_self_ty) {
- self_match_impls.push((def_id, impl_substs));
+ self_match_impls.push((def_id, impl_args));
- if iter::zip(
- trait_ref.substs.types().skip(1),
- impl_trait_ref.substs.types().skip(1),
- )
- .all(|(u, v)| self.fuzzy_match_tys(u, v, false).is_some())
+ if iter::zip(trait_ref.args.types().skip(1), impl_trait_ref.args.types().skip(1))
+ .all(|(u, v)| self.fuzzy_match_tys(u, v, false).is_some())
{
- fuzzy_match_impls.push((def_id, impl_substs));
+ fuzzy_match_impls.push((def_id, impl_args));
}
}
});
- let impl_def_id_and_substs = if self_match_impls.len() == 1 {
+ let impl_def_id_and_args = if self_match_impls.len() == 1 {
self_match_impls[0]
} else if fuzzy_match_impls.len() == 1 {
fuzzy_match_impls[0]
@@ -93,8 +90,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
return None;
};
- tcx.has_attr(impl_def_id_and_substs.0, sym::rustc_on_unimplemented)
- .then_some(impl_def_id_and_substs)
+ tcx.has_attr(impl_def_id_and_args.0, sym::rustc_on_unimplemented)
+ .then_some(impl_def_id_and_args)
}
/// Used to set on_unimplemented's `ItemContext`
@@ -143,9 +140,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
trait_ref: ty::PolyTraitRef<'tcx>,
obligation: &PredicateObligation<'tcx>,
) -> OnUnimplementedNote {
- let (def_id, substs) = self
+ let (def_id, args) = self
.impl_similar_to(trait_ref, obligation)
- .unwrap_or_else(|| (trait_ref.def_id(), trait_ref.skip_binder().substs));
+ .unwrap_or_else(|| (trait_ref.def_id(), trait_ref.skip_binder().args));
let trait_ref = trait_ref.skip_binder();
let mut flags = vec![];
@@ -173,7 +170,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
if let Some(k) = obligation.cause.span.desugaring_kind() {
flags.push((sym::from_desugaring, None));
- flags.push((sym::from_desugaring, Some(format!("{:?}", k))));
+ flags.push((sym::from_desugaring, Some(format!("{k:?}"))));
}
if let ObligationCauseCode::MainFunctionType = obligation.cause.code() {
@@ -192,14 +189,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// signature with no type arguments resolved
flags.push((
sym::_Self,
- Some(self.tcx.type_of(def.did()).subst_identity().to_string()),
+ Some(self.tcx.type_of(def.did()).instantiate_identity().to_string()),
));
}
for param in generics.params.iter() {
let value = match param.kind {
GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
- substs[param.index as usize].to_string()
+ args[param.index as usize].to_string()
}
GenericParamDefKind::Lifetime => continue,
};
@@ -207,13 +204,13 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
flags.push((name, Some(value)));
if let GenericParamDefKind::Type { .. } = param.kind {
- let param_ty = substs[param.index as usize].expect_ty();
+ let param_ty = args[param.index as usize].expect_ty();
if let Some(def) = param_ty.ty_adt_def() {
// We also want to be able to select the parameter's
// original signature with no type arguments resolved
flags.push((
name,
- Some(self.tcx.type_of(def.did()).subst_identity().to_string()),
+ Some(self.tcx.type_of(def.did()).instantiate_identity().to_string()),
));
}
}
@@ -249,7 +246,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// signature with no type arguments resolved
flags.push((
sym::_Self,
- Some(format!("[{}]", self.tcx.type_of(def.did()).subst_identity())),
+ Some(format!("[{}]", self.tcx.type_of(def.did()).instantiate_identity())),
));
}
if aty.is_integral() {
@@ -261,14 +258,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
if let ty::Array(aty, len) = self_ty.kind() {
flags.push((sym::_Self, Some("[]".to_string())));
let len = len.try_to_value().and_then(|v| v.try_to_target_usize(self.tcx));
- flags.push((sym::_Self, Some(format!("[{}; _]", aty))));
+ flags.push((sym::_Self, Some(format!("[{aty}; _]"))));
if let Some(n) = len {
- flags.push((sym::_Self, Some(format!("[{}; {}]", aty, n))));
+ flags.push((sym::_Self, Some(format!("[{aty}; {n}]"))));
}
if let Some(def) = aty.ty_adt_def() {
// We also want to be able to select the array's type's original
// signature with no type arguments resolved
- let def_ty = self.tcx.type_of(def.did()).subst_identity();
+ let def_ty = self.tcx.type_of(def.did()).instantiate_identity();
flags.push((sym::_Self, Some(format!("[{def_ty}; _]"))));
if let Some(n) = len {
flags.push((sym::_Self, Some(format!("[{def_ty}; {n}]"))));
@@ -332,18 +329,13 @@ pub struct OnUnimplementedNote {
}
/// Append a message for `~const Trait` errors.
-#[derive(Clone, Copy, PartialEq, Eq, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
pub enum AppendConstMessage {
+ #[default]
Default,
Custom(Symbol),
}
-impl Default for AppendConstMessage {
- fn default() -> Self {
- AppendConstMessage::Default
- }
-}
-
impl<'tcx> OnUnimplementedDirective {
fn parse(
tcx: TyCtxt<'tcx>,
@@ -587,7 +579,7 @@ impl<'tcx> OnUnimplementedFormatString {
"there is no parameter `{}` on {}",
s,
if trait_def_id == item_def_id {
- format!("trait `{}`", trait_name)
+ format!("trait `{trait_name}`")
} else {
"impl".to_string()
}
@@ -629,7 +621,7 @@ impl<'tcx> OnUnimplementedFormatString {
.filter_map(|param| {
let value = match param.kind {
GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
- trait_ref.substs[param.index as usize].to_string()
+ trait_ref.args[param.index as usize].to_string()
}
GenericParamDefKind::Lifetime => return None,
};
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 9ac1ba027..611ec6b00 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -5,6 +5,7 @@ use super::{
PredicateObligation,
};
+use crate::errors;
use crate::infer::InferCtxt;
use crate::traits::{NormalizeExt, ObligationCtxt};
@@ -30,7 +31,7 @@ use rustc_middle::hir::map;
use rustc_middle::ty::error::TypeError::{self, Sorts};
use rustc_middle::ty::{
self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind,
- GeneratorDiagnosticData, GeneratorInteriorTypeCause, InferTy, InternalSubsts, IsSuggestable,
+ GeneratorDiagnosticData, GeneratorInteriorTypeCause, GenericArgs, InferTy, IsSuggestable,
ToPredicate, Ty, TyCtxt, TypeAndMut, TypeFoldable, TypeFolder, TypeSuperFoldable,
TypeVisitableExt, TypeckResults,
};
@@ -40,7 +41,6 @@ use rustc_span::{BytePos, DesugaringKind, ExpnKind, MacroKind, Span, DUMMY_SP};
use rustc_target::spec::abi;
use std::borrow::Cow;
use std::iter;
-use std::ops::Deref;
use super::InferCtxtPrivExt;
use crate::infer::InferCtxtExt as _;
@@ -398,9 +398,10 @@ pub trait TypeErrCtxtExt<'tcx> {
param_env: ty::ParamEnv<'tcx>,
) -> Vec<Option<(Span, (DefId, Ty<'tcx>))>>;
- fn maybe_suggest_convert_to_slice(
+ fn suggest_convert_to_slice(
&self,
err: &mut Diagnostic,
+ obligation: &PredicateObligation<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>,
candidate_impls: &[ImplCandidate<'tcx>],
span: Span,
@@ -435,7 +436,7 @@ fn suggest_restriction<'tcx>(
) {
if hir_generics.where_clause_span.from_expansion()
|| hir_generics.where_clause_span.desugaring_kind().is_some()
- || projection.is_some_and(|projection| tcx.opt_rpitit_info(projection.def_id).is_some())
+ || projection.is_some_and(|projection| tcx.is_impl_trait_in_trait(projection.def_id))
{
return;
}
@@ -479,13 +480,13 @@ fn suggest_restriction<'tcx>(
.visit_ty(input);
}
// The type param `T: Trait` we will suggest to introduce.
- let type_param = format!("{}: {}", type_param_name, bound_str);
+ let type_param = format!("{type_param_name}: {bound_str}");
let mut sugg = vec![
if let Some(span) = hir_generics.span_for_param_suggestion() {
- (span, format!(", {}", type_param))
+ (span, format!(", {type_param}"))
} else {
- (hir_generics.span, format!("<{}>", type_param))
+ (hir_generics.span, format!("<{type_param}>"))
},
// `fn foo(t: impl Trait)`
// ^ suggest `where <T as Trait>::A: Bound`
@@ -530,7 +531,7 @@ fn suggest_restriction<'tcx>(
err.span_suggestion_verbose(
sp,
- format!("consider further restricting {}", msg),
+ format!("consider further restricting {msg}"),
suggestion,
Applicability::MachineApplicable,
);
@@ -654,6 +655,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
| hir::ItemKind::Impl(hir::Impl { generics, .. })
| hir::ItemKind::Fn(_, generics, _)
| hir::ItemKind::TyAlias(_, generics)
+ | hir::ItemKind::Const(_, generics, _)
| hir::ItemKind::TraitAlias(generics, _)
| hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. }),
..
@@ -670,7 +672,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// this that we do in `suggest_restriction` and pull the
// `impl Trait` into a new generic if it shows up somewhere
// else in the predicate.
- if !trait_pred.skip_binder().trait_ref.substs[1..]
+ if !trait_pred.skip_binder().trait_ref.args[1..]
.iter()
.all(|g| g.is_suggestable(self.tcx, false))
{
@@ -693,7 +695,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
term
);
} else {
- constraint.push_str(&format!("<{} = {}>", name, term));
+ constraint.push_str(&format!("<{name} = {term}>"));
}
}
@@ -719,6 +721,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
| hir::ItemKind::Impl(hir::Impl { generics, .. })
| hir::ItemKind::Fn(_, generics, _)
| hir::ItemKind::TyAlias(_, generics)
+ | hir::ItemKind::Const(_, generics, _)
| hir::ItemKind::TraitAlias(generics, _)
| hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. }),
..
@@ -752,14 +755,20 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
trait_pred: ty::PolyTraitPredicate<'tcx>,
) -> bool {
// It only make sense when suggesting dereferences for arguments
- let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, call_hir_id, .. } = obligation.cause.code()
- else { return false; };
- let Some(typeck_results) = &self.typeck_results
- else { return false; };
- let hir::Node::Expr(expr) = self.tcx.hir().get(*arg_hir_id)
- else { return false; };
- let Some(arg_ty) = typeck_results.expr_ty_adjusted_opt(expr)
- else { return false; };
+ let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, call_hir_id, .. } =
+ obligation.cause.code()
+ else {
+ return false;
+ };
+ let Some(typeck_results) = &self.typeck_results else {
+ return false;
+ };
+ let hir::Node::Expr(expr) = self.tcx.hir().get(*arg_hir_id) else {
+ return false;
+ };
+ let Some(arg_ty) = typeck_results.expr_ty_adjusted_opt(expr) else {
+ return false;
+ };
let span = obligation.cause.span;
let mut real_trait_pred = trait_pred;
@@ -770,18 +779,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
real_trait_pred = parent_trait_pred;
}
- let real_ty = real_trait_pred.self_ty();
// We `erase_late_bound_regions` here because `make_subregion` does not handle
// `ReLateBound`, and we don't particularly care about the regions.
- if !self.can_eq(
- obligation.param_env,
- self.tcx.erase_late_bound_regions(real_ty),
- arg_ty,
- ) {
+ let real_ty = self.tcx.erase_late_bound_regions(real_trait_pred.self_ty());
+ if !self.can_eq(obligation.param_env, real_ty, arg_ty) {
continue;
}
- if let ty::Ref(region, base_ty, mutbl) = *real_ty.skip_binder().kind() {
+ if let ty::Ref(region, base_ty, mutbl) = *real_ty.kind() {
let autoderef = (self.autoderef_steps)(base_ty);
if let Some(steps) =
autoderef.into_iter().enumerate().find_map(|(steps, (ty, obligations))| {
@@ -933,11 +938,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
trait_pred.self_ty(),
);
- let Some((def_id_or_name, output, inputs)) = self.extract_callable_info(
- obligation.cause.body_id,
- obligation.param_env,
- self_ty,
- ) else { return false; };
+ let Some((def_id_or_name, output, inputs)) =
+ self.extract_callable_info(obligation.cause.body_id, obligation.param_env, self_ty)
+ else {
+ return false;
+ };
// Remapping bound vars here
let trait_pred_and_self = trait_pred.map_bound(|trait_pred| (trait_pred, output));
@@ -1012,7 +1017,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let name = self.tcx.def_path_str(def_id);
err.span_label(
self.tcx.def_span(def_id),
- format!("consider calling the constructor for `{}`", name),
+ format!("consider calling the constructor for `{name}`"),
);
name
}
@@ -1035,26 +1040,40 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
span.remove_mark();
}
let mut expr_finder = FindExprBySpan::new(span);
- let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) else { return; };
+ let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) else {
+ return;
+ };
let body = self.tcx.hir().body(body_id);
expr_finder.visit_expr(body.value);
- let Some(expr) = expr_finder.result else { return; };
- let Some(typeck) = &self.typeck_results else { return; };
- let Some(ty) = typeck.expr_ty_adjusted_opt(expr) else { return; };
+ let Some(expr) = expr_finder.result else {
+ return;
+ };
+ let Some(typeck) = &self.typeck_results else {
+ return;
+ };
+ let Some(ty) = typeck.expr_ty_adjusted_opt(expr) else {
+ return;
+ };
if !ty.is_unit() {
return;
};
- let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind else { return; };
- let hir::def::Res::Local(hir_id) = path.res else { return; };
+ let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind else {
+ return;
+ };
+ let hir::def::Res::Local(hir_id) = path.res else {
+ return;
+ };
let Some(hir::Node::Pat(pat)) = self.tcx.hir().find(hir_id) else {
return;
};
- let Some(hir::Node::Local(hir::Local {
- ty: None,
- init: Some(init),
- ..
- })) = self.tcx.hir().find_parent(pat.hir_id) else { return; };
- let hir::ExprKind::Block(block, None) = init.kind else { return; };
+ let Some(hir::Node::Local(hir::Local { ty: None, init: Some(init), .. })) =
+ self.tcx.hir().find_parent(pat.hir_id)
+ else {
+ return;
+ };
+ let hir::ExprKind::Block(block, None) = init.kind else {
+ return;
+ };
if block.expr.is_some() {
return;
}
@@ -1062,7 +1081,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
err.span_label(block.span, "this empty block is missing a tail expression");
return;
};
- let hir::StmtKind::Semi(tail_expr) = stmt.kind else { return; };
+ let hir::StmtKind::Semi(tail_expr) = stmt.kind else {
+ return;
+ };
let Some(ty) = typeck.expr_ty_opt(tail_expr) else {
err.span_label(block.span, "this block is missing a tail expression");
return;
@@ -1092,12 +1113,18 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
) -> bool {
let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty());
let ty = self.instantiate_binder_with_placeholders(self_ty);
- let Some(generics) = self.tcx.hir().get_generics(obligation.cause.body_id) else { return false };
+ let Some(generics) = self.tcx.hir().get_generics(obligation.cause.body_id) else {
+ return false;
+ };
let ty::Ref(_, inner_ty, hir::Mutability::Not) = ty.kind() else { return false };
let ty::Param(param) = inner_ty.kind() else { return false };
- let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } = obligation.cause.code() else { return false };
+ let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } =
+ obligation.cause.code()
+ else {
+ return false;
+ };
let arg_node = self.tcx.hir().get(*arg_hir_id);
- let Node::Expr(Expr { kind: hir::ExprKind::Path(_), ..}) = arg_node else { return false };
+ let Node::Expr(Expr { kind: hir::ExprKind::Path(_), .. }) = arg_node else { return false };
let clone_trait = self.tcx.require_lang_item(LangItem::Clone, None);
let has_clone = |ty| {
@@ -1143,24 +1170,33 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
found: Ty<'tcx>,
) -> Option<(DefIdOrName, Ty<'tcx>, Vec<Ty<'tcx>>)> {
// Autoderef is useful here because sometimes we box callables, etc.
- let Some((def_id_or_name, output, inputs)) = (self.autoderef_steps)(found).into_iter().find_map(|(found, _)| {
- match *found.kind() {
- ty::FnPtr(fn_sig) =>
- Some((DefIdOrName::Name("function pointer"), fn_sig.output(), fn_sig.inputs())),
- ty::FnDef(def_id, _) => {
- let fn_sig = found.fn_sig(self.tcx);
- Some((DefIdOrName::DefId(def_id), fn_sig.output(), fn_sig.inputs()))
- }
- ty::Closure(def_id, substs) => {
- let fn_sig = substs.as_closure().sig();
- Some((DefIdOrName::DefId(def_id), fn_sig.output(), fn_sig.inputs().map_bound(|inputs| &inputs[1..])))
- }
- ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
- self.tcx.item_bounds(def_id).subst(self.tcx, substs).iter().find_map(|pred| {
- if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder()
+ let Some((def_id_or_name, output, inputs)) =
+ (self.autoderef_steps)(found).into_iter().find_map(|(found, _)| {
+ match *found.kind() {
+ ty::FnPtr(fn_sig) => Some((
+ DefIdOrName::Name("function pointer"),
+ fn_sig.output(),
+ fn_sig.inputs(),
+ )),
+ ty::FnDef(def_id, _) => {
+ let fn_sig = found.fn_sig(self.tcx);
+ Some((DefIdOrName::DefId(def_id), fn_sig.output(), fn_sig.inputs()))
+ }
+ ty::Closure(def_id, args) => {
+ let fn_sig = args.as_closure().sig();
+ Some((
+ DefIdOrName::DefId(def_id),
+ fn_sig.output(),
+ fn_sig.inputs().map_bound(|inputs| &inputs[1..]),
+ ))
+ }
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
+ self.tcx.item_bounds(def_id).instantiate(self.tcx, args).iter().find_map(
+ |pred| {
+ if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder()
&& Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output()
- // args tuple will always be substs[1]
- && let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind()
+ // args tuple will always be args[1]
+ && let ty::Tuple(args) = proj.projection_ty.args.type_at(1).kind()
{
Some((
DefIdOrName::DefId(def_id),
@@ -1170,14 +1206,15 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
} else {
None
}
- })
- }
- ty::Dynamic(data, _, ty::Dyn) => {
- data.iter().find_map(|pred| {
- if let ty::ExistentialPredicate::Projection(proj) = pred.skip_binder()
+ },
+ )
+ }
+ ty::Dynamic(data, _, ty::Dyn) => {
+ data.iter().find_map(|pred| {
+ if let ty::ExistentialPredicate::Projection(proj) = pred.skip_binder()
&& Some(proj.def_id) == self.tcx.lang_items().fn_once_output()
- // for existential projection, substs are shifted over by 1
- && let ty::Tuple(args) = proj.substs.type_at(0).kind()
+ // for existential projection, args are shifted over by 1
+ && let ty::Tuple(args) = proj.args.type_at(0).kind()
{
Some((
DefIdOrName::Name("trait object"),
@@ -1187,11 +1224,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
} else {
None
}
- })
- }
- ty::Param(param) => {
- let generics = self.tcx.generics_of(body_id);
- let name = if generics.count() > param.index as usize
+ })
+ }
+ ty::Param(param) => {
+ let generics = self.tcx.generics_of(body_id);
+ let name = if generics.count() > param.index as usize
&& let def = generics.param_at(param.index as usize, self.tcx)
&& matches!(def.kind, ty::GenericParamDefKind::Type { .. })
&& def.name == param.name
@@ -1200,12 +1237,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
} else {
DefIdOrName::Name("type parameter")
};
- param_env.caller_bounds().iter().find_map(|pred| {
- if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder()
+ param_env.caller_bounds().iter().find_map(|pred| {
+ if let ty::ClauseKind::Projection(proj) = pred.kind().skip_binder()
&& Some(proj.projection_ty.def_id) == self.tcx.lang_items().fn_once_output()
&& proj.projection_ty.self_ty() == found
- // args tuple will always be substs[1]
- && let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind()
+ // args tuple will always be args[1]
+ && let ty::Tuple(args) = proj.projection_ty.args.type_at(1).kind()
{
Some((
name,
@@ -1215,11 +1252,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
} else {
None
}
- })
+ })
+ }
+ _ => None,
}
- _ => None,
- }
- }) else { return None; };
+ })
+ else {
+ return None;
+ };
let output = self.instantiate_binder_with_fresh_vars(
DUMMY_SP,
@@ -1356,7 +1396,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// Because of this, we modify the error to refer to the original obligation and
// return early in the caller.
- let msg = format!("the trait bound `{}` is not satisfied", old_pred);
+ let msg = format!("the trait bound `{old_pred}` is not satisfied");
if has_custom_message {
err.note(msg);
} else {
@@ -1389,30 +1429,34 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// Issue #109436, we need to add parentheses properly for method calls
// for example, `foo.into()` should be `(&foo).into()`
- if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(
- self.tcx.sess.source_map().span_look_ahead(span, Some("."), Some(50)),
- ) {
- if snippet == "." {
- err.multipart_suggestion_verbose(
- sugg_msg,
- vec![
- (span.shrink_to_lo(), format!("({}", sugg_prefix)),
- (span.shrink_to_hi(), ")".to_string()),
- ],
- Applicability::MaybeIncorrect,
- );
- return true;
- }
+ if let Some(_) =
+ self.tcx.sess.source_map().span_look_ahead(span, ".", Some(50))
+ {
+ err.multipart_suggestion_verbose(
+ sugg_msg,
+ vec![
+ (span.shrink_to_lo(), format!("({sugg_prefix}")),
+ (span.shrink_to_hi(), ")".to_string()),
+ ],
+ Applicability::MaybeIncorrect,
+ );
+ return true;
}
// Issue #104961, we need to add parentheses properly for compound expressions
// for example, `x.starts_with("hi".to_string() + "you")`
// should be `x.starts_with(&("hi".to_string() + "you"))`
- let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) else { return false; };
+ let Some(body_id) =
+ self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id)
+ else {
+ return false;
+ };
let body = self.tcx.hir().body(body_id);
let mut expr_finder = FindExprBySpan::new(span);
expr_finder.visit_expr(body.value);
- let Some(expr) = expr_finder.result else { return false; };
+ let Some(expr) = expr_finder.result else {
+ return false;
+ };
let needs_parens = match expr.kind {
// parenthesize if needed (Issue #46756)
hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true,
@@ -1423,10 +1467,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let span = if needs_parens { span } else { span.shrink_to_lo() };
let suggestions = if !needs_parens {
- vec![(span.shrink_to_lo(), format!("{}", sugg_prefix))]
+ vec![(span.shrink_to_lo(), sugg_prefix)]
} else {
vec![
- (span.shrink_to_lo(), format!("{}(", sugg_prefix)),
+ (span.shrink_to_lo(), format!("{sugg_prefix}(")),
(span.shrink_to_hi(), ")".to_string()),
]
};
@@ -1463,8 +1507,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
self_ty: Ty<'tcx>,
target_ty: Ty<'tcx>,
) {
- let ty::Ref(_, object_ty, hir::Mutability::Not) = target_ty.kind() else { return; };
- let ty::Dynamic(predicates, _, ty::Dyn) = object_ty.kind() else { return; };
+ let ty::Ref(_, object_ty, hir::Mutability::Not) = target_ty.kind() else {
+ return;
+ };
+ let ty::Dynamic(predicates, _, ty::Dyn) = object_ty.kind() else {
+ return;
+ };
let self_ref_ty = Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, self_ty);
for predicate in predicates.iter() {
@@ -1566,7 +1614,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
// Maybe suggest removal of borrows from expressions, like in `for i in &&&foo {}`.
- let Some(mut expr) = expr_finder.result else { return false; };
+ let Some(mut expr) = expr_finder.result else {
+ return false;
+ };
let mut count = 0;
let mut suggestions = vec![];
// Skipping binder here, remapping below
@@ -1646,13 +1696,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
if let Some(typeck_results) = &self.typeck_results
&& let ty = typeck_results.expr_ty_adjusted(base)
- && let ty::FnDef(def_id, _substs) = ty.kind()
+ && let ty::FnDef(def_id, _args) = ty.kind()
&& let Some(hir::Node::Item(hir::Item { ident, span, vis_span, .. })) =
hir.get_if_local(*def_id)
{
let msg = format!(
- "alternatively, consider making `fn {}` asynchronous",
- ident
+ "alternatively, consider making `fn {ident}` asynchronous"
);
if vis_span.is_empty() {
err.span_suggestion_verbose(
@@ -1798,7 +1847,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option<Span> {
let hir = self.tcx.hir();
- let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, ..), .. })) = hir.find_by_def_id(obligation.cause.body_id) else {
+ let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, ..), .. })) =
+ hir.find_by_def_id(obligation.cause.body_id)
+ else {
return None;
};
@@ -1901,10 +1952,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// don't print out the [type error] here
err.delay_as_bug();
} else {
- err.span_label(
- expr.span,
- format!("this returned value is of type `{}`", ty),
- );
+ err.span_label(expr.span, format!("this returned value is of type `{ty}`"));
}
}
}
@@ -1925,7 +1973,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
infcx: &InferCtxt<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>,
) -> Ty<'tcx> {
- let inputs = trait_ref.skip_binder().substs.type_at(1);
+ let inputs = trait_ref.skip_binder().args.type_at(1);
let sig = match inputs.kind() {
ty::Tuple(inputs) if infcx.tcx.is_fn_trait(trait_ref.def_id()) => {
infcx.tcx.mk_fn_sig(
@@ -2006,12 +2054,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
{
let expected_self =
self.tcx.anonymize_bound_vars(pred.kind().rebind(trait_pred.self_ty()));
- let expected_substs = self
+ let expected_args = self
.tcx
- .anonymize_bound_vars(pred.kind().rebind(trait_pred.trait_ref.substs));
+ .anonymize_bound_vars(pred.kind().rebind(trait_pred.trait_ref.args));
// Find another predicate whose self-type is equal to the expected self type,
- // but whose substs don't match.
+ // but whose args don't match.
let other_pred = predicates.into_iter()
.enumerate()
.find(|(other_idx, (pred, _))| match pred.kind().skip_binder() {
@@ -2024,10 +2072,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
== self.tcx.anonymize_bound_vars(
pred.kind().rebind(trait_pred.self_ty()),
)
- // But the substs don't match (i.e. incompatible args)
- && expected_substs
+ // But the args don't match (i.e. incompatible args)
+ && expected_args
!= self.tcx.anonymize_bound_vars(
- pred.kind().rebind(trait_pred.trait_ref.substs),
+ pred.kind().rebind(trait_pred.trait_ref.args),
) =>
{
true
@@ -2222,7 +2270,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// Only continue if a generator was found.
debug!(?generator, ?trait_ref, ?target_ty);
- let (Some(generator_did), Some(trait_ref), Some(target_ty)) = (generator, trait_ref, target_ty) else {
+ let (Some(generator_did), Some(trait_ref), Some(target_ty)) =
+ (generator, trait_ref, target_ty)
+ else {
return false;
};
@@ -2403,8 +2453,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
err.clear_code();
err.set_primary_message(format!(
- "{} cannot be {} between threads safely",
- future_or_generator, trait_verb
+ "{future_or_generator} cannot be {trait_verb} between threads safely"
));
let original_span = err.span.primary_span().unwrap();
@@ -2413,7 +2462,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let message = outer_generator
.and_then(|generator_did| {
Some(match self.tcx.generator_kind(generator_did).unwrap() {
- GeneratorKind::Gen => format!("generator is not {}", trait_name),
+ GeneratorKind::Gen => format!("generator is not {trait_name}"),
GeneratorKind::Async(AsyncGeneratorKind::Fn) => self
.tcx
.parent(generator_did)
@@ -2421,73 +2470,73 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
.map(|parent_did| hir.local_def_id_to_hir_id(parent_did))
.and_then(|parent_hir_id| hir.opt_name(parent_hir_id))
.map(|name| {
- format!("future returned by `{}` is not {}", name, trait_name)
+ format!("future returned by `{name}` is not {trait_name}")
})?,
GeneratorKind::Async(AsyncGeneratorKind::Block) => {
- format!("future created by async block is not {}", trait_name)
+ format!("future created by async block is not {trait_name}")
}
GeneratorKind::Async(AsyncGeneratorKind::Closure) => {
- format!("future created by async closure is not {}", trait_name)
+ format!("future created by async closure is not {trait_name}")
}
})
})
- .unwrap_or_else(|| format!("{} is not {}", future_or_generator, trait_name));
+ .unwrap_or_else(|| format!("{future_or_generator} is not {trait_name}"));
span.push_span_label(original_span, message);
err.set_span(span);
- format!("is not {}", trait_name)
+ format!("is not {trait_name}")
} else {
format!("does not implement `{}`", trait_pred.print_modifiers_and_trait_path())
};
- let mut explain_yield =
- |interior_span: Span, yield_span: Span, scope_span: Option<Span>| {
- let mut span = MultiSpan::from_span(yield_span);
- let snippet = match source_map.span_to_snippet(interior_span) {
- // #70935: If snippet contains newlines, display "the value" instead
- // so that we do not emit complex diagnostics.
- Ok(snippet) if !snippet.contains('\n') => format!("`{}`", snippet),
- _ => "the value".to_string(),
- };
- // note: future is not `Send` as this value is used across an await
- // --> $DIR/issue-70935-complex-spans.rs:13:9
- // |
- // LL | baz(|| async {
- // | ______________-
- // | |
- // | |
- // LL | | foo(tx.clone());
- // LL | | }).await;
- // | | - ^^^^^^ await occurs here, with value maybe used later
- // | |__________|
- // | has type `closure` which is not `Send`
- // note: value is later dropped here
- // LL | | }).await;
- // | | ^
- //
- span.push_span_label(
- yield_span,
- format!("{} occurs here, with {} maybe used later", await_or_yield, snippet),
- );
- span.push_span_label(
- interior_span,
- format!("has type `{}` which {}", target_ty, trait_explanation),
- );
- if let Some(scope_span) = scope_span {
- let scope_span = source_map.end_point(scope_span);
+ let mut explain_yield = |interior_span: Span,
+ yield_span: Span,
+ scope_span: Option<Span>| {
+ let mut span = MultiSpan::from_span(yield_span);
+ let snippet = match source_map.span_to_snippet(interior_span) {
+ // #70935: If snippet contains newlines, display "the value" instead
+ // so that we do not emit complex diagnostics.
+ Ok(snippet) if !snippet.contains('\n') => format!("`{snippet}`"),
+ _ => "the value".to_string(),
+ };
+ // note: future is not `Send` as this value is used across an await
+ // --> $DIR/issue-70935-complex-spans.rs:13:9
+ // |
+ // LL | baz(|| async {
+ // | ______________-
+ // | |
+ // | |
+ // LL | | foo(tx.clone());
+ // LL | | }).await;
+ // | | - ^^^^^^ await occurs here, with value maybe used later
+ // | |__________|
+ // | has type `closure` which is not `Send`
+ // note: value is later dropped here
+ // LL | | }).await;
+ // | | ^
+ //
+ span.push_span_label(
+ yield_span,
+ format!("{await_or_yield} occurs here, with {snippet} maybe used later"),
+ );
+ span.push_span_label(
+ interior_span,
+ format!("has type `{target_ty}` which {trait_explanation}"),
+ );
+ if let Some(scope_span) = scope_span {
+ let scope_span = source_map.end_point(scope_span);
- let msg = format!("{} is later dropped here", snippet);
- span.push_span_label(scope_span, msg);
- }
- err.span_note(
+ let msg = format!("{snippet} is later dropped here");
+ span.push_span_label(scope_span, msg);
+ }
+ err.span_note(
span,
format!(
- "{} {} as this value is used across {}",
- future_or_generator, trait_explanation, an_await_or_yield
+ "{future_or_generator} {trait_explanation} as this value is used across {an_await_or_yield}"
),
);
- };
+ };
match interior_or_upvar_span {
GeneratorInteriorOrUpvar::Interior(interior_span, interior_extra_info) => {
if let Some((scope_span, yield_span, expr, from_awaited_ty)) = interior_extra_info {
@@ -2497,15 +2546,13 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
span.push_span_label(
await_span,
format!(
- "await occurs here on type `{}`, which {}",
- target_ty, trait_explanation
+ "await occurs here on type `{target_ty}`, which {trait_explanation}"
),
);
err.span_note(
span,
format!(
- "future {not_trait} as it awaits another future which {not_trait}",
- not_trait = trait_explanation
+ "future {trait_explanation} as it awaits another future which {trait_explanation}"
),
);
} else {
@@ -2588,18 +2635,16 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let ref_kind = if is_mut { "&mut" } else { "&" };
(
format!(
- "has type `{}` which {}, because `{}` is not `{}`",
- target_ty, trait_explanation, ref_ty, ref_ty_trait
+ "has type `{target_ty}` which {trait_explanation}, because `{ref_ty}` is not `{ref_ty_trait}`"
),
format!(
- "captured value {} because `{}` references cannot be sent unless their referent is `{}`",
- trait_explanation, ref_kind, ref_ty_trait
+ "captured value {trait_explanation} because `{ref_kind}` references cannot be sent unless their referent is `{ref_ty_trait}`"
),
)
}
None => (
- format!("has type `{}` which {}", target_ty, trait_explanation),
- format!("captured value {}", trait_explanation),
+ format!("has type `{target_ty}` which {trait_explanation}"),
+ format!("captured value {trait_explanation}"),
),
};
@@ -2655,7 +2700,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
| ObligationCauseCode::MatchImpl(..)
| ObligationCauseCode::ReturnType
| ObligationCauseCode::ReturnValue(_)
- | ObligationCauseCode::BlockTailExpression(_)
+ | ObligationCauseCode::BlockTailExpression(..)
| ObligationCauseCode::AwaitableExpr(_)
| ObligationCauseCode::ForLoopIterator
| ObligationCauseCode::QuestionMark
@@ -2688,8 +2733,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
ObligationCauseCode::ObjectTypeBound(object_ty, region) => {
err.note(format!(
- "required so that the lifetime bound of `{}` for `{}` is satisfied",
- region, object_ty,
+ "required so that the lifetime bound of `{region}` for `{object_ty}` is satisfied",
));
}
ObligationCauseCode::ItemObligation(_)
@@ -2743,7 +2787,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// implement this trait and list them.
err.note(format!(
"`{short_item_name}` is a \"sealed trait\", because to implement \
- it you also need to implelement `{}`, which is not accessible; \
+ it you also need to implement `{}`, which is not accessible; \
this is usually done to force you to use one of the provided \
types that already implement it",
with_no_trimmed_paths!(tcx.def_path_str(def_id)),
@@ -2808,7 +2852,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
err.note("all local variables must have a statically known size");
}
Some(Node::Local(hir::Local {
- init: Some(hir::Expr { kind: hir::ExprKind::Index(_, _), span, .. }),
+ init: Some(hir::Expr { kind: hir::ExprKind::Index(..), span, .. }),
..
})) => {
// When encountering an assignment of an unsized trait, like
@@ -3009,11 +3053,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let mut msg =
"required because it captures the following types: ".to_owned();
for ty in bound_tys.skip_binder() {
- with_forced_trimmed_paths!(write!(msg, "`{}`, ", ty).unwrap());
+ with_forced_trimmed_paths!(write!(msg, "`{ty}`, ").unwrap());
}
err.note(msg.trim_end_matches(", ").to_string())
}
- ty::GeneratorWitnessMIR(def_id, substs) => {
+ ty::GeneratorWitnessMIR(def_id, args) => {
use std::fmt::Write;
// FIXME: this is kind of an unusual format for rustc, can we make it more clear?
@@ -3022,8 +3066,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let mut msg =
"required because it captures the following types: ".to_owned();
for bty in tcx.generator_hidden_types(*def_id) {
- let ty = bty.subst(tcx, substs);
- write!(msg, "`{}`, ", ty).unwrap();
+ let ty = bty.instantiate(tcx, args);
+ write!(msg, "`{ty}`, ").unwrap();
}
err.note(msg.trim_end_matches(", ").to_string())
}
@@ -3082,7 +3126,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
ObligationCauseCode::ImplDerivedObligation(ref data) => {
let mut parent_trait_pred =
self.resolve_vars_if_possible(data.derived.parent_trait_pred);
- parent_trait_pred.remap_constness_diag(param_env);
let parent_def_id = parent_trait_pred.def_id();
let (self_ty, file) =
self.tcx.short_ty_string(parent_trait_pred.skip_binder().self_ty());
@@ -3350,7 +3393,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
Ty::new_projection(
self.tcx,
item_def_id,
- // Future::Output has no substs
+ // Future::Output has no args
[trait_pred.self_ty()],
)
});
@@ -3391,7 +3434,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
_ => return,
};
if let ty::Float(_) = trait_ref.skip_binder().self_ty().kind()
- && let ty::Infer(InferTy::IntVar(_)) = trait_ref.skip_binder().substs.type_at(1).kind()
+ && let ty::Infer(InferTy::IntVar(_)) = trait_ref.skip_binder().args.type_at(1).kind()
{
err.span_suggestion_verbose(
rhs_span.shrink_to_hi(),
@@ -3411,15 +3454,15 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) else {
return;
};
- let (adt, substs) = match trait_pred.skip_binder().self_ty().kind() {
- ty::Adt(adt, substs) if adt.did().is_local() => (adt, substs),
+ let (adt, args) = match trait_pred.skip_binder().self_ty().kind() {
+ ty::Adt(adt, args) if adt.did().is_local() => (adt, args),
_ => return,
};
let can_derive = {
let is_derivable_trait = match diagnostic_name {
sym::Default => !adt.is_enum(),
sym::PartialEq | sym::PartialOrd => {
- let rhs_ty = trait_pred.skip_binder().trait_ref.substs.type_at(1);
+ let rhs_ty = trait_pred.skip_binder().trait_ref.args.type_at(1);
trait_pred.skip_binder().self_ty() == rhs_ty
}
sym::Eq | sym::Ord | sym::Clone | sym::Copy | sym::Hash | sym::Debug => true,
@@ -3428,8 +3471,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
is_derivable_trait &&
// Ensure all fields impl the trait.
adt.all_fields().all(|field| {
- let field_ty = field.ty(self.tcx, substs);
- let trait_substs = match diagnostic_name {
+ let field_ty = field.ty(self.tcx, args);
+ let trait_args = match diagnostic_name {
sym::PartialEq | sym::PartialOrd => {
Some(field_ty)
}
@@ -3438,7 +3481,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let trait_pred = trait_pred.map_bound_ref(|tr| ty::TraitPredicate {
trait_ref: ty::TraitRef::new(self.tcx,
trait_pred.def_id(),
- [field_ty].into_iter().chain(trait_substs),
+ [field_ty].into_iter().chain(trait_args),
),
..*tr
});
@@ -3459,7 +3502,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
trait_pred.skip_binder().self_ty(),
diagnostic_name,
),
- format!("#[derive({})]\n", diagnostic_name),
+ format!("#[derive({diagnostic_name})]\n"),
Applicability::MaybeIncorrect,
);
}
@@ -3473,7 +3516,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
) {
if let ObligationCauseCode::ImplDerivedObligation(_) = obligation.cause.code()
&& self.tcx.is_diagnostic_item(sym::SliceIndex, trait_pred.skip_binder().trait_ref.def_id)
- && let ty::Slice(_) = trait_pred.skip_binder().trait_ref.substs.type_at(1).kind()
+ && let ty::Slice(_) = trait_pred.skip_binder().trait_ref.args.type_at(1).kind()
&& let ty::Ref(_, inner_ty, _) = trait_pred.skip_binder().self_ty().kind()
&& let ty::Uint(ty::UintTy::Usize) = inner_ty.kind()
{
@@ -3522,9 +3565,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// to an associated type (as seen from `trait_pred`) in the predicate. Like in
// trait_pred `S: Sum<<Self as Iterator>::Item>` and predicate `i32: Sum<&()>`
let mut type_diffs = vec![];
- if let ObligationCauseCode::ExprBindingObligation(def_id, _, _, idx) = parent_code.deref()
- && let Some(node_substs) = typeck_results.node_substs_opt(call_hir_id)
- && let where_clauses = self.tcx.predicates_of(def_id).instantiate(self.tcx, node_substs)
+ if let ObligationCauseCode::ExprBindingObligation(def_id, _, _, idx) = parent_code
+ && let Some(node_args) = typeck_results.node_args_opt(call_hir_id)
+ && let where_clauses = self.tcx.predicates_of(def_id).instantiate(self.tcx, node_args)
&& let Some(where_pred) = where_clauses.predicates.get(*idx)
{
if let Some(where_pred) = where_pred.as_trait_clause()
@@ -3538,7 +3581,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
);
let zipped =
- iter::zip(where_pred.trait_ref.substs, failed_pred.trait_ref.substs);
+ iter::zip(where_pred.trait_ref.args, failed_pred.trait_ref.args);
for (expected, actual) in zipped {
self.probe(|_| {
match self
@@ -3617,7 +3660,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let Some(typeck_results) = self.typeck_results.as_ref() else { return };
// Make sure we're dealing with the `Option` type.
- let Some(option_ty_adt) = typeck_results.expr_ty_adjusted(expr).ty_adt_def() else { return };
+ let Some(option_ty_adt) = typeck_results.expr_ty_adjusted(expr).ty_adt_def() else {
+ return;
+ };
if !tcx.is_diagnostic_item(sym::Option, option_ty_adt.did()) {
return;
}
@@ -3627,7 +3672,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, .. }))
= failed_pred.kind().skip_binder()
&& tcx.is_fn_trait(trait_ref.def_id)
- && let [self_ty, found_ty] = trait_ref.substs.as_slice()
+ && let [self_ty, found_ty] = trait_ref.args.as_slice()
&& let Some(fn_ty) = self_ty.as_type().filter(|ty| ty.is_fn())
&& let fn_sig @ ty::FnSig {
abi: abi::Abi::Rust,
@@ -3647,7 +3692,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// Extract `<U as Deref>::Target` assoc type and check that it is `T`
&& let Some(deref_target_did) = tcx.lang_items().deref_target()
- && let projection = Ty::new_projection(tcx,deref_target_did, tcx.mk_substs(&[ty::GenericArg::from(found_ty)]))
+ && let projection = Ty::new_projection(tcx,deref_target_did, tcx.mk_args(&[ty::GenericArg::from(found_ty)]))
&& let InferOk { value: deref_target, obligations } = infcx.at(&ObligationCause::dummy(), param_env).normalize(projection)
&& obligations.iter().all(|obligation| infcx.predicate_must_hold_modulo_regions(obligation))
&& infcx.can_eq(param_env, deref_target, target_ty)
@@ -3749,11 +3794,17 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
while let Some(assocs_in_method) = assocs.next() {
let Some(prev_assoc_in_method) = assocs.peek() else {
for entry in assocs_in_method {
- let Some((span, (assoc, ty))) = entry else { continue; };
- if primary_spans.is_empty() || type_diffs.iter().any(|diff| {
- let Sorts(expected_found) = diff else { return false; };
- self.can_eq(param_env, expected_found.found, ty)
- }) {
+ let Some((span, (assoc, ty))) = entry else {
+ continue;
+ };
+ if primary_spans.is_empty()
+ || type_diffs.iter().any(|diff| {
+ let Sorts(expected_found) = diff else {
+ return false;
+ };
+ self.can_eq(param_env, expected_found.found, ty)
+ })
+ {
// FIXME: this doesn't quite work for `Iterator::collect`
// because we have `Vec<i32>` and `()`, but we'd want `i32`
// to point at the `.into_iter()` call, but as long as we
@@ -3781,7 +3832,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let assoc = with_forced_trimmed_paths!(self.tcx.def_path_str(assoc));
if !self.can_eq(param_env, ty, *prev_ty) {
if type_diffs.iter().any(|diff| {
- let Sorts(expected_found) = diff else { return false; };
+ let Sorts(expected_found) = diff else {
+ return false;
+ };
self.can_eq(param_env, expected_found.found, ty)
}) {
primary_spans.push(span);
@@ -3829,15 +3882,19 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let ocx = ObligationCtxt::new(self.infcx);
let mut assocs_in_this_method = Vec::with_capacity(type_diffs.len());
for diff in type_diffs {
- let Sorts(expected_found) = diff else { continue; };
- let ty::Alias(ty::Projection, proj) = expected_found.expected.kind() else { continue; };
+ let Sorts(expected_found) = diff else {
+ continue;
+ };
+ let ty::Alias(ty::Projection, proj) = expected_found.expected.kind() else {
+ continue;
+ };
let origin = TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span };
let trait_def_id = proj.trait_def_id(self.tcx);
// Make `Self` be equivalent to the type of the call chain
// expression we're looking at now, so that we can tell what
// for example `Iterator::Item` is at this point in the chain.
- let substs = InternalSubsts::for_item(self.tcx, trait_def_id, |param, _| {
+ let args = GenericArgs::for_item(self.tcx, trait_def_id, |param, _| {
match param.kind {
ty::GenericParamDefKind::Type { .. } => {
if param.index == 0 {
@@ -3855,7 +3912,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// This corresponds to `<ExprTy as Iterator>::Item = _`.
let projection = ty::Binder::dummy(ty::PredicateKind::Clause(
ty::ClauseKind::Projection(ty::ProjectionPredicate {
- projection_ty: self.tcx.mk_alias_ty(proj.def_id, substs),
+ projection_ty: self.tcx.mk_alias_ty(proj.def_id, args),
term: ty_var.into(),
}),
));
@@ -3886,13 +3943,22 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
/// If the type that failed selection is an array or a reference to an array,
/// but the trait is implemented for slices, suggest that the user converts
/// the array into a slice.
- fn maybe_suggest_convert_to_slice(
+ fn suggest_convert_to_slice(
&self,
err: &mut Diagnostic,
+ obligation: &PredicateObligation<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>,
candidate_impls: &[ImplCandidate<'tcx>],
span: Span,
) {
+ // We can only suggest the slice coersion for function and binary operation arguments,
+ // since the suggestion would make no sense in turbofish or call
+ let (ObligationCauseCode::BinOp { .. }
+ | ObligationCauseCode::FunctionArgumentObligation { .. }) = obligation.cause.code()
+ else {
+ return;
+ };
+
// Three cases where we can make a suggestion:
// 1. `[T; _]` (array of T)
// 2. `&[T; _]` (reference to array of T)
@@ -3931,7 +3997,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
.map(|trait_ref| trait_ref.trait_ref.self_ty())
.find(|t| is_slice(*t))
{
- let msg = format!("convert the array to a `{}` slice instead", slice_ty);
+ let msg = format!("convert the array to a `{slice_ty}` slice instead");
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
let mut suggestions = vec![];
@@ -3960,6 +4026,10 @@ fn hint_missing_borrow<'tcx>(
found_node: Node<'_>,
err: &mut Diagnostic,
) {
+ if matches!(found_node, Node::TraitItem(..)) {
+ return;
+ }
+
let found_args = match found.kind() {
ty::FnPtr(f) => infcx.instantiate_binder_with_placeholders(*f).inputs().iter(),
kind => {
@@ -3974,7 +4044,9 @@ fn hint_missing_borrow<'tcx>(
};
// This could be a variant constructor, for example.
- let Some(fn_decl) = found_node.fn_decl() else { return; };
+ let Some(fn_decl) = found_node.fn_decl() else {
+ return;
+ };
let args = fn_decl.inputs.iter();
@@ -4029,19 +4101,11 @@ fn hint_missing_borrow<'tcx>(
}
if !to_borrow.is_empty() {
- err.multipart_suggestion_verbose(
- "consider borrowing the argument",
- to_borrow,
- Applicability::MaybeIncorrect,
- );
+ err.subdiagnostic(errors::AdjustSignatureBorrow::Borrow { to_borrow });
}
if !remove_borrow.is_empty() {
- err.multipart_suggestion_verbose(
- "do not borrow the argument",
- remove_borrow,
- Applicability::MaybeIncorrect,
- );
+ err.subdiagnostic(errors::AdjustSignatureBorrow::RemoveBorrow { remove_borrow });
}
}
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index cf9d9315f..3ebf1246a 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -8,7 +8,7 @@ use rustc_infer::traits::{PolyTraitObligation, SelectionError, TraitEngine};
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
-use rustc_middle::ty::subst::SubstsRef;
+use rustc_middle::ty::GenericArgsRef;
use rustc_middle::ty::{self, Binder, Const, TypeVisitableExt};
use std::marker::PhantomData;
@@ -410,8 +410,8 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
}
}
- ty::PredicateKind::ClosureKind(_, closure_substs, kind) => {
- match self.selcx.infcx.closure_kind(closure_substs) {
+ ty::PredicateKind::ClosureKind(_, closure_args, kind) => {
+ match self.selcx.infcx.closure_kind(closure_args) {
Some(closure_kind) => {
if closure_kind.extends(kind) {
ProcessResult::Changed(vec![])
@@ -536,7 +536,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
if let Ok(new_obligations) = infcx
.at(&obligation.cause, obligation.param_env)
.trace(c1, c2)
- .eq(DefineOpaqueTypes::No, a.substs, b.substs)
+ .eq(DefineOpaqueTypes::No, a.args, b.args)
{
return ProcessResult::Changed(mk_pending(
new_obligations.into_obligations(),
@@ -559,31 +559,30 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
let stalled_on = &mut pending_obligation.stalled_on;
- let mut evaluate = |c: Const<'tcx>| {
- if let ty::ConstKind::Unevaluated(unevaluated) = c.kind() {
- match self.selcx.infcx.try_const_eval_resolve(
- obligation.param_env,
- unevaluated,
- c.ty(),
- Some(obligation.cause.span),
- ) {
- Ok(val) => Ok(val),
- Err(e) => match e {
- ErrorHandled::TooGeneric => {
- stalled_on.extend(
- unevaluated.substs.iter().filter_map(
+ let mut evaluate =
+ |c: Const<'tcx>| {
+ if let ty::ConstKind::Unevaluated(unevaluated) = c.kind() {
+ match self.selcx.infcx.try_const_eval_resolve(
+ obligation.param_env,
+ unevaluated,
+ c.ty(),
+ Some(obligation.cause.span),
+ ) {
+ Ok(val) => Ok(val),
+ Err(e) => match e {
+ ErrorHandled::TooGeneric => {
+ stalled_on.extend(unevaluated.args.iter().filter_map(
TyOrConstInferVar::maybe_from_generic_arg,
- ),
- );
- Err(ErrorHandled::TooGeneric)
- }
- _ => Err(e),
- },
+ ));
+ Err(ErrorHandled::TooGeneric)
+ }
+ _ => Err(e),
+ },
+ }
+ } else {
+ Ok(c)
}
- } else {
- Ok(c)
- }
- };
+ };
match (evaluate(c1), evaluate(c2)) {
(Ok(c1), Ok(c2)) => {
@@ -671,7 +670,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
stalled_on: &mut Vec<TyOrConstInferVar<'tcx>>,
) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
let infcx = self.selcx.infcx;
- if obligation.predicate.is_global() {
+ if obligation.predicate.is_global() && !self.selcx.is_intercrate() {
// no type variables present, can use evaluation for better caching.
// FIXME: consider caching errors too.
if infcx.predicate_must_hold_considering_regions(obligation) {
@@ -696,9 +695,9 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
// trait selection is because we don't have enough
// information about the types in the trait.
stalled_on.clear();
- stalled_on.extend(substs_infer_vars(
+ stalled_on.extend(args_infer_vars(
&self.selcx,
- trait_obligation.predicate.map_bound(|pred| pred.trait_ref.substs),
+ trait_obligation.predicate.map_bound(|pred| pred.trait_ref.args),
));
debug!(
@@ -725,7 +724,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
let tcx = self.selcx.tcx();
- if obligation.predicate.is_global() {
+ if obligation.predicate.is_global() && !self.selcx.is_intercrate() {
// no type variables present, can use evaluation for better caching.
// FIXME: consider caching errors too.
if self.selcx.infcx.predicate_must_hold_considering_regions(obligation) {
@@ -753,9 +752,9 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
ProjectAndUnifyResult::Holds(os) => ProcessResult::Changed(mk_pending(os)),
ProjectAndUnifyResult::FailedNormalization => {
stalled_on.clear();
- stalled_on.extend(substs_infer_vars(
+ stalled_on.extend(args_infer_vars(
&self.selcx,
- project_obligation.predicate.map_bound(|pred| pred.projection_ty.substs),
+ project_obligation.predicate.map_bound(|pred| pred.projection_ty.args),
));
ProcessResult::Unchanged
}
@@ -770,14 +769,14 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
}
}
-/// Returns the set of inference variables contained in `substs`.
-fn substs_infer_vars<'a, 'tcx>(
+/// Returns the set of inference variables contained in `args`.
+fn args_infer_vars<'a, 'tcx>(
selcx: &SelectionContext<'a, 'tcx>,
- substs: ty::Binder<'tcx, SubstsRef<'tcx>>,
+ args: ty::Binder<'tcx, GenericArgsRef<'tcx>>,
) -> impl Iterator<Item = TyOrConstInferVar<'tcx>> {
selcx
.infcx
- .resolve_vars_if_possible(substs)
+ .resolve_vars_if_possible(args)
.skip_binder() // ok because this check doesn't care about regions
.iter()
.filter(|arg| arg.has_non_region_infer())
diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs
index e9cfd63e2..ab07b10c6 100644
--- a/compiler/rustc_trait_selection/src/traits/misc.rs
+++ b/compiler/rustc_trait_selection/src/traits/misc.rs
@@ -43,7 +43,7 @@ pub fn type_allowed_to_implement_copy<'tcx>(
self_type: Ty<'tcx>,
parent_cause: ObligationCause<'tcx>,
) -> Result<(), CopyImplementationError<'tcx>> {
- let (adt, substs) = match self_type.kind() {
+ let (adt, args) = match self_type.kind() {
// These types used to have a builtin impl.
// Now libcore provides that impl.
ty::Uint(_)
@@ -56,7 +56,7 @@ pub fn type_allowed_to_implement_copy<'tcx>(
| ty::Ref(_, _, hir::Mutability::Not)
| ty::Array(..) => return Ok(()),
- &ty::Adt(adt, substs) => (adt, substs),
+ &ty::Adt(adt, args) => (adt, args),
_ => return Err(CopyImplementationError::NotAnAdt),
};
@@ -66,7 +66,7 @@ pub fn type_allowed_to_implement_copy<'tcx>(
param_env,
self_type,
adt,
- substs,
+ args,
parent_cause,
hir::LangItem::Copy,
)
@@ -91,7 +91,7 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
self_type: Ty<'tcx>,
parent_cause: ObligationCause<'tcx>,
) -> Result<(), ConstParamTyImplementationError<'tcx>> {
- let (adt, substs) = match self_type.kind() {
+ let (adt, args) = match self_type.kind() {
// `core` provides these impls.
ty::Uint(_)
| ty::Int(_)
@@ -103,7 +103,7 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
| ty::Ref(.., hir::Mutability::Not)
| ty::Tuple(_) => return Ok(()),
- &ty::Adt(adt, substs) => (adt, substs),
+ &ty::Adt(adt, args) => (adt, args),
_ => return Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed),
};
@@ -113,7 +113,7 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
param_env,
self_type,
adt,
- substs,
+ args,
parent_cause,
hir::LangItem::ConstParamTy,
)
@@ -128,7 +128,7 @@ pub fn all_fields_implement_trait<'tcx>(
param_env: ty::ParamEnv<'tcx>,
self_type: Ty<'tcx>,
adt: AdtDef<'tcx>,
- substs: &'tcx List<GenericArg<'tcx>>,
+ args: &'tcx List<GenericArg<'tcx>>,
parent_cause: ObligationCause<'tcx>,
lang_item: LangItem,
) -> Result<(), Vec<(&'tcx ty::FieldDef, Ty<'tcx>, InfringingFieldsReason<'tcx>)>> {
@@ -141,7 +141,7 @@ pub fn all_fields_implement_trait<'tcx>(
let infcx = tcx.infer_ctxt().build();
let ocx = traits::ObligationCtxt::new(&infcx);
- let unnormalized_ty = field.ty(tcx, substs);
+ let unnormalized_ty = field.ty(tcx, args);
if unnormalized_ty.references_error() {
continue;
}
@@ -154,11 +154,11 @@ pub fn all_fields_implement_trait<'tcx>(
// FIXME(compiler-errors): This gives us better spans for bad
// projection types like in issue-50480.
- // If the ADT has substs, point to the cause we are given.
+ // If the ADT has args, point to the cause we are given.
// If it does not, then this field probably doesn't normalize
// to begin with, and point to the bad field's span instead.
let normalization_cause = if field
- .ty(tcx, traits::InternalSubsts::identity_for_item(tcx, adt.did()))
+ .ty(tcx, traits::GenericArgs::identity_for_item(tcx, adt.did()))
.has_non_region_param()
{
parent_cause.clone()
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 1af8323b6..d2210c6d5 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -13,12 +13,12 @@ mod object_safety;
pub mod outlives_bounds;
pub mod project;
pub mod query;
-#[cfg_attr(not(bootstrap), allow(hidden_glob_reexports))]
+#[allow(hidden_glob_reexports)]
mod select;
mod specialize;
mod structural_match;
mod structural_normalize;
-#[cfg_attr(not(bootstrap), allow(hidden_glob_reexports))]
+#[allow(hidden_glob_reexports)]
mod util;
pub mod vtable;
pub mod wf;
@@ -32,7 +32,7 @@ use rustc_middle::query::Providers;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFolder, TypeSuperVisitable};
-use rustc_middle::ty::{InternalSubsts, SubstsRef};
+use rustc_middle::ty::{GenericArgs, GenericArgsRef};
use rustc_span::def_id::DefId;
use rustc_span::Span;
@@ -61,13 +61,13 @@ pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError
pub use self::specialize::specialization_graph::FutureCompatOverlapError;
pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind;
pub use self::specialize::{
- specialization_graph, translate_substs, translate_substs_with_cause, OverlapError,
+ specialization_graph, translate_args, translate_args_with_cause, OverlapError,
};
pub use self::structural_match::search_for_structural_match_violation;
pub use self::structural_normalize::StructurallyNormalizeExt;
pub use self::util::elaborate;
pub use self::util::{
- check_substs_compatible, supertrait_def_ids, supertraits, transitive_bounds,
+ check_args_compatible, supertrait_def_ids, supertraits, transitive_bounds,
transitive_bounds_that_define_assoc_item, SupertraitDefIds,
};
pub use self::util::{expand_trait_aliases, TraitAliasExpander};
@@ -133,7 +133,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'tcx>(
def_id: DefId,
) -> bool {
let trait_ref = ty::TraitRef::new(infcx.tcx, def_id, [ty]);
- pred_known_to_hold_modulo_regions(infcx, param_env, trait_ref.without_const())
+ pred_known_to_hold_modulo_regions(infcx, param_env, trait_ref)
}
/// FIXME(@lcnr): this function doesn't seem right and shouldn't exist?
@@ -328,11 +328,7 @@ pub fn normalize_param_env_or_error<'tcx>(
debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates);
- let elaborated_env = ty::ParamEnv::new(
- tcx.mk_clauses(&predicates),
- unnormalized_env.reveal(),
- unnormalized_env.constness(),
- );
+ let elaborated_env = ty::ParamEnv::new(tcx.mk_clauses(&predicates), unnormalized_env.reveal());
// HACK: we are trying to normalize the param-env inside *itself*. The problem is that
// normalization expects its param-env to be already normalized, which means we have
@@ -362,12 +358,9 @@ pub fn normalize_param_env_or_error<'tcx>(
"normalize_param_env_or_error: predicates=(non-outlives={:?}, outlives={:?})",
predicates, outlives_predicates
);
- let Ok(non_outlives_predicates) = do_normalize_predicates(
- tcx,
- cause.clone(),
- elaborated_env,
- predicates,
- ) else {
+ let Ok(non_outlives_predicates) =
+ do_normalize_predicates(tcx, cause.clone(), elaborated_env, predicates)
+ else {
// An unnormalized env is better than nothing.
debug!("normalize_param_env_or_error: errored resolving non-outlives predicates");
return elaborated_env;
@@ -379,17 +372,11 @@ pub fn normalize_param_env_or_error<'tcx>(
// here. I believe they should not matter, because we are ignoring TypeOutlives param-env
// predicates here anyway. Keeping them here anyway because it seems safer.
let outlives_env = non_outlives_predicates.iter().chain(&outlives_predicates).cloned();
- let outlives_env = ty::ParamEnv::new(
- tcx.mk_clauses_from_iter(outlives_env),
- unnormalized_env.reveal(),
- unnormalized_env.constness(),
- );
- let Ok(outlives_predicates) = do_normalize_predicates(
- tcx,
- cause,
- outlives_env,
- outlives_predicates,
- ) else {
+ let outlives_env =
+ ty::ParamEnv::new(tcx.mk_clauses_from_iter(outlives_env), unnormalized_env.reveal());
+ let Ok(outlives_predicates) =
+ do_normalize_predicates(tcx, cause, outlives_env, outlives_predicates)
+ else {
// An unnormalized env is better than nothing.
debug!("normalize_param_env_or_error: errored resolving outlives predicates");
return elaborated_env;
@@ -399,11 +386,7 @@ pub fn normalize_param_env_or_error<'tcx>(
let mut predicates = non_outlives_predicates;
predicates.extend(outlives_predicates);
debug!("normalize_param_env_or_error: final predicates={:?}", predicates);
- ty::ParamEnv::new(
- tcx.mk_clauses(&predicates),
- unnormalized_env.reveal(),
- unnormalized_env.constness(),
- )
+ ty::ParamEnv::new(tcx.mk_clauses(&predicates), unnormalized_env.reveal())
}
/// Normalize a type and process all resulting obligations, returning any errors.
@@ -460,7 +443,7 @@ pub fn impossible_predicates<'tcx>(tcx: TyCtxt<'tcx>, predicates: Vec<ty::Clause
fn subst_and_check_impossible_predicates<'tcx>(
tcx: TyCtxt<'tcx>,
- key: (DefId, SubstsRef<'tcx>),
+ key: (DefId, GenericArgsRef<'tcx>),
) -> bool {
debug!("subst_and_check_impossible_predicates(key={:?})", key);
@@ -480,11 +463,14 @@ fn subst_and_check_impossible_predicates<'tcx>(
result
}
-/// Checks whether a trait's method is impossible to call on a given impl.
+/// Checks whether a trait's associated item is impossible to reference on a given impl.
///
/// This only considers predicates that reference the impl's generics, and not
/// those that reference the method's generics.
-fn is_impossible_method(tcx: TyCtxt<'_>, (impl_def_id, trait_item_def_id): (DefId, DefId)) -> bool {
+fn is_impossible_associated_item(
+ tcx: TyCtxt<'_>,
+ (impl_def_id, trait_item_def_id): (DefId, DefId),
+) -> bool {
struct ReferencesOnlyParentGenerics<'tcx> {
tcx: TyCtxt<'tcx>,
generics: &'tcx ty::Generics,
@@ -527,7 +513,7 @@ fn is_impossible_method(tcx: TyCtxt<'_>, (impl_def_id, trait_item_def_id): (DefI
let impl_trait_ref = tcx
.impl_trait_ref(impl_def_id)
.expect("expected impl to correspond to trait")
- .subst_identity();
+ .instantiate_identity();
let param_env = tcx.param_env(impl_def_id);
let mut visitor = ReferencesOnlyParentGenerics { tcx, generics, trait_item_def_id };
@@ -537,7 +523,7 @@ fn is_impossible_method(tcx: TyCtxt<'_>, (impl_def_id, trait_item_def_id): (DefI
tcx,
ObligationCause::dummy_with_span(*span),
param_env,
- ty::EarlyBinder::bind(*pred).subst(tcx, impl_trait_ref.substs),
+ ty::EarlyBinder::bind(*pred).instantiate(tcx, impl_trait_ref.args),
)
})
});
@@ -562,7 +548,7 @@ pub fn provide(providers: &mut Providers) {
specializes: specialize::specializes,
subst_and_check_impossible_predicates,
check_tys_might_be_eq: misc::check_tys_might_be_eq,
- is_impossible_method,
+ is_impossible_associated_item,
..*providers
};
}
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index c31944c16..5823b4508 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -17,10 +17,10 @@ use rustc_errors::{DelayDm, FatalError, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_middle::query::Providers;
-use rustc_middle::ty::subst::{GenericArg, InternalSubsts};
use rustc_middle::ty::{
self, EarlyBinder, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
};
+use rustc_middle::ty::{GenericArg, GenericArgs};
use rustc_middle::ty::{ToPredicate, TypeVisitableExt};
use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY;
use rustc_span::symbol::Symbol;
@@ -270,7 +270,7 @@ fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span
tcx.associated_items(trait_def_id)
.in_definition_order()
.filter(|item| item.kind == ty::AssocKind::Type)
- .flat_map(|item| tcx.explicit_item_bounds(item.def_id).subst_identity_iter_copied())
+ .flat_map(|item| tcx.explicit_item_bounds(item.def_id).instantiate_identity_iter_copied())
.filter_map(|c| predicate_references_self(tcx, c))
.collect()
}
@@ -284,7 +284,7 @@ fn predicate_references_self<'tcx>(
match predicate.kind().skip_binder() {
ty::ClauseKind::Trait(ref data) => {
// In the case of a trait predicate, we can skip the "self" type.
- data.trait_ref.substs[1..].iter().any(has_self_ty).then_some(sp)
+ data.trait_ref.args[1..].iter().any(has_self_ty).then_some(sp)
}
ty::ClauseKind::Projection(ref data) => {
// And similarly for projections. This should be redundant with
@@ -302,7 +302,7 @@ fn predicate_references_self<'tcx>(
//
// This is ALT2 in issue #56288, see that for discussion of the
// possible alternatives.
- data.projection_ty.substs[1..].iter().any(has_self_ty).then_some(sp)
+ data.projection_ty.args[1..].iter().any(has_self_ty).then_some(sp)
}
ty::ClauseKind::ConstArgHasType(_ct, ty) => has_self_ty(&ty.into()).then_some(sp),
@@ -393,7 +393,7 @@ fn object_safety_violation_for_assoc_item(
ty::AssocKind::Type => {
if !tcx.features().generic_associated_types_extended
&& !tcx.generics_of(item.def_id).params.is_empty()
- && item.opt_rpitit_info.is_none()
+ && !item.is_impl_trait_in_trait()
{
Some(ObjectSafetyViolation::GAT(item.name, item.ident(tcx).span))
} else {
@@ -414,7 +414,7 @@ fn virtual_call_violation_for_method<'tcx>(
trait_def_id: DefId,
method: ty::AssocItem,
) -> Option<MethodViolationCode> {
- let sig = tcx.fn_sig(method.def_id).subst_identity();
+ let sig = tcx.fn_sig(method.def_id).instantiate_identity();
// The method's first parameter must be named `self`
if !method.fn_has_self_parameter {
@@ -517,8 +517,7 @@ fn virtual_call_violation_for_method<'tcx>(
tcx.sess.delay_span_bug(
tcx.def_span(method.def_id),
format!(
- "receiver when `Self = ()` should have a Scalar ABI; found {:?}",
- abi
+ "receiver when `Self = ()` should have a Scalar ABI; found {abi:?}"
),
);
}
@@ -536,8 +535,7 @@ fn virtual_call_violation_for_method<'tcx>(
tcx.sess.delay_span_bug(
tcx.def_span(method.def_id),
format!(
- "receiver when `Self = {}` should have a ScalarPair ABI; found {:?}",
- trait_object_ty, abi
+ "receiver when `Self = {trait_object_ty}` should have a ScalarPair ABI; found {abi:?}"
),
);
}
@@ -576,7 +574,6 @@ fn virtual_call_violation_for_method<'tcx>(
// implement auto traits if the underlying type does as well.
if let ty::ClauseKind::Trait(ty::TraitPredicate {
trait_ref: pred_trait_ref,
- constness: ty::BoundConstness::NotConst,
polarity: ty::ImplPolarity::Positive,
}) = pred.kind().skip_binder()
&& pred_trait_ref.self_ty() == tcx.types.self_param
@@ -586,7 +583,7 @@ fn virtual_call_violation_for_method<'tcx>(
// allowed to have generic parameters so `auto trait Bound<T> {}`
// would already have reported an error at the definition of the
// auto trait.
- if pred_trait_ref.substs.len() != 1 {
+ if pred_trait_ref.args.len() != 1 {
tcx.sess.diagnostic().delay_span_bug(
span,
"auto traits cannot have generic parameters",
@@ -612,11 +609,11 @@ fn receiver_for_self_ty<'tcx>(
method_def_id: DefId,
) -> Ty<'tcx> {
debug!("receiver_for_self_ty({:?}, {:?}, {:?})", receiver_ty, self_ty, method_def_id);
- let substs = InternalSubsts::for_item(tcx, method_def_id, |param, _| {
+ let args = GenericArgs::for_item(tcx, method_def_id, |param, _| {
if param.index == 0 { self_ty.into() } else { tcx.mk_param_from_def(param) }
});
- let result = EarlyBinder::bind(receiver_ty).subst(tcx, substs);
+ let result = EarlyBinder::bind(receiver_ty).instantiate(tcx, args);
debug!(
"receiver_for_self_ty({:?}, {:?}, {:?}) = {:?}",
receiver_ty, self_ty, method_def_id, result
@@ -751,21 +748,17 @@ fn receiver_is_dispatchable<'tcx>(
// U: Trait<Arg1, ..., ArgN>
let trait_predicate = {
let trait_def_id = method.trait_container(tcx).unwrap();
- let substs = InternalSubsts::for_item(tcx, trait_def_id, |param, _| {
+ let args = GenericArgs::for_item(tcx, trait_def_id, |param, _| {
if param.index == 0 { unsized_self_ty.into() } else { tcx.mk_param_from_def(param) }
});
- ty::TraitRef::new(tcx, trait_def_id, substs).to_predicate(tcx)
+ ty::TraitRef::new(tcx, trait_def_id, args).to_predicate(tcx)
};
let caller_bounds =
param_env.caller_bounds().iter().chain([unsize_predicate, trait_predicate]);
- ty::ParamEnv::new(
- tcx.mk_clauses_from_iter(caller_bounds),
- param_env.reveal(),
- param_env.constness(),
- )
+ ty::ParamEnv::new(tcx.mk_clauses_from_iter(caller_bounds), param_env.reveal())
};
// Receiver: DispatchFromDyn<Receiver[Self => U]>
diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
index ae6fc7cf8..32bbd626d 100644
--- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
@@ -79,7 +79,8 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> {
&canonical_var_values,
canonical_result,
&mut constraints,
- ) else {
+ )
+ else {
return vec![];
};
assert_eq!(&obligations, &[]);
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index a10bca31f..06a1027e5 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1,10 +1,9 @@
//! Code for projecting associated types out of trait references.
-use super::check_substs_compatible;
+use super::check_args_compatible;
use super::specialization_graph;
-use super::translate_substs;
+use super::translate_args;
use super::util;
-use super::ImplSourceUserDefinedData;
use super::MismatchedProjectionTypes;
use super::Obligation;
use super::ObligationCause;
@@ -13,6 +12,9 @@ use super::Selection;
use super::SelectionContext;
use super::SelectionError;
use super::{Normalized, NormalizedTy, ProjectionCacheEntry, ProjectionCacheKey};
+use rustc_middle::traits::BuiltinImplSource;
+use rustc_middle::traits::ImplSource;
+use rustc_middle::traits::ImplSourceUserDefinedData;
use crate::errors::InherentProjectionNormalizationOverflow;
use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -131,8 +133,6 @@ enum ProjectionCandidate<'tcx> {
/// From an "impl" (or a "pseudo-impl" returned by select)
Select(Selection<'tcx>),
-
- ImplTraitInTrait(ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>),
}
enum ProjectionCandidateSet<'tcx> {
@@ -483,8 +483,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
assert!(
!value.has_escaping_bound_vars(),
- "Normalizing {:?} without wrapping in a `Binder`",
- value
+ "Normalizing {value:?} without wrapping in a `Binder`"
);
if !needs_normalization(&value, self.param_env.reveal()) {
@@ -526,7 +525,7 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
// ```
// for<'a> fn(<T as Foo>::One<'a, Box<dyn Bar<'a, Item=<T as Foo>::Two<'a>>>>)
// ```
- // We normalize the substs on the projection before the projecting, but
+ // We normalize the args on the projection before the projecting, but
// if we're naive, we'll
// replace bound vars on inner, project inner, replace placeholders on inner,
// replace bound vars on outer, project outer, replace placeholders on outer
@@ -541,7 +540,7 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
//
// On the other hand, this does add a bit of complexity, since we only
// replace bound vars if the current type is a `Projection` and we need
- // to make sure we don't forget to fold the substs regardless.
+ // to make sure we don't forget to fold the args regardless.
match kind {
ty::Opaque => {
@@ -560,9 +559,9 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
);
}
- let substs = data.substs.fold_with(self);
+ let args = data.args.fold_with(self);
let generic_ty = self.interner().type_of(data.def_id);
- let concrete_ty = generic_ty.subst(self.interner(), substs);
+ let concrete_ty = generic_ty.instantiate(self.interner(), args);
self.depth += 1;
let folded_ty = self.fold_ty(concrete_ty);
self.depth -= 1;
@@ -662,11 +661,8 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
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)| {
+ infcx.tcx.predicates_of(data.def_id).instantiate_own(infcx.tcx, data.args).map(
+ |(mut predicate, span)| {
if data.has_escaping_bound_vars() {
(predicate, ..) = BoundVarReplacer::replace_bound_vars(
infcx,
@@ -679,9 +675,10 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
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)
+ infcx.tcx.type_of(data.def_id).instantiate(infcx.tcx, data.args).fold_with(self)
}
ty::Inherent if !data.has_escaping_bound_vars() => {
@@ -1217,7 +1214,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
let projected_term = selcx.infcx.resolve_vars_if_possible(projected_term);
- let mut result = if projected_term.has_projections() {
+ let result = if projected_term.has_projections() {
let mut normalizer = AssocTypeNormalizer::new(
selcx,
param_env,
@@ -1227,19 +1224,14 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
);
let normalized_ty = normalizer.fold(projected_term);
+ let mut deduped = SsoHashSet::with_capacity(projected_obligations.len());
+ projected_obligations.retain(|obligation| deduped.insert(obligation.clone()));
+
Normalized { value: normalized_ty, obligations: projected_obligations }
} else {
Normalized { value: projected_term, obligations: projected_obligations }
};
- let mut deduped: SsoHashSet<_> = Default::default();
- result.obligations.retain(|projected_obligation| {
- if !deduped.insert(projected_obligation.clone()) {
- return false;
- }
- true
- });
-
if use_cache {
infcx.inner.borrow_mut().projection_cache().insert_term(cache_key, result.clone());
}
@@ -1309,7 +1301,7 @@ fn normalize_to_error<'a, 'tcx>(
cause,
recursion_depth: depth,
param_env,
- predicate: trait_ref.without_const().to_predicate(selcx.tcx()),
+ predicate: trait_ref.to_predicate(selcx.tcx()),
};
let tcx = selcx.infcx.tcx;
let new_value = selcx.infcx.next_ty_var(TypeVariableOrigin {
@@ -1339,7 +1331,7 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>(
});
}
- let substs = compute_inherent_assoc_ty_substs(
+ let args = compute_inherent_assoc_ty_args(
selcx,
param_env,
alias_ty,
@@ -1349,7 +1341,7 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>(
);
// Register the obligations arising from the impl and from the associated type itself.
- let predicates = tcx.predicates_of(alias_ty.def_id).instantiate(tcx, substs);
+ let predicates = tcx.predicates_of(alias_ty.def_id).instantiate(tcx, args);
for (predicate, span) in predicates {
let predicate = normalize_with_depth_to(
selcx,
@@ -1383,7 +1375,7 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>(
));
}
- let ty = tcx.type_of(alias_ty.def_id).subst(tcx, substs);
+ let ty = tcx.type_of(alias_ty.def_id).instantiate(tcx, args);
let mut ty = selcx.infcx.resolve_vars_if_possible(ty);
if ty.has_projections() {
@@ -1393,22 +1385,30 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>(
ty
}
-pub fn compute_inherent_assoc_ty_substs<'a, 'b, 'tcx>(
+pub fn compute_inherent_assoc_ty_args<'a, 'b, 'tcx>(
selcx: &'a mut SelectionContext<'b, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
alias_ty: ty::AliasTy<'tcx>,
cause: ObligationCause<'tcx>,
depth: usize,
obligations: &mut Vec<PredicateObligation<'tcx>>,
-) -> ty::SubstsRef<'tcx> {
+) -> ty::GenericArgsRef<'tcx> {
let tcx = selcx.tcx();
let impl_def_id = tcx.parent(alias_ty.def_id);
- let impl_substs = selcx.infcx.fresh_substs_for_item(cause.span, impl_def_id);
+ let impl_args = selcx.infcx.fresh_args_for_item(cause.span, impl_def_id);
- let impl_ty = tcx.type_of(impl_def_id).subst(tcx, impl_substs);
- let impl_ty =
- normalize_with_depth_to(selcx, param_env, cause.clone(), depth + 1, impl_ty, obligations);
+ let mut impl_ty = tcx.type_of(impl_def_id).instantiate(tcx, impl_args);
+ if !selcx.infcx.next_trait_solver() {
+ impl_ty = normalize_with_depth_to(
+ selcx,
+ param_env,
+ cause.clone(),
+ depth + 1,
+ impl_ty,
+ obligations,
+ );
+ }
// Infer the generic parameters of the impl by unifying the
// impl type with the self type of the projection.
@@ -1425,7 +1425,7 @@ pub fn compute_inherent_assoc_ty_substs<'a, 'b, 'tcx>(
}
}
- alias_ty.rebase_substs_onto_impl(impl_substs, tcx)
+ alias_ty.rebase_inherent_args_onto_impl(impl_args, tcx)
}
enum Projected<'tcx> {
@@ -1472,8 +1472,6 @@ fn project<'cx, 'tcx>(
let mut candidates = ProjectionCandidateSet::None;
- assemble_candidate_for_impl_trait_in_trait(selcx, obligation, &mut candidates);
-
// Make sure that the following procedures are kept in order. ParamEnv
// needs to be first because it has highest priority, and Select checks
// the return value of push_candidate which assumes it's ran at last.
@@ -1499,20 +1497,18 @@ fn project<'cx, 'tcx>(
ProjectionCandidateSet::None => {
let tcx = selcx.tcx();
let term = match tcx.def_kind(obligation.predicate.def_id) {
- DefKind::AssocTy | DefKind::ImplTraitPlaceholder => Ty::new_projection(
- tcx,
- obligation.predicate.def_id,
- obligation.predicate.substs,
- )
- .into(),
+ DefKind::AssocTy => {
+ Ty::new_projection(tcx, obligation.predicate.def_id, obligation.predicate.args)
+ .into()
+ }
DefKind::AssocConst => ty::Const::new_unevaluated(
tcx,
ty::UnevaluatedConst::new(
obligation.predicate.def_id,
- obligation.predicate.substs,
+ obligation.predicate.args,
),
tcx.type_of(obligation.predicate.def_id)
- .subst(tcx, obligation.predicate.substs),
+ .instantiate(tcx, obligation.predicate.args),
)
.into(),
kind => {
@@ -1530,47 +1526,6 @@ fn project<'cx, 'tcx>(
}
}
-/// If the predicate's item is an `ImplTraitPlaceholder`, we do a select on the
-/// corresponding trait ref. If this yields an `impl`, then we're able to project
-/// to a concrete type, since we have an `impl`'s method to provide the RPITIT.
-fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
- selcx: &mut SelectionContext<'cx, 'tcx>,
- obligation: &ProjectionTyObligation<'tcx>,
- candidate_set: &mut ProjectionCandidateSet<'tcx>,
-) {
- let tcx = selcx.tcx();
- if tcx.def_kind(obligation.predicate.def_id) == DefKind::ImplTraitPlaceholder {
- let trait_fn_def_id = tcx.impl_trait_in_trait_parent_fn(obligation.predicate.def_id);
-
- let trait_def_id = tcx.parent(trait_fn_def_id);
- let trait_substs =
- obligation.predicate.substs.truncate_to(tcx, tcx.generics_of(trait_def_id));
- let trait_predicate = ty::TraitRef::new(tcx, trait_def_id, trait_substs);
-
- let _ = selcx.infcx.commit_if_ok(|_| {
- match selcx.select(&obligation.with(tcx, trait_predicate)) {
- Ok(Some(super::ImplSource::UserDefined(data))) => {
- candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(data));
- Ok(())
- }
- Ok(None) => {
- candidate_set.mark_ambiguous();
- Err(())
- }
- Ok(Some(_)) => {
- // Don't know enough about the impl to provide a useful signature
- Err(())
- }
- Err(e) => {
- debug!(error = ?e, "selection error");
- candidate_set.mark_error(e);
- Err(())
- }
- }
- });
- }
-}
-
/// The first thing we have to do is scan through the parameter
/// environment to see whether there are any projection predicates
/// there that can answer this question.
@@ -1612,7 +1567,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
let bounds = match *obligation.predicate.self_ty().kind() {
// 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)
+ tcx.item_bounds(data.def_id).instantiate(tcx, data.args)
}
ty::Infer(ty::TyVar(_)) => {
// If the self-type is an inference variable, then it MAY wind up
@@ -1739,11 +1694,6 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
obligation: &ProjectionTyObligation<'tcx>,
candidate_set: &mut ProjectionCandidateSet<'tcx>,
) {
- // Can't assemble candidate from impl for RPITIT
- if selcx.tcx().def_kind(obligation.predicate.def_id) == DefKind::ImplTraitPlaceholder {
- return;
- }
-
// If we are resolving `<T as TraitRef<...>>::Item == Type`,
// start out by selecting the predicate `T as TraitRef<...>`:
let trait_ref = obligation.predicate.trait_ref(selcx.tcx());
@@ -1763,7 +1713,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
};
let eligible = match &impl_source {
- super::ImplSource::UserDefined(impl_data) => {
+ ImplSource::UserDefined(impl_data) => {
// We have to be careful when projecting out of an
// impl because of specialization. If we are not in
// codegen (i.e., projection mode is not "any"), and the
@@ -1813,7 +1763,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
}
}
}
- super::ImplSource::Builtin(..) => {
+ ImplSource::Builtin(BuiltinImplSource::Misc, _) => {
// While a builtin impl may be known to exist, the associated type may not yet
// be known. Any type with multiple potential associated types is therefore
// not eligible.
@@ -1912,8 +1862,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
if selcx.infcx.predicate_must_hold_modulo_regions(
&obligation.with(
selcx.tcx(),
- ty::TraitRef::from_lang_item(selcx.tcx(), LangItem::Sized, obligation.cause.span(),[self_ty])
- .without_const(),
+ ty::TraitRef::from_lang_item(selcx.tcx(), LangItem::Sized, obligation.cause.span(),[self_ty]),
),
) =>
{
@@ -1937,7 +1886,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
bug!("unexpected builtin trait with associated type: {trait_ref:?}")
}
}
- super::ImplSource::Param(..) => {
+ ImplSource::Param(..) => {
// This case tell us nothing about the value of an
// associated type. Consider:
//
@@ -1965,17 +1914,18 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
// in `assemble_candidates_from_param_env`.
false
}
- super::ImplSource::Object(_) => {
+ ImplSource::Builtin(BuiltinImplSource::Object { .. }, _) => {
// Handled by the `Object` projection candidate. See
// `assemble_candidates_from_object_ty` for an explanation of
// why we special case object types.
false
}
- | super::ImplSource::TraitUpcasting(_) => {
+ ImplSource::Builtin(BuiltinImplSource::TraitUpcasting { .. }, _)
+ | ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, _) => {
// These traits have no associated types.
selcx.tcx().sess.delay_span_bug(
obligation.cause.span,
- format!("Cannot project an associated type from `{:?}`", impl_source),
+ format!("Cannot project an associated type from `{impl_source:?}`"),
);
return Err(());
}
@@ -2012,9 +1962,6 @@ fn confirm_candidate<'cx, 'tcx>(
ProjectionCandidate::Select(impl_source) => {
confirm_select_candidate(selcx, obligation, impl_source)
}
- ProjectionCandidate::ImplTraitInTrait(data) => {
- confirm_impl_trait_in_trait_candidate(selcx, obligation, data)
- }
};
// When checking for cycle during evaluation, we compare predicates with
@@ -2034,8 +1981,8 @@ fn confirm_select_candidate<'cx, 'tcx>(
impl_source: Selection<'tcx>,
) -> Progress<'tcx> {
match impl_source {
- super::ImplSource::UserDefined(data) => confirm_impl_candidate(selcx, obligation, data),
- super::ImplSource::Builtin(data) => {
+ ImplSource::UserDefined(data) => confirm_impl_candidate(selcx, obligation, data),
+ ImplSource::Builtin(BuiltinImplSource::Misc, data) => {
let trait_def_id = obligation.predicate.trait_def_id(selcx.tcx());
let lang_items = selcx.tcx().lang_items();
if lang_items.gen_trait() == Some(trait_def_id) {
@@ -2052,9 +1999,10 @@ fn confirm_select_candidate<'cx, 'tcx>(
confirm_builtin_candidate(selcx, obligation, data)
}
}
- super::ImplSource::Object(_)
- | super::ImplSource::Param(..)
- | super::ImplSource::TraitUpcasting(_) => {
+ ImplSource::Builtin(BuiltinImplSource::Object { .. }, _)
+ | ImplSource::Param(..)
+ | ImplSource::Builtin(BuiltinImplSource::TraitUpcasting { .. }, _)
+ | ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, _) => {
// we don't create Select candidates with this kind of resolution
span_bug!(
obligation.cause.span,
@@ -2070,12 +2018,12 @@ fn confirm_generator_candidate<'cx, 'tcx>(
obligation: &ProjectionTyObligation<'tcx>,
nested: Vec<PredicateObligation<'tcx>>,
) -> Progress<'tcx> {
- let ty::Generator(_, substs, _) =
+ let ty::Generator(_, args, _) =
selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind()
else {
unreachable!()
};
- let gen_sig = substs.as_generator().poly_sig();
+ let gen_sig = args.as_generator().poly_sig();
let Normalized { value: gen_sig, obligations } = normalize_with_depth(
selcx,
obligation.param_env,
@@ -2107,7 +2055,7 @@ fn confirm_generator_candidate<'cx, 'tcx>(
};
ty::ProjectionPredicate {
- projection_ty: tcx.mk_alias_ty(obligation.predicate.def_id, trait_ref.substs),
+ projection_ty: tcx.mk_alias_ty(obligation.predicate.def_id, trait_ref.args),
term: ty.into(),
}
});
@@ -2122,12 +2070,12 @@ fn confirm_future_candidate<'cx, 'tcx>(
obligation: &ProjectionTyObligation<'tcx>,
nested: Vec<PredicateObligation<'tcx>>,
) -> Progress<'tcx> {
- let ty::Generator(_, substs, _) =
+ let ty::Generator(_, args, _) =
selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind()
else {
unreachable!()
};
- let gen_sig = substs.as_generator().poly_sig();
+ let gen_sig = args.as_generator().poly_sig();
let Normalized { value: gen_sig, obligations } = normalize_with_depth(
selcx,
obligation.param_env,
@@ -2151,7 +2099,7 @@ fn confirm_future_candidate<'cx, 'tcx>(
debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name, sym::Output);
ty::ProjectionPredicate {
- projection_ty: tcx.mk_alias_ty(obligation.predicate.def_id, trait_ref.substs),
+ projection_ty: tcx.mk_alias_ty(obligation.predicate.def_id, trait_ref.args),
term: return_ty.into(),
}
});
@@ -2168,7 +2116,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>(
) -> Progress<'tcx> {
let tcx = selcx.tcx();
let self_ty = obligation.predicate.self_ty();
- let substs = tcx.mk_substs(&[self_ty.into()]);
+ let args = tcx.mk_args(&[self_ty.into()]);
let lang_items = tcx.lang_items();
let item_def_id = obligation.predicate.def_id;
let trait_def_id = tcx.trait_of_item(item_def_id).unwrap();
@@ -2198,8 +2146,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>(
LangItem::Sized,
obligation.cause.span(),
[self_ty],
- )
- .without_const();
+ );
obligations.push(obligation.with(tcx, sized_predicate));
}
(metadata_ty.into(), obligations)
@@ -2208,7 +2155,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>(
};
let predicate =
- ty::ProjectionPredicate { projection_ty: tcx.mk_alias_ty(item_def_id, substs), term };
+ ty::ProjectionPredicate { projection_ty: tcx.mk_alias_ty(item_def_id, args), term };
confirm_param_env_candidate(selcx, obligation, ty::Binder::dummy(predicate), false)
.with_addl_obligations(obligations)
@@ -2240,12 +2187,11 @@ fn confirm_closure_candidate<'cx, 'tcx>(
obligation: &ProjectionTyObligation<'tcx>,
nested: Vec<PredicateObligation<'tcx>>,
) -> Progress<'tcx> {
- let ty::Closure(_, substs) =
- selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind()
+ let ty::Closure(_, args) = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind()
else {
unreachable!()
};
- let closure_sig = substs.as_closure().sig();
+ let closure_sig = args.as_closure().sig();
let Normalized { value: closure_sig, obligations } = normalize_with_depth(
selcx,
obligation.param_env,
@@ -2282,7 +2228,7 @@ fn confirm_callable_candidate<'cx, 'tcx>(
flag,
)
.map_bound(|(trait_ref, ret_type)| ty::ProjectionPredicate {
- projection_ty: tcx.mk_alias_ty(fn_once_output_def_id, trait_ref.substs),
+ projection_ty: tcx.mk_alias_ty(fn_once_output_def_id, trait_ref.args),
term: ret_type.into(),
});
@@ -2349,8 +2295,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>(
}
Err(e) => {
let msg = format!(
- "Failed to unify obligation `{:?}` with poly_projection `{:?}`: {:?}",
- obligation, poly_cache_entry, e,
+ "Failed to unify obligation `{obligation:?}` with poly_projection `{poly_cache_entry:?}`: {e:?}",
);
debug!("confirm_param_env_candidate: {}", msg);
let err = Ty::new_error_with_message(infcx.tcx, obligation.cause.span, msg);
@@ -2366,7 +2311,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
) -> Progress<'tcx> {
let tcx = selcx.tcx();
- let ImplSourceUserDefinedData { impl_def_id, substs, mut nested } = impl_impl_source;
+ let ImplSourceUserDefinedData { impl_def_id, args, mut nested } = impl_impl_source;
let assoc_item_id = obligation.predicate.def_id;
let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap();
@@ -2390,23 +2335,22 @@ fn confirm_impl_candidate<'cx, 'tcx>(
// If we're trying to normalize `<Vec<u32> as X>::A<S>` using
//`impl<T> X for Vec<T> { type A<Y> = Box<Y>; }`, then:
//
- // * `obligation.predicate.substs` is `[Vec<u32>, S]`
- // * `substs` is `[u32]`
- // * `substs` ends up as `[u32, S]`
- let substs = obligation.predicate.substs.rebase_onto(tcx, trait_def_id, substs);
- let substs =
- translate_substs(selcx.infcx, param_env, impl_def_id, substs, assoc_ty.defining_node);
+ // * `obligation.predicate.args` is `[Vec<u32>, S]`
+ // * `args` is `[u32]`
+ // * `args` ends up as `[u32, S]`
+ let args = obligation.predicate.args.rebase_onto(tcx, trait_def_id, args);
+ let args = translate_args(selcx.infcx, param_env, impl_def_id, args, assoc_ty.defining_node);
let ty = tcx.type_of(assoc_ty.item.def_id);
let is_const = matches!(tcx.def_kind(assoc_ty.item.def_id), DefKind::AssocConst);
let term: ty::EarlyBinder<ty::Term<'tcx>> = if is_const {
let did = assoc_ty.item.def_id;
- let identity_substs = crate::traits::InternalSubsts::identity_for_item(tcx, did);
- let uv = ty::UnevaluatedConst::new(did, identity_substs);
+ let identity_args = crate::traits::GenericArgs::identity_for_item(tcx, did);
+ let uv = ty::UnevaluatedConst::new(did, identity_args);
ty.map_bound(|ty| ty::Const::new_unevaluated(tcx, uv, ty).into())
} else {
ty.map_bound(|ty| ty.into())
};
- if !check_substs_compatible(tcx, assoc_ty.item, substs) {
+ if !check_args_compatible(tcx, assoc_ty.item, args) {
let err = Ty::new_error_with_message(
tcx,
obligation.cause.span,
@@ -2415,107 +2359,10 @@ fn confirm_impl_candidate<'cx, 'tcx>(
Progress { term: err.into(), obligations: nested }
} else {
assoc_ty_own_obligations(selcx, obligation, &mut nested);
- Progress { term: term.subst(tcx, substs), obligations: nested }
+ Progress { term: term.instantiate(tcx, args), obligations: nested }
}
}
-fn confirm_impl_trait_in_trait_candidate<'tcx>(
- selcx: &mut SelectionContext<'_, 'tcx>,
- obligation: &ProjectionTyObligation<'tcx>,
- data: ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>,
-) -> Progress<'tcx> {
- let tcx = selcx.tcx();
- let mut obligations = data.nested;
-
- let trait_fn_def_id = tcx.impl_trait_in_trait_parent_fn(obligation.predicate.def_id);
- let leaf_def = match specialization_graph::assoc_def(tcx, data.impl_def_id, trait_fn_def_id) {
- Ok(assoc_ty) => assoc_ty,
- Err(guar) => return Progress::error(tcx, guar),
- };
- // We don't support specialization for RPITITs anyways... yet.
- // Also don't try to project to an RPITIT that has no value
- if !leaf_def.is_final() || !leaf_def.item.defaultness(tcx).has_value() {
- return Progress { term: Ty::new_misc_error(tcx).into(), obligations };
- }
-
- // Use the default `impl Trait` for the trait, e.g., for a default trait body
- if leaf_def.item.container == ty::AssocItemContainer::TraitContainer {
- return Progress {
- term: Ty::new_opaque(tcx, obligation.predicate.def_id, obligation.predicate.substs)
- .into(),
- obligations,
- };
- }
-
- // Rebase from {trait}::{fn}::{opaque} to {impl}::{fn}::{opaque},
- // since `data.substs` are the impl substs.
- let impl_fn_substs =
- obligation.predicate.substs.rebase_onto(tcx, tcx.parent(trait_fn_def_id), data.substs);
- let impl_fn_substs = translate_substs(
- selcx.infcx,
- obligation.param_env,
- data.impl_def_id,
- impl_fn_substs,
- leaf_def.defining_node,
- );
-
- if !check_substs_compatible(tcx, leaf_def.item, impl_fn_substs) {
- let err = Ty::new_error_with_message(
- tcx,
- obligation.cause.span,
- "impl method and trait method have different parameters",
- );
- return Progress { term: err.into(), obligations };
- }
-
- let impl_fn_def_id = leaf_def.item.def_id;
-
- let cause = ObligationCause::new(
- obligation.cause.span,
- obligation.cause.body_id,
- super::ItemObligation(impl_fn_def_id),
- );
- let predicates = normalize_with_depth_to(
- selcx,
- obligation.param_env,
- cause.clone(),
- obligation.recursion_depth + 1,
- tcx.predicates_of(impl_fn_def_id).instantiate(tcx, impl_fn_substs),
- &mut obligations,
- );
- obligations.extend(predicates.into_iter().map(|(pred, span)| {
- Obligation::with_depth(
- tcx,
- ObligationCause::new(
- obligation.cause.span,
- obligation.cause.body_id,
- if span.is_dummy() {
- super::ItemObligation(impl_fn_def_id)
- } else {
- super::BindingObligation(impl_fn_def_id, span)
- },
- ),
- obligation.recursion_depth + 1,
- obligation.param_env,
- pred,
- )
- }));
-
- let ty = normalize_with_depth_to(
- selcx,
- obligation.param_env,
- cause.clone(),
- obligation.recursion_depth + 1,
- tcx.collect_return_position_impl_trait_in_trait_tys(impl_fn_def_id).map_or_else(
- |guar| Ty::new_error(tcx, guar),
- |tys| tys[&obligation.predicate.def_id].subst(tcx, impl_fn_substs),
- ),
- &mut obligations,
- );
-
- Progress { term: ty.into(), obligations }
-}
-
// Get obligations corresponding to the predicates from the where-clause of the
// associated type itself.
fn assoc_ty_own_obligations<'cx, 'tcx>(
@@ -2526,7 +2373,7 @@ fn assoc_ty_own_obligations<'cx, 'tcx>(
let tcx = selcx.tcx();
let predicates = tcx
.predicates_of(obligation.predicate.def_id)
- .instantiate_own(tcx, obligation.predicate.substs);
+ .instantiate_own(tcx, obligation.predicate.args);
for (predicate, span) in predicates {
let normalized = normalize_with_depth_to(
selcx,
diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
index 709c3f432..9484a50e3 100644
--- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
@@ -49,8 +49,8 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
// (T1..Tn) and closures have same properties as T1..Tn --
// check if *all* of them are trivial.
ty::Tuple(tys) => tys.iter().all(|t| trivial_dropck_outlives(tcx, t)),
- ty::Closure(_, ref substs) => {
- trivial_dropck_outlives(tcx, substs.as_closure().tupled_upvars_ty())
+ ty::Closure(_, ref args) => {
+ trivial_dropck_outlives(tcx, args.as_closure().tupled_upvars_ty())
}
ty::Adt(def, _) => {
@@ -237,8 +237,8 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
Ok::<_, NoSolution>(())
})?,
- ty::Closure(_, substs) => {
- if !substs.as_closure().is_valid() {
+ ty::Closure(_, args) => {
+ if !args.as_closure().is_valid() {
// By the time this code runs, all type variables ought to
// be fully resolved.
@@ -250,14 +250,14 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
}
rustc_data_structures::stack::ensure_sufficient_stack(|| {
- for ty in substs.as_closure().upvar_tys() {
+ for ty in args.as_closure().upvar_tys() {
dtorck_constraint_for_ty_inner(tcx, span, for_ty, depth + 1, ty, constraints)?;
}
Ok::<_, NoSolution>(())
})?
}
- ty::Generator(_, substs, _movability) => {
+ ty::Generator(_, args, _movability) => {
// rust-lang/rust#49918: types can be constructed, stored
// in the interior, and sit idle when generator yields
// (and is subsequently dropped).
@@ -281,7 +281,7 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
// derived from lifetimes attached to the upvars and resume
// argument, and we *do* incorporate those here.
- if !substs.as_generator().is_valid() {
+ if !args.as_generator().is_valid() {
// By the time this code runs, all type variables ought to
// be fully resolved.
tcx.sess.delay_span_bug(
@@ -291,29 +291,26 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
return Err(NoSolution);
}
- constraints.outlives.extend(
- substs
- .as_generator()
- .upvar_tys()
- .map(|t| -> ty::subst::GenericArg<'tcx> { t.into() }),
- );
- constraints.outlives.push(substs.as_generator().resume_ty().into());
+ constraints
+ .outlives
+ .extend(args.as_generator().upvar_tys().iter().map(ty::GenericArg::from));
+ constraints.outlives.push(args.as_generator().resume_ty().into());
}
- ty::Adt(def, substs) => {
+ ty::Adt(def, args) => {
let DropckConstraint { dtorck_types, outlives, overflows } =
tcx.at(span).adt_dtorck_constraint(def.did())?;
// FIXME: we can try to recursively `dtorck_constraint_on_ty`
// there, but that needs some way to handle cycles.
constraints
.dtorck_types
- .extend(dtorck_types.iter().map(|t| EarlyBinder::bind(*t).subst(tcx, substs)));
+ .extend(dtorck_types.iter().map(|t| EarlyBinder::bind(*t).instantiate(tcx, args)));
constraints
.outlives
- .extend(outlives.iter().map(|t| EarlyBinder::bind(*t).subst(tcx, substs)));
+ .extend(outlives.iter().map(|t| EarlyBinder::bind(*t).instantiate(tcx, args)));
constraints
.overflows
- .extend(overflows.iter().map(|t| EarlyBinder::bind(*t).subst(tcx, substs)));
+ .extend(overflows.iter().map(|t| EarlyBinder::bind(*t).instantiate(tcx, args)));
}
// Objects must be alive in order for their destructor
diff --git a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
index a50644bb7..65f32b1c4 100644
--- a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
@@ -1,5 +1,4 @@
use rustc_infer::traits::{TraitEngine, TraitEngineExt};
-use rustc_middle::ty;
use crate::infer::canonical::OriginalQueryValues;
use crate::infer::InferCtxt;
@@ -66,17 +65,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
) -> Result<EvaluationResult, OverflowError> {
let mut _orig_values = OriginalQueryValues::default();
- let param_env = match obligation.predicate.kind().skip_binder() {
- ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
- // we ignore the value set to it.
- let mut _constness = pred.constness;
- obligation
- .param_env
- .with_constness(_constness.and(obligation.param_env.constness()))
- }
- // constness has no effect on the given predicate.
- _ => obligation.param_env.without_const(),
- };
+ let param_env = obligation.param_env;
if self.next_trait_solver() {
self.probe(|snapshot| {
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index 7fe79fd86..87beaddc6 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -61,8 +61,27 @@ impl<'cx, 'tcx> QueryNormalizeExt<'tcx> for At<'cx, 'tcx> {
self.cause,
);
+ // This is actually a consequence by the way `normalize_erasing_regions` works currently.
+ // Because it needs to call the `normalize_generic_arg_after_erasing_regions`, it folds
+ // through tys and consts in a `TypeFoldable`. Importantly, it skips binders, leaving us
+ // with trying to normalize with escaping bound vars.
+ //
+ // Here, we just add the universes that we *would* have created had we passed through the binders.
+ //
+ // We *could* replace escaping bound vars eagerly here, but it doesn't seem really necessary.
+ // The rest of the code is already set up to be lazy about replacing bound vars,
+ // and only when we actually have to normalize.
+ let universes = if value.has_escaping_bound_vars() {
+ let mut max_visitor =
+ MaxEscapingBoundVarVisitor { outer_index: ty::INNERMOST, escaping: 0 };
+ value.visit_with(&mut max_visitor);
+ vec![None; max_visitor.escaping]
+ } else {
+ vec![]
+ };
+
if self.infcx.next_trait_solver() {
- match crate::solve::deeply_normalize(self, value) {
+ match crate::solve::deeply_normalize_with_skipped_universes(self, value, universes) {
Ok(value) => return Ok(Normalized { value, obligations: vec![] }),
Err(_errors) => {
return Err(NoSolution);
@@ -81,27 +100,9 @@ impl<'cx, 'tcx> QueryNormalizeExt<'tcx> for At<'cx, 'tcx> {
obligations: vec![],
cache: SsoHashMap::new(),
anon_depth: 0,
- universes: vec![],
+ universes,
};
- // This is actually a consequence by the way `normalize_erasing_regions` works currently.
- // Because it needs to call the `normalize_generic_arg_after_erasing_regions`, it folds
- // through tys and consts in a `TypeFoldable`. Importantly, it skips binders, leaving us
- // with trying to normalize with escaping bound vars.
- //
- // Here, we just add the universes that we *would* have created had we passed through the binders.
- //
- // We *could* replace escaping bound vars eagerly here, but it doesn't seem really necessary.
- // The rest of the code is already set up to be lazy about replacing bound vars,
- // and only when we actually have to normalize.
- if value.has_escaping_bound_vars() {
- let mut max_visitor =
- MaxEscapingBoundVarVisitor { outer_index: ty::INNERMOST, escaping: 0 };
- value.visit_with(&mut max_visitor);
- if max_visitor.escaping > 0 {
- normalizer.universes.extend((0..max_visitor.escaping).map(|_| None));
- }
- }
let result = value.try_fold_with(&mut normalizer);
info!(
"normalize::<{}>: result={:?} with {} obligations",
@@ -217,7 +218,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
};
// See note in `rustc_trait_selection::traits::project` about why we
- // wait to fold the substs.
+ // wait to fold the args.
// Wrap this in a closure so we don't accidentally return from the outer function
let res = match kind {
@@ -227,7 +228,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
Reveal::UserFacing => ty.try_super_fold_with(self)?,
Reveal::All => {
- let substs = data.substs.try_fold_with(self)?;
+ let args = data.args.try_fold_with(self)?;
let recursion_limit = self.interner().recursion_limit();
if !recursion_limit.value_within_limit(self.anon_depth) {
// A closure or generator may have itself as in its upvars.
@@ -243,14 +244,14 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
}
let generic_ty = self.interner().type_of(data.def_id);
- let concrete_ty = generic_ty.subst(self.interner(), substs);
+ let concrete_ty = generic_ty.instantiate(self.interner(), args);
self.anon_depth += 1;
if concrete_ty == ty {
bug!(
- "infinite recursion generic_ty: {:#?}, substs: {:#?}, \
+ "infinite recursion generic_ty: {:#?}, args: {:#?}, \
concrete_ty: {:#?}, ty: {:#?}",
generic_ty,
- substs,
+ args,
concrete_ty,
ty
);
@@ -298,7 +299,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
if !tcx.sess.opts.actually_rustdoc {
tcx.sess.delay_span_bug(
DUMMY_SP,
- format!("unexpected ambiguity: {:?} {:?}", c_data, result),
+ format!("unexpected ambiguity: {c_data:?} {result:?}"),
);
}
return Err(NoSolution);
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs
index 44671a076..302b6016e 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs
@@ -4,7 +4,7 @@ use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
use rustc_infer::traits::Obligation;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
-use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, UserSelfTy, UserSubsts, UserType};
+use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, UserArgs, UserSelfTy, UserType};
pub use rustc_middle::traits::query::type_op::AscribeUserType;
use rustc_span::{Span, DUMMY_SP};
@@ -47,8 +47,8 @@ pub fn type_op_ascribe_user_type_with_span<'tcx>(
let span = span.unwrap_or(DUMMY_SP);
match user_ty {
UserType::Ty(user_ty) => relate_mir_and_user_ty(ocx, param_env, span, mir_ty, user_ty)?,
- UserType::TypeOf(def_id, user_substs) => {
- relate_mir_and_user_substs(ocx, param_env, span, mir_ty, def_id, user_substs)?
+ UserType::TypeOf(def_id, user_args) => {
+ relate_mir_and_user_args(ocx, param_env, span, mir_ty, def_id, user_args)?
}
};
Ok(())
@@ -74,20 +74,19 @@ fn relate_mir_and_user_ty<'tcx>(
}
#[instrument(level = "debug", skip(ocx, param_env, span))]
-fn relate_mir_and_user_substs<'tcx>(
+fn relate_mir_and_user_args<'tcx>(
ocx: &ObligationCtxt<'_, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
span: Span,
mir_ty: Ty<'tcx>,
def_id: DefId,
- user_substs: UserSubsts<'tcx>,
+ user_args: UserArgs<'tcx>,
) -> Result<(), NoSolution> {
- let param_env = param_env.without_const();
- let UserSubsts { user_self_ty, substs } = user_substs;
+ let UserArgs { user_self_ty, args } = user_args;
let tcx = ocx.infcx.tcx;
let cause = ObligationCause::dummy_with_span(span);
- let ty = tcx.type_of(def_id).subst(tcx, substs);
+ let ty = tcx.type_of(def_id).instantiate(tcx, args);
let ty = ocx.normalize(&cause, param_env, ty);
debug!("relate_type_and_user_type: ty of def-id is {:?}", ty);
@@ -98,7 +97,7 @@ fn relate_mir_and_user_substs<'tcx>(
// Also, normalize the `instantiated_predicates`
// because otherwise we wind up with duplicate "type
// outlives" error messages.
- let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs);
+ let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, args);
debug!(?instantiated_predicates);
for (instantiated_predicate, predicate_span) in instantiated_predicates {
@@ -116,7 +115,7 @@ fn relate_mir_and_user_substs<'tcx>(
if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty {
let self_ty = ocx.normalize(&cause, param_env, self_ty);
- let impl_self_ty = tcx.type_of(impl_def_id).subst(tcx, substs);
+ let impl_self_ty = tcx.type_of(impl_def_id).instantiate(tcx, args);
let impl_self_ty = ocx.normalize(&cause, param_env, impl_self_ty);
ocx.eq(&cause, param_env, self_ty, impl_self_ty)?;
@@ -128,9 +127,9 @@ fn relate_mir_and_user_substs<'tcx>(
// In addition to proving the predicates, we have to
// prove that `ty` is well-formed -- this is because
- // the WF of `ty` is predicated on the substs being
+ // the WF of `ty` is predicated on the args being
// well-formed, and we haven't proven *that*. We don't
- // want to prove the WF of types from `substs` directly because they
+ // want to prove the WF of types from `args` directly because they
// haven't been normalized.
//
// FIXME(nmatsakis): Well, perhaps we should normalize
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
index 5420caee3..c99e018e9 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
@@ -77,8 +77,7 @@ where
let pre_obligations = infcx.take_registered_region_obligations();
assert!(
pre_obligations.is_empty(),
- "scrape_region_constraints: incoming region obligations = {:#?}",
- pre_obligations,
+ "scrape_region_constraints: incoming region obligations = {pre_obligations:#?}",
);
let value = infcx.commit_if_ok(|_| {
@@ -92,7 +91,7 @@ where
} else {
Err(infcx.tcx.sess.delay_span_bug(
DUMMY_SP,
- format!("errors selecting obligation during MIR typeck: {:?}", errors),
+ format!("errors selecting obligation during MIR typeck: {errors:?}"),
))
}
})?;
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs
index 988942633..59f4a22ac 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs
@@ -31,16 +31,6 @@ impl<'tcx> super::QueryTypeOp<'tcx> for DropckOutlives<'tcx> {
tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
) -> Result<CanonicalQueryResponse<'tcx, Self::QueryResponse>, NoSolution> {
- // Subtle: note that we are not invoking
- // `infcx.at(...).dropck_outlives(...)` here, but rather the
- // underlying `dropck_outlives` query. This same underlying
- // query is also used by the
- // `infcx.at(...).dropck_outlives(...)` fn. Avoiding the
- // wrapper means we don't need an infcx in this code, which is
- // good because the interface doesn't give us one (so that we
- // know we are not registering any subregion relations or
- // other things).
-
// FIXME convert to the type expected by the `dropck_outlives`
// query. This should eventually be fixed by changing the
// *underlying query*.
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index d5f6aaa7f..e3da87a22 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -124,11 +124,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
self.assemble_candidates_from_projected_tys(obligation, &mut candidates);
self.assemble_candidates_from_caller_bounds(stack, &mut candidates)?;
- // Auto implementations have lower priority, so we only
- // consider triggering a default if there is no other impl that can apply.
- if candidates.vec.is_empty() {
- self.assemble_candidates_from_auto_impls(obligation, &mut candidates);
- }
+ self.assemble_candidates_from_auto_impls(obligation, &mut candidates);
}
debug!("candidate list size: {}", candidates.vec.len());
Ok(candidates)
@@ -158,9 +154,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.infcx
.probe(|_| self.match_projection_obligation_against_definition_bounds(obligation));
- candidates
- .vec
- .extend(result.into_iter().map(|(idx, constness)| ProjectionCandidate(idx, constness)));
+ // FIXME(effects) proper constness needed?
+ candidates.vec.extend(
+ result.into_iter().map(|idx| ProjectionCandidate(idx, ty::BoundConstness::NotConst)),
+ );
}
/// Given an obligation like `<SomeTrait for T>`, searches the obligations that the caller
@@ -209,7 +206,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
- // Okay to skip binder because the substs on generator types never
+ // Okay to skip binder because the args on generator types never
// touch bound regions, they just capture the in-scope
// type/region parameters.
let self_ty = obligation.self_ty().skip_binder();
@@ -261,14 +258,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
return;
};
- // Okay to skip binder because the substs on closure types never
+ // Okay to skip binder because the args on closure types never
// touch bound regions, they just capture the in-scope
// type/region parameters
match *obligation.self_ty().skip_binder().kind() {
- ty::Closure(def_id, closure_substs) => {
+ ty::Closure(def_id, closure_args) => {
let is_const = self.tcx().is_const_fn_raw(def_id);
debug!(?kind, ?obligation, "assemble_unboxed_candidates");
- match self.infcx.closure_kind(closure_substs) {
+ match self.infcx.closure_kind(closure_args) {
Some(closure_kind) => {
debug!(?closure_kind, "assemble_unboxed_candidates");
if closure_kind.extends(kind) {
@@ -351,7 +348,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup };
- let obligation_substs = obligation.predicate.skip_binder().trait_ref.substs;
+ let obligation_args = obligation.predicate.skip_binder().trait_ref.args;
self.tcx().for_each_relevant_impl(
obligation.predicate.def_id(),
obligation.predicate.skip_binder().trait_ref.self_ty(),
@@ -360,9 +357,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// consider a "quick reject". This avoids creating more types
// and so forth that we need to.
let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap();
- if !drcx
- .substs_refs_may_unify(obligation_substs, impl_trait_ref.skip_binder().substs)
- {
+ if !drcx.args_refs_may_unify(obligation_args, impl_trait_ref.skip_binder().args) {
return;
}
if self.reject_fn_ptr_impls(
@@ -374,7 +369,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
self.infcx.probe(|_| {
- if let Ok(_substs) = self.match_impl(impl_def_id, impl_trait_ref, obligation) {
+ if let Ok(_args) = self.match_impl(impl_def_id, impl_trait_ref, obligation) {
candidates.vec.push(ImplCandidate(impl_def_id));
}
});
@@ -402,8 +397,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
};
for &(predicate, _) in self.tcx().predicates_of(impl_def_id).predicates {
- let ty::ClauseKind::Trait(pred)
- = predicate.kind().skip_binder() else { continue };
+ let ty::ClauseKind::Trait(pred) = predicate.kind().skip_binder() else { continue };
if fn_ptr_trait != pred.trait_ref.def_id {
continue;
}
@@ -516,7 +510,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// for an example of a test case that exercises
// this path.
}
- ty::Infer(ty::TyVar(_)) => {
+ ty::Infer(ty::TyVar(_) | ty::IntVar(_) | ty::FloatVar(_)) => {
// The auto impl might apply; we don't know.
candidates.ambiguous = true;
}
@@ -536,7 +530,63 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
}
- _ => candidates.vec.push(AutoImplCandidate),
+ ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
+ bug!(
+ "asked to assemble auto trait candidates of unexpected type: {:?}",
+ self_ty
+ );
+ }
+
+ ty::Alias(_, _)
+ if candidates.vec.iter().any(|c| matches!(c, ProjectionCandidate(..))) =>
+ {
+ // We do not generate an auto impl candidate for `impl Trait`s which already
+ // reference our auto trait.
+ //
+ // For example during candidate assembly for `impl Send: Send`, we don't have
+ // to look at the constituent types for this opaque types to figure out that this
+ // trivially holds.
+ //
+ // Note that this is only sound as projection candidates of opaque types
+ // are always applicable for auto traits.
+ }
+ ty::Alias(_, _) => candidates.vec.push(AutoImplCandidate),
+
+ ty::Bool
+ | ty::Char
+ | ty::Int(_)
+ | ty::Uint(_)
+ | ty::Float(_)
+ | ty::Str
+ | ty::Array(_, _)
+ | ty::Slice(_)
+ | ty::Adt(..)
+ | ty::RawPtr(_)
+ | ty::Ref(..)
+ | ty::FnDef(..)
+ | ty::FnPtr(_)
+ | ty::Closure(_, _)
+ | ty::Generator(..)
+ | ty::Never
+ | ty::Tuple(_)
+ | ty::GeneratorWitness(_)
+ | ty::GeneratorWitnessMIR(..) => {
+ // Only consider auto impls if there are no manual impls for the root of `self_ty`.
+ //
+ // For example, we only consider auto candidates for `&i32: Auto` if no explicit impl
+ // for `&SomeType: Auto` exists. Due to E0321 the only crate where impls
+ // for `&SomeType: Auto` can be defined is the crate where `Auto` has been defined.
+ //
+ // Generally, we have to guarantee that for all `SimplifiedType`s the only crate
+ // which may define impls for that type is either the crate defining the type
+ // or the trait. This should be guaranteed by the orphan check.
+ let mut has_impl = false;
+ self.tcx().for_each_relevant_impl(def_id, self_ty, |_| has_impl = true);
+ if !has_impl {
+ candidates.vec.push(AutoImplCandidate)
+ }
+ }
+ ty::Error(_) => {} // do not add an auto trait impl for `ty::Error` for now.
}
}
}
@@ -651,7 +701,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let ty = traits::normalize_projection_type(
self,
param_env,
- tcx.mk_alias_ty(tcx.lang_items().deref_target()?, trait_ref.substs),
+ tcx.mk_alias_ty(tcx.lang_items().deref_target()?, trait_ref.args),
cause.clone(),
0,
// We're *intentionally* throwing these away,
@@ -689,13 +739,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// Don't add any candidates if there are bound regions.
return;
};
- let target = obligation.predicate.skip_binder().trait_ref.substs.type_at(1);
+ let target = obligation.predicate.skip_binder().trait_ref.args.type_at(1);
debug!(?source, ?target, "assemble_candidates_for_unsizing");
match (source.kind(), target.kind()) {
// Trait+Kx+'a -> Trait+Ky+'b (upcasts).
- (&ty::Dynamic(ref data_a, _, ty::Dyn), &ty::Dynamic(ref data_b, _, ty::Dyn)) => {
+ (
+ &ty::Dynamic(ref a_data, a_region, ty::Dyn),
+ &ty::Dynamic(ref b_data, b_region, ty::Dyn),
+ ) => {
// Upcast coercions permit several things:
//
// 1. Dropping auto traits, e.g., `Foo + Send` to `Foo`
@@ -707,19 +760,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
//
// We always perform upcasting coercions when we can because of reason
// #2 (region bounds).
- let auto_traits_compatible = data_b
+ let auto_traits_compatible = b_data
.auto_traits()
// All of a's auto traits need to be in b's auto traits.
- .all(|b| data_a.auto_traits().any(|a| a == b));
+ .all(|b| a_data.auto_traits().any(|a| a == b));
if auto_traits_compatible {
- let principal_def_id_a = data_a.principal_def_id();
- let principal_def_id_b = data_b.principal_def_id();
+ let principal_def_id_a = a_data.principal_def_id();
+ let principal_def_id_b = b_data.principal_def_id();
if principal_def_id_a == principal_def_id_b {
// no cyclic
candidates.vec.push(BuiltinUnsizeCandidate);
} else if principal_def_id_a.is_some() && principal_def_id_b.is_some() {
// not casual unsizing, now check whether this is trait upcasting coercion.
- let principal_a = data_a.principal().unwrap();
+ let principal_a = a_data.principal().unwrap();
let target_trait_did = principal_def_id_b.unwrap();
let source_trait_ref = principal_a.with_self_ty(self.tcx(), source);
if let Some(deref_trait_ref) = self.need_migrate_deref_output_trait_object(
@@ -735,9 +788,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
for (idx, upcast_trait_ref) in
util::supertraits(self.tcx(), source_trait_ref).enumerate()
{
- if upcast_trait_ref.def_id() == target_trait_did {
- candidates.vec.push(TraitUpcastingUnsizeCandidate(idx));
- }
+ self.infcx.probe(|_| {
+ if upcast_trait_ref.def_id() == target_trait_did
+ && let Ok(nested) = self.match_upcast_principal(
+ obligation,
+ upcast_trait_ref,
+ a_data,
+ b_data,
+ a_region,
+ b_region,
+ )
+ {
+ if nested.is_none() {
+ candidates.ambiguous = true;
+ }
+ candidates.vec.push(TraitUpcastingUnsizeCandidate(idx));
+ }
+ })
}
}
}
@@ -842,7 +909,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
) {
// If the predicate is `~const Destruct` in a non-const environment, we don't actually need
// to check anything. We'll short-circuit checking any obligations in confirmation, too.
- if !obligation.is_const() {
+ // FIXME(effects)
+ if true {
candidates.vec.push(ConstDestructCandidate(None));
return;
}
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 7adc29bbb..88d030033 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -11,10 +11,10 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_hir::lang_items::LangItem;
use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
-use rustc_middle::traits::SelectionOutputTypeParameterMismatch;
+use rustc_middle::traits::{BuiltinImplSource, SelectionOutputTypeParameterMismatch};
use rustc_middle::ty::{
- self, Binder, GenericParamDefKind, InternalSubsts, SubstsRef, ToPolyTraitRef, ToPredicate,
- TraitPredicate, TraitRef, Ty, TyCtxt, TypeVisitableExt,
+ self, GenericArgs, GenericArgsRef, GenericParamDefKind, ToPolyTraitRef, ToPredicate,
+ TraitPredicate, Ty, TyCtxt, TypeVisitableExt,
};
use rustc_span::def_id::DefId;
@@ -26,9 +26,9 @@ use crate::traits::vtable::{
};
use crate::traits::{
BuiltinDerivedObligation, ImplDerivedObligation, ImplDerivedObligationCause, ImplSource,
- ImplSourceObjectData, ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, Normalized,
- Obligation, ObligationCause, OutputTypeParameterMismatch, PolyTraitObligation,
- PredicateObligation, Selection, SelectionError, TraitNotObjectSafe, Unimplemented,
+ ImplSourceUserDefinedData, Normalized, Obligation, ObligationCause,
+ OutputTypeParameterMismatch, PolyTraitObligation, PredicateObligation, Selection,
+ SelectionError, TraitNotObjectSafe, Unimplemented,
};
use super::BuiltinImplConditions;
@@ -48,18 +48,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let mut impl_src = match candidate {
BuiltinCandidate { has_nested } => {
let data = self.confirm_builtin_candidate(obligation, has_nested);
- ImplSource::Builtin(data)
+ ImplSource::Builtin(BuiltinImplSource::Misc, data)
}
TransmutabilityCandidate => {
let data = self.confirm_transmutability_candidate(obligation)?;
- ImplSource::Builtin(data)
+ ImplSource::Builtin(BuiltinImplSource::Misc, data)
}
ParamCandidate(param) => {
let obligations =
self.confirm_param_candidate(obligation, param.map_bound(|t| t.trait_ref));
- ImplSource::Param(obligations, param.skip_binder().constness)
+ ImplSource::Param(obligations)
}
ImplCandidate(impl_def_id) => {
@@ -68,64 +68,57 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
AutoImplCandidate => {
let data = self.confirm_auto_impl_candidate(obligation)?;
- ImplSource::Builtin(data)
+ ImplSource::Builtin(BuiltinImplSource::Misc, data)
}
- ProjectionCandidate(idx, constness) => {
+ ProjectionCandidate(idx, _) => {
let obligations = self.confirm_projection_candidate(obligation, idx)?;
- ImplSource::Param(obligations, constness)
+ ImplSource::Param(obligations)
}
- ObjectCandidate(idx) => {
- let data = self.confirm_object_candidate(obligation, idx)?;
- ImplSource::Object(data)
- }
+ ObjectCandidate(idx) => self.confirm_object_candidate(obligation, idx)?,
ClosureCandidate { .. } => {
let vtable_closure = self.confirm_closure_candidate(obligation)?;
- ImplSource::Builtin(vtable_closure)
+ ImplSource::Builtin(BuiltinImplSource::Misc, vtable_closure)
}
GeneratorCandidate => {
let vtable_generator = self.confirm_generator_candidate(obligation)?;
- ImplSource::Builtin(vtable_generator)
+ ImplSource::Builtin(BuiltinImplSource::Misc, vtable_generator)
}
FutureCandidate => {
let vtable_future = self.confirm_future_candidate(obligation)?;
- ImplSource::Builtin(vtable_future)
+ ImplSource::Builtin(BuiltinImplSource::Misc, vtable_future)
}
FnPointerCandidate { is_const } => {
let data = self.confirm_fn_pointer_candidate(obligation, is_const)?;
- ImplSource::Builtin(data)
+ ImplSource::Builtin(BuiltinImplSource::Misc, data)
}
TraitAliasCandidate => {
let data = self.confirm_trait_alias_candidate(obligation);
- ImplSource::Builtin(data)
+ ImplSource::Builtin(BuiltinImplSource::Misc, data)
}
BuiltinObjectCandidate => {
// This indicates something like `Trait + Send: Send`. In this case, we know that
// this holds because that's what the object type is telling us, and there's really
// no additional obligations to prove and no types in particular to unify, etc.
- ImplSource::Builtin(Vec::new())
+ ImplSource::Builtin(BuiltinImplSource::Misc, Vec::new())
}
- BuiltinUnsizeCandidate => {
- let data = self.confirm_builtin_unsize_candidate(obligation)?;
- ImplSource::Builtin(data)
- }
+ BuiltinUnsizeCandidate => self.confirm_builtin_unsize_candidate(obligation)?,
TraitUpcastingUnsizeCandidate(idx) => {
- let data = self.confirm_trait_upcasting_unsize_candidate(obligation, idx)?;
- ImplSource::TraitUpcasting(data)
+ self.confirm_trait_upcasting_unsize_candidate(obligation, idx)?
}
ConstDestructCandidate(def_id) => {
let data = self.confirm_const_destruct_candidate(obligation, def_id)?;
- ImplSource::Builtin(data)
+ ImplSource::Builtin(BuiltinImplSource::Misc, data)
}
};
@@ -135,14 +128,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
subobligation.set_depth_from_parent(obligation.recursion_depth);
}
- if !obligation.predicate.is_const_if_const() {
- // normalize nested predicates according to parent predicate's constness.
- impl_src = impl_src.map(|mut o| {
- o.predicate = o.predicate.without_const(self.tcx());
- o
- });
- }
-
Ok(impl_src)
}
@@ -158,15 +143,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
self.infcx.instantiate_binder_with_placeholders(trait_predicate).trait_ref;
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() {
+ let (def_id, args) = match *placeholder_self_ty.kind() {
// 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)
+ ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
+ (def_id, args)
}
_ => bug!("projection candidate for unexpected type: {:?}", placeholder_self_ty),
};
- let candidate_predicate = tcx.item_bounds(def_id).map_bound(|i| i[idx]).subst(tcx, substs);
+ let candidate_predicate =
+ tcx.item_bounds(def_id).map_bound(|i| i[idx]).instantiate(tcx, args);
let candidate = candidate_predicate
.as_trait_clause()
.expect("projection candidate is not a trait predicate")
@@ -190,7 +176,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
})?);
if let ty::Alias(ty::Projection, ..) = placeholder_self_ty.kind() {
- let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs);
+ let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, args);
for (predicate, _) in predicates {
let normalized = normalize_with_depth_to(
self,
@@ -298,8 +284,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.collect(),
Condition::IfTransmutable { src, dst } => {
let trait_def_id = obligation.predicate.def_id();
- let scope = predicate.trait_ref.substs.type_at(2);
- let assume_const = predicate.trait_ref.substs.const_at(3);
+ let scope = predicate.trait_ref.args.type_at(2);
+ let assume_const = predicate.trait_ref.args.const_at(3);
let make_obl = |from_ty, to_ty| {
let trait_ref1 = ty::TraitRef::new(
tcx,
@@ -342,19 +328,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let Some(assume) = rustc_transmute::Assume::from_const(
self.infcx.tcx,
obligation.param_env,
- predicate.trait_ref.substs.const_at(3)
+ predicate.trait_ref.args.const_at(3),
) else {
return Err(Unimplemented);
};
- let dst = predicate.trait_ref.substs.type_at(0);
- let src = predicate.trait_ref.substs.type_at(1);
+ let dst = predicate.trait_ref.args.type_at(0);
+ let src = predicate.trait_ref.args.type_at(1);
debug!(?src, ?dst);
let mut transmute_env = rustc_transmute::TransmuteTypeEnv::new(self.infcx);
let maybe_transmutable = transmute_env.is_transmutable(
obligation.cause.clone(),
rustc_transmute::Types { dst, src },
- predicate.trait_ref.substs.type_at(2),
+ predicate.trait_ref.args.type_at(2),
assume,
);
@@ -402,7 +388,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation.recursion_depth + 1,
obligation.param_env,
trait_def_id,
- &trait_ref.substs,
+ &trait_ref.args,
obligation.predicate,
);
@@ -433,12 +419,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// First, create the substitutions by matching the impl again,
// this time not in a probe.
- let substs = self.rematch_impl(impl_def_id, obligation);
- debug!(?substs, "impl substs");
+ let args = self.rematch_impl(impl_def_id, obligation);
+ debug!(?args, "impl args");
ensure_sufficient_stack(|| {
self.vtable_impl(
impl_def_id,
- substs,
+ args,
&obligation.cause,
obligation.recursion_depth + 1,
obligation.param_env,
@@ -450,40 +436,40 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn vtable_impl(
&mut self,
impl_def_id: DefId,
- substs: Normalized<'tcx, SubstsRef<'tcx>>,
+ args: Normalized<'tcx, GenericArgsRef<'tcx>>,
cause: &ObligationCause<'tcx>,
recursion_depth: usize,
param_env: ty::ParamEnv<'tcx>,
parent_trait_pred: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
) -> ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>> {
- debug!(?impl_def_id, ?substs, ?recursion_depth, "vtable_impl");
+ debug!(?impl_def_id, ?args, ?recursion_depth, "vtable_impl");
let mut impl_obligations = self.impl_or_trait_obligations(
cause,
recursion_depth,
param_env,
impl_def_id,
- &substs.value,
+ &args.value,
parent_trait_pred,
);
debug!(?impl_obligations, "vtable_impl");
// Because of RFC447, the impl-trait-ref and obligations
- // are sufficient to determine the impl substs, without
+ // are sufficient to determine the impl args, without
// relying on projections in the impl-trait-ref.
//
// e.g., `impl<U: Tr, V: Iterator<Item=U>> Foo<<U as Tr>::T> for V`
- impl_obligations.extend(substs.obligations);
+ impl_obligations.extend(args.obligations);
- ImplSourceUserDefinedData { impl_def_id, substs: substs.value, nested: impl_obligations }
+ ImplSourceUserDefinedData { impl_def_id, args: args.value, nested: impl_obligations }
}
fn confirm_object_candidate(
&mut self,
obligation: &PolyTraitObligation<'tcx>,
index: usize,
- ) -> Result<ImplSourceObjectData<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
+ ) -> Result<ImplSource<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
let tcx = self.tcx();
debug!(?obligation, ?index, "confirm_object_candidate");
@@ -531,7 +517,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// will be checked in the code below.
for super_trait in tcx
.super_predicates_of(trait_predicate.def_id())
- .instantiate(tcx, trait_predicate.trait_ref.substs)
+ .instantiate(tcx, trait_predicate.trait_ref.args)
.predicates
.into_iter()
{
@@ -569,68 +555,65 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// higher-ranked things.
// Prevent, e.g., `dyn Iterator<Item = str>`.
for bound in self.tcx().item_bounds(assoc_type).transpose_iter() {
- let subst_bound =
- if defs.count() == 0 {
- bound.subst(tcx, trait_predicate.trait_ref.substs)
- } else {
- let mut substs = smallvec::SmallVec::with_capacity(defs.count());
- substs.extend(trait_predicate.trait_ref.substs.iter());
- let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> =
- smallvec::SmallVec::with_capacity(
- bound.skip_binder().kind().bound_vars().len() + defs.count(),
- );
- bound_vars.extend(bound.skip_binder().kind().bound_vars().into_iter());
- InternalSubsts::fill_single(&mut substs, defs, &mut |param, _| match param
- .kind
- {
- GenericParamDefKind::Type { .. } => {
- let kind = ty::BoundTyKind::Param(param.def_id, param.name);
- let bound_var = ty::BoundVariableKind::Ty(kind);
- bound_vars.push(bound_var);
- Ty::new_bound(
- tcx,
- ty::INNERMOST,
- ty::BoundTy {
- var: ty::BoundVar::from_usize(bound_vars.len() - 1),
- kind,
- },
- )
- .into()
- }
- GenericParamDefKind::Lifetime => {
- let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name);
- let bound_var = ty::BoundVariableKind::Region(kind);
- bound_vars.push(bound_var);
- ty::Region::new_late_bound(
- tcx,
- ty::INNERMOST,
- ty::BoundRegion {
- var: ty::BoundVar::from_usize(bound_vars.len() - 1),
- kind,
- },
- )
- .into()
- }
- GenericParamDefKind::Const { .. } => {
- let bound_var = ty::BoundVariableKind::Const;
- bound_vars.push(bound_var);
- ty::Const::new_bound(
- tcx,
- ty::INNERMOST,
- ty::BoundVar::from_usize(bound_vars.len() - 1),
- tcx.type_of(param.def_id)
- .no_bound_vars()
- .expect("const parameter types cannot be generic"),
- )
- .into()
- }
- });
- let bound_vars = tcx.mk_bound_variable_kinds(&bound_vars);
- let assoc_ty_substs = tcx.mk_substs(&substs);
- let bound =
- bound.map_bound(|b| b.kind().skip_binder()).subst(tcx, assoc_ty_substs);
- ty::Binder::bind_with_vars(bound, bound_vars).to_predicate(tcx)
- };
+ let subst_bound = if defs.count() == 0 {
+ bound.instantiate(tcx, trait_predicate.trait_ref.args)
+ } else {
+ let mut args = smallvec::SmallVec::with_capacity(defs.count());
+ args.extend(trait_predicate.trait_ref.args.iter());
+ let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> =
+ smallvec::SmallVec::with_capacity(
+ bound.skip_binder().kind().bound_vars().len() + defs.count(),
+ );
+ bound_vars.extend(bound.skip_binder().kind().bound_vars().into_iter());
+ GenericArgs::fill_single(&mut args, defs, &mut |param, _| match param.kind {
+ GenericParamDefKind::Type { .. } => {
+ let kind = ty::BoundTyKind::Param(param.def_id, param.name);
+ let bound_var = ty::BoundVariableKind::Ty(kind);
+ bound_vars.push(bound_var);
+ Ty::new_bound(
+ tcx,
+ ty::INNERMOST,
+ ty::BoundTy {
+ var: ty::BoundVar::from_usize(bound_vars.len() - 1),
+ kind,
+ },
+ )
+ .into()
+ }
+ GenericParamDefKind::Lifetime => {
+ let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name);
+ let bound_var = ty::BoundVariableKind::Region(kind);
+ bound_vars.push(bound_var);
+ ty::Region::new_late_bound(
+ tcx,
+ ty::INNERMOST,
+ ty::BoundRegion {
+ var: ty::BoundVar::from_usize(bound_vars.len() - 1),
+ kind,
+ },
+ )
+ .into()
+ }
+ GenericParamDefKind::Const { .. } => {
+ let bound_var = ty::BoundVariableKind::Const;
+ bound_vars.push(bound_var);
+ ty::Const::new_bound(
+ tcx,
+ ty::INNERMOST,
+ ty::BoundVar::from_usize(bound_vars.len() - 1),
+ tcx.type_of(param.def_id)
+ .no_bound_vars()
+ .expect("const parameter types cannot be generic"),
+ )
+ .into()
+ }
+ });
+ let bound_vars = tcx.mk_bound_variable_kinds(&bound_vars);
+ let assoc_ty_args = tcx.mk_args(&args);
+ let bound =
+ bound.map_bound(|b| b.kind().skip_binder()).instantiate(tcx, assoc_ty_args);
+ ty::Binder::bind_with_vars(bound, bound_vars).to_predicate(tcx)
+ };
let normalized_bound = normalize_with_depth_to(
self,
obligation.param_env,
@@ -650,22 +633,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
(unnormalized_upcast_trait_ref, ty::Binder::dummy(object_trait_ref)),
);
- Ok(ImplSourceObjectData { vtable_base, nested })
+ Ok(ImplSource::Builtin(BuiltinImplSource::Object { vtable_base: vtable_base }, nested))
}
fn confirm_fn_pointer_candidate(
&mut self,
obligation: &PolyTraitObligation<'tcx>,
- is_const: bool,
+ // FIXME(effects)
+ _is_const: bool,
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
debug!(?obligation, "confirm_fn_pointer_candidate");
let tcx = self.tcx();
- let Some(self_ty) = self
- .infcx
- .shallow_resolve(obligation.self_ty().no_bound_vars()) else
- {
+ let Some(self_ty) = self.infcx.shallow_resolve(obligation.self_ty().no_bound_vars()) else {
// FIXME: Ideally we'd support `for<'a> fn(&'a ()): Fn(&'a ())`,
// but we do not currently. Luckily, such a bound is not
// particularly useful, so we don't expect users to write
@@ -686,16 +667,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let mut nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
let cause = obligation.derived_cause(BuiltinDerivedObligation);
- if obligation.is_const() && !is_const {
- // function is a trait method
- if let ty::FnDef(def_id, substs) = self_ty.kind() && let Some(trait_id) = tcx.trait_of_item(*def_id) {
- let trait_ref = TraitRef::from_method(tcx, trait_id, *substs);
- let poly_trait_pred = Binder::dummy(trait_ref).with_constness(ty::BoundConstness::ConstIfConst);
- let obligation = Obligation::new(tcx, cause.clone(), obligation.param_env, poly_trait_pred);
- nested.push(obligation);
- }
- }
-
// Confirm the `type Output: Sized;` bound that is present on `FnOnce`
let output_ty = self.infcx.instantiate_binder_with_placeholders(sig.output());
let output_ty = normalize_with_depth_to(
@@ -721,14 +692,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let predicate = self.infcx.instantiate_binder_with_placeholders(obligation.predicate);
let trait_ref = predicate.trait_ref;
let trait_def_id = trait_ref.def_id;
- let substs = trait_ref.substs;
+ let args = trait_ref.args;
let trait_obligations = self.impl_or_trait_obligations(
&obligation.cause,
obligation.recursion_depth,
obligation.param_env,
trait_def_id,
- &substs,
+ &args,
obligation.predicate,
);
@@ -741,17 +712,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
&mut self,
obligation: &PolyTraitObligation<'tcx>,
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
- // Okay to skip binder because the substs on generator types never
+ // Okay to skip binder because the args on generator types never
// touch bound regions, they just capture the in-scope
// type/region parameters.
let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
- let ty::Generator(generator_def_id, substs, _) = *self_ty.kind() else {
+ let ty::Generator(generator_def_id, args, _) = *self_ty.kind() else {
bug!("closure candidate for non-closure {:?}", obligation);
};
- debug!(?obligation, ?generator_def_id, ?substs, "confirm_generator_candidate");
+ debug!(?obligation, ?generator_def_id, ?args, "confirm_generator_candidate");
- let gen_sig = substs.as_generator().poly_sig();
+ let gen_sig = args.as_generator().poly_sig();
// NOTE: The self-type is a generator type and hence is
// in fact unparameterized (or at least does not reference any
@@ -780,17 +751,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
&mut self,
obligation: &PolyTraitObligation<'tcx>,
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
- // Okay to skip binder because the substs on generator types never
+ // Okay to skip binder because the args on generator types never
// touch bound regions, they just capture the in-scope
// type/region parameters.
let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
- let ty::Generator(generator_def_id, substs, _) = *self_ty.kind() else {
+ let ty::Generator(generator_def_id, args, _) = *self_ty.kind() else {
bug!("closure candidate for non-closure {:?}", obligation);
};
- debug!(?obligation, ?generator_def_id, ?substs, "confirm_future_candidate");
+ debug!(?obligation, ?generator_def_id, ?args, "confirm_future_candidate");
- let gen_sig = substs.as_generator().poly_sig();
+ let gen_sig = args.as_generator().poly_sig();
let trait_ref = super::util::future_trait_ref_and_outputs(
self.tcx(),
@@ -816,22 +787,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.fn_trait_kind_from_def_id(obligation.predicate.def_id())
.unwrap_or_else(|| bug!("closure candidate for non-fn trait {:?}", obligation));
- // Okay to skip binder because the substs on closure types never
+ // Okay to skip binder because the args on closure types never
// touch bound regions, they just capture the in-scope
// type/region parameters.
let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
- let ty::Closure(closure_def_id, substs) = *self_ty.kind() else {
+ let ty::Closure(closure_def_id, args) = *self_ty.kind() else {
bug!("closure candidate for non-closure {:?}", obligation);
};
- let trait_ref = self.closure_trait_ref_unnormalized(obligation, substs);
+ let trait_ref = self.closure_trait_ref_unnormalized(obligation, args);
let mut nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
debug!(?closure_def_id, ?trait_ref, ?nested, "confirm closure candidate obligations");
nested.push(obligation.with(
self.tcx(),
- ty::Binder::dummy(ty::PredicateKind::ClosureKind(closure_def_id, substs, kind)),
+ ty::Binder::dummy(ty::PredicateKind::ClosureKind(closure_def_id, args, kind)),
));
Ok(nested)
@@ -902,73 +873,32 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
&mut self,
obligation: &PolyTraitObligation<'tcx>,
idx: usize,
- ) -> Result<ImplSourceTraitUpcastingData<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
+ ) -> Result<ImplSource<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
let tcx = self.tcx();
// `assemble_candidates_for_unsizing` should ensure there are no late-bound
// regions here. See the comment there for more details.
- let source = self.infcx.shallow_resolve(obligation.self_ty().no_bound_vars().unwrap());
- let target = obligation.predicate.skip_binder().trait_ref.substs.type_at(1);
- let target = self.infcx.shallow_resolve(target);
-
- debug!(?source, ?target, "confirm_trait_upcasting_unsize_candidate");
-
- let mut nested = vec![];
- let source_trait_ref;
- let upcast_trait_ref;
- match (source.kind(), target.kind()) {
- // TraitA+Kx+'a -> TraitB+Ky+'b (trait upcasting coercion).
- (
- &ty::Dynamic(ref data_a, r_a, repr_a @ ty::Dyn),
- &ty::Dynamic(ref data_b, r_b, ty::Dyn),
- ) => {
- // See `assemble_candidates_for_unsizing` for more info.
- // We already checked the compatibility of auto traits within `assemble_candidates_for_unsizing`.
- let principal_a = data_a.principal().unwrap();
- source_trait_ref = principal_a.with_self_ty(tcx, source);
- upcast_trait_ref = util::supertraits(tcx, source_trait_ref).nth(idx).unwrap();
- assert_eq!(data_b.principal_def_id(), Some(upcast_trait_ref.def_id()));
- let existential_predicate = upcast_trait_ref.map_bound(|trait_ref| {
- ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef::erase_self_ty(
- tcx, trait_ref,
- ))
- });
- let iter = Some(existential_predicate)
- .into_iter()
- .chain(
- data_a
- .projection_bounds()
- .map(|b| b.map_bound(ty::ExistentialPredicate::Projection)),
- )
- .chain(
- data_b
- .auto_traits()
- .map(ty::ExistentialPredicate::AutoTrait)
- .map(ty::Binder::dummy),
- );
- let existential_predicates = tcx.mk_poly_existential_predicates_from_iter(iter);
- let source_trait = Ty::new_dynamic(tcx, existential_predicates, r_b, repr_a);
-
- // Require that the traits involved in this upcast are **equal**;
- // only the **lifetime bound** is changed.
- let InferOk { obligations, .. } = self
- .infcx
- .at(&obligation.cause, obligation.param_env)
- .sup(DefineOpaqueTypes::No, target, source_trait)
- .map_err(|_| Unimplemented)?;
- nested.extend(obligations);
-
- let outlives = ty::OutlivesPredicate(r_a, r_b);
- nested.push(Obligation::with_depth(
- tcx,
- obligation.cause.clone(),
- obligation.recursion_depth + 1,
- obligation.param_env,
- obligation.predicate.rebind(outlives),
- ));
- }
- _ => bug!(),
- };
+ let predicate = obligation.predicate.no_bound_vars().unwrap();
+ let a_ty = self.infcx.shallow_resolve(predicate.self_ty());
+ let b_ty = self.infcx.shallow_resolve(predicate.trait_ref.args.type_at(1));
+
+ let ty::Dynamic(a_data, a_region, ty::Dyn) = *a_ty.kind() else { bug!() };
+ let ty::Dynamic(b_data, b_region, ty::Dyn) = *b_ty.kind() else { bug!() };
+
+ let source_principal = a_data.principal().unwrap().with_self_ty(tcx, a_ty);
+ let unnormalized_upcast_principal =
+ util::supertraits(tcx, source_principal).nth(idx).unwrap();
+
+ let nested = self
+ .match_upcast_principal(
+ obligation,
+ unnormalized_upcast_principal,
+ a_data,
+ b_data,
+ a_region,
+ b_region,
+ )?
+ .expect("did not expect ambiguity during confirmation");
let vtable_segment_callback = {
let mut vptr_offset = 0;
@@ -979,7 +909,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
vptr_offset += count_own_vtable_entries(tcx, trait_ref);
- if trait_ref == upcast_trait_ref {
+ if trait_ref == unnormalized_upcast_principal {
if emit_vptr {
return ControlFlow::Break(Some(vptr_offset));
} else {
@@ -997,27 +927,25 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
};
let vtable_vptr_slot =
- prepare_vtable_segments(tcx, source_trait_ref, vtable_segment_callback).unwrap();
+ prepare_vtable_segments(tcx, source_principal, vtable_segment_callback).unwrap();
- Ok(ImplSourceTraitUpcastingData { vtable_vptr_slot, nested })
+ Ok(ImplSource::Builtin(BuiltinImplSource::TraitUpcasting { vtable_vptr_slot }, nested))
}
fn confirm_builtin_unsize_candidate(
&mut self,
obligation: &PolyTraitObligation<'tcx>,
- ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
+ ) -> Result<ImplSource<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
let tcx = self.tcx();
// `assemble_candidates_for_unsizing` should ensure there are no late-bound
// regions here. See the comment there for more details.
let source = self.infcx.shallow_resolve(obligation.self_ty().no_bound_vars().unwrap());
- let target = obligation.predicate.skip_binder().trait_ref.substs.type_at(1);
+ let target = obligation.predicate.skip_binder().trait_ref.args.type_at(1);
let target = self.infcx.shallow_resolve(target);
-
debug!(?source, ?target, "confirm_builtin_unsize_candidate");
- let mut nested = vec![];
- match (source.kind(), target.kind()) {
+ Ok(match (source.kind(), target.kind()) {
// Trait+Kx+'a -> Trait+Ky+'b (auto traits and lifetime subtyping).
(&ty::Dynamic(ref data_a, r_a, dyn_a), &ty::Dynamic(ref data_b, r_b, dyn_b))
if dyn_a == dyn_b =>
@@ -1044,22 +972,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// Require that the traits involved in this upcast are **equal**;
// only the **lifetime bound** is changed.
- let InferOk { obligations, .. } = self
+ let InferOk { mut obligations, .. } = self
.infcx
.at(&obligation.cause, obligation.param_env)
.sup(DefineOpaqueTypes::No, target, source_trait)
.map_err(|_| Unimplemented)?;
- nested.extend(obligations);
// Register one obligation for 'a: 'b.
let outlives = ty::OutlivesPredicate(r_a, r_b);
- nested.push(Obligation::with_depth(
+ obligations.push(Obligation::with_depth(
tcx,
obligation.cause.clone(),
obligation.recursion_depth + 1,
obligation.param_env,
obligation.predicate.rebind(outlives),
));
+
+ ImplSource::Builtin(BuiltinImplSource::Misc, obligations)
}
// `T` -> `Trait`
@@ -1085,11 +1014,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// words, if the object type is `Foo + Send`, this would create an obligation for
// the `Send` check.)
// - Projection predicates
- nested.extend(
- data.iter().map(|predicate| {
- predicate_to_obligation(predicate.with_self_ty(tcx, source))
- }),
- );
+ let mut nested: Vec<_> = data
+ .iter()
+ .map(|predicate| predicate_to_obligation(predicate.with_self_ty(tcx, source)))
+ .collect();
// We can only make objects from sized types.
let tr = ty::TraitRef::from_lang_item(
@@ -1106,6 +1034,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
nested.push(predicate_to_obligation(
ty::Binder::dummy(ty::ClauseKind::TypeOutlives(outlives)).to_predicate(tcx),
));
+
+ ImplSource::Builtin(BuiltinImplSource::Misc, nested)
}
// `[T; n]` -> `[T]`
@@ -1115,11 +1045,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.at(&obligation.cause, obligation.param_env)
.eq(DefineOpaqueTypes::No, b, a)
.map_err(|_| Unimplemented)?;
- nested.extend(obligations);
+
+ ImplSource::Builtin(BuiltinImplSource::Misc, obligations)
}
// `Struct<T>` -> `Struct<U>`
- (&ty::Adt(def, substs_a), &ty::Adt(_, substs_b)) => {
+ (&ty::Adt(def, args_a), &ty::Adt(_, args_b)) => {
let unsizing_params = tcx.unsizing_params_for_adt(def.did());
if unsizing_params.is_empty() {
return Err(Unimplemented);
@@ -1128,6 +1059,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let tail_field = def.non_enum_variant().tail();
let tail_field_ty = tcx.type_of(tail_field.did);
+ let mut nested = vec![];
+
// Extract `TailField<T>` and `TailField<U>` from `Struct<T>` and `Struct<U>`,
// normalizing in the process, since `type_of` returns something directly from
// astconv (which means it's un-normalized).
@@ -1136,7 +1069,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation.param_env,
obligation.cause.clone(),
obligation.recursion_depth + 1,
- tail_field_ty.subst(tcx, substs_a),
+ tail_field_ty.instantiate(tcx, args_a),
&mut nested,
);
let target_tail = normalize_with_depth_to(
@@ -1144,16 +1077,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation.param_env,
obligation.cause.clone(),
obligation.recursion_depth + 1,
- tail_field_ty.subst(tcx, substs_b),
+ tail_field_ty.instantiate(tcx, args_b),
&mut nested,
);
// Check that the source struct with the target's
// unsizing parameters is equal to the target.
- let substs = tcx.mk_substs_from_iter(substs_a.iter().enumerate().map(|(i, k)| {
- if unsizing_params.contains(i as u32) { substs_b[i] } else { k }
- }));
- let new_struct = Ty::new_adt(tcx, def, substs);
+ let args =
+ tcx.mk_args_from_iter(args_a.iter().enumerate().map(|(i, k)| {
+ if unsizing_params.contains(i as u32) { args_b[i] } else { k }
+ }));
+ let new_struct = Ty::new_adt(tcx, def, args);
let InferOk { obligations, .. } = self
.infcx
.at(&obligation.cause, obligation.param_env)
@@ -1171,6 +1105,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
),
);
nested.push(tail_unsize_obligation);
+
+ ImplSource::Builtin(BuiltinImplSource::Misc, nested)
}
// `(.., T)` -> `(.., U)`
@@ -1185,25 +1121,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// last element is equal to the target.
let new_tuple =
Ty::new_tup_from_iter(tcx, a_mid.iter().copied().chain(iter::once(b_last)));
- let InferOk { obligations, .. } = self
+ let InferOk { mut obligations, .. } = self
.infcx
.at(&obligation.cause, obligation.param_env)
.eq(DefineOpaqueTypes::No, target, new_tuple)
.map_err(|_| Unimplemented)?;
- nested.extend(obligations);
// Add a nested `T: Unsize<U>` predicate.
let last_unsize_obligation = obligation.with(
tcx,
ty::TraitRef::new(tcx, obligation.predicate.def_id(), [a_last, b_last]),
);
- nested.push(last_unsize_obligation);
+ obligations.push(last_unsize_obligation);
+
+ ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, obligations)
}
_ => bug!("source: {source}, target: {target}"),
- };
-
- Ok(nested)
+ })
}
fn confirm_const_destruct_candidate(
@@ -1212,7 +1147,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
impl_def_id: Option<DefId>,
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
// `~const Destruct` in a non-const environment is always trivially true, since our type is `Drop`
- if !obligation.is_const() {
+ // FIXME(effects)
+ if true {
return Ok(vec![]);
}
@@ -1233,8 +1169,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
trait_pred.trait_ref.def_id = drop_trait;
trait_pred
});
- let substs = self.rematch_impl(impl_def_id, &new_obligation);
- debug!(?substs, "impl substs");
+ let args = self.rematch_impl(impl_def_id, &new_obligation);
+ debug!(?args, "impl args");
let cause = obligation.derived_cause(|derived| {
ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
@@ -1247,7 +1183,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let obligations = ensure_sufficient_stack(|| {
self.vtable_impl(
impl_def_id,
- substs,
+ args,
&cause,
new_obligation.recursion_depth + 1,
new_obligation.param_env,
@@ -1259,7 +1195,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// We want to confirm the ADT's fields if we have an ADT
let mut stack = match *self_ty.skip_binder().kind() {
- ty::Adt(def, substs) => def.all_fields().map(|f| f.ty(tcx, substs)).collect(),
+ ty::Adt(def, args) => def.all_fields().map(|f| f.ty(tcx, args)).collect(),
_ => vec![self_ty.skip_binder()],
};
@@ -1292,20 +1228,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ty::Tuple(tys) => {
stack.extend(tys.iter());
}
- ty::Closure(_, substs) => {
- stack.push(substs.as_closure().tupled_upvars_ty());
+ ty::Closure(_, args) => {
+ stack.push(args.as_closure().tupled_upvars_ty());
}
- ty::Generator(_, substs, _) => {
- let generator = substs.as_generator();
+ ty::Generator(_, args, _) => {
+ let generator = args.as_generator();
stack.extend([generator.tupled_upvars_ty(), generator.witness()]);
}
ty::GeneratorWitness(tys) => {
stack.extend(tcx.erase_late_bound_regions(tys).to_vec());
}
- ty::GeneratorWitnessMIR(def_id, substs) => {
+ ty::GeneratorWitnessMIR(def_id, args) => {
let tcx = self.tcx();
stack.extend(tcx.generator_hidden_types(def_id).map(|bty| {
- let ty = bty.subst(tcx, substs);
+ let ty = bty.instantiate(tcx, args);
debug_assert!(!ty.has_late_bound_regions());
ty
}))
@@ -1314,6 +1250,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// If we have a projection type, make sure to normalize it so we replace it
// with a fresh infer variable
ty::Alias(ty::Projection | ty::Inherent, ..) => {
+ // FIXME(effects) this needs constness
let predicate = normalize_with_depth_to(
self,
obligation.param_env,
@@ -1326,7 +1263,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
cause.span,
[nested_ty],
),
- constness: ty::BoundConstness::ConstIfConst,
polarity: ty::ImplPolarity::Positive,
}),
&mut nested,
@@ -1345,6 +1281,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// since it's either not `const Drop` (and we raise an error during selection),
// or it's an ADT (and we need to check for a custom impl during selection)
_ => {
+ // FIXME(effects) this needs constness
let predicate = self_ty.rebind(ty::TraitPredicate {
trait_ref: ty::TraitRef::from_lang_item(
self.tcx(),
@@ -1352,7 +1289,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
cause.span,
[nested_ty],
),
- constness: ty::BoundConstness::ConstIfConst,
polarity: ty::ImplPolarity::Positive,
});
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 7f31ab751..19385e2d7 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -40,7 +40,7 @@ use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
use rustc_middle::ty::fold::BottomUpFolder;
use rustc_middle::ty::relate::TypeRelation;
-use rustc_middle::ty::SubstsRef;
+use rustc_middle::ty::GenericArgsRef;
use rustc_middle::ty::{self, EarlyBinder, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate};
use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
use rustc_span::symbol::sym;
@@ -74,22 +74,21 @@ impl IntercrateAmbiguityCause {
match self {
IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc } => {
let self_desc = if let Some(ty) = self_desc {
- format!(" for type `{}`", ty)
+ format!(" for type `{ty}`")
} else {
String::new()
};
- format!("downstream crates may implement trait `{}`{}", trait_desc, self_desc)
+ format!("downstream crates may implement trait `{trait_desc}`{self_desc}")
}
IntercrateAmbiguityCause::UpstreamCrateUpdate { trait_desc, self_desc } => {
let self_desc = if let Some(ty) = self_desc {
- format!(" for type `{}`", ty)
+ format!(" for type `{ty}`")
} else {
String::new()
};
format!(
- "upstream crates may add a new impl of trait `{}`{} \
- in future versions",
- trait_desc, self_desc
+ "upstream crates may add a new impl of trait `{trait_desc}`{self_desc} \
+ in future versions"
)
}
IntercrateAmbiguityCause::ReservationImpl { message } => message.clone(),
@@ -119,6 +118,8 @@ pub struct SelectionContext<'cx, 'tcx> {
/// policy. In essence, canonicalized queries need their errors propagated
/// rather than immediately reported because we do not have accurate spans.
query_mode: TraitQueryMode,
+
+ treat_inductive_cycle: TreatInductiveCycleAs,
}
// A stack that walks back up the stack frame.
@@ -199,6 +200,27 @@ enum BuiltinImplConditions<'tcx> {
Ambiguous,
}
+#[derive(Copy, Clone)]
+pub enum TreatInductiveCycleAs {
+ /// This is the previous behavior, where `Recur` represents an inductive
+ /// cycle that is known not to hold. This is not forwards-compatible with
+ /// coinduction, and will be deprecated. This is the default behavior
+ /// of the old trait solver due to back-compat reasons.
+ Recur,
+ /// This is the behavior of the new trait solver, where inductive cycles
+ /// are treated as ambiguous and possibly holding.
+ Ambig,
+}
+
+impl From<TreatInductiveCycleAs> for EvaluationResult {
+ fn from(treat: TreatInductiveCycleAs) -> EvaluationResult {
+ match treat {
+ TreatInductiveCycleAs::Ambig => EvaluatedToUnknown,
+ TreatInductiveCycleAs::Recur => EvaluatedToRecur,
+ }
+ }
+}
+
impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
pub fn new(infcx: &'cx InferCtxt<'tcx>) -> SelectionContext<'cx, 'tcx> {
SelectionContext {
@@ -206,9 +228,26 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
freshener: infcx.freshener(),
intercrate_ambiguity_causes: None,
query_mode: TraitQueryMode::Standard,
+ treat_inductive_cycle: TreatInductiveCycleAs::Recur,
}
}
+ // Sets the `TreatInductiveCycleAs` mode temporarily in the selection context
+ pub fn with_treat_inductive_cycle_as<T>(
+ &mut self,
+ treat_inductive_cycle: TreatInductiveCycleAs,
+ f: impl FnOnce(&mut Self) -> T,
+ ) -> T {
+ // Should be executed in a context where caching is disabled,
+ // otherwise the cache is poisoned with the temporary result.
+ assert!(self.is_intercrate());
+ let treat_inductive_cycle =
+ std::mem::replace(&mut self.treat_inductive_cycle, treat_inductive_cycle);
+ let value = f(self);
+ self.treat_inductive_cycle = treat_inductive_cycle;
+ value
+ }
+
pub fn with_query_mode(
infcx: &'cx InferCtxt<'tcx>,
query_mode: TraitQueryMode,
@@ -720,7 +759,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
stack.update_reached_depth(stack_arg.1);
return Ok(EvaluatedToOk);
} else {
- return Ok(EvaluatedToRecur);
+ return Ok(self.treat_inductive_cycle.into());
}
}
return Ok(EvaluatedToOk);
@@ -838,13 +877,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
}
ProjectAndUnifyResult::FailedNormalization => Ok(EvaluatedToAmbig),
- ProjectAndUnifyResult::Recursive => Ok(EvaluatedToRecur),
+ ProjectAndUnifyResult::Recursive => Ok(self.treat_inductive_cycle.into()),
ProjectAndUnifyResult::MismatchedProjectionTypes(_) => Ok(EvaluatedToErr),
}
}
- ty::PredicateKind::ClosureKind(_, closure_substs, kind) => {
- match self.infcx.closure_kind(closure_substs) {
+ ty::PredicateKind::ClosureKind(_, closure_args, kind) => {
+ match self.infcx.closure_kind(closure_args) {
Some(closure_kind) => {
if closure_kind.extends(kind) {
Ok(EvaluatedToOk)
@@ -895,7 +934,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.infcx
.at(&obligation.cause, obligation.param_env)
.trace(c1, c2)
- .eq(DefineOpaqueTypes::No, a.substs, b.substs)
+ .eq(DefineOpaqueTypes::No, a.args, b.args)
{
return self.evaluate_predicates_recursively(
previous_stack,
@@ -1000,13 +1039,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
let stack = self.push_stack(previous_stack, &obligation);
- let mut fresh_trait_pred = stack.fresh_trait_pred;
- let mut param_env = obligation.param_env;
-
- fresh_trait_pred = fresh_trait_pred.map_bound(|mut pred| {
- pred.remap_constness(&mut param_env);
- pred
- });
+ let fresh_trait_pred = stack.fresh_trait_pred;
+ let param_env = obligation.param_env;
debug!(?fresh_trait_pred);
@@ -1157,7 +1191,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
Some(EvaluatedToOk)
} else {
debug!("evaluate_stack --> recursive, inductive");
- Some(EvaluatedToRecur)
+ Some(self.treat_inductive_cycle.into())
}
} else {
None
@@ -1194,7 +1228,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// terms of `Fn` etc, but we could probably make this more
// precise still.
let unbound_input_types =
- stack.fresh_trait_pred.skip_binder().trait_ref.substs.types().any(|ty| ty.is_fresh());
+ stack.fresh_trait_pred.skip_binder().trait_ref.args.types().any(|ty| ty.is_fresh());
if unbound_input_types
&& stack.iter().skip(1).any(|prev| {
@@ -1386,8 +1420,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
(result, dep_node)
}
- /// filter_impls filters constant trait obligations and candidates that have a positive impl
- /// for a negative goal and a negative impl for a positive goal
+ /// filter_impls filters candidates that have a positive impl for a negative
+ /// goal and a negative impl for a positive goal
#[instrument(level = "debug", skip(self, candidates))]
fn filter_impls(
&mut self,
@@ -1399,42 +1433,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let mut result = Vec::with_capacity(candidates.len());
for candidate in candidates {
- // Respect const trait obligations
- if obligation.is_const() {
- match candidate {
- // const impl
- ImplCandidate(def_id) if tcx.constness(def_id) == hir::Constness::Const => {}
- // const param
- ParamCandidate(trait_pred) if trait_pred.is_const_if_const() => {}
- // const projection
- ProjectionCandidate(_, ty::BoundConstness::ConstIfConst)
- // auto trait impl
- | AutoImplCandidate
- // generator / future, this will raise error in other places
- // or ignore error with const_async_blocks feature
- | GeneratorCandidate
- | FutureCandidate
- // FnDef where the function is const
- | FnPointerCandidate { is_const: true }
- | ConstDestructCandidate(_)
- | ClosureCandidate { is_const: true } => {}
-
- FnPointerCandidate { is_const: false } => {
- if let ty::FnDef(def_id, _) = obligation.self_ty().skip_binder().kind() && tcx.trait_of_item(*def_id).is_some() {
- // Trait methods are not seen as const unless the trait is implemented as const.
- // We do not filter that out in here, but nested obligations will be needed to confirm this.
- } else {
- continue
- }
- }
-
- _ => {
- // reject all other types of candidates
- continue;
- }
- }
- }
-
if let ImplCandidate(def_id) = candidate {
if ty::ImplPolarity::Reservation == tcx.impl_polarity(def_id)
|| obligation.polarity() == tcx.impl_polarity(def_id)
@@ -1487,7 +1485,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Result<(), Conflict> {
debug!("is_knowable(intercrate={:?})", self.is_intercrate());
- if !self.is_intercrate() || stack.obligation.polarity() == ty::ImplPolarity::Negative {
+ if !self.is_intercrate() {
return Ok(());
}
@@ -1499,7 +1497,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// bound regions.
let trait_ref = predicate.skip_binder().trait_ref;
- coherence::trait_ref_is_knowable(self.tcx(), trait_ref)
+ coherence::trait_ref_is_knowable::<!>(self.tcx(), trait_ref, |ty| Ok(ty)).unwrap()
}
/// Returns `true` if the global caches can be used.
@@ -1528,7 +1526,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn check_candidate_cache(
&mut self,
- mut param_env: ty::ParamEnv<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>,
) -> Option<SelectionResult<'tcx, SelectionCandidate<'tcx>>> {
// Neither the global nor local cache is aware of intercrate
@@ -1539,8 +1537,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
return None;
}
let tcx = self.tcx();
- let mut pred = cache_fresh_trait_pred.skip_binder();
- pred.remap_constness(&mut param_env);
+ let pred = cache_fresh_trait_pred.skip_binder();
if self.can_use_global_caches(param_env) {
if let Some(res) = tcx.selection_cache.get(&(param_env, pred), tcx) {
@@ -1586,15 +1583,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
#[instrument(skip(self, param_env, cache_fresh_trait_pred, dep_node), level = "debug")]
fn insert_candidate_cache(
&mut self,
- mut param_env: ty::ParamEnv<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>,
dep_node: DepNodeIndex,
candidate: SelectionResult<'tcx, SelectionCandidate<'tcx>>,
) {
let tcx = self.tcx();
- let mut pred = cache_fresh_trait_pred.skip_binder();
-
- pred.remap_constness(&mut param_env);
+ let pred = cache_fresh_trait_pred.skip_binder();
if !self.can_cache_candidate(&candidate) {
debug!(?pred, ?candidate, "insert_candidate_cache - candidate is not cacheable");
@@ -1628,16 +1623,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn match_projection_obligation_against_definition_bounds(
&mut self,
obligation: &PolyTraitObligation<'tcx>,
- ) -> smallvec::SmallVec<[(usize, ty::BoundConstness); 2]> {
+ ) -> smallvec::SmallVec<[usize; 2]> {
let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);
let placeholder_trait_predicate =
self.infcx.instantiate_binder_with_placeholders(poly_trait_predicate);
debug!(?placeholder_trait_predicate);
let tcx = self.infcx.tcx;
- let (def_id, substs) = match *placeholder_trait_predicate.trait_ref.self_ty().kind() {
- ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
- (def_id, substs)
+ let (def_id, args) = match *placeholder_trait_predicate.trait_ref.self_ty().kind() {
+ ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
+ (def_id, args)
}
_ => {
span_bug!(
@@ -1648,7 +1643,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
);
}
};
- let bounds = tcx.item_bounds(def_id).subst(tcx, substs);
+ let bounds = tcx.item_bounds(def_id).instantiate(tcx, args);
// The bounds returned by `item_bounds` may contain duplicates after
// normalization, so try to deduplicate when possible to avoid
@@ -1677,7 +1672,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
_ => false,
}
}) {
- return Some((idx, pred.constness));
+ return Some(idx);
}
}
None
@@ -1785,11 +1780,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
if is_match {
let generics = self.tcx().generics_of(obligation.predicate.def_id);
// FIXME(generic-associated-types): Addresses aggressive inference in #92917.
- // If this type is a GAT, and of the GAT substs resolve to something new,
+ // If this type is a GAT, and of the GAT args resolve to something new,
// that means that we must have newly inferred something about the GAT.
// We should give up in that case.
if !generics.params.is_empty()
- && obligation.predicate.substs[generics.parent_count..]
+ && obligation.predicate.args[generics.parent_count..]
.iter()
.any(|&p| p.has_non_region_infer() && self.infcx.shallow_resolve(p) != p)
{
@@ -1827,6 +1822,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
/// candidates and prefer where-clause candidates.
///
/// See the comment for "SelectionCandidate" for more details.
+ #[instrument(level = "debug", skip(self))]
fn candidate_should_be_dropped_in_favor_of(
&mut self,
victim: &EvaluatedCandidate<'tcx>,
@@ -1850,13 +1846,6 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
// This is a fix for #53123 and prevents winnowing from accidentally extending the
// lifetime of a variable.
match (&other.candidate, &victim.candidate) {
- (_, AutoImplCandidate) | (AutoImplCandidate, _) => {
- bug!(
- "default implementations shouldn't be recorded \
- when there are other valid candidates"
- );
- }
-
// FIXME(@jswrenn): this should probably be more sophisticated
(TransmutabilityCandidate, _) | (_, TransmutabilityCandidate) => DropVictim::No,
@@ -1871,7 +1860,6 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
(ParamCandidate(other), ParamCandidate(victim)) => {
let same_except_bound_vars = other.skip_binder().trait_ref
== victim.skip_binder().trait_ref
- && other.skip_binder().constness == victim.skip_binder().constness
&& other.skip_binder().polarity == victim.skip_binder().polarity
&& !other.skip_binder().trait_ref.has_escaping_bound_vars();
if same_except_bound_vars {
@@ -1881,12 +1869,6 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
// probably best characterized as a "hack", since we might prefer to just do our
// best to *not* create essentially duplicate candidates in the first place.
DropVictim::drop_if(other.bound_vars().len() <= victim.bound_vars().len())
- } else if other.skip_binder().trait_ref == victim.skip_binder().trait_ref
- && victim.skip_binder().constness == ty::BoundConstness::NotConst
- && other.skip_binder().polarity == victim.skip_binder().polarity
- {
- // Drop otherwise equivalent non-const candidates in favor of const candidates.
- DropVictim::Yes
} else {
DropVictim::No
}
@@ -1898,6 +1880,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
(
ParamCandidate(ref other_cand),
ImplCandidate(..)
+ | AutoImplCandidate
| ClosureCandidate { .. }
| GeneratorCandidate
| FutureCandidate
@@ -1925,6 +1908,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
}
(
ImplCandidate(_)
+ | AutoImplCandidate
| ClosureCandidate { .. }
| GeneratorCandidate
| FutureCandidate
@@ -1958,6 +1942,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
(
ObjectCandidate(_) | ProjectionCandidate(..),
ImplCandidate(..)
+ | AutoImplCandidate
| ClosureCandidate { .. }
| GeneratorCandidate
| FutureCandidate
@@ -1971,6 +1956,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
(
ImplCandidate(..)
+ | AutoImplCandidate
| ClosureCandidate { .. }
| GeneratorCandidate
| FutureCandidate
@@ -2061,6 +2047,19 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
}
}
+ (AutoImplCandidate, ImplCandidate(_)) | (ImplCandidate(_), AutoImplCandidate) => {
+ DropVictim::No
+ }
+
+ (AutoImplCandidate, _) | (_, AutoImplCandidate) => {
+ bug!(
+ "default implementations shouldn't be recorded \
+ when there are other global candidates: {:?} {:?}",
+ other,
+ victim
+ );
+ }
+
// Everything else is ambiguous
(
ImplCandidate(_)
@@ -2127,13 +2126,13 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
obligation.predicate.rebind(tys.last().map_or_else(Vec::new, |&last| vec![last])),
),
- ty::Adt(def, substs) => {
+ ty::Adt(def, args) => {
let sized_crit = def.sized_constraint(self.tcx());
// (*) binder moved here
Where(
obligation
.predicate
- .rebind(sized_crit.subst_iter_copied(self.tcx(), substs).collect()),
+ .rebind(sized_crit.iter_instantiated(self.tcx(), args).collect()),
)
}
@@ -2159,14 +2158,11 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
use self::BuiltinImplConditions::{Ambiguous, None, Where};
match *self_ty.kind() {
- ty::Infer(ty::IntVar(_))
- | ty::Infer(ty::FloatVar(_))
- | ty::FnDef(..)
- | ty::FnPtr(_)
- | ty::Error(_) => Where(ty::Binder::dummy(Vec::new())),
+ ty::FnDef(..) | ty::FnPtr(_) | ty::Error(_) => Where(ty::Binder::dummy(Vec::new())),
ty::Uint(_)
| ty::Int(_)
+ | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
| ty::Bool
| ty::Float(_)
| ty::Char
@@ -2190,20 +2186,21 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
Where(obligation.predicate.rebind(tys.iter().collect()))
}
- ty::Generator(_, substs, hir::Movability::Movable) => {
+ ty::Generator(_, args, hir::Movability::Movable) => {
if self.tcx().features().generator_clone {
let resolved_upvars =
- self.infcx.shallow_resolve(substs.as_generator().tupled_upvars_ty());
+ self.infcx.shallow_resolve(args.as_generator().tupled_upvars_ty());
let resolved_witness =
- self.infcx.shallow_resolve(substs.as_generator().witness());
+ self.infcx.shallow_resolve(args.as_generator().witness());
if resolved_upvars.is_ty_var() || resolved_witness.is_ty_var() {
// Not yet resolved.
Ambiguous
} else {
- let all = substs
+ let all = args
.as_generator()
.upvar_tys()
- .chain(iter::once(substs.as_generator().witness()))
+ .iter()
+ .chain([args.as_generator().witness()])
.collect::<Vec<_>>();
Where(obligation.predicate.rebind(all))
}
@@ -2227,24 +2224,24 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
Where(ty::Binder::bind_with_vars(witness_tys.to_vec(), all_vars))
}
- ty::GeneratorWitnessMIR(def_id, ref substs) => {
+ ty::GeneratorWitnessMIR(def_id, ref args) => {
let hidden_types = bind_generator_hidden_types_above(
self.infcx,
def_id,
- substs,
+ args,
obligation.predicate.bound_vars(),
);
Where(hidden_types)
}
- ty::Closure(_, substs) => {
+ ty::Closure(_, args) => {
// (*) binder moved here
- let ty = self.infcx.shallow_resolve(substs.as_closure().tupled_upvars_ty());
+ let ty = self.infcx.shallow_resolve(args.as_closure().tupled_upvars_ty());
if let ty::Infer(ty::TyVar(_)) = ty.kind() {
// Not yet resolved.
Ambiguous
} else {
- Where(obligation.predicate.rebind(substs.as_closure().upvar_tys().collect()))
+ Where(obligation.predicate.rebind(args.as_closure().upvar_tys().to_vec()))
}
}
@@ -2321,14 +2318,14 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
t.rebind(tys.iter().collect())
}
- ty::Closure(_, ref substs) => {
- let ty = self.infcx.shallow_resolve(substs.as_closure().tupled_upvars_ty());
+ ty::Closure(_, ref args) => {
+ let ty = self.infcx.shallow_resolve(args.as_closure().tupled_upvars_ty());
t.rebind(vec![ty])
}
- ty::Generator(_, ref substs, _) => {
- let ty = self.infcx.shallow_resolve(substs.as_generator().tupled_upvars_ty());
- let witness = substs.as_generator().witness();
+ ty::Generator(_, ref args, _) => {
+ let ty = self.infcx.shallow_resolve(args.as_generator().tupled_upvars_ty());
+ let witness = args.as_generator().witness();
t.rebind([ty].into_iter().chain(iter::once(witness)).collect())
}
@@ -2337,18 +2334,18 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
types.map_bound(|types| types.to_vec())
}
- ty::GeneratorWitnessMIR(def_id, ref substs) => {
- bind_generator_hidden_types_above(self.infcx, def_id, substs, t.bound_vars())
+ ty::GeneratorWitnessMIR(def_id, ref args) => {
+ bind_generator_hidden_types_above(self.infcx, def_id, args, t.bound_vars())
}
// For `PhantomData<T>`, we pass `T`.
- ty::Adt(def, substs) if def.is_phantom_data() => t.rebind(substs.types().collect()),
+ ty::Adt(def, args) if def.is_phantom_data() => t.rebind(args.types().collect()),
- ty::Adt(def, substs) => {
- t.rebind(def.all_fields().map(|f| f.ty(self.tcx(), substs)).collect())
+ ty::Adt(def, args) => {
+ t.rebind(def.all_fields().map(|f| f.ty(self.tcx(), args)).collect())
}
- ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
let ty = self.tcx().type_of(def_id);
if ty.skip_binder().references_error() {
return Err(SelectionError::OpaqueTypeAutoTraitLeakageUnknown(def_id));
@@ -2356,7 +2353,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
// We can resolve the `impl Trait` to its concrete type,
// which enforces a DAG between the functions requiring
// the auto trait bounds in question.
- t.rebind(vec![ty.subst(self.tcx(), substs)])
+ t.rebind(vec![ty.instantiate(self.tcx(), args)])
}
})
}
@@ -2428,13 +2425,13 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
&mut self,
impl_def_id: DefId,
obligation: &PolyTraitObligation<'tcx>,
- ) -> Normalized<'tcx, SubstsRef<'tcx>> {
+ ) -> Normalized<'tcx, GenericArgsRef<'tcx>> {
let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap();
match self.match_impl(impl_def_id, impl_trait_ref, obligation) {
- Ok(substs) => substs,
+ Ok(args) => args,
Err(()) => {
// FIXME: A rematch may fail when a candidate cache hit occurs
- // on thefreshened form of the trait predicate, but the match
+ // on the freshened form of the trait predicate, but the match
// fails for some reason that is not captured in the freshened
// cache key. For example, equating an impl trait ref against
// the placeholder trait ref may fail due the Generalizer relation
@@ -2443,11 +2440,10 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
let guar = self.infcx.tcx.sess.delay_span_bug(
obligation.cause.span,
format!(
- "Impl {:?} was matchable against {:?} but now is not",
- impl_def_id, obligation
+ "Impl {impl_def_id:?} was matchable against {obligation:?} but now is not"
),
);
- let value = self.infcx.fresh_substs_for_item(obligation.cause.span, impl_def_id);
+ let value = self.infcx.fresh_args_for_item(obligation.cause.span, impl_def_id);
let err = Ty::new_error(self.tcx(), guar);
let value = value.fold_with(&mut BottomUpFolder {
tcx: self.tcx(),
@@ -2466,14 +2462,14 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
impl_def_id: DefId,
impl_trait_ref: EarlyBinder<ty::TraitRef<'tcx>>,
obligation: &PolyTraitObligation<'tcx>,
- ) -> Result<Normalized<'tcx, SubstsRef<'tcx>>, ()> {
+ ) -> Result<Normalized<'tcx, GenericArgsRef<'tcx>>, ()> {
let placeholder_obligation =
self.infcx.instantiate_binder_with_placeholders(obligation.predicate);
let placeholder_obligation_trait_ref = placeholder_obligation.trait_ref;
- let impl_substs = self.infcx.fresh_substs_for_item(obligation.cause.span, impl_def_id);
+ let impl_args = self.infcx.fresh_args_for_item(obligation.cause.span, impl_def_id);
- let impl_trait_ref = impl_trait_ref.subst(self.tcx(), impl_substs);
+ let impl_trait_ref = impl_trait_ref.instantiate(self.tcx(), impl_args);
if impl_trait_ref.references_error() {
return Err(());
}
@@ -2515,7 +2511,99 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
return Err(());
}
- Ok(Normalized { value: impl_substs, obligations: nested_obligations })
+ Ok(Normalized { value: impl_args, obligations: nested_obligations })
+ }
+
+ fn match_upcast_principal(
+ &mut self,
+ obligation: &PolyTraitObligation<'tcx>,
+ unnormalized_upcast_principal: ty::PolyTraitRef<'tcx>,
+ a_data: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
+ b_data: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
+ a_region: ty::Region<'tcx>,
+ b_region: ty::Region<'tcx>,
+ ) -> SelectionResult<'tcx, Vec<PredicateObligation<'tcx>>> {
+ let tcx = self.tcx();
+ let mut nested = vec![];
+
+ let upcast_principal = normalize_with_depth_to(
+ self,
+ obligation.param_env,
+ obligation.cause.clone(),
+ obligation.recursion_depth + 1,
+ unnormalized_upcast_principal,
+ &mut nested,
+ );
+
+ for bound in b_data {
+ match bound.skip_binder() {
+ // Check that a_ty's supertrait (upcast_principal) is compatible
+ // with the target (b_ty).
+ ty::ExistentialPredicate::Trait(target_principal) => {
+ nested.extend(
+ self.infcx
+ .at(&obligation.cause, obligation.param_env)
+ .sup(
+ DefineOpaqueTypes::No,
+ upcast_principal.map_bound(|trait_ref| {
+ ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)
+ }),
+ bound.rebind(target_principal),
+ )
+ .map_err(|_| SelectionError::Unimplemented)?
+ .into_obligations(),
+ );
+ }
+ // Check that b_ty's projection is satisfied by exactly one of
+ // a_ty's projections. First, we look through the list to see if
+ // any match. If not, error. Then, if *more* than one matches, we
+ // return ambiguity. Otherwise, if exactly one matches, equate
+ // it with b_ty's projection.
+ ty::ExistentialPredicate::Projection(target_projection) => {
+ let target_projection = bound.rebind(target_projection);
+ let mut matching_projections =
+ a_data.projection_bounds().filter(|source_projection| {
+ // Eager normalization means that we can just use can_eq
+ // here instead of equating and processing obligations.
+ source_projection.item_def_id() == target_projection.item_def_id()
+ && self.infcx.can_eq(
+ obligation.param_env,
+ *source_projection,
+ target_projection,
+ )
+ });
+ let Some(source_projection) = matching_projections.next() else {
+ return Err(SelectionError::Unimplemented);
+ };
+ if matching_projections.next().is_some() {
+ return Ok(None);
+ }
+ nested.extend(
+ self.infcx
+ .at(&obligation.cause, obligation.param_env)
+ .sup(DefineOpaqueTypes::No, source_projection, target_projection)
+ .map_err(|_| SelectionError::Unimplemented)?
+ .into_obligations(),
+ );
+ }
+ // Check that b_ty's auto traits are present in a_ty's bounds.
+ ty::ExistentialPredicate::AutoTrait(def_id) => {
+ if !a_data.auto_traits().any(|source_def_id| source_def_id == def_id) {
+ return Err(SelectionError::Unimplemented);
+ }
+ }
+ }
+ }
+
+ nested.push(Obligation::with_depth(
+ tcx,
+ obligation.cause.clone(),
+ obligation.recursion_depth + 1,
+ obligation.param_env,
+ ty::Binder::dummy(ty::OutlivesPredicate(a_region, b_region)),
+ ));
+
+ Ok(Some(nested))
}
/// Normalize `where_clause_trait_ref` and try to match it against
@@ -2580,9 +2668,9 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
fn closure_trait_ref_unnormalized(
&mut self,
obligation: &PolyTraitObligation<'tcx>,
- substs: SubstsRef<'tcx>,
+ args: GenericArgsRef<'tcx>,
) -> ty::PolyTraitRef<'tcx> {
- let closure_sig = substs.as_closure().sig();
+ let closure_sig = args.as_closure().sig();
debug!(?closure_sig);
@@ -2615,8 +2703,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
cause: &ObligationCause<'tcx>,
recursion_depth: usize,
param_env: ty::ParamEnv<'tcx>,
- def_id: DefId, // of impl or trait
- substs: SubstsRef<'tcx>, // for impl or trait
+ def_id: DefId, // of impl or trait
+ args: GenericArgsRef<'tcx>, // for impl or trait
parent_trait_pred: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
) -> Vec<PredicateObligation<'tcx>> {
let tcx = self.tcx();
@@ -2637,7 +2725,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
// that order.
let predicates = tcx.predicates_of(def_id);
assert_eq!(predicates.parent, None);
- let predicates = predicates.instantiate_own(tcx, substs);
+ let predicates = predicates.instantiate_own(tcx, args);
let mut obligations = Vec::with_capacity(predicates.len());
for (index, (predicate, span)) in predicates.into_iter().enumerate() {
let cause =
@@ -2990,7 +3078,7 @@ pub enum ProjectionMatchesProjection {
fn bind_generator_hidden_types_above<'tcx>(
infcx: &InferCtxt<'tcx>,
def_id: DefId,
- substs: ty::SubstsRef<'tcx>,
+ args: ty::GenericArgsRef<'tcx>,
bound_vars: &ty::List<ty::BoundVariableKind>,
) -> ty::Binder<'tcx, Vec<Ty<'tcx>>> {
let tcx = infcx.tcx;
@@ -3006,7 +3094,7 @@ fn bind_generator_hidden_types_above<'tcx>(
// Deduplicate tys to avoid repeated work.
.filter(|bty| seen_tys.insert(*bty))
.map(|bty| {
- let mut ty = bty.subst(tcx, substs);
+ let mut ty = bty.instantiate(tcx, args);
// Only remap erased regions if we use them.
if considering_regions {
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index 96f128741..729cf2f33 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -23,7 +23,7 @@ use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::{error_code, DelayDm, Diagnostic};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt, TypeVisitableExt};
-use rustc_middle::ty::{InternalSubsts, SubstsRef};
+use rustc_middle::ty::{GenericArgs, GenericArgsRef};
use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK;
use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS;
use rustc_span::{Span, DUMMY_SP};
@@ -48,7 +48,7 @@ pub struct OverlapError<'tcx> {
/// When we have selected one impl, but are actually using item definitions from
/// a parent impl providing a default, we need a way to translate between the
/// type parameters of the two impls. Here the `source_impl` is the one we've
-/// selected, and `source_substs` is a substitution of its generics.
+/// selected, and `source_args` is a substitution of its generics.
/// And `target_node` is the impl/trait we're actually going to get the
/// definition from. The resulting substitution will map from `target_node`'s
/// generics to `source_impl`'s generics as instantiated by `source_subst`.
@@ -76,51 +76,46 @@ pub struct OverlapError<'tcx> {
/// through associated type projection. We deal with such cases by using
/// *fulfillment* to relate the two impls, requiring that all projections are
/// resolved.
-pub fn translate_substs<'tcx>(
+pub fn translate_args<'tcx>(
infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
source_impl: DefId,
- source_substs: SubstsRef<'tcx>,
+ source_args: GenericArgsRef<'tcx>,
target_node: specialization_graph::Node,
-) -> SubstsRef<'tcx> {
- translate_substs_with_cause(
- infcx,
- param_env,
- source_impl,
- source_substs,
- target_node,
- |_, _| ObligationCause::dummy(),
- )
+) -> GenericArgsRef<'tcx> {
+ translate_args_with_cause(infcx, param_env, source_impl, source_args, target_node, |_, _| {
+ ObligationCause::dummy()
+ })
}
-/// Like [translate_substs], but obligations from the parent implementation
+/// Like [translate_args], but obligations from the parent implementation
/// are registered with the provided `ObligationCause`.
///
/// This is for reporting *region* errors from those bounds. Type errors should
/// not happen because the specialization graph already checks for those, and
/// will result in an ICE.
-pub fn translate_substs_with_cause<'tcx>(
+pub fn translate_args_with_cause<'tcx>(
infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
source_impl: DefId,
- source_substs: SubstsRef<'tcx>,
+ source_args: GenericArgsRef<'tcx>,
target_node: specialization_graph::Node,
cause: impl Fn(usize, Span) -> ObligationCause<'tcx>,
-) -> SubstsRef<'tcx> {
+) -> GenericArgsRef<'tcx> {
debug!(
- "translate_substs({:?}, {:?}, {:?}, {:?})",
- param_env, source_impl, source_substs, target_node
+ "translate_args({:?}, {:?}, {:?}, {:?})",
+ param_env, source_impl, source_args, target_node
);
let source_trait_ref =
- infcx.tcx.impl_trait_ref(source_impl).unwrap().subst(infcx.tcx, &source_substs);
+ infcx.tcx.impl_trait_ref(source_impl).unwrap().instantiate(infcx.tcx, &source_args);
// translate the Self and Param parts of the substitution, since those
// vary across impls
- let target_substs = match target_node {
+ let target_args = match target_node {
specialization_graph::Node::Impl(target_impl) => {
// no need to translate if we're targeting the impl we started with
if source_impl == target_impl {
- return source_substs;
+ return source_args;
}
fulfill_implication(infcx, param_env, source_trait_ref, source_impl, target_impl, cause)
@@ -131,11 +126,11 @@ pub fn translate_substs_with_cause<'tcx>(
)
})
}
- specialization_graph::Node::Trait(..) => source_trait_ref.substs,
+ specialization_graph::Node::Trait(..) => source_trait_ref.args,
};
// directly inherent the method generics, since those do not vary across impls
- source_substs.rebase_onto(infcx.tcx, source_impl, target_substs)
+ source_args.rebase_onto(infcx.tcx, source_impl, target_args)
}
/// Is `impl1` a specialization of `impl2`?
@@ -172,7 +167,7 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId,
// create a parameter environment corresponding to a (placeholder) instantiation of impl1
let penv = tcx.param_env(impl1_def_id);
- let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id).unwrap().subst_identity();
+ let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id).unwrap().instantiate_identity();
// Create an infcx, taking the predicates of impl1 as assumptions:
let infcx = tcx.infer_ctxt().build();
@@ -196,7 +191,7 @@ fn fulfill_implication<'tcx>(
source_impl: DefId,
target_impl: DefId,
error_cause: impl Fn(usize, Span) -> ObligationCause<'tcx>,
-) -> Result<SubstsRef<'tcx>, ()> {
+) -> Result<GenericArgsRef<'tcx>, ()> {
debug!(
"fulfill_implication({:?}, trait_ref={:?} |- {:?} applies)",
param_env, source_trait_ref, target_impl
@@ -221,18 +216,16 @@ fn fulfill_implication<'tcx>(
let source_trait = ImplSubject::Trait(source_trait_ref);
let selcx = &mut SelectionContext::new(&infcx);
- let target_substs = infcx.fresh_substs_for_item(DUMMY_SP, target_impl);
+ let target_args = infcx.fresh_args_for_item(DUMMY_SP, target_impl);
let (target_trait, obligations) =
- util::impl_subject_and_oblig(selcx, param_env, target_impl, target_substs, error_cause);
+ util::impl_subject_and_oblig(selcx, param_env, target_impl, target_args, error_cause);
// do the impls unify? If not, no specialization.
- let Ok(InferOk { obligations: more_obligations, .. }) =
- infcx.at(&ObligationCause::dummy(), param_env).eq(DefineOpaqueTypes::No, source_trait, target_trait)
+ let Ok(InferOk { obligations: more_obligations, .. }) = infcx
+ .at(&ObligationCause::dummy(), param_env)
+ .eq(DefineOpaqueTypes::No, source_trait, target_trait)
else {
- debug!(
- "fulfill_implication: {:?} does not unify with {:?}",
- source_trait, target_trait
- );
+ debug!("fulfill_implication: {:?} does not unify with {:?}", source_trait, target_trait);
return Err(());
};
@@ -261,7 +254,7 @@ fn fulfill_implication<'tcx>(
// Now resolve the *substitution* we built for the target earlier, replacing
// the inference variables inside with whatever we got from fulfillment.
- Ok(infcx.resolve_vars_if_possible(target_substs))
+ Ok(infcx.resolve_vars_if_possible(target_args))
}
/// Query provider for `specialization_graph_of`.
@@ -395,16 +388,16 @@ fn report_conflicting_impls<'tcx>(
impl_span,
format!(
"conflicting implementation{}",
- overlap.self_ty.map_or_else(String::new, |ty| format!(" for `{}`", ty))
+ overlap.self_ty.map_or_else(String::new, |ty| format!(" for `{ty}`"))
),
);
}
Err(cname) => {
let msg = match to_pretty_impl_header(tcx, overlap.with_impl) {
Some(s) => {
- format!("conflicting implementation in crate `{}`:\n- {}", cname, s)
+ format!("conflicting implementation in crate `{cname}`:\n- {s}")
}
- None => format!("conflicting implementation in crate `{}`", cname),
+ None => format!("conflicting implementation in crate `{cname}`"),
};
err.note(msg);
}
@@ -469,21 +462,21 @@ fn report_conflicting_impls<'tcx>(
pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option<String> {
use std::fmt::Write;
- let trait_ref = tcx.impl_trait_ref(impl_def_id)?.subst_identity();
+ let trait_ref = tcx.impl_trait_ref(impl_def_id)?.instantiate_identity();
let mut w = "impl".to_owned();
- let substs = InternalSubsts::identity_for_item(tcx, impl_def_id);
+ let args = GenericArgs::identity_for_item(tcx, impl_def_id);
// FIXME: Currently only handles ?Sized.
// Needs to support ?Move and ?DynSized when they are implemented.
let mut types_without_default_bounds = FxIndexSet::default();
let sized_trait = tcx.lang_items().sized_trait();
- if !substs.is_empty() {
- types_without_default_bounds.extend(substs.types());
+ if !args.is_empty() {
+ types_without_default_bounds.extend(args.types());
w.push('<');
w.push_str(
- &substs
+ &args
.iter()
.map(|k| k.to_string())
.filter(|k| k != "'_")
@@ -497,7 +490,7 @@ pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Opti
w,
" {} for {}",
trait_ref.print_only_trait_path(),
- tcx.type_of(impl_def_id).subst_identity()
+ tcx.type_of(impl_def_id).instantiate_identity()
)
.unwrap();
@@ -507,22 +500,17 @@ pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Opti
let mut pretty_predicates =
Vec::with_capacity(predicates.len() + types_without_default_bounds.len());
- for (mut p, _) in predicates {
+ for (p, _) in predicates {
if let Some(poly_trait_ref) = p.as_trait_clause() {
if Some(poly_trait_ref.def_id()) == sized_trait {
types_without_default_bounds.remove(&poly_trait_ref.self_ty().skip_binder());
continue;
}
-
- if ty::BoundConstness::ConstIfConst == poly_trait_ref.skip_binder().constness {
- p = p.without_const(tcx);
- }
}
pretty_predicates.push(p.to_string());
}
- pretty_predicates
- .extend(types_without_default_bounds.iter().map(|ty| format!("{}: ?Sized", ty)));
+ pretty_predicates.extend(types_without_default_bounds.iter().map(|ty| format!("{ty}: ?Sized")));
if !pretty_predicates.is_empty() {
write!(w, "\n where {}", pretty_predicates.join(", ")).unwrap();
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
index aa5c624f4..e9a592bde 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
@@ -180,7 +180,7 @@ impl<'tcx> ChildrenExt<'tcx> for Children {
if le && !ge {
debug!(
"descending as child of TraitRef {:?}",
- tcx.impl_trait_ref(possible_sibling).unwrap().subst_identity()
+ tcx.impl_trait_ref(possible_sibling).unwrap().instantiate_identity()
);
// The impl specializes `possible_sibling`.
@@ -188,7 +188,7 @@ impl<'tcx> ChildrenExt<'tcx> for Children {
} else if ge && !le {
debug!(
"placing as parent of TraitRef {:?}",
- tcx.impl_trait_ref(possible_sibling).unwrap().subst_identity()
+ tcx.impl_trait_ref(possible_sibling).unwrap().instantiate_identity()
);
replace_children.push(possible_sibling);
diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs
index 420f8c5dc..0864e4dc8 100644
--- a/compiler/rustc_trait_selection/src/traits/structural_match.rs
+++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs
@@ -62,8 +62,8 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for Search<'tcx> {
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
debug!("Search visiting ty: {:?}", ty);
- let (adt_def, substs) = match *ty.kind() {
- ty::Adt(adt_def, substs) => (adt_def, substs),
+ let (adt_def, args) = match *ty.kind() {
+ ty::Adt(adt_def, args) => (adt_def, args),
ty::Param(_) => {
return ControlFlow::Break(ty);
}
@@ -157,15 +157,15 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for Search<'tcx> {
// instead looks directly at its fields outside
// this match), so we skip super_visit_with.
//
- // (Must not recur on substs for `PhantomData<T>` cf
+ // (Must not recur on args for `PhantomData<T>` cf
// rust-lang/rust#55028 and rust-lang/rust#55837; but also
- // want to skip substs when only uses of generic are
+ // want to skip args when only uses of generic are
// behind unsafe pointers `*const T`/`*mut T`.)
// even though we skip super_visit_with, we must recur on
// fields of ADT.
let tcx = self.tcx;
- adt_def.all_fields().map(|field| field.ty(tcx, substs)).try_for_each(|field_ty| {
+ adt_def.all_fields().map(|field| field.ty(tcx, args)).try_for_each(|field_ty| {
let ty = self.tcx.normalize_erasing_regions(ty::ParamEnv::empty(), field_ty);
debug!("structural-match ADT: field_ty={:?}, ty={:?}", field_ty, ty);
ty.visit_with(self)
diff --git a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
index 84746eba3..d3c4dc459 100644
--- a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
@@ -22,7 +22,9 @@ impl<'tcx> StructurallyNormalizeExt<'tcx> for At<'_, 'tcx> {
assert!(!ty.is_ty_var(), "should have resolved vars before calling");
if self.infcx.next_trait_solver() {
- while let ty::Alias(ty::Projection, projection_ty) = *ty.kind() {
+ while let ty::Alias(ty::Projection | ty::Inherent | ty::Weak, projection_ty) =
+ *ty.kind()
+ {
let new_infer_ty = self.infcx.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::NormalizeProjectionType,
span: self.cause.span,
diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs
index 302b6cacf..a76272e9d 100644
--- a/compiler/rustc_trait_selection/src/traits/util.rs
+++ b/compiler/rustc_trait_selection/src/traits/util.rs
@@ -4,7 +4,7 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Diagnostic;
use rustc_hir::def_id::DefId;
use rustc_infer::infer::InferOk;
-use rustc_middle::ty::SubstsRef;
+use rustc_middle::ty::GenericArgsRef;
use rustc_middle::ty::{self, ImplSubject, ToPredicate, Ty, TyCtxt, TypeVisitableExt};
use rustc_span::Span;
use smallvec::SmallVec;
@@ -50,7 +50,7 @@ impl<'tcx> TraitAliasExpansionInfo<'tcx> {
diag.span_label(self.top().1, top_label);
if self.path.len() > 1 {
for (_, sp) in self.path.iter().rev().skip(1).take(self.path.len() - 2) {
- diag.span_label(*sp, format!("referenced here ({})", use_desc));
+ diag.span_label(*sp, format!("referenced here ({use_desc})"));
}
}
if self.top().1 != self.bottom().1 {
@@ -58,7 +58,7 @@ impl<'tcx> TraitAliasExpansionInfo<'tcx> {
// redundant labels.
diag.span_label(
self.bottom().1,
- format!("trait alias used in trait object type ({})", use_desc),
+ format!("trait alias used in trait object type ({use_desc})"),
);
}
}
@@ -101,7 +101,7 @@ impl<'tcx> TraitAliasExpander<'tcx> {
fn expand(&mut self, item: &TraitAliasExpansionInfo<'tcx>) -> bool {
let tcx = self.tcx;
let trait_ref = item.trait_ref();
- let pred = trait_ref.without_const().to_predicate(tcx);
+ let pred = trait_ref.to_predicate(tcx);
debug!("expand_trait_aliases: trait_ref={:?}", trait_ref);
@@ -113,9 +113,13 @@ impl<'tcx> TraitAliasExpander<'tcx> {
// Don't recurse if this trait alias is already on the stack for the DFS search.
let anon_pred = anonymize_predicate(tcx, pred);
- if item.path.iter().rev().skip(1).any(|&(tr, _)| {
- anonymize_predicate(tcx, tr.without_const().to_predicate(tcx)) == anon_pred
- }) {
+ if item
+ .path
+ .iter()
+ .rev()
+ .skip(1)
+ .any(|&(tr, _)| anonymize_predicate(tcx, tr.to_predicate(tcx)) == anon_pred)
+ {
return false;
}
@@ -194,24 +198,24 @@ impl Iterator for SupertraitDefIds<'_> {
// Other
///////////////////////////////////////////////////////////////////////////
-/// Instantiate all bound parameters of the impl subject with the given substs,
+/// Instantiate all bound parameters of the impl subject with the given args,
/// returning the resulting subject and all obligations that arise.
/// The obligations are closed under normalization.
pub fn impl_subject_and_oblig<'a, 'tcx>(
selcx: &mut SelectionContext<'a, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
impl_def_id: DefId,
- impl_substs: SubstsRef<'tcx>,
+ impl_args: GenericArgsRef<'tcx>,
cause: impl Fn(usize, Span) -> ObligationCause<'tcx>,
) -> (ImplSubject<'tcx>, impl Iterator<Item = PredicateObligation<'tcx>>) {
let subject = selcx.tcx().impl_subject(impl_def_id);
- let subject = subject.subst(selcx.tcx(), impl_substs);
+ let subject = subject.instantiate(selcx.tcx(), impl_args);
let InferOk { value: subject, obligations: normalization_obligations1 } =
selcx.infcx.at(&ObligationCause::dummy(), param_env).normalize(subject);
let predicates = selcx.tcx().predicates_of(impl_def_id);
- let predicates = predicates.instantiate(selcx.tcx(), impl_substs);
+ let predicates = predicates.instantiate(selcx.tcx(), impl_args);
let InferOk { value: predicates, obligations: normalization_obligations2 } =
selcx.infcx.at(&ObligationCause::dummy(), param_env).normalize(predicates);
let impl_obligations = super::predicates_for_generics(cause, param_env, predicates);
@@ -241,9 +245,9 @@ pub fn upcast_choices<'tcx>(
/// Given an upcast trait object described by `object`, returns the
/// index of the method `method_def_id` (which should be part of
/// `object.upcast_trait_ref`) within the vtable for `object`.
-pub fn get_vtable_index_of_object_method<'tcx, N>(
+pub fn get_vtable_index_of_object_method<'tcx>(
tcx: TyCtxt<'tcx>,
- object: &super::ImplSourceObjectData<N>,
+ vtable_base: usize,
method_def_id: DefId,
) -> Option<usize> {
// Count number of methods preceding the one we are selecting and
@@ -252,7 +256,7 @@ pub fn get_vtable_index_of_object_method<'tcx, N>(
.iter()
.copied()
.position(|def_id| def_id == method_def_id)
- .map(|index| object.vtable_base + index)
+ .map(|index| vtable_base + index)
}
pub fn closure_trait_ref_and_return_type<'tcx>(
@@ -303,13 +307,13 @@ pub enum TupleArgumentsFlag {
No,
}
-// Verify that the trait item and its implementation have compatible substs lists
-pub fn check_substs_compatible<'tcx>(
+// Verify that the trait item and its implementation have compatible args lists
+pub fn check_args_compatible<'tcx>(
tcx: TyCtxt<'tcx>,
assoc_item: ty::AssocItem,
- substs: ty::SubstsRef<'tcx>,
+ args: ty::GenericArgsRef<'tcx>,
) -> bool {
- fn check_substs_compatible_inner<'tcx>(
+ fn check_args_compatible_inner<'tcx>(
tcx: TyCtxt<'tcx>,
generics: &'tcx ty::Generics,
args: &'tcx [ty::GenericArg<'tcx>],
@@ -322,7 +326,7 @@ pub fn check_substs_compatible<'tcx>(
if let Some(parent) = generics.parent
&& let parent_generics = tcx.generics_of(parent)
- && !check_substs_compatible_inner(tcx, parent_generics, parent_args) {
+ && !check_args_compatible_inner(tcx, parent_generics, parent_args) {
return false;
}
@@ -339,7 +343,7 @@ pub fn check_substs_compatible<'tcx>(
}
let generics = tcx.generics_of(assoc_item.def_id);
- // Chop off any additional substs (RPITIT) substs
- let substs = &substs[0..generics.count().min(substs.len())];
- check_substs_compatible_inner(tcx, generics, substs)
+ // Chop off any additional args (RPITIT) args
+ let args = &args[0..generics.count().min(args.len())];
+ check_args_compatible_inner(tcx, generics, args)
}
diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs
index 1f83f1f44..427ac3684 100644
--- a/compiler/rustc_trait_selection/src/traits/vtable.rs
+++ b/compiler/rustc_trait_selection/src/traits/vtable.rs
@@ -5,8 +5,9 @@ use rustc_hir::lang_items::LangItem;
use rustc_infer::traits::util::PredicateSet;
use rustc_infer::traits::ImplSource;
use rustc_middle::query::Providers;
+use rustc_middle::traits::BuiltinImplSource;
use rustc_middle::ty::visit::TypeVisitableExt;
-use rustc_middle::ty::InternalSubsts;
+use rustc_middle::ty::GenericArgs;
use rustc_middle::ty::{self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, VtblEntry};
use rustc_span::{sym, Span};
use smallvec::SmallVec;
@@ -24,8 +25,18 @@ pub enum VtblSegment<'tcx> {
pub fn prepare_vtable_segments<'tcx, T>(
tcx: TyCtxt<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>,
- mut segment_visitor: impl FnMut(VtblSegment<'tcx>) -> ControlFlow<T>,
+ segment_visitor: impl FnMut(VtblSegment<'tcx>) -> ControlFlow<T>,
) -> Option<T> {
+ prepare_vtable_segments_inner(tcx, trait_ref, segment_visitor).break_value()
+}
+
+/// Helper for [`prepare_vtable_segments`] that returns `ControlFlow`,
+/// such that we can use `?` in the body.
+fn prepare_vtable_segments_inner<'tcx, T>(
+ tcx: TyCtxt<'tcx>,
+ trait_ref: ty::PolyTraitRef<'tcx>,
+ mut segment_visitor: impl FnMut(VtblSegment<'tcx>) -> ControlFlow<T>,
+) -> ControlFlow<T> {
// The following constraints holds for the final arrangement.
// 1. The whole virtual table of the first direct super trait is included as the
// the prefix. If this trait doesn't have any super traits, then this step
@@ -71,20 +82,18 @@ pub fn prepare_vtable_segments<'tcx, T>(
// N, N-vptr, O
// emit dsa segment first.
- if let ControlFlow::Break(v) = (segment_visitor)(VtblSegment::MetadataDSA) {
- return Some(v);
- }
+ segment_visitor(VtblSegment::MetadataDSA)?;
let mut emit_vptr_on_new_entry = false;
let mut visited = PredicateSet::new(tcx);
- let predicate = trait_ref.without_const().to_predicate(tcx);
+ let predicate = trait_ref.to_predicate(tcx);
let mut stack: SmallVec<[(ty::PolyTraitRef<'tcx>, _, _); 5]> =
- smallvec![(trait_ref, emit_vptr_on_new_entry, None)];
+ smallvec![(trait_ref, emit_vptr_on_new_entry, maybe_iter(None))];
visited.insert(predicate);
// the main traversal loop:
// basically we want to cut the inheritance directed graph into a few non-overlapping slices of nodes
- // that each node is emitted after all its descendents have been emitted.
+ // such that each node is emitted after all its descendants have been emitted.
// so we convert the directed graph into a tree by skipping all previously visited nodes using a visited set.
// this is done on the fly.
// Each loop run emits a slice - it starts by find a "childless" unvisited node, backtracking upwards, and it
@@ -105,98 +114,107 @@ pub fn prepare_vtable_segments<'tcx, T>(
// Loop run #1: Emitting the slice [D C] (in reverse order). No one has a next-sibling node.
// Loop run #1: Stack after exiting out is []. Now the function exits.
- loop {
+ 'outer: loop {
// dive deeper into the stack, recording the path
'diving_in: loop {
- if let Some((inner_most_trait_ref, _, _)) = stack.last() {
- let inner_most_trait_ref = *inner_most_trait_ref;
- let mut direct_super_traits_iter = tcx
- .super_predicates_of(inner_most_trait_ref.def_id())
- .predicates
- .into_iter()
- .filter_map(move |(pred, _)| {
- pred.subst_supertrait(tcx, &inner_most_trait_ref).as_trait_clause()
- });
+ let &(inner_most_trait_ref, _, _) = stack.last().unwrap();
+
+ let mut direct_super_traits_iter = tcx
+ .super_predicates_of(inner_most_trait_ref.def_id())
+ .predicates
+ .into_iter()
+ .filter_map(move |(pred, _)| {
+ pred.subst_supertrait(tcx, &inner_most_trait_ref).as_trait_clause()
+ });
- 'diving_in_skip_visited_traits: loop {
- if let Some(next_super_trait) = direct_super_traits_iter.next() {
- if visited.insert(next_super_trait.to_predicate(tcx)) {
- // We're throwing away potential constness of super traits here.
- // FIXME: handle ~const super traits
- let next_super_trait = next_super_trait.map_bound(|t| t.trait_ref);
- stack.push((
- next_super_trait,
- emit_vptr_on_new_entry,
- Some(direct_super_traits_iter),
- ));
- break 'diving_in_skip_visited_traits;
- } else {
- continue 'diving_in_skip_visited_traits;
- }
- } else {
- break 'diving_in;
- }
+ // Find an unvisited supertrait
+ match direct_super_traits_iter
+ .find(|&super_trait| visited.insert(super_trait.to_predicate(tcx)))
+ {
+ // Push it to the stack for the next iteration of 'diving_in to pick up
+ Some(unvisited_super_trait) => {
+ // We're throwing away potential constness of super traits here.
+ // FIXME: handle ~const super traits
+ let next_super_trait = unvisited_super_trait.map_bound(|t| t.trait_ref);
+ stack.push((
+ next_super_trait,
+ emit_vptr_on_new_entry,
+ maybe_iter(Some(direct_super_traits_iter)),
+ ))
}
+
+ // There are no more unvisited direct super traits, dive-in finished
+ None => break 'diving_in,
}
}
- // Other than the left-most path, vptr should be emitted for each trait.
- emit_vptr_on_new_entry = true;
-
// emit innermost item, move to next sibling and stop there if possible, otherwise jump to outer level.
- 'exiting_out: loop {
- if let Some((inner_most_trait_ref, emit_vptr, siblings_opt)) = stack.last_mut() {
- if let ControlFlow::Break(v) = (segment_visitor)(VtblSegment::TraitOwnEntries {
- trait_ref: *inner_most_trait_ref,
- emit_vptr: *emit_vptr,
- }) {
- return Some(v);
- }
+ while let Some((inner_most_trait_ref, emit_vptr, mut siblings)) = stack.pop() {
+ segment_visitor(VtblSegment::TraitOwnEntries {
+ trait_ref: inner_most_trait_ref,
+ emit_vptr,
+ })?;
+
+ // If we've emitted (fed to `segment_visitor`) a trait that has methods present in the vtable,
+ // we'll need to emit vptrs from now on.
+ if !emit_vptr_on_new_entry
+ && has_own_existential_vtable_entries(tcx, inner_most_trait_ref.def_id())
+ {
+ emit_vptr_on_new_entry = true;
+ }
- 'exiting_out_skip_visited_traits: loop {
- if let Some(siblings) = siblings_opt {
- if let Some(next_inner_most_trait_ref) = siblings.next() {
- if visited.insert(next_inner_most_trait_ref.to_predicate(tcx)) {
- // We're throwing away potential constness of super traits here.
- // FIXME: handle ~const super traits
- let next_inner_most_trait_ref =
- next_inner_most_trait_ref.map_bound(|t| t.trait_ref);
- *inner_most_trait_ref = next_inner_most_trait_ref;
- *emit_vptr = emit_vptr_on_new_entry;
- break 'exiting_out;
- } else {
- continue 'exiting_out_skip_visited_traits;
- }
- }
- }
- stack.pop();
- continue 'exiting_out;
- }
+ if let Some(next_inner_most_trait_ref) =
+ siblings.find(|&sibling| visited.insert(sibling.to_predicate(tcx)))
+ {
+ // We're throwing away potential constness of super traits here.
+ // FIXME: handle ~const super traits
+ let next_inner_most_trait_ref =
+ next_inner_most_trait_ref.map_bound(|t| t.trait_ref);
+
+ stack.push((next_inner_most_trait_ref, emit_vptr_on_new_entry, siblings));
+
+ // just pushed a new trait onto the stack, so we need to go through its super traits
+ continue 'outer;
}
- // all done
- return None;
}
+
+ // the stack is empty, all done
+ return ControlFlow::Continue(());
}
}
+/// Turns option of iterator into an iterator (this is just flatten)
+fn maybe_iter<I: Iterator>(i: Option<I>) -> impl Iterator<Item = I::Item> {
+ // Flatten is bad perf-vise, we could probably implement a special case here that is better
+ i.into_iter().flatten()
+}
+
fn dump_vtable_entries<'tcx>(
tcx: TyCtxt<'tcx>,
sp: Span,
trait_ref: ty::PolyTraitRef<'tcx>,
entries: &[VtblEntry<'tcx>],
) {
- tcx.sess.emit_err(DumpVTableEntries {
- span: sp,
- trait_ref,
- entries: format!("{:#?}", entries),
- });
+ tcx.sess.emit_err(DumpVTableEntries { span: sp, trait_ref, entries: format!("{entries:#?}") });
+}
+
+fn has_own_existential_vtable_entries(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
+ own_existential_vtable_entries_iter(tcx, trait_def_id).next().is_some()
}
fn own_existential_vtable_entries(tcx: TyCtxt<'_>, trait_def_id: DefId) -> &[DefId] {
+ tcx.arena.alloc_from_iter(own_existential_vtable_entries_iter(tcx, trait_def_id))
+}
+
+fn own_existential_vtable_entries_iter(
+ tcx: TyCtxt<'_>,
+ trait_def_id: DefId,
+) -> impl Iterator<Item = DefId> + '_ {
let trait_methods = tcx
.associated_items(trait_def_id)
.in_definition_order()
.filter(|item| item.kind == ty::AssocKind::Fn);
+
// Now list each method's DefId (for within its trait).
let own_entries = trait_methods.filter_map(move |&trait_method| {
debug!("own_existential_vtable_entry: trait_method={:?}", trait_method);
@@ -211,7 +229,7 @@ fn own_existential_vtable_entries(tcx: TyCtxt<'_>, trait_def_id: DefId) -> &[Def
Some(def_id)
});
- tcx.arena.alloc_from_iter(own_entries.into_iter())
+ own_entries
}
/// Given a trait `trait_ref`, iterates the vtable entries
@@ -241,12 +259,12 @@ fn vtable_entries<'tcx>(
debug!("vtable_entries: trait_method={:?}", def_id);
// The method may have some early-bound lifetimes; add regions for those.
- let substs = trait_ref.map_bound(|trait_ref| {
- InternalSubsts::for_item(tcx, def_id, |param, _| match param.kind {
+ let args = trait_ref.map_bound(|trait_ref| {
+ GenericArgs::for_item(tcx, def_id, |param, _| match param.kind {
GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
GenericParamDefKind::Type { .. }
| GenericParamDefKind::Const { .. } => {
- trait_ref.substs[param.index as usize]
+ trait_ref.args[param.index as usize]
}
})
});
@@ -254,14 +272,14 @@ fn vtable_entries<'tcx>(
// The trait type may have higher-ranked lifetimes in it;
// erase them if they appear, so that we get the type
// at some particular call site.
- let substs = tcx
- .normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), substs);
+ let args =
+ tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), args);
// It's possible that the method relies on where-clauses that
// do not hold for this particular set of type parameters.
// Note that this method could then never be called, so we
// do not want to try and codegen it, in that case (see #23435).
- let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs);
+ let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, args);
if impossible_predicates(
tcx,
predicates.map(|(predicate, _)| predicate).collect(),
@@ -274,7 +292,7 @@ fn vtable_entries<'tcx>(
tcx,
ty::ParamEnv::reveal_all(),
def_id,
- substs,
+ args,
)
.expect("resolution failed during building vtable representation");
VtblEntry::Method(instance)
@@ -363,8 +381,8 @@ pub(crate) fn vtable_trait_upcasting_coercion_new_vptr_slot<'tcx>(
let trait_ref = ty::TraitRef::new(tcx, unsize_trait_did, [source, target]);
match tcx.codegen_select_candidate((ty::ParamEnv::reveal_all(), trait_ref)) {
- Ok(ImplSource::TraitUpcasting(implsrc_traitcasting)) => {
- implsrc_traitcasting.vtable_vptr_slot
+ Ok(ImplSource::Builtin(BuiltinImplSource::TraitUpcasting { vtable_vptr_slot }, _)) => {
+ *vtable_vptr_slot
}
otherwise => bug!("expected TraitUpcasting candidate, got {otherwise:?}"),
}
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index d81722ce2..f26310665 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -2,8 +2,8 @@ use crate::infer::InferCtxt;
use crate::traits;
use rustc_hir as hir;
use rustc_hir::lang_items::LangItem;
-use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{GenericArg, GenericArgKind, GenericArgsRef};
use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
use rustc_span::{Span, DUMMY_SP};
@@ -341,18 +341,14 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
let trait_ref = &trait_pred.trait_ref;
// Negative trait predicates don't require supertraits to hold, just
- // that their substs are WF.
+ // that their args are WF.
if trait_pred.polarity == ty::ImplPolarity::Negative {
self.compute_negative_trait_pred(trait_ref);
return;
}
// if the trait predicate is not const, the wf obligations should not be const as well.
- let obligations = if trait_pred.constness == ty::BoundConstness::NotConst {
- self.nominal_obligations_without_const(trait_ref.def_id, trait_ref.substs)
- } else {
- self.nominal_obligations(trait_ref.def_id, trait_ref.substs)
- };
+ let obligations = self.nominal_obligations(trait_ref.def_id, trait_ref.args);
debug!("compute_trait_pred obligations {:?}", obligations);
let param_env = self.param_env;
@@ -383,7 +379,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
self.out.extend(
trait_ref
- .substs
+ .args
.iter()
.enumerate()
.filter(|(_, arg)| {
@@ -416,7 +412,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
// Compute the obligations that are required for `trait_ref` to be WF,
// given that it is a *negative* trait predicate.
fn compute_negative_trait_pred(&mut self, trait_ref: &ty::TraitRef<'tcx>) {
- for arg in trait_ref.substs {
+ for arg in trait_ref.args {
self.compute(arg);
}
}
@@ -427,7 +423,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
// A projection is well-formed if
//
// (a) its predicates hold (*)
- // (b) its substs are wf
+ // (b) its args are wf
//
// (*) The predicates of an associated type include the predicates of
// the trait that it's contained in. For example, given
@@ -445,18 +441,17 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
// `i32: Clone`
// `i32: Copy`
// ]
- // Projection types do not require const predicates.
- let obligations = self.nominal_obligations_without_const(data.def_id, data.substs);
+ let obligations = self.nominal_obligations(data.def_id, data.args);
self.out.extend(obligations);
- self.compute_projection_substs(data.substs);
+ self.compute_projection_args(data.args);
}
fn compute_inherent_projection(&mut self, data: ty::AliasTy<'tcx>) {
// An inherent projection is well-formed if
//
// (a) its predicates hold (*)
- // (b) its substs are wf
+ // (b) its args are wf
//
// (*) The predicates of an inherent associated type include the
// predicates of the impl that it's contained in.
@@ -464,7 +459,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
if !data.self_ty().has_escaping_bound_vars() {
// FIXME(inherent_associated_types): Should this happen inside of a snapshot?
// FIXME(inherent_associated_types): This is incompatible with the new solver and lazy norm!
- let substs = traits::project::compute_inherent_assoc_ty_substs(
+ let args = traits::project::compute_inherent_assoc_ty_args(
&mut traits::SelectionContext::new(self.infcx),
self.param_env,
data,
@@ -472,23 +467,21 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
self.recursion_depth,
&mut self.out,
);
- // Inherent projection types do not require const predicates.
- let obligations = self.nominal_obligations_without_const(data.def_id, substs);
+ let obligations = self.nominal_obligations(data.def_id, args);
self.out.extend(obligations);
}
- self.compute_projection_substs(data.substs);
+ self.compute_projection_args(data.args);
}
- fn compute_projection_substs(&mut self, substs: SubstsRef<'tcx>) {
+ fn compute_projection_args(&mut self, args: GenericArgsRef<'tcx>) {
let tcx = self.tcx();
let cause = self.cause(traits::WellFormed(None));
let param_env = self.param_env;
let depth = self.recursion_depth;
self.out.extend(
- substs
- .iter()
+ args.iter()
.filter(|arg| {
matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..))
})
@@ -517,7 +510,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
cause,
self.recursion_depth,
self.param_env,
- ty::Binder::dummy(trait_ref).without_const(),
+ ty::Binder::dummy(trait_ref),
));
}
}
@@ -541,7 +534,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
match ct.kind() {
ty::ConstKind::Unevaluated(uv) => {
if !ct.has_escaping_bound_vars() {
- let obligations = self.nominal_obligations(uv.def, uv.substs);
+ let obligations = self.nominal_obligations(uv.def, uv.args);
self.out.extend(obligations);
let predicate = ty::Binder::dummy(ty::PredicateKind::Clause(
@@ -571,7 +564,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
));
}
ty::ConstKind::Expr(_) => {
- // FIXME(generic_const_exprs): this doesnt verify that given `Expr(N + 1)` the
+ // FIXME(generic_const_exprs): this doesn't verify that given `Expr(N + 1)` the
// trait bound `typeof(N): Add<typeof(1)>` holds. This is currently unnecessary
// as `ConstKind::Expr` is only produced via normalization of `ConstKind::Unevaluated`
// which means that the `DefId` would have been typeck'd elsewhere. However in
@@ -661,14 +654,14 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
self.compute_inherent_projection(data);
}
- ty::Adt(def, substs) => {
+ ty::Adt(def, args) => {
// WfNominalType
- let obligations = self.nominal_obligations(def.did(), substs);
+ let obligations = self.nominal_obligations(def.did(), args);
self.out.extend(obligations);
}
- ty::FnDef(did, substs) => {
- let obligations = self.nominal_obligations_without_const(did, substs);
+ ty::FnDef(did, args) => {
+ let obligations = self.nominal_obligations(did, args);
self.out.extend(obligations);
}
@@ -688,7 +681,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
}
}
- ty::Generator(did, substs, ..) => {
+ ty::Generator(did, args, ..) => {
// Walk ALL the types in the generator: this will
// include the upvar types as well as the yield
// type. Note that this is mildly distinct from
@@ -696,11 +689,11 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
// about the signature of the closure. We don't
// have the problem of implied bounds here since
// generators don't take arguments.
- let obligations = self.nominal_obligations(did, substs);
+ let obligations = self.nominal_obligations(did, args);
self.out.extend(obligations);
}
- ty::Closure(did, substs) => {
+ ty::Closure(did, args) => {
// Only check the upvar types for WF, not the rest
// of the types within. This is needed because we
// capture the signature and it may not be WF
@@ -723,7 +716,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
// fn(&'a T) }`, as discussed in #25860.
walker.skip_current_subtree(); // subtree handled below
// FIXME(eddyb) add the type to `walker` instead of recursing.
- self.compute(substs.as_closure().tupled_upvars_ty().into());
+ self.compute(args.as_closure().tupled_upvars_ty().into());
// Note that we cannot skip the generic types
// types. Normally, within the fn
// body where they are created, the generics will
@@ -739,7 +732,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
// can cause compiler crashes when the user abuses unsafe
// code to procure such a closure.
// See tests/ui/type-alias-impl-trait/wf_check_closures.rs
- let obligations = self.nominal_obligations(did, substs);
+ let obligations = self.nominal_obligations(did, args);
self.out.extend(obligations);
}
@@ -748,18 +741,18 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
// types appearing in the fn signature
}
- ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
// All of the requirements on type parameters
// have already been checked for `impl Trait` in
// return position. We do need to check type-alias-impl-trait though.
if self.tcx().is_type_alias_impl_trait(def_id) {
- let obligations = self.nominal_obligations(def_id, substs);
+ let obligations = self.nominal_obligations(def_id, args);
self.out.extend(obligations);
}
}
- ty::Alias(ty::Weak, ty::AliasTy { def_id, substs, .. }) => {
- let obligations = self.nominal_obligations(def_id, substs);
+ ty::Alias(ty::Weak, ty::AliasTy { def_id, args, .. }) => {
+ let obligations = self.nominal_obligations(def_id, args);
self.out.extend(obligations);
}
@@ -823,11 +816,10 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
}
#[instrument(level = "debug", skip(self))]
- fn nominal_obligations_inner(
+ fn nominal_obligations(
&mut self,
def_id: DefId,
- substs: SubstsRef<'tcx>,
- remap_constness: bool,
+ args: GenericArgsRef<'tcx>,
) -> Vec<traits::PredicateObligation<'tcx>> {
let predicates = self.tcx().predicates_of(def_id);
let mut origins = vec![def_id; predicates.predicates.len()];
@@ -837,21 +829,18 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
origins.extend(iter::repeat(parent).take(head.predicates.len()));
}
- let predicates = predicates.instantiate(self.tcx(), substs);
+ let predicates = predicates.instantiate(self.tcx(), args);
trace!("{:#?}", predicates);
debug_assert_eq!(predicates.predicates.len(), origins.len());
iter::zip(predicates, origins.into_iter().rev())
- .map(|((mut pred, span), origin_def_id)| {
+ .map(|((pred, span), origin_def_id)| {
let code = if span.is_dummy() {
traits::ItemObligation(origin_def_id)
} else {
traits::BindingObligation(origin_def_id, span)
};
let cause = self.cause(code);
- if remap_constness {
- pred = pred.without_const(self.tcx());
- }
traits::Obligation::with_depth(
self.tcx(),
cause,
@@ -864,22 +853,6 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
.collect()
}
- fn nominal_obligations(
- &mut self,
- def_id: DefId,
- substs: SubstsRef<'tcx>,
- ) -> Vec<traits::PredicateObligation<'tcx>> {
- self.nominal_obligations_inner(def_id, substs, false)
- }
-
- fn nominal_obligations_without_const(
- &mut self,
- def_id: DefId,
- substs: SubstsRef<'tcx>,
- ) -> Vec<traits::PredicateObligation<'tcx>> {
- self.nominal_obligations_inner(def_id, substs, true)
- }
-
fn from_object_ty(
&mut self,
ty: Ty<'tcx>,