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.rs14
-rw-r--r--compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs35
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs24
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/engine.rs11
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs15
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs131
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs30
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs287
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs161
-rw-r--r--compiler/rustc_trait_selection/src/traits/misc.rs23
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs46
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs162
-rw-r--r--compiler/rustc_trait_selection/src/traits/outlives_bounds.rs13
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs160
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs43
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/normalize.rs38
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/relationships.rs48
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs27
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs110
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs247
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/mod.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/structural_match.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/util.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/vtable.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs54
32 files changed, 1088 insertions, 652 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index 948632ccc..1fb8659bb 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -9,7 +9,7 @@ use crate::infer::InferCtxt;
use crate::traits::project::ProjectAndUnifyResult;
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
-use rustc_middle::ty::visit::TypeVisitable;
+use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{ImplPolarity, Region, RegionVid};
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
@@ -350,14 +350,14 @@ impl<'tcx> AutoTraitFinder<'tcx> {
)
.map(|o| o.predicate);
new_env = ty::ParamEnv::new(
- tcx.mk_predicates(normalized_preds),
+ tcx.mk_predicates_from_iter(normalized_preds),
param_env.reveal(),
param_env.constness(),
);
}
let final_user_env = ty::ParamEnv::new(
- tcx.mk_predicates(user_computed_preds.into_iter()),
+ tcx.mk_predicates_from_iter(user_computed_preds.into_iter()),
user_env.reveal(),
user_env.constness(),
);
@@ -823,14 +823,18 @@ impl<'tcx> AutoTraitFinder<'tcx> {
_ => return false,
}
}
+
// There's not really much we can do with these predicates -
// we start out with a `ParamEnv` with no inference variables,
// and these don't correspond to adding any new bounds to
// the `ParamEnv`.
ty::PredicateKind::WellFormed(..)
+ | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
+ | ty::PredicateKind::AliasEq(..)
| ty::PredicateKind::ObjectSafe(..)
| ty::PredicateKind::ClosureKind(..)
| ty::PredicateKind::Subtype(..)
+ // FIXME(generic_const_exprs): you can absolutely add this as a where clauses
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::Coerce(..)
| ty::PredicateKind::TypeWellFormedFromEnv(..) => {}
@@ -855,8 +859,8 @@ pub struct RegionReplacer<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
}
-impl<'a, 'tcx> TypeFolder<'tcx> for RegionReplacer<'a, 'tcx> {
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for RegionReplacer<'a, 'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
diff --git a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
index e88950523..b42a49eb4 100644
--- a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
@@ -7,24 +7,18 @@ use crate::traits::{
ChalkEnvironmentAndGoal, FulfillmentError, FulfillmentErrorCode, PredicateObligation,
SelectionError, TraitEngine,
};
-use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
-use rustc_middle::ty::{self, TypeVisitable};
+use rustc_data_structures::fx::FxIndexSet;
+use rustc_middle::ty::TypeVisitableExt;
pub struct FulfillmentContext<'tcx> {
obligations: FxIndexSet<PredicateObligation<'tcx>>,
- relationships: FxHashMap<ty::TyVid, ty::FoundRelationships>,
-
usable_in_snapshot: bool,
}
impl FulfillmentContext<'_> {
pub(super) fn new() -> Self {
- FulfillmentContext {
- obligations: FxIndexSet::default(),
- relationships: FxHashMap::default(),
- usable_in_snapshot: false,
- }
+ FulfillmentContext { obligations: FxIndexSet::default(), usable_in_snapshot: false }
}
pub(crate) fn new_in_snapshot() -> Self {
@@ -43,20 +37,10 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
}
let obligation = infcx.resolve_vars_if_possible(obligation);
- super::relationships::update(self, infcx, &obligation);
-
self.obligations.insert(obligation);
}
- fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
- {
- let errors = self.select_where_possible(infcx);
-
- if !errors.is_empty() {
- return errors;
- }
- }
-
+ fn collect_remaining_errors(&mut self) -> Vec<FulfillmentError<'tcx>> {
// any remaining obligations are errors
self.obligations
.iter()
@@ -151,11 +135,14 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
errors
}
- fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
- self.obligations.iter().cloned().collect()
+ fn drain_unstalled_obligations(
+ &mut self,
+ _: &InferCtxt<'tcx>,
+ ) -> Vec<PredicateObligation<'tcx>> {
+ unimplemented!()
}
- fn relationships(&mut self) -> &mut FxHashMap<ty::TyVid, ty::FoundRelationships> {
- &mut self.relationships
+ fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
+ self.obligations.iter().cloned().collect()
}
}
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index 225c1050c..6b688c322 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -17,12 +17,11 @@ use crate::traits::{
use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::Diagnostic;
use rustc_hir::def_id::{DefId, CRATE_DEF_ID, LOCAL_CRATE};
-use rustc_hir::CRATE_HIR_ID;
use rustc_infer::infer::{DefiningAnchor, InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::util;
use rustc_middle::traits::specialization_graph::OverlapMode;
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
-use rustc_middle::ty::visit::TypeVisitable;
+use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt, TypeVisitor};
use rustc_span::symbol::sym;
use rustc_span::DUMMY_SP;
@@ -83,8 +82,8 @@ pub fn overlapping_impls(
(Some(a), Some(b)) => iter::zip(a.skip_binder().substs, b.skip_binder().substs)
.all(|(arg1, arg2)| drcx.generic_args_may_unify(arg1, arg2)),
(None, None) => {
- let self_ty1 = tcx.type_of(impl1_def_id);
- let self_ty2 = tcx.type_of(impl2_def_id);
+ let self_ty1 = tcx.type_of(impl1_def_id).skip_binder();
+ let self_ty2 = tcx.type_of(impl2_def_id).skip_binder();
drcx.types_may_unify(self_ty1, self_ty2)
}
_ => bug!("unexpected impls: {impl1_def_id:?} {impl2_def_id:?}"),
@@ -125,7 +124,7 @@ fn with_fresh_ty_vars<'cx, 'tcx>(
let header = ty::ImplHeader {
impl_def_id,
- self_ty: tcx.bound_type_of(impl_def_id).subst(tcx, impl_substs),
+ 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)),
predicates: tcx.predicates_of(impl_def_id).instantiate(tcx, impl_substs).predicates,
};
@@ -218,6 +217,7 @@ fn equate_impl_headers<'cx, 'tcx>(
selcx
.infcx
.at(&ObligationCause::dummy(), ty::ParamEnv::empty())
+ .define_opaque_types(true)
.eq_impl_headers(impl1_header, impl2_header)
.map(|infer_ok| infer_ok.obligations)
.ok()
@@ -382,18 +382,14 @@ fn resolve_negative_obligation<'tcx>(
return false;
}
- let (body_id, body_def_id) = if let Some(body_def_id) = body_def_id.as_local() {
- (tcx.hir().local_def_id_to_hir_id(body_def_id), body_def_id)
- } else {
- (CRATE_HIR_ID, CRATE_DEF_ID)
- };
+ let body_def_id = body_def_id.as_local().unwrap_or(CRATE_DEF_ID);
let ocx = ObligationCtxt::new(&infcx);
let wf_tys = ocx.assumed_wf_types(param_env, DUMMY_SP, body_def_id);
let outlives_env = OutlivesEnvironment::with_bounds(
param_env,
Some(&infcx),
- infcx.implied_bounds_tys(param_env, body_id, wf_tys),
+ infcx.implied_bounds_tys(param_env, body_def_id, wf_tys),
);
infcx.process_registered_region_obligations(outlives_env.region_bound_pairs(), param_env);
@@ -632,7 +628,7 @@ enum OrphanCheckEarlyExit<'tcx> {
LocalTy(Ty<'tcx>),
}
-impl<'tcx> TypeVisitor<'tcx> for OrphanChecker<'tcx> {
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OrphanChecker<'tcx> {
type BreakTy = OrphanCheckEarlyExit<'tcx>;
fn visit_region(&mut self, _r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
ControlFlow::Continue(())
@@ -701,7 +697,9 @@ impl<'tcx> TypeVisitor<'tcx> for OrphanChecker<'tcx> {
// This should only be created when checking whether we have to check whether some
// auto trait impl applies. There will never be multiple impls, so we can just
// act as if it were a local type here.
- ty::GeneratorWitness(_) => ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)),
+ ty::GeneratorWitness(_) | ty::GeneratorWitnessMIR(..) => {
+ ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty))
+ }
ty::Alias(ty::Opaque, ..) => {
// This merits some explanation.
// Normally, opaque types are not involved when performing
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index f779d9dd8..345e84990 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -14,7 +14,7 @@ use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
-use rustc_middle::ty::{self, TyCtxt, TypeVisitable, TypeVisitor};
+use rustc_middle::ty::{self, TyCtxt, TypeVisitable, TypeVisitableExt, TypeVisitor};
use rustc_span::Span;
use std::ops::ControlFlow;
@@ -171,7 +171,7 @@ fn satisfied_from_param_env<'tcx>(
single_match: Option<Result<ty::Const<'tcx>, ()>>,
}
- impl<'a, 'tcx> TypeVisitor<'tcx> for Visitor<'a, 'tcx> {
+ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for Visitor<'a, 'tcx> {
type BreakTy = ();
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
debug!("is_const_evaluatable: candidate={:?}", c);
@@ -219,7 +219,7 @@ fn satisfied_from_param_env<'tcx>(
}
if let Some(Ok(c)) = single_match {
- let ocx = ObligationCtxt::new(infcx);
+ let ocx = ObligationCtxt::new_in_snapshot(infcx);
assert!(ocx.eq(&ObligationCause::dummy(), param_env, c.ty(), ct.ty()).is_ok());
assert!(ocx.eq(&ObligationCause::dummy(), param_env, c, ct).is_ok());
assert!(ocx.select_all_or_error().is_empty());
diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs
index 369f80139..b20636174 100644
--- a/compiler/rustc_trait_selection/src/traits/engine.rs
+++ b/compiler/rustc_trait_selection/src/traits/engine.rs
@@ -104,7 +104,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
});
}
- pub fn normalize<T: TypeFoldable<'tcx>>(
+ pub fn normalize<T: TypeFoldable<TyCtxt<'tcx>>>(
&self,
cause: &ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
@@ -128,6 +128,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
{
self.infcx
.at(cause, param_env)
+ .define_opaque_types(true)
.eq_exp(a_is_expected, a, b)
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
}
@@ -141,6 +142,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
) -> Result<(), TypeError<'tcx>> {
self.infcx
.at(cause, param_env)
+ .define_opaque_types(true)
.eq(expected, actual)
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
}
@@ -155,6 +157,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
) -> Result<(), TypeError<'tcx>> {
self.infcx
.at(cause, param_env)
+ .define_opaque_types(true)
.sup(expected, actual)
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
}
@@ -169,6 +172,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
) -> Result<(), TypeError<'tcx>> {
self.infcx
.at(cause, param_env)
+ .define_opaque_types(true)
.sup(expected, actual)
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
}
@@ -190,8 +194,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
let tcx = self.infcx.tcx;
let assumed_wf_types = tcx.assumed_wf_types(def_id);
let mut implied_bounds = FxIndexSet::default();
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
- let cause = ObligationCause::misc(span, hir_id);
+ let cause = ObligationCause::misc(span, def_id);
for ty in assumed_wf_types {
// FIXME(@lcnr): rustc currently does not check wf for types
// pre-normalization, meaning that implied bounds are sometimes
@@ -217,7 +220,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
answer: T,
) -> Fallible<CanonicalQueryResponse<'tcx, T>>
where
- T: Debug + TypeFoldable<'tcx>,
+ T: Debug + TypeFoldable<TyCtxt<'tcx>>,
Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>,
{
self.infcx.make_canonicalized_query_response(
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 0419bb3f7..84045c4d0 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
@@ -22,7 +22,7 @@ pub fn recompute_applicable_impls<'tcx>(
let impl_may_apply = |impl_def_id| {
let ocx = ObligationCtxt::new_in_snapshot(infcx);
let placeholder_obligation =
- infcx.replace_bound_vars_with_placeholders(obligation.predicate);
+ infcx.instantiate_binder_with_placeholders(obligation.predicate);
let obligation_trait_ref =
ocx.normalize(&ObligationCause::dummy(), param_env, placeholder_obligation.trait_ref);
@@ -47,11 +47,11 @@ pub fn recompute_applicable_impls<'tcx>(
let param_env_candidate_may_apply = |poly_trait_predicate: ty::PolyTraitPredicate<'tcx>| {
let ocx = ObligationCtxt::new_in_snapshot(infcx);
let placeholder_obligation =
- infcx.replace_bound_vars_with_placeholders(obligation.predicate);
+ infcx.instantiate_binder_with_placeholders(obligation.predicate);
let obligation_trait_ref =
ocx.normalize(&ObligationCause::dummy(), param_env, placeholder_obligation.trait_ref);
- let param_env_predicate = infcx.replace_bound_vars_with_fresh_vars(
+ let param_env_predicate = infcx.instantiate_binder_with_fresh_vars(
DUMMY_SP,
LateBoundRegionConversionTime::HigherRankedType,
poly_trait_predicate,
@@ -81,7 +81,7 @@ pub fn recompute_applicable_impls<'tcx>(
);
let predicates =
- tcx.predicates_of(obligation.cause.body_id.owner.to_def_id()).instantiate_identity(tcx);
+ tcx.predicates_of(obligation.cause.body_id.to_def_id()).instantiate_identity(tcx);
for obligation in elaborate_predicates_with_span(tcx, predicates.into_iter()) {
let kind = obligation.predicate.kind();
if let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = kind.skip_binder()
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs
index ba9ee57d4..1174efdbf 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/method_chain.rs
@@ -1,5 +1,7 @@
use crate::infer::InferCtxt;
+use rustc_infer::infer::ObligationEmittingRelation;
+use rustc_infer::traits::PredicateObligations;
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -88,3 +90,16 @@ impl<'a, 'tcx> TypeRelation<'tcx> for CollectAllMismatches<'a, 'tcx> {
Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?))
}
}
+
+impl<'tcx> ObligationEmittingRelation<'tcx> for CollectAllMismatches<'_, 'tcx> {
+ fn register_obligations(&mut self, _obligations: PredicateObligations<'tcx>) {
+ // FIXME(deferred_projection_equality)
+ }
+
+ fn register_predicates(
+ &mut self,
+ _obligations: impl IntoIterator<Item: ty::ToPredicate<'tcx>>,
+ ) {
+ // FIXME(deferred_projection_equality)
+ }
+}
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 52971486c..a844a1494 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -38,7 +38,7 @@ use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
use rustc_middle::ty::print::{with_forced_trimmed_paths, FmtPrinter, Print};
use rustc_middle::ty::{
self, SubtypePredicate, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable,
- TypeVisitable,
+ TypeVisitable, TypeVisitableExt,
};
use rustc_session::config::TraitSolver;
use rustc_session::Limit;
@@ -101,6 +101,18 @@ pub trait InferCtxtExt<'tcx> {
}
pub trait TypeErrCtxtExt<'tcx> {
+ fn build_overflow_error<T>(
+ &self,
+ predicate: &T,
+ span: Span,
+ suggest_increasing_limit: bool,
+ ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>
+ where
+ T: fmt::Display
+ + TypeFoldable<TyCtxt<'tcx>>
+ + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
+ <T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug;
+
fn report_overflow_error<T>(
&self,
predicate: &T,
@@ -110,7 +122,7 @@ pub trait TypeErrCtxtExt<'tcx> {
) -> !
where
T: fmt::Display
- + TypeFoldable<'tcx>
+ + TypeFoldable<TyCtxt<'tcx>>
+ Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
<T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug;
@@ -480,7 +492,27 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
) -> !
where
T: fmt::Display
- + TypeFoldable<'tcx>
+ + TypeFoldable<TyCtxt<'tcx>>
+ + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
+ <T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug,
+ {
+ let mut err = self.build_overflow_error(predicate, span, suggest_increasing_limit);
+ mutate(&mut err);
+ err.emit();
+
+ self.tcx.sess.abort_if_errors();
+ bug!();
+ }
+
+ fn build_overflow_error<T>(
+ &self,
+ predicate: &T,
+ span: Span,
+ suggest_increasing_limit: bool,
+ ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>
+ where
+ T: fmt::Display
+ + TypeFoldable<TyCtxt<'tcx>>
+ Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
<T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug,
{
@@ -511,11 +543,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
self.suggest_new_overflow_limit(&mut err);
}
- mutate(&mut err);
-
- err.emit();
- self.tcx.sess.abort_if_errors();
- bug!();
+ err
}
/// Reports that an overflow has occurred and halts compilation. We
@@ -839,14 +867,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
err.note(s.as_str());
}
if let Some(ref s) = parent_label {
- let body = tcx
- .hir()
- .opt_local_def_id(obligation.cause.body_id)
- .unwrap_or_else(|| {
- tcx.hir().body_owner_def_id(hir::BodyId {
- hir_id: obligation.cause.body_id,
- })
- });
+ let body = obligation.cause.body_id;
err.span_label(tcx.def_span(body), s);
}
@@ -934,6 +955,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
);
}
+ let body_hir_id =
+ self.tcx.hir().local_def_id_to_hir_id(obligation.cause.body_id);
// Try to report a help message
if is_fn_trait
&& let Ok((implemented_kind, params)) = self.type_implements_fn_trait(
@@ -1014,7 +1037,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
if !self.report_similar_impl_candidates(
impl_candidates,
trait_ref,
- obligation.cause.body_id,
+ body_hir_id,
&mut err,
true,
) {
@@ -1050,7 +1073,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
self.report_similar_impl_candidates(
impl_candidates,
trait_ref,
- obligation.cause.body_id,
+ body_hir_id,
&mut err,
true,
);
@@ -1207,20 +1230,23 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
ty::PredicateKind::WellFormed(ty) => {
- if self.tcx.sess.opts.unstable_opts.trait_solver == TraitSolver::Classic {
- // WF predicates cannot themselves make
- // errors. They can only block due to
- // ambiguity; otherwise, they always
- // degenerate into other obligations
- // (which may fail).
- span_bug!(span, "WF predicate not satisfied for {:?}", ty);
- } else {
- // FIXME: we'll need a better message which takes into account
- // which bounds actually failed to hold.
- self.tcx.sess.struct_span_err(
- span,
- &format!("the type `{}` is not well-formed", ty),
- )
+ match self.tcx.sess.opts.unstable_opts.trait_solver {
+ TraitSolver::Classic => {
+ // WF predicates cannot themselves make
+ // errors. They can only block due to
+ // ambiguity; otherwise, they always
+ // degenerate into other obligations
+ // (which may fail).
+ span_bug!(span, "WF predicate not satisfied for {:?}", ty);
+ }
+ TraitSolver::Chalk | TraitSolver::Next => {
+ // FIXME: we'll need a better message which takes into account
+ // which bounds actually failed to hold.
+ self.tcx.sess.struct_span_err(
+ span,
+ &format!("the type `{}` is not well-formed", ty),
+ )
+ }
}
}
@@ -1252,6 +1278,18 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
span,
"TypeWellFormedFromEnv predicate should only exist in the environment"
),
+
+ ty::PredicateKind::AliasEq(..) => span_bug!(
+ span,
+ "AliasEq predicate should never be the predicate cause of a SelectionError"
+ ),
+
+ ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
+ self.tcx.sess.struct_span_err(
+ span,
+ &format!("the constant `{}` is not of type `{}`", ct, ty),
+ )
+ }
}
}
@@ -1598,7 +1636,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// Eventually I'll need to implement param-env-aware
// `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic.
let param_env = ty::ParamEnv::empty();
- if self.can_sub(param_env, error, implication).is_ok() {
+ if self.can_sub(param_env, error, implication) {
debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication);
return true;
}
@@ -1690,7 +1728,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let (values, err) = if let ty::PredicateKind::Clause(ty::Clause::Projection(data)) =
bound_predicate.skip_binder()
{
- let data = self.replace_bound_vars_with_fresh_vars(
+ let data = self.instantiate_binder_with_fresh_vars(
obligation.cause.span,
infer::LateBoundRegionConversionTime::HigherRankedType,
bound_predicate.rebind(data),
@@ -1843,10 +1881,14 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
with_forced_trimmed_paths! {
if Some(pred.projection_ty.def_id) == self.tcx.lang_items().fn_once_output() {
+ let fn_kind = self_ty.prefix_string(self.tcx);
+ let item = match self_ty.kind() {
+ ty::FnDef(def, _) => self.tcx.item_name(*def).to_string(),
+ _ => self_ty.to_string(),
+ };
Some(format!(
- "expected `{self_ty}` to be a {fn_kind} that returns `{expected_ty}`, but it \
+ "expected `{item}` to be a {fn_kind} that returns `{expected_ty}`, but it \
returns `{normalized_ty}`",
- fn_kind = self_ty.prefix_string(self.tcx)
))
} else if Some(trait_def_id) == self.tcx.lang_items().future_trait() {
Some(format!(
@@ -1896,6 +1938,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
ty::Generator(..) => Some(16),
ty::Foreign(..) => Some(17),
ty::GeneratorWitness(..) => Some(18),
+ ty::GeneratorWitnessMIR(..) => Some(19),
ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => None,
}
}
@@ -2062,7 +2105,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// Ignore automatically derived impls and `!Trait` impls.
.filter(|&def_id| {
self.tcx.impl_polarity(def_id) != ty::ImplPolarity::Negative
- || self.tcx.is_builtin_derive(def_id)
+ || self.tcx.is_automatically_derived(def_id)
})
.filter_map(|def_id| self.tcx.impl_trait_ref(def_id))
.map(ty::EarlyBinder::subst_identity)
@@ -2305,10 +2348,12 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
predicate.to_opt_poly_trait_pred().unwrap(),
);
if impl_candidates.len() < 10 {
+ let hir =
+ self.tcx.hir().local_def_id_to_hir_id(obligation.cause.body_id);
self.report_similar_impl_candidates(
impl_candidates,
trait_ref,
- body_id.map(|id| id.hir_id).unwrap_or(obligation.cause.body_id),
+ body_id.map(|id| id.hir_id).unwrap_or(hir),
&mut err,
false,
);
@@ -2395,7 +2440,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
};
let mut suggestions = vec![(
path.span.shrink_to_lo(),
- format!("<{} as ", self.tcx.type_of(impl_def_id))
+ format!("<{} as ", self.tcx.type_of(impl_def_id).subst_identity())
)];
if let Some(generic_arg) = trait_path_segment.args {
let between_span = trait_path_segment.ident.span.between(generic_arg.span_ext);
@@ -2637,8 +2682,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
var_map: FxHashMap<Ty<'tcx>, Ty<'tcx>>,
}
- impl<'a, 'tcx> TypeFolder<'tcx> for ParamToVarFolder<'a, 'tcx> {
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ParamToVarFolder<'a, 'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.infcx.tcx
}
@@ -2828,7 +2873,7 @@ pub struct FindExprBySpan<'hir> {
}
impl<'hir> FindExprBySpan<'hir> {
- fn new(span: Span) -> Self {
+ pub fn new(span: Span) -> Self {
Self { span, result: None, ty_result: None }
}
}
@@ -2926,7 +2971,7 @@ impl ArgKind {
struct HasNumericInferVisitor;
-impl<'tcx> ty::TypeVisitor<'tcx> for HasNumericInferVisitor {
+impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for HasNumericInferVisitor {
type BreakTy = ();
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
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 18d308f71..b3bf9ad59 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
@@ -60,7 +60,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
) -> Option<(DefId, SubstsRef<'tcx>)> {
let tcx = self.tcx;
let param_env = obligation.param_env;
- let trait_ref = tcx.erase_late_bound_regions(trait_ref);
+ let trait_ref = self.instantiate_binder_with_placeholders(trait_ref);
let trait_self_ty = trait_ref.self_ty();
let mut self_match_impls = vec![];
@@ -72,7 +72,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let impl_self_ty = impl_trait_ref.self_ty();
- if let Ok(..) = self.can_eq(param_env, trait_self_ty, impl_self_ty) {
+ if self.can_eq(param_env, trait_self_ty, impl_self_ty) {
self_match_impls.push((def_id, impl_substs));
if iter::zip(
@@ -149,10 +149,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
.unwrap_or_else(|| (trait_ref.def_id(), trait_ref.skip_binder().substs));
let trait_ref = trait_ref.skip_binder();
- let mut flags = vec![(
- sym::ItemContext,
- self.describe_enclosure(obligation.cause.body_id).map(|s| s.to_owned()),
- )];
+ let body_hir = self.tcx.hir().local_def_id_to_hir_id(obligation.cause.body_id);
+ let mut flags =
+ vec![(sym::ItemContext, self.describe_enclosure(body_hir).map(|s| s.to_owned()))];
match obligation.cause.code() {
ObligationCauseCode::BuiltinDerivedObligation(..)
@@ -201,7 +200,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
if let Some(def) = self_ty.ty_adt_def() {
// We also want to be able to select self's original
// signature with no type arguments resolved
- flags.push((sym::_Self, Some(self.tcx.type_of(def.did()).to_string())));
+ flags.push((
+ sym::_Self,
+ Some(self.tcx.type_of(def.did()).subst_identity().to_string()),
+ ));
}
for param in generics.params.iter() {
@@ -219,7 +221,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
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()).to_string())));
+ flags.push((
+ name,
+ Some(self.tcx.type_of(def.did()).subst_identity().to_string()),
+ ));
}
}
}
@@ -252,7 +257,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
if let Some(def) = aty.ty_adt_def() {
// We also want to be able to select the slice's type's original
// signature with no type arguments resolved
- flags.push((sym::_Self, Some(format!("[{}]", self.tcx.type_of(def.did())))));
+ flags.push((
+ sym::_Self,
+ Some(format!("[{}]", self.tcx.type_of(def.did()).subst_identity())),
+ ));
}
if aty.is_integral() {
flags.push((sym::_Self, Some("[{integral}]".to_string())));
@@ -262,7 +270,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// Arrays give us `[]`, `[{ty}; _]` and `[{ty}; N]`
if let ty::Array(aty, len) = self_ty.kind() {
flags.push((sym::_Self, Some("[]".to_string())));
- let len = len.kind().try_to_value().and_then(|v| v.try_to_machine_usize(self.tcx));
+ let len = len.kind().try_to_value().and_then(|v| v.try_to_target_usize(self.tcx));
flags.push((sym::_Self, Some(format!("[{}; _]", aty))));
if let Some(n) = len {
flags.push((sym::_Self, Some(format!("[{}; {}]", aty, n))));
@@ -270,7 +278,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
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());
+ let def_ty = self.tcx.type_of(def.did()).subst_identity();
flags.push((sym::_Self, Some(format!("[{def_ty}; _]"))));
if let Some(n) = len {
flags.push((sym::_Self, Some(format!("[{def_ty}; {n}]"))));
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 39e50b2ac..66d74fd05 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -9,7 +9,6 @@ use crate::infer::InferCtxt;
use crate::traits::{NormalizeExt, ObligationCtxt};
use hir::def::CtorOf;
-use hir::{Expr, HirId};
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::{
@@ -20,8 +19,10 @@ use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor;
+use rustc_hir::is_range_literal;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Node};
+use rustc_hir::{Expr, HirId};
use rustc_infer::infer::error_reporting::TypeErrCtxt;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::{InferOk, LateBoundRegionConversionTime};
@@ -32,8 +33,9 @@ use rustc_middle::ty::{
self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, DefIdTree,
GeneratorDiagnosticData, GeneratorInteriorTypeCause, Infer, InferTy, InternalSubsts,
IsSuggestable, ToPredicate, Ty, TyCtxt, TypeAndMut, TypeFoldable, TypeFolder,
- TypeSuperFoldable, TypeVisitable, TypeckResults,
+ TypeSuperFoldable, TypeVisitableExt, TypeckResults,
};
+use rustc_span::def_id::LocalDefId;
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::{BytePos, DesugaringKind, ExpnKind, MacroKind, Span, DUMMY_SP};
use rustc_target::spec::abi;
@@ -80,11 +82,8 @@ impl<'tcx, 'a> GeneratorData<'tcx, 'a> {
upvars.iter().find_map(|(upvar_id, upvar)| {
let upvar_ty = typeck_results.node_type(*upvar_id);
let upvar_ty = infer_context.resolve_vars_if_possible(upvar_ty);
- if ty_matches(ty::Binder::dummy(upvar_ty)) {
- Some(GeneratorInteriorOrUpvar::Upvar(upvar.span))
- } else {
- None
- }
+ ty_matches(ty::Binder::dummy(upvar_ty))
+ .then(|| GeneratorInteriorOrUpvar::Upvar(upvar.span))
})
})
}
@@ -97,6 +96,7 @@ impl<'tcx, 'a> GeneratorData<'tcx, 'a> {
// obligation
fn get_from_await_ty<F>(
&self,
+ tcx: TyCtxt<'tcx>,
visitor: AwaitsVisitor,
hir: map::Map<'tcx>,
ty_matches: F,
@@ -132,10 +132,8 @@ impl<'tcx, 'a> GeneratorData<'tcx, 'a> {
.cloned()
.unwrap_or_else(|| {
bug!(
- "node_type: no type for node `{}`",
- ty::tls::with(|tcx| tcx
- .hir()
- .node_to_string(await_expr.hir_id))
+ "node_type: no type for node {}",
+ tcx.hir().node_to_string(await_expr.hir_id)
)
})
},
@@ -179,7 +177,7 @@ pub trait TypeErrCtxtExt<'tcx> {
err: &mut Diagnostic,
trait_pred: ty::PolyTraitPredicate<'tcx>,
associated_item: Option<(&'static str, Ty<'tcx>)>,
- body_id: hir::HirId,
+ body_id: LocalDefId,
);
fn suggest_dereferences(
@@ -398,7 +396,7 @@ fn predicate_constraint(generics: &hir::Generics<'_>, pred: ty::Predicate<'_>) -
/// param for cleaner code.
fn suggest_restriction<'tcx>(
tcx: TyCtxt<'tcx>,
- hir_id: HirId,
+ item_id: LocalDefId,
hir_generics: &hir::Generics<'tcx>,
msg: &str,
err: &mut Diagnostic,
@@ -417,7 +415,6 @@ fn suggest_restriction<'tcx>(
{
return;
}
- let Some(item_id) = hir_id.as_owner() else { return; };
let generics = tcx.generics_of(item_id);
// Given `fn foo(t: impl Trait)` where `Trait` requires assoc type `A`...
if let Some((param, bound_str, fn_sig)) =
@@ -522,7 +519,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
mut err: &mut Diagnostic,
trait_pred: ty::PolyTraitPredicate<'tcx>,
associated_ty: Option<(&'static str, Ty<'tcx>)>,
- body_id: hir::HirId,
+ mut body_id: LocalDefId,
) {
let trait_pred = self.resolve_numeric_literals_with_default(trait_pred);
@@ -535,8 +532,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// FIXME: Add check for trait bound that is already present, particularly `?Sized` so we
// don't suggest `T: Sized + ?Sized`.
- let mut hir_id = body_id;
- while let Some(node) = self.tcx.hir().find(hir_id) {
+ while let Some(node) = self.tcx.hir().find_by_def_id(body_id) {
match node {
hir::Node::Item(hir::Item {
ident,
@@ -547,7 +543,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// Restricting `Self` for a single method.
suggest_restriction(
self.tcx,
- hir_id,
+ body_id,
&generics,
"`Self`",
err,
@@ -567,7 +563,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
assert!(param_ty);
// Restricting `Self` for a single method.
suggest_restriction(
- self.tcx, hir_id, &generics, "`Self`", err, None, projection, trait_pred,
+ self.tcx, body_id, &generics, "`Self`", err, None, projection, trait_pred,
None,
);
return;
@@ -589,7 +585,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// Missing restriction on associated type of type parameter (unmet projection).
suggest_restriction(
self.tcx,
- hir_id,
+ body_id,
&generics,
"the associated type",
err,
@@ -609,7 +605,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// Missing restriction on associated type of type parameter (unmet projection).
suggest_restriction(
self.tcx,
- hir_id,
+ body_id,
&generics,
"the associated type",
err,
@@ -680,6 +676,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
&param_name,
&constraint,
Some(trait_pred.def_id()),
+ None,
) {
return;
}
@@ -713,8 +710,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
_ => {}
}
-
- hir_id = self.tcx.hir().get_parent_item(hir_id).into();
+ body_id = self.tcx.local_parent(body_id);
}
}
@@ -749,10 +745,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
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)
- .is_err()
- {
+ if !self.can_eq(
+ obligation.param_env,
+ self.tcx.erase_late_bound_regions(real_ty),
+ arg_ty,
+ ) {
continue;
}
@@ -770,15 +767,13 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
obligation.param_env,
real_trait_pred_and_ty,
);
- if obligations
+ let may_hold = obligations
.iter()
.chain([&obligation])
.all(|obligation| self.predicate_may_hold(obligation))
- {
- Some(steps)
- } else {
- None
- }
+ .then_some(steps);
+
+ may_hold
})
{
if steps > 0 {
@@ -899,14 +894,15 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
return false;
}
- let self_ty = self.replace_bound_vars_with_fresh_vars(
+ let self_ty = self.instantiate_binder_with_fresh_vars(
DUMMY_SP,
LateBoundRegionConversionTime::FnCall,
trait_pred.self_ty(),
);
+ let body_hir_id = self.tcx.hir().local_def_id_to_hir_id(obligation.cause.body_id);
let Some((def_id_or_name, output, inputs)) = self.extract_callable_info(
- obligation.cause.body_id,
+ body_hir_id,
obligation.param_env,
self_ty,
) else { return false; };
@@ -931,7 +927,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
DefKind::Ctor(CtorOf::Variant, _) => {
"use parentheses to construct this tuple variant".to_string()
}
- kind => format!("use parentheses to call this {}", kind.descr(def_id)),
+ kind => format!(
+ "use parentheses to call this {}",
+ self.tcx.def_kind_descr(kind, def_id)
+ ),
},
DefIdOrName::Name(name) => format!("use parentheses to call this {name}"),
};
@@ -1004,8 +1003,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
span.remove_mark();
}
let mut expr_finder = FindExprBySpan::new(span);
- let Some(hir::Node::Expr(body)) = self.tcx.hir().find(obligation.cause.body_id) else { return; };
- expr_finder.visit_expr(&body);
+ 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; };
@@ -1059,9 +1059,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
trait_pred: ty::PolyTraitPredicate<'tcx>,
) -> bool {
let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty());
- let ty = self.tcx.erase_late_bound_regions(self_ty);
- let owner = self.tcx.hir().get_parent_item(obligation.cause.body_id);
- let Some(generics) = self.tcx.hir().get_generics(owner.def_id) else { return false };
+ 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 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 };
@@ -1088,6 +1087,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
param.name.as_str(),
"Clone",
Some(clone_trait),
+ None,
);
}
err.span_suggestion_verbose(
@@ -1104,6 +1104,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
/// Extracts information about a callable type for diagnostics. This is a
/// heuristic -- it doesn't necessarily mean that a type is always callable,
/// because the callable type must also be well-formed to be called.
+ // FIXME(vincenzopalazzo): move the HirId to a LocalDefId
fn extract_callable_info(
&self,
hir_id: HirId,
@@ -1189,7 +1190,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
}) else { return None; };
- let output = self.replace_bound_vars_with_fresh_vars(
+ let output = self.instantiate_binder_with_fresh_vars(
DUMMY_SP,
LateBoundRegionConversionTime::FnCall,
output,
@@ -1198,7 +1199,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
.skip_binder()
.iter()
.map(|ty| {
- self.replace_bound_vars_with_fresh_vars(
+ self.instantiate_binder_with_fresh_vars(
DUMMY_SP,
LateBoundRegionConversionTime::FnCall,
inputs.rebind(*ty),
@@ -1348,14 +1349,41 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
Applicability::MaybeIncorrect,
);
} else {
+ // Issue #104961, we need to add parentheses properly for compond 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 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 needs_parens = match expr.kind {
+ // parenthesize if needed (Issue #46756)
+ hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true,
+ // parenthesize borrows of range literals (Issue #54505)
+ _ if is_range_literal(expr) => true,
+ _ => false,
+ };
+
let is_mut = mut_ref_self_ty_satisfies_pred || ref_inner_ty_mut;
- err.span_suggestion_verbose(
- span.shrink_to_lo(),
- &format!(
- "consider{} borrowing here",
- if is_mut { " mutably" } else { "" }
- ),
- format!("&{}", if is_mut { "mut " } else { "" }),
+ let span = if needs_parens { span } else { span.shrink_to_lo() };
+ let sugg_prefix = format!("&{}", if is_mut { "mut " } else { "" });
+ let sugg_msg = &format!(
+ "consider{} borrowing here",
+ if is_mut { " mutably" } else { "" }
+ );
+
+ let suggestions = if !needs_parens {
+ vec![(span.shrink_to_lo(), format!("{}", sugg_prefix))]
+ } else {
+ vec![
+ (span.shrink_to_lo(), format!("{}(", sugg_prefix)),
+ (span.shrink_to_hi(), ")".to_string()),
+ ]
+ };
+ err.multipart_suggestion_verbose(
+ sugg_msg,
+ suggestions,
Applicability::MaybeIncorrect,
);
}
@@ -1429,10 +1457,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
span.remove_mark();
}
let mut expr_finder = super::FindExprBySpan::new(span);
- let Some(hir::Node::Expr(body)) = self.tcx.hir().find(obligation.cause.body_id) else {
+ let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) else {
return false;
};
- expr_finder.visit_expr(&body);
+ let body = self.tcx.hir().body(body_id);
+ expr_finder.visit_expr(body.value);
let mut maybe_suggest = |suggested_ty, count, suggestions| {
// Remapping bound vars here
let trait_pred_and_suggested_ty =
@@ -1670,8 +1699,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
trait_pred: ty::PolyTraitPredicate<'tcx>,
) -> bool {
let hir = self.tcx.hir();
- let parent_node = hir.parent_id(obligation.cause.body_id);
- let node = hir.find(parent_node);
+ let node = hir.find_by_def_id(obligation.cause.body_id);
if let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. })) = node
&& let hir::ExprKind::Block(blk, _) = &hir.body(*body_id).value.kind
&& sig.decl.output.span().overlaps(span)
@@ -1707,8 +1735,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option<Span> {
let hir = self.tcx.hir();
- let parent_node = hir.parent_id(obligation.cause.body_id);
- let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, ..), .. })) = hir.find(parent_node) 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;
};
@@ -1732,8 +1759,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
let hir = self.tcx.hir();
- let fn_hir_id = hir.parent_id(obligation.cause.body_id);
- let node = hir.find(fn_hir_id);
+ let fn_hir_id = hir.local_def_id_to_hir_id(obligation.cause.body_id);
+ let node = hir.find_by_def_id(obligation.cause.body_id);
let Some(hir::Node::Item(hir::Item {
kind: hir::ItemKind::Fn(sig, _, body_id),
..
@@ -1749,7 +1776,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// If the `dyn Trait` is not object safe, do not suggest `Box<dyn Trait>`.
predicates
.principal_def_id()
- .map_or(true, |def_id| self.tcx.object_safety_violations(def_id).is_empty())
+ .map_or(true, |def_id| self.tcx.check_is_object_safe(def_id))
}
// We only want to suggest `impl Trait` to `dyn Trait`s.
// For example, `fn foo() -> str` needs to be filtered out.
@@ -1806,7 +1833,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
match liberated_sig.output().kind() {
ty::Dynamic(predicates, _, ty::Dyn) => {
- let cause = ObligationCause::misc(ret_ty.span, fn_hir_id);
+ let cause = ObligationCause::misc(ret_ty.span, obligation.cause.body_id);
let param_env = ty::ParamEnv::empty();
if !only_never_return {
@@ -1944,8 +1971,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
let hir = self.tcx.hir();
- let parent_node = hir.parent_id(obligation.cause.body_id);
- let node = hir.find(parent_node);
+ let node = hir.find_by_def_id(obligation.cause.body_id);
if let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })) =
node
{
@@ -1989,7 +2015,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let sig = match inputs.kind() {
ty::Tuple(inputs) if infcx.tcx.is_fn_trait(trait_ref.def_id()) => {
infcx.tcx.mk_fn_sig(
- inputs.iter(),
+ *inputs,
infcx.next_ty_var(TypeVariableOrigin {
span: DUMMY_SP,
kind: TypeVariableOriginKind::MiscVariable,
@@ -2000,7 +2026,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
)
}
_ => infcx.tcx.mk_fn_sig(
- std::iter::once(inputs),
+ [inputs],
infcx.next_ty_var(TypeVariableOrigin {
span: DUMMY_SP,
kind: TypeVariableOriginKind::MiscVariable,
@@ -2116,7 +2142,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
err.note(&format!(
"{}s cannot be accessed directly on a `trait`, they can only be \
accessed through a specific `impl`",
- assoc_item.kind.as_def_kind().descr(item_def_id)
+ self.tcx.def_kind_descr(assoc_item.kind.as_def_kind(), item_def_id)
));
err.span_suggestion(
span,
@@ -2225,7 +2251,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
);
match *ty.kind() {
- ty::Generator(did, ..) => {
+ ty::Generator(did, ..) | ty::GeneratorWitnessMIR(did, _) => {
generator = generator.or(Some(did));
outer_generator = Some(did);
}
@@ -2255,7 +2281,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
);
match *ty.kind() {
- ty::Generator(did, ..) => {
+ ty::Generator(did, ..) | ty::GeneratorWitnessMIR(did, ..) => {
generator = generator.or(Some(did));
outer_generator = Some(did);
}
@@ -2344,9 +2370,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
_ => return false,
};
+ let generator_within_in_progress_typeck = match &self.typeck_results {
+ Some(t) => t.hir_owner.to_def_id() == generator_did_root,
+ _ => false,
+ };
+
let mut interior_or_upvar_span = None;
- let from_awaited_ty = generator_data.get_from_await_ty(visitor, hir, ty_matches);
+ let from_awaited_ty = generator_data.get_from_await_ty(self.tcx, visitor, hir, ty_matches);
debug!(?from_awaited_ty);
// The generator interior types share the same binders
@@ -2363,6 +2394,35 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
*span,
Some((*scope_span, *yield_span, *expr, from_awaited_ty)),
));
+
+ if interior_or_upvar_span.is_none() && generator_data.is_foreign() {
+ interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(*span, None));
+ }
+ } else if self.tcx.sess.opts.unstable_opts.drop_tracking_mir
+ // Avoid disclosing internal information to downstream crates.
+ && generator_did.is_local()
+ // Try to avoid cycles.
+ && !generator_within_in_progress_typeck
+ {
+ let generator_info = &self.tcx.mir_generator_witnesses(generator_did);
+ debug!(?generator_info);
+
+ 'find_source: for (variant, source_info) in
+ generator_info.variant_fields.iter().zip(&generator_info.variant_source_info)
+ {
+ debug!(?variant);
+ for &local in variant {
+ let decl = &generator_info.field_tys[local];
+ debug!(?decl);
+ if ty_matches(ty::Binder::dummy(decl.ty)) && !decl.ignore_for_traits {
+ interior_or_upvar_span = Some(GeneratorInteriorOrUpvar::Interior(
+ decl.source_info.span,
+ Some((None, source_info.span, None, from_awaited_ty)),
+ ));
+ break 'find_source;
+ }
+ }
+ }
}
if interior_or_upvar_span.is_none() {
@@ -2727,7 +2787,13 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
_ => true,
};
if ident.span.is_visible(sm) && !ident.span.overlaps(span) && !same_line {
- multispan.push_span_label(ident.span, "required by a bound in this");
+ multispan.push_span_label(
+ ident.span,
+ format!(
+ "required by a bound in this {}",
+ tcx.def_kind(item_def_id).descr(item_def_id)
+ ),
+ );
}
}
let descr = format!("required by a bound in `{item_name}`");
@@ -3011,6 +3077,20 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
err.note(msg.trim_end_matches(", "))
}
+ ty::GeneratorWitnessMIR(def_id, substs) => {
+ use std::fmt::Write;
+
+ // FIXME: this is kind of an unusual format for rustc, can we make it more clear?
+ // Maybe we should just remove this note altogether?
+ // FIXME: only print types which don't meet the trait requirement
+ 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();
+ }
+ err.note(msg.trim_end_matches(", "))
+ }
ty::Generator(def_id, _, _) => {
let sp = self.tcx.def_span(def_id);
@@ -3027,6 +3107,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
self.tcx.def_span(def_id),
"required because it's used within this closure",
),
+ ty::Str => err.note("`str` is considered to contain a `[u8]` slice for auto trait purposes"),
_ => err.note(&msg),
};
}
@@ -3072,7 +3153,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
parent_trait_pred.print_modifiers_and_trait_path()
);
let mut is_auto_trait = false;
- match self.tcx.hir().get_if_local(data.impl_def_id) {
+ match self.tcx.hir().get_if_local(data.impl_or_alias_def_id) {
Some(Node::Item(hir::Item {
kind: hir::ItemKind::Trait(is_auto, ..),
ident,
@@ -3283,12 +3364,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
trait_pred: ty::PolyTraitPredicate<'tcx>,
span: Span,
) {
- let body_hir_id = obligation.cause.body_id;
- let item_id = self.tcx.hir().parent_id(body_hir_id);
-
- if let Some(body_id) =
- self.tcx.hir().maybe_body_owned_by(self.tcx.hir().local_def_id(item_id))
- {
+ if let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) {
let body = self.tcx.hir().body(body_id);
if let Some(hir::GeneratorKind::Async(_)) = body.generator_kind {
let future_trait = self.tcx.require_lang_item(LangItem::Future, None);
@@ -3459,7 +3535,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
{
if let hir::Expr { kind: hir::ExprKind::Block(..), .. } = expr {
let expr = expr.peel_blocks();
- let ty = typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error());
+ let ty = typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error_misc());
let span = expr.span;
if Some(span) != err.span.primary_span() {
err.span_label(
@@ -3502,7 +3578,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
{
type_diffs = vec![
Sorts(ty::error::ExpectedFound {
- expected: self.tcx.mk_ty(ty::Alias(ty::Projection, where_pred.skip_binder().projection_ty)),
+ expected: self.tcx.mk_alias(ty::Projection, where_pred.skip_binder().projection_ty),
found,
}),
];
@@ -3562,7 +3638,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let mut assocs = vec![];
let mut expr = expr;
let mut prev_ty = self.resolve_vars_if_possible(
- typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()),
+ typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error_misc()),
);
while let hir::ExprKind::MethodCall(_path_segment, rcvr_expr, _args, span) = expr.kind {
// Point at every method call in the chain with the resulting type.
@@ -3573,7 +3649,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
self.probe_assoc_types_at_expr(&type_diffs, span, prev_ty, expr.hir_id, param_env);
assocs.push(assocs_in_this_method);
prev_ty = self.resolve_vars_if_possible(
- typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()),
+ typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error_misc()),
);
if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
@@ -3591,7 +3667,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
if let hir::Node::Param(param) = parent {
// ...and it is a an fn argument.
let prev_ty = self.resolve_vars_if_possible(
- typeck_results.node_type_opt(param.hir_id).unwrap_or(tcx.ty_error()),
+ typeck_results.node_type_opt(param.hir_id).unwrap_or(tcx.ty_error_misc()),
);
let assocs_in_this_method = self.probe_assoc_types_at_expr(&type_diffs, param.ty_span, prev_ty, param.hir_id, param_env);
if assocs_in_this_method.iter().any(|a| a.is_some()) {
@@ -3620,7 +3696,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
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).is_ok()
+ 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`
@@ -3647,10 +3723,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let ty_str = with_forced_trimmed_paths!(self.ty_to_string(ty));
let assoc = with_forced_trimmed_paths!(self.tcx.def_path_str(assoc));
- if self.can_eq(param_env, ty, *prev_ty).is_err() {
+ if !self.can_eq(param_env, ty, *prev_ty) {
if type_diffs.iter().any(|diff| {
let Sorts(expected_found) = diff else { return false; };
- self.can_eq(param_env, expected_found.found, ty).is_ok()
+ self.can_eq(param_env, expected_found.found, ty)
}) {
primary_spans.push(span);
}
@@ -3727,9 +3803,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
term: ty_var.into(),
},
)));
+ let body_def_id = self.tcx.hir().enclosing_body_owner(body_id);
// Add `<ExprTy as Iterator>::Item = _` obligation.
ocx.register_obligation(Obligation::misc(
- self.tcx, span, body_id, param_env, projection,
+ self.tcx,
+ span,
+ body_def_id,
+ param_env,
+ projection,
));
if ocx.select_where_possible().is_empty() {
// `ty_var` now holds the type that `Item` is for `ExprTy`.
@@ -3758,13 +3839,13 @@ fn hint_missing_borrow<'tcx>(
err: &mut Diagnostic,
) {
let found_args = match found.kind() {
- ty::FnPtr(f) => f.inputs().skip_binder().iter(),
+ ty::FnPtr(f) => infcx.instantiate_binder_with_placeholders(*f).inputs().iter(),
kind => {
span_bug!(span, "found was converted to a FnPtr above but is now {:?}", kind)
}
};
let expected_args = match expected.kind() {
- ty::FnPtr(f) => f.inputs().skip_binder().iter(),
+ ty::FnPtr(f) => infcx.instantiate_binder_with_placeholders(*f).inputs().iter(),
kind => {
span_bug!(span, "expected was converted to a FnPtr above but is now {:?}", kind)
}
@@ -3775,12 +3856,12 @@ fn hint_missing_borrow<'tcx>(
let args = fn_decl.inputs.iter().map(|ty| ty);
- fn get_deref_type_and_refs(mut ty: Ty<'_>) -> (Ty<'_>, usize) {
- let mut refs = 0;
+ fn get_deref_type_and_refs(mut ty: Ty<'_>) -> (Ty<'_>, Vec<hir::Mutability>) {
+ let mut refs = vec![];
- while let ty::Ref(_, new_ty, _) = ty.kind() {
+ while let ty::Ref(_, new_ty, mutbl) = ty.kind() {
ty = *new_ty;
- refs += 1;
+ refs.push(*mutbl);
}
(ty, refs)
@@ -3793,12 +3874,22 @@ fn hint_missing_borrow<'tcx>(
let (found_ty, found_refs) = get_deref_type_and_refs(*found_arg);
let (expected_ty, expected_refs) = get_deref_type_and_refs(*expected_arg);
- if infcx.can_eq(param_env, found_ty, expected_ty).is_ok() {
- if found_refs < expected_refs {
- to_borrow.push((arg.span.shrink_to_lo(), "&".repeat(expected_refs - found_refs)));
- } else if found_refs > expected_refs {
+ if infcx.can_eq(param_env, found_ty, expected_ty) {
+ // FIXME: This could handle more exotic cases like mutability mismatches too!
+ if found_refs.len() < expected_refs.len()
+ && found_refs[..] == expected_refs[expected_refs.len() - found_refs.len()..]
+ {
+ to_borrow.push((
+ arg.span.shrink_to_lo(),
+ expected_refs[..expected_refs.len() - found_refs.len()]
+ .iter()
+ .map(|mutbl| format!("&{}", mutbl.prefix_str()))
+ .collect::<Vec<_>>()
+ .join(""),
+ ));
+ } else if found_refs.len() > expected_refs.len() {
let mut span = arg.span.shrink_to_lo();
- let mut left = found_refs - expected_refs;
+ let mut left = found_refs.len() - expected_refs.len();
let mut ty = arg;
while let hir::TyKind::Ref(_, mut_ty) = &ty.kind && left > 0 {
span = span.with_hi(mut_ty.ty.span.lo());
@@ -3996,7 +4087,7 @@ struct ReplaceImplTraitFolder<'tcx> {
replace_ty: Ty<'tcx>,
}
-impl<'tcx> TypeFolder<'tcx> for ReplaceImplTraitFolder<'tcx> {
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceImplTraitFolder<'tcx> {
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
if let ty::Param(ty::ParamTy { index, .. }) = t.kind() {
if self.param.index == *index {
@@ -4006,7 +4097,7 @@ impl<'tcx> TypeFolder<'tcx> for ReplaceImplTraitFolder<'tcx> {
t.super_fold_with(self)
}
- fn tcx(&self) -> TyCtxt<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.tcx
}
}
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 76a755ed9..944436ab8 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -1,5 +1,4 @@
use crate::infer::{InferCtxt, TyOrConstInferVar};
-use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::obligation_forest::ProcessResult;
use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome};
use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor};
@@ -9,7 +8,7 @@ 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::{self, Binder, Const, TypeVisitable};
+use rustc_middle::ty::{self, Binder, Const, TypeVisitableExt};
use std::marker::PhantomData;
use super::const_evaluatable;
@@ -54,8 +53,6 @@ pub struct FulfillmentContext<'tcx> {
// fulfillment context.
predicates: ObligationForest<PendingPredicateObligation<'tcx>>,
- relationships: FxHashMap<ty::TyVid, ty::FoundRelationships>,
-
// Is it OK to register obligations into this infcx inside
// an infcx snapshot?
//
@@ -85,19 +82,11 @@ static_assert_size!(PendingPredicateObligation<'_>, 72);
impl<'a, 'tcx> FulfillmentContext<'tcx> {
/// Creates a new fulfillment context.
pub(super) fn new() -> FulfillmentContext<'tcx> {
- FulfillmentContext {
- predicates: ObligationForest::new(),
- relationships: FxHashMap::default(),
- usable_in_snapshot: false,
- }
+ FulfillmentContext { predicates: ObligationForest::new(), usable_in_snapshot: false }
}
pub(super) fn new_in_snapshot() -> FulfillmentContext<'tcx> {
- FulfillmentContext {
- predicates: ObligationForest::new(),
- relationships: FxHashMap::default(),
- usable_in_snapshot: true,
- }
+ FulfillmentContext { predicates: ObligationForest::new(), usable_in_snapshot: true }
}
/// Attempts to select obligations using `selcx`.
@@ -139,20 +128,11 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
assert!(!infcx.is_in_snapshot() || self.usable_in_snapshot);
- super::relationships::update(self, infcx, &obligation);
-
self.predicates
.register_obligation(PendingPredicateObligation { obligation, stalled_on: vec![] });
}
- fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
- {
- let errors = self.select_where_possible(infcx);
- if !errors.is_empty() {
- return errors;
- }
- }
-
+ fn collect_remaining_errors(&mut self) -> Vec<FulfillmentError<'tcx>> {
self.predicates.to_errors(CodeAmbiguity).into_iter().map(to_fulfillment_error).collect()
}
@@ -161,12 +141,57 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
self.select(selcx)
}
- fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
- self.predicates.map_pending_obligations(|o| o.obligation.clone())
+ fn drain_unstalled_obligations(
+ &mut self,
+ infcx: &InferCtxt<'tcx>,
+ ) -> Vec<PredicateObligation<'tcx>> {
+ let mut processor = DrainProcessor { removed_predicates: Vec::new(), infcx };
+ let outcome: Outcome<_, _> = self.predicates.process_obligations(&mut processor);
+ assert!(outcome.errors.is_empty());
+ return processor.removed_predicates;
+
+ struct DrainProcessor<'a, 'tcx> {
+ infcx: &'a InferCtxt<'tcx>,
+ removed_predicates: Vec<PredicateObligation<'tcx>>,
+ }
+
+ impl<'tcx> ObligationProcessor for DrainProcessor<'_, 'tcx> {
+ type Obligation = PendingPredicateObligation<'tcx>;
+ type Error = !;
+ type OUT = Outcome<Self::Obligation, Self::Error>;
+
+ fn needs_process_obligation(&self, pending_obligation: &Self::Obligation) -> bool {
+ pending_obligation
+ .stalled_on
+ .iter()
+ .any(|&var| self.infcx.ty_or_const_infer_var_changed(var))
+ }
+
+ fn process_obligation(
+ &mut self,
+ pending_obligation: &mut PendingPredicateObligation<'tcx>,
+ ) -> ProcessResult<PendingPredicateObligation<'tcx>, !> {
+ assert!(self.needs_process_obligation(pending_obligation));
+ self.removed_predicates.push(pending_obligation.obligation.clone());
+ ProcessResult::Changed(vec![])
+ }
+
+ fn process_backedge<'c, I>(
+ &mut self,
+ cycle: I,
+ _marker: PhantomData<&'c PendingPredicateObligation<'tcx>>,
+ ) -> Result<(), !>
+ where
+ I: Clone + Iterator<Item = &'c PendingPredicateObligation<'tcx>>,
+ {
+ self.removed_predicates.extend(cycle.map(|c| c.obligation.clone()));
+ Ok(())
+ }
+ }
}
- fn relationships(&mut self) -> &mut FxHashMap<ty::TyVid, ty::FoundRelationships> {
- &mut self.relationships
+ fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
+ self.predicates.map_pending_obligations(|o| o.obligation.clone())
}
}
@@ -187,36 +212,44 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
/// Identifies whether a predicate obligation needs processing.
///
- /// This is always inlined, despite its size, because it has a single
- /// callsite and it is called *very* frequently.
+ /// This is always inlined because it has a single callsite and it is
+ /// called *very* frequently. Be careful modifying this code! Several
+ /// compile-time benchmarks are very sensitive to even small changes.
#[inline(always)]
fn needs_process_obligation(&self, pending_obligation: &Self::Obligation) -> bool {
// If we were stalled on some unresolved variables, first check whether
// any of them have been resolved; if not, don't bother doing more work
// yet.
- match pending_obligation.stalled_on.len() {
- // Match arms are in order of frequency, which matters because this
- // code is so hot. 1 and 0 dominate; 2+ is fairly rare.
- 1 => {
- let infer_var = pending_obligation.stalled_on[0];
- self.selcx.infcx.ty_or_const_infer_var_changed(infer_var)
- }
- 0 => {
- // In this case we haven't changed, but wish to make a change.
- true
- }
- _ => {
- // This `for` loop was once a call to `all()`, but this lower-level
- // form was a perf win. See #64545 for details.
- (|| {
- for &infer_var in &pending_obligation.stalled_on {
- if self.selcx.infcx.ty_or_const_infer_var_changed(infer_var) {
- return true;
- }
+ let stalled_on = &pending_obligation.stalled_on;
+ match stalled_on.len() {
+ // This case is the hottest most of the time, being hit up to 99%
+ // of the time. `keccak` and `cranelift-codegen-0.82.1` are
+ // benchmarks that particularly stress this path.
+ 1 => self.selcx.infcx.ty_or_const_infer_var_changed(stalled_on[0]),
+
+ // In this case we haven't changed, but wish to make a change. Note
+ // that this is a special case, and is not equivalent to the `_`
+ // case below, which would return `false` for an empty `stalled_on`
+ // vector.
+ //
+ // This case is usually hit only 1% of the time or less, though it
+ // reaches 20% in `wasmparser-0.101.0`.
+ 0 => true,
+
+ // This case is usually hit only 1% of the time or less, though it
+ // reaches 95% in `mime-0.3.16`, 64% in `wast-54.0.0`, and 12% in
+ // `inflate-0.4.5`.
+ //
+ // The obvious way of writing this, with a call to `any()` and no
+ // closure, is currently slower than this version.
+ _ => (|| {
+ for &infer_var in stalled_on {
+ if self.selcx.infcx.ty_or_const_infer_var_changed(infer_var) {
+ return true;
}
- false
- })()
- }
+ }
+ false
+ })(),
}
}
@@ -288,6 +321,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
}
ty::PredicateKind::Clause(ty::Clause::RegionOutlives(_))
| ty::PredicateKind::Clause(ty::Clause::TypeOutlives(_))
+ | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
| ty::PredicateKind::WellFormed(_)
| ty::PredicateKind::ObjectSafe(_)
| ty::PredicateKind::ClosureKind(..)
@@ -296,13 +330,16 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::ConstEquate(..) => {
let pred =
- ty::Binder::dummy(infcx.replace_bound_vars_with_placeholders(binder));
+ ty::Binder::dummy(infcx.instantiate_binder_with_placeholders(binder));
ProcessResult::Changed(mk_pending(vec![obligation.with(infcx.tcx, pred)]))
}
ty::PredicateKind::Ambiguous => ProcessResult::Unchanged,
ty::PredicateKind::TypeWellFormedFromEnv(..) => {
bug!("TypeWellFormedFromEnv is only used for Chalk")
}
+ ty::PredicateKind::AliasEq(..) => {
+ bug!("AliasEq is only used for new solver")
+ }
},
Some(pred) => match pred {
ty::PredicateKind::Clause(ty::Clause::Trait(data)) => {
@@ -344,7 +381,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
}
ty::PredicateKind::ObjectSafe(trait_def_id) => {
- if !self.selcx.tcx().is_object_safe(trait_def_id) {
+ if !self.selcx.tcx().check_is_object_safe(trait_def_id) {
ProcessResult::Error(CodeSelectionError(Unimplemented))
} else {
ProcessResult::Changed(vec![])
@@ -569,6 +606,22 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
ty::PredicateKind::TypeWellFormedFromEnv(..) => {
bug!("TypeWellFormedFromEnv is only used for Chalk")
}
+ ty::PredicateKind::AliasEq(..) => {
+ bug!("AliasEq is only used for new solver")
+ }
+ ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
+ match self
+ .selcx
+ .infcx
+ .at(&obligation.cause, obligation.param_env)
+ .eq(ct.ty(), ty)
+ {
+ Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())),
+ Err(_) => ProcessResult::Error(FulfillmentErrorCode::CodeSelectionError(
+ SelectionError::Unimplemented,
+ )),
+ }
+ }
},
}
}
diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs
index a41a601f2..b94346b09 100644
--- a/compiler/rustc_trait_selection/src/traits/misc.rs
+++ b/compiler/rustc_trait_selection/src/traits/misc.rs
@@ -1,12 +1,15 @@
//! Miscellaneous type-system utilities that are too small to deserve their own modules.
-use crate::traits::{self, ObligationCause};
+use crate::traits::{self, ObligationCause, ObligationCtxt};
use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir;
+use rustc_infer::infer::canonical::Canonical;
use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
+use rustc_infer::traits::query::NoSolution;
use rustc_infer::{infer::outlives::env::OutlivesEnvironment, traits::FulfillmentError};
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeVisitableExt};
+use rustc_span::DUMMY_SP;
use super::outlives_bounds::InferCtxtExt;
@@ -131,3 +134,19 @@ pub fn type_allowed_to_implement_copy<'tcx>(
Ok(())
}
+
+pub fn check_tys_might_be_eq<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ canonical: Canonical<'tcx, (ParamEnv<'tcx>, Ty<'tcx>, Ty<'tcx>)>,
+) -> Result<(), NoSolution> {
+ let (infcx, (param_env, ty_a, ty_b), _) =
+ tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &canonical);
+ let ocx = ObligationCtxt::new(&infcx);
+
+ let result = ocx.eq(&ObligationCause::dummy(), param_env, ty_a, ty_b);
+ // use `select_where_possible` instead of `select_all_or_error` so that
+ // we don't get errors from obligations being ambiguous.
+ let errors = ocx.select_where_possible();
+
+ if errors.len() > 0 || result.is_err() { Err(NoSolution) } else { Ok(()) }
+}
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index f036a311d..4e30108be 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -14,7 +14,6 @@ mod object_safety;
pub mod outlives_bounds;
mod project;
pub mod query;
-pub(crate) mod relationships;
mod select;
mod specialize;
mod structural_match;
@@ -27,12 +26,11 @@ use crate::infer::{InferCtxt, TyCtxtInferExt};
use crate::traits::error_reporting::TypeErrCtxtExt as _;
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
use rustc_errors::ErrorGuaranteed;
-use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
use rustc_middle::ty::fold::TypeFoldable;
-use rustc_middle::ty::visit::TypeVisitable;
+use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeSuperVisitable};
use rustc_middle::ty::{InternalSubsts, SubstsRef};
+use rustc_span::def_id::{DefId, CRATE_DEF_ID};
use rustc_span::Span;
use std::fmt::Debug;
@@ -143,7 +141,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'tcx>(
fn pred_known_to_hold_modulo_regions<'tcx>(
infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
- pred: impl ToPredicate<'tcx> + TypeVisitable<'tcx>,
+ pred: impl ToPredicate<'tcx> + TypeVisitable<TyCtxt<'tcx>>,
span: Span,
) -> bool {
let has_non_region_infer = pred.has_non_region_infer();
@@ -152,29 +150,29 @@ fn pred_known_to_hold_modulo_regions<'tcx>(
// We can use a dummy node-id here because we won't pay any mind
// to region obligations that arise (there shouldn't really be any
// anyhow).
- cause: ObligationCause::misc(span, hir::CRATE_HIR_ID),
+ cause: ObligationCause::misc(span, CRATE_DEF_ID),
recursion_depth: 0,
predicate: pred.to_predicate(infcx.tcx),
};
- let result = infcx.predicate_must_hold_modulo_regions(&obligation);
+ let result = infcx.evaluate_obligation_no_overflow(&obligation);
debug!(?result);
- if result && has_non_region_infer {
+ if result.must_apply_modulo_regions() && !has_non_region_infer {
+ true
+ } else if result.may_apply() {
// Because of inference "guessing", selection can sometimes claim
// to succeed while the success requires a guess. To ensure
// this function's result remains infallible, we must confirm
// that guess. While imperfect, I believe this is sound.
// FIXME(@lcnr): this function doesn't seem right.
+ //
// The handling of regions in this area of the code is terrible,
// see issue #29149. We should be able to improve on this with
// NLL.
let errors = fully_solve_obligation(infcx, obligation);
- // Note: we only assume something is `Copy` if we can
- // *definitively* show that it implements `Copy`. Otherwise,
- // assume it is move; linear is always ok.
match &errors[..] {
[] => true,
errors => {
@@ -183,7 +181,7 @@ fn pred_known_to_hold_modulo_regions<'tcx>(
}
}
} else {
- result
+ false
}
}
@@ -285,7 +283,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.intern_predicates(&predicates),
+ tcx.mk_predicates(&predicates),
unnormalized_env.reveal(),
unnormalized_env.constness(),
);
@@ -337,10 +335,9 @@ pub fn normalize_param_env_or_error<'tcx>(
// Not sure whether it is better to include the unnormalized TypeOutlives predicates
// 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: Vec<_> =
- non_outlives_predicates.iter().chain(&outlives_predicates).cloned().collect();
+ let outlives_env = non_outlives_predicates.iter().chain(&outlives_predicates).cloned();
let outlives_env = ty::ParamEnv::new(
- tcx.intern_predicates(&outlives_env),
+ tcx.mk_predicates_from_iter(outlives_env),
unnormalized_env.reveal(),
unnormalized_env.constness(),
);
@@ -360,7 +357,7 @@ pub fn normalize_param_env_or_error<'tcx>(
predicates.extend(outlives_predicates);
debug!("normalize_param_env_or_error: final predicates={:?}", predicates);
ty::ParamEnv::new(
- tcx.intern_predicates(&predicates),
+ tcx.mk_predicates(&predicates),
unnormalized_env.reveal(),
unnormalized_env.constness(),
)
@@ -375,7 +372,7 @@ pub fn fully_normalize<'tcx, T>(
value: T,
) -> Result<T, Vec<FulfillmentError<'tcx>>>
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
let ocx = ObligationCtxt::new(infcx);
debug!(?value);
@@ -485,7 +482,7 @@ fn is_impossible_method(tcx: TyCtxt<'_>, (impl_def_id, trait_item_def_id): (DefI
generics: &'tcx ty::Generics,
trait_item_def_id: DefId,
}
- impl<'tcx> ty::TypeVisitor<'tcx> for ReferencesOnlyParentGenerics<'tcx> {
+ impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for ReferencesOnlyParentGenerics<'tcx> {
type BreakTy = ();
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
// If this is a parameter from the trait item's own generics, then bail
@@ -527,16 +524,14 @@ fn is_impossible_method(tcx: TyCtxt<'_>, (impl_def_id, trait_item_def_id): (DefI
let mut visitor = ReferencesOnlyParentGenerics { tcx, generics, trait_item_def_id };
let predicates_for_trait = predicates.predicates.iter().filter_map(|(pred, span)| {
- if pred.visit_with(&mut visitor).is_continue() {
- Some(Obligation::new(
+ pred.visit_with(&mut visitor).is_continue().then(|| {
+ Obligation::new(
tcx,
ObligationCause::dummy_with_span(*span),
param_env,
ty::EarlyBinder(*pred).subst(tcx, impl_trait_ref.substs),
- ))
- } else {
- None
- }
+ )
+ })
});
let infcx = tcx.infer_ctxt().ignoring_regions().build();
@@ -558,6 +553,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
specialization_graph_of: specialize::specialization_graph_provider,
specializes: specialize::specializes,
subst_and_check_impossible_predicates,
+ check_tys_might_be_eq: misc::check_tys_might_be_eq,
is_impossible_method,
..*providers
};
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index c9121212c..4eacb5211 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -18,10 +18,10 @@ use rustc_errors::{DelayDm, FatalError, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::subst::{GenericArg, InternalSubsts};
+use rustc_middle::ty::ToPredicate;
use rustc_middle::ty::{
self, EarlyBinder, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
};
-use rustc_middle::ty::{Predicate, ToPredicate};
use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY;
use rustc_span::symbol::Symbol;
use rustc_span::Span;
@@ -62,11 +62,42 @@ fn object_safety_violations(tcx: TyCtxt<'_>, trait_def_id: DefId) -> &'_ [Object
)
}
+fn check_is_object_safe(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
+ let violations = tcx.object_safety_violations(trait_def_id);
+
+ if violations.is_empty() {
+ return true;
+ }
+
+ // If the trait contains any other violations, then let the error reporting path
+ // report it instead of emitting a warning here.
+ if violations.iter().all(|violation| {
+ matches!(
+ violation,
+ ObjectSafetyViolation::Method(_, MethodViolationCode::WhereClauseReferencesSelf, _)
+ )
+ }) {
+ for violation in violations {
+ if let ObjectSafetyViolation::Method(
+ _,
+ MethodViolationCode::WhereClauseReferencesSelf,
+ span,
+ ) = violation
+ {
+ lint_object_unsafe_trait(tcx, *span, trait_def_id, &violation);
+ }
+ }
+ return true;
+ }
+
+ false
+}
+
/// We say a method is *vtable safe* if it can be invoked on a trait
/// object. Note that object-safe traits can have some
/// non-vtable-safe methods, so long as they require `Self: Sized` or
/// otherwise ensure that they cannot be used when `Self = Trait`.
-pub fn is_vtable_safe_method(tcx: TyCtxt<'_>, trait_def_id: DefId, method: &ty::AssocItem) -> bool {
+pub fn is_vtable_safe_method(tcx: TyCtxt<'_>, trait_def_id: DefId, method: ty::AssocItem) -> bool {
debug_assert!(tcx.generics_of(trait_def_id).has_self);
debug!("is_vtable_safe_method({:?}, {:?})", trait_def_id, method);
// Any method that has a `Self: Sized` bound cannot be called.
@@ -89,23 +120,10 @@ fn object_safety_violations_for_trait(
.associated_items(trait_def_id)
.in_definition_order()
.filter(|item| item.kind == ty::AssocKind::Fn)
- .filter_map(|item| {
- object_safety_violation_for_method(tcx, trait_def_id, &item)
+ .filter_map(|&item| {
+ object_safety_violation_for_method(tcx, trait_def_id, item)
.map(|(code, span)| ObjectSafetyViolation::Method(item.name, code, span))
})
- .filter(|violation| {
- if let ObjectSafetyViolation::Method(
- _,
- MethodViolationCode::WhereClauseReferencesSelf,
- span,
- ) = violation
- {
- lint_object_unsafe_trait(tcx, *span, trait_def_id, &violation);
- false
- } else {
- true
- }
- })
.collect();
// Check the trait itself.
@@ -289,7 +307,7 @@ fn predicate_references_self<'tcx>(
match predicate.kind().skip_binder() {
ty::PredicateKind::Clause(ty::Clause::Trait(ref data)) => {
// In the case of a trait predicate, we can skip the "self" type.
- if data.trait_ref.substs[1..].iter().any(has_self_ty) { Some(sp) } else { None }
+ data.trait_ref.substs[1..].iter().any(has_self_ty).then_some(sp)
}
ty::PredicateKind::Clause(ty::Clause::Projection(ref data)) => {
// And similarly for projections. This should be redundant with
@@ -307,8 +325,14 @@ fn predicate_references_self<'tcx>(
//
// This is ALT2 in issue #56288, see that for discussion of the
// possible alternatives.
- if data.projection_ty.substs[1..].iter().any(has_self_ty) { Some(sp) } else { None }
+ data.projection_ty.substs[1..].iter().any(has_self_ty).then_some(sp)
+ }
+ ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(_ct, ty)) => {
+ has_self_ty(&ty.into()).then_some(sp)
}
+
+ ty::PredicateKind::AliasEq(..) => bug!("`AliasEq` not allowed as assumption"),
+
ty::PredicateKind::WellFormed(..)
| ty::PredicateKind::ObjectSafe(..)
| ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..))
@@ -316,6 +340,7 @@ fn predicate_references_self<'tcx>(
| ty::PredicateKind::ClosureKind(..)
| ty::PredicateKind::Subtype(..)
| ty::PredicateKind::Coerce(..)
+ // FIXME(generic_const_exprs): this can mention `Self`
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::ConstEquate(..)
| ty::PredicateKind::Ambiguous
@@ -341,6 +366,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
trait_pred.def_id() == sized_def_id && trait_pred.self_ty().is_param(0)
}
ty::PredicateKind::Clause(ty::Clause::Projection(..))
+ | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
| ty::PredicateKind::Subtype(..)
| ty::PredicateKind::Coerce(..)
| ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..))
@@ -350,6 +376,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
| ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..))
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::ConstEquate(..)
+ | ty::PredicateKind::AliasEq(..)
| ty::PredicateKind::Ambiguous
| ty::PredicateKind::TypeWellFormedFromEnv(..) => false,
}
@@ -360,7 +387,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
fn object_safety_violation_for_method(
tcx: TyCtxt<'_>,
trait_def_id: DefId,
- method: &ty::AssocItem,
+ method: ty::AssocItem,
) -> Option<(MethodViolationCode, Span)> {
debug!("object_safety_violation_for_method({:?}, {:?})", trait_def_id, method);
// Any method that has a `Self : Sized` requisite is otherwise
@@ -393,9 +420,9 @@ fn object_safety_violation_for_method(
fn virtual_call_violation_for_method<'tcx>(
tcx: TyCtxt<'tcx>,
trait_def_id: DefId,
- method: &ty::AssocItem,
+ method: ty::AssocItem,
) -> Option<MethodViolationCode> {
- let sig = tcx.fn_sig(method.def_id);
+ let sig = tcx.fn_sig(method.def_id).subst_identity();
// The method's first parameter must be named `self`
if !method.fn_has_self_parameter {
@@ -505,8 +532,7 @@ fn virtual_call_violation_for_method<'tcx>(
}
}
- let trait_object_ty =
- object_ty_for_trait(tcx, trait_def_id, tcx.mk_region(ty::ReStatic));
+ let trait_object_ty = object_ty_for_trait(tcx, trait_def_id, tcx.lifetimes.re_static);
// e.g., `Rc<dyn Trait>`
let trait_object_receiver =
@@ -529,16 +555,56 @@ fn virtual_call_violation_for_method<'tcx>(
// NOTE: This check happens last, because it results in a lint, and not a
// hard error.
- if tcx
- .predicates_of(method.def_id)
- .predicates
- .iter()
- // A trait object can't claim to live more than the concrete type,
- // so outlives predicates will always hold.
- .cloned()
- .filter(|(p, _)| p.to_opt_type_outlives().is_none())
- .any(|pred| contains_illegal_self_type_reference(tcx, trait_def_id, pred))
- {
+ if tcx.predicates_of(method.def_id).predicates.iter().any(|&(pred, span)| {
+ // dyn Trait is okay:
+ //
+ // trait Trait {
+ // fn f(&self) where Self: 'static;
+ // }
+ //
+ // because a trait object can't claim to live longer than the concrete
+ // type. If the lifetime bound holds on dyn Trait then it's guaranteed
+ // to hold as well on the concrete type.
+ if pred.to_opt_type_outlives().is_some() {
+ return false;
+ }
+
+ // dyn Trait is okay:
+ //
+ // auto trait AutoTrait {}
+ //
+ // trait Trait {
+ // fn f(&self) where Self: AutoTrait;
+ // }
+ //
+ // because `impl AutoTrait for dyn Trait` is disallowed by coherence.
+ // Traits with a default impl are implemented for a trait object if and
+ // only if the autotrait is one of the trait object's trait bounds, like
+ // in `dyn Trait + AutoTrait`. This guarantees that trait objects only
+ // implement auto traits if the underlying type does as well.
+ if let ty::PredicateKind::Clause(ty::Clause::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
+ && tcx.trait_is_auto(pred_trait_ref.def_id)
+ {
+ // Consider bounds like `Self: Bound<Self>`. Auto traits are not
+ // 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 {
+ tcx.sess.diagnostic().delay_span_bug(
+ span,
+ "auto traits cannot have generic parameters",
+ );
+ }
+ return false;
+ }
+
+ contains_illegal_self_type_reference(tcx, trait_def_id, pred)
+ }) {
return Some(MethodViolationCode::WhereClauseReferencesSelf);
}
@@ -588,11 +654,9 @@ fn object_ty_for_trait<'tcx>(
debug!(?obligation);
let pred = obligation.predicate.to_opt_poly_projection_pred()?;
Some(pred.map_bound(|p| {
- ty::ExistentialPredicate::Projection(ty::ExistentialProjection {
- def_id: p.projection_ty.def_id,
- substs: p.projection_ty.substs,
- term: p.term,
- })
+ ty::ExistentialPredicate::Projection(ty::ExistentialProjection::erase_self_ty(
+ tcx, p,
+ ))
}))
})
.collect();
@@ -602,8 +666,9 @@ fn object_ty_for_trait<'tcx>(
elaborated_predicates.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
elaborated_predicates.dedup();
- let existential_predicates = tcx
- .mk_poly_existential_predicates(iter::once(trait_predicate).chain(elaborated_predicates));
+ let existential_predicates = tcx.mk_poly_existential_predicates_from_iter(
+ iter::once(trait_predicate).chain(elaborated_predicates),
+ );
debug!(?existential_predicates);
tcx.mk_dynamic(existential_predicates, lifetime, ty::Dyn)
@@ -658,7 +723,7 @@ fn object_ty_for_trait<'tcx>(
#[allow(dead_code)]
fn receiver_is_dispatchable<'tcx>(
tcx: TyCtxt<'tcx>,
- method: &ty::AssocItem,
+ method: ty::AssocItem,
receiver_ty: Ty<'tcx>,
) -> bool {
debug!("receiver_is_dispatchable: method = {:?}, receiver_ty = {:?}", method, receiver_ty);
@@ -702,11 +767,11 @@ fn receiver_is_dispatchable<'tcx>(
ty::Binder::dummy(tcx.mk_trait_ref(trait_def_id, substs)).to_predicate(tcx)
};
- let caller_bounds: Vec<Predicate<'tcx>> =
- param_env.caller_bounds().iter().chain([unsize_predicate, trait_predicate]).collect();
+ let caller_bounds =
+ param_env.caller_bounds().iter().chain([unsize_predicate, trait_predicate]);
ty::ParamEnv::new(
- tcx.intern_predicates(&caller_bounds),
+ tcx.mk_predicates_from_iter(caller_bounds),
param_env.reveal(),
param_env.constness(),
)
@@ -726,7 +791,7 @@ fn receiver_is_dispatchable<'tcx>(
infcx.predicate_must_hold_modulo_regions(&obligation)
}
-fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<'tcx>>(
+fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<TyCtxt<'tcx>>>(
tcx: TyCtxt<'tcx>,
trait_def_id: DefId,
value: T,
@@ -776,7 +841,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<'tcx>>(
supertraits: Option<Vec<DefId>>,
}
- impl<'tcx> TypeVisitor<'tcx> for IllegalSelfTypeVisitor<'tcx> {
+ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IllegalSelfTypeVisitor<'tcx> {
type BreakTy = ();
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
@@ -866,5 +931,6 @@ pub fn contains_illegal_impl_trait_in_trait<'tcx>(
}
pub fn provide(providers: &mut ty::query::Providers) {
- *providers = ty::query::Providers { object_safety_violations, ..*providers };
+ *providers =
+ ty::query::Providers { object_safety_violations, check_is_object_safe, ..*providers };
}
diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
index f2c5f730b..6cb64ad57 100644
--- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
@@ -3,9 +3,8 @@ use crate::traits::query::type_op::{self, TypeOp, TypeOpOutput};
use crate::traits::query::NoSolution;
use crate::traits::ObligationCause;
use rustc_data_structures::fx::FxIndexSet;
-use rustc_hir as hir;
-use rustc_hir::HirId;
use rustc_middle::ty::{self, ParamEnv, Ty};
+use rustc_span::def_id::LocalDefId;
pub use rustc_middle::traits::query::OutlivesBound;
@@ -14,14 +13,14 @@ pub trait InferCtxtExt<'a, 'tcx> {
fn implied_outlives_bounds(
&self,
param_env: ty::ParamEnv<'tcx>,
- body_id: hir::HirId,
+ body_id: LocalDefId,
ty: Ty<'tcx>,
) -> Vec<OutlivesBound<'tcx>>;
fn implied_bounds_tys(
&'a self,
param_env: ty::ParamEnv<'tcx>,
- body_id: hir::HirId,
+ body_id: LocalDefId,
tys: FxIndexSet<Ty<'tcx>>,
) -> Bounds<'a, 'tcx>;
}
@@ -50,10 +49,10 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> {
fn implied_outlives_bounds(
&self,
param_env: ty::ParamEnv<'tcx>,
- body_id: hir::HirId,
+ body_id: LocalDefId,
ty: Ty<'tcx>,
) -> Vec<OutlivesBound<'tcx>> {
- let span = self.tcx.hir().span(body_id);
+ let span = self.tcx.def_span(body_id);
let result = param_env
.and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty })
.fully_perform(self);
@@ -102,7 +101,7 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> {
fn implied_bounds_tys(
&'a self,
param_env: ParamEnv<'tcx>,
- body_id: HirId,
+ body_id: LocalDefId,
tys: FxIndexSet<Ty<'tcx>>,
) -> Bounds<'a, 'tcx> {
tys.into_iter()
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index fbc7ecced..870ecc2a9 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -31,7 +31,7 @@ use rustc_infer::infer::resolve::OpportunisticRegionResolver;
use rustc_infer::traits::ImplSourceBuiltinData;
use rustc_middle::traits::select::OverflowError;
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
-use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable};
+use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable, TypeVisitableExt};
use rustc_middle::ty::DefIdTree;
use rustc_middle::ty::{self, Term, ToPredicate, Ty, TyCtxt};
use rustc_span::symbol::sym;
@@ -53,11 +53,11 @@ pub trait NormalizeExt<'tcx> {
///
/// This normalization should be used when the type contains inference variables or the
/// projection may be fallible.
- fn normalize<T: TypeFoldable<'tcx>>(&self, t: T) -> InferOk<'tcx, T>;
+ fn normalize<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> InferOk<'tcx, T>;
}
impl<'tcx> NormalizeExt<'tcx> for At<'_, 'tcx> {
- fn normalize<T: TypeFoldable<'tcx>>(&self, value: T) -> InferOk<'tcx, T> {
+ fn normalize<T: TypeFoldable<TyCtxt<'tcx>>>(&self, value: T) -> InferOk<'tcx, T> {
let mut selcx = SelectionContext::new(self.infcx);
let Normalized { value, obligations } =
normalize_with_depth(&mut selcx, self.param_env, self.cause.clone(), 0, value);
@@ -90,15 +90,7 @@ enum ProjectionCandidate<'tcx> {
/// From an "impl" (or a "pseudo-impl" returned by select)
Select(Selection<'tcx>),
- ImplTraitInTrait(ImplTraitInTraitCandidate<'tcx>),
-}
-
-#[derive(PartialEq, Eq, Debug)]
-enum ImplTraitInTraitCandidate<'tcx> {
- // The `impl Trait` from a trait function's default body
- Trait,
- // A concrete type provided from a trait's `impl Trait` from an impl
- Impl(ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>),
+ ImplTraitInTrait(ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>),
}
enum ProjectionCandidateSet<'tcx> {
@@ -215,7 +207,7 @@ pub(super) fn poly_project_and_unify_type<'cx, 'tcx>(
let r = infcx.commit_if_ok(|_snapshot| {
let old_universe = infcx.universe();
let placeholder_predicate =
- infcx.replace_bound_vars_with_placeholders(obligation.predicate);
+ infcx.instantiate_binder_with_placeholders(obligation.predicate);
let new_universe = infcx.universe();
let placeholder_obligation = obligation.with(infcx.tcx, placeholder_predicate);
@@ -294,7 +286,12 @@ fn project_and_unify_type<'cx, 'tcx>(
);
obligations.extend(new);
- match infcx.at(&obligation.cause, obligation.param_env).eq(normalized, actual) {
+ match infcx
+ .at(&obligation.cause, obligation.param_env)
+ // This is needed to support nested opaque types like `impl Fn() -> impl Trait`
+ .define_opaque_types(true)
+ .eq(normalized, actual)
+ {
Ok(InferOk { obligations: inferred_obligations, value: () }) => {
obligations.extend(inferred_obligations);
ProjectAndUnifyResult::Holds(obligations)
@@ -315,7 +312,7 @@ pub(crate) fn normalize_with_depth<'a, 'b, 'tcx, T>(
value: T,
) -> Normalized<'tcx, T>
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
let mut obligations = Vec::new();
let value = normalize_with_depth_to(selcx, param_env, cause, depth, value, &mut obligations);
@@ -332,7 +329,7 @@ pub(crate) fn normalize_with_depth_to<'a, 'b, 'tcx, T>(
obligations: &mut Vec<PredicateObligation<'tcx>>,
) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
debug!(obligations.len = obligations.len());
let mut normalizer = AssocTypeNormalizer::new(selcx, param_env, cause, depth, obligations);
@@ -352,7 +349,7 @@ pub(crate) fn try_normalize_with_depth_to<'a, 'b, 'tcx, T>(
obligations: &mut Vec<PredicateObligation<'tcx>>,
) -> T
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
debug!(obligations.len = obligations.len());
let mut normalizer = AssocTypeNormalizer::new_without_eager_inference_replacement(
@@ -368,7 +365,10 @@ where
result
}
-pub(crate) fn needs_normalization<'tcx, T: TypeVisitable<'tcx>>(value: &T, reveal: Reveal) -> bool {
+pub(crate) fn needs_normalization<'tcx, T: TypeVisitable<TyCtxt<'tcx>>>(
+ value: &T,
+ reveal: Reveal,
+) -> bool {
match reveal {
Reveal::UserFacing => value
.has_type_flags(ty::TypeFlags::HAS_TY_PROJECTION | ty::TypeFlags::HAS_CT_PROJECTION),
@@ -430,7 +430,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
}
}
- fn fold<T: TypeFoldable<'tcx>>(&mut self, value: T) -> T {
+ fn fold<T: TypeFoldable<TyCtxt<'tcx>>>(&mut self, value: T) -> T {
let value = self.selcx.infcx.resolve_vars_if_possible(value);
debug!(?value);
@@ -448,12 +448,12 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
}
}
-impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
- fn tcx<'c>(&'c self) -> TyCtxt<'tcx> {
+impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.selcx.tcx()
}
- fn fold_binder<T: TypeFoldable<'tcx>>(
+ fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
&mut self,
t: ty::Binder<'tcx, T>,
) -> ty::Binder<'tcx, T> {
@@ -503,7 +503,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
Reveal::UserFacing => ty.super_fold_with(self),
Reveal::All => {
- let recursion_limit = self.tcx().recursion_limit();
+ let recursion_limit = self.interner().recursion_limit();
if !recursion_limit.value_within_limit(self.depth) {
self.selcx.infcx.err_ctxt().report_overflow_error(
&ty,
@@ -514,8 +514,8 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
}
let substs = substs.fold_with(self);
- let generic_ty = self.tcx().bound_type_of(def_id);
- let concrete_ty = generic_ty.subst(self.tcx(), substs);
+ let generic_ty = self.interner().type_of(def_id);
+ let concrete_ty = generic_ty.subst(self.interner(), substs);
self.depth += 1;
let folded_ty = self.fold_ty(concrete_ty);
self.depth -= 1;
@@ -672,7 +672,12 @@ pub struct BoundVarReplacer<'me, 'tcx> {
///
/// FIXME(@lcnr): We may even consider experimenting with eagerly replacing bound vars during
/// normalization as well, at which point this function will be unnecessary and can be removed.
-pub fn with_replaced_escaping_bound_vars<'a, 'tcx, T: TypeFoldable<'tcx>, R: TypeFoldable<'tcx>>(
+pub fn with_replaced_escaping_bound_vars<
+ 'a,
+ 'tcx,
+ T: TypeFoldable<TyCtxt<'tcx>>,
+ R: TypeFoldable<TyCtxt<'tcx>>,
+>(
infcx: &'a InferCtxt<'tcx>,
universe_indices: &'a mut Vec<Option<ty::UniverseIndex>>,
value: T,
@@ -698,7 +703,7 @@ pub fn with_replaced_escaping_bound_vars<'a, 'tcx, T: TypeFoldable<'tcx>, R: Typ
impl<'me, 'tcx> BoundVarReplacer<'me, 'tcx> {
/// Returns `Some` if we *were* able to replace bound vars. If there are any bound vars that
/// use a binding level above `universe_indices.len()`, we fail.
- pub fn replace_bound_vars<T: TypeFoldable<'tcx>>(
+ pub fn replace_bound_vars<T: TypeFoldable<TyCtxt<'tcx>>>(
infcx: &'me InferCtxt<'tcx>,
universe_indices: &'me mut Vec<Option<ty::UniverseIndex>>,
value: T,
@@ -740,12 +745,12 @@ impl<'me, 'tcx> BoundVarReplacer<'me, 'tcx> {
}
}
-impl<'tcx> TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> {
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for BoundVarReplacer<'_, 'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.infcx.tcx
}
- fn fold_binder<T: TypeFoldable<'tcx>>(
+ fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
&mut self,
t: ty::Binder<'tcx, T>,
) -> ty::Binder<'tcx, T> {
@@ -767,7 +772,7 @@ impl<'tcx> TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> {
let universe = self.universe_for(debruijn);
let p = ty::PlaceholderRegion { universe, name: br.kind };
self.mapped_regions.insert(p, br);
- self.infcx.tcx.mk_region(ty::RePlaceholder(p))
+ self.infcx.tcx.mk_re_placeholder(p)
}
_ => r,
}
@@ -783,9 +788,9 @@ impl<'tcx> TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> {
}
ty::Bound(debruijn, bound_ty) if debruijn >= self.current_index => {
let universe = self.universe_for(debruijn);
- let p = ty::PlaceholderType { universe, name: bound_ty.var };
+ let p = ty::PlaceholderType { universe, name: bound_ty.kind };
self.mapped_types.insert(p, bound_ty);
- self.infcx.tcx.mk_ty(ty::Placeholder(p))
+ self.infcx.tcx.mk_placeholder(p)
}
_ if t.has_vars_bound_at_or_above(self.current_index) => t.super_fold_with(self),
_ => t,
@@ -826,7 +831,7 @@ pub struct PlaceholderReplacer<'me, 'tcx> {
}
impl<'me, 'tcx> PlaceholderReplacer<'me, 'tcx> {
- pub fn replace_placeholders<T: TypeFoldable<'tcx>>(
+ pub fn replace_placeholders<T: TypeFoldable<TyCtxt<'tcx>>>(
infcx: &'me InferCtxt<'tcx>,
mapped_regions: BTreeMap<ty::PlaceholderRegion, ty::BoundRegion>,
mapped_types: BTreeMap<ty::PlaceholderType, ty::BoundTy>,
@@ -846,12 +851,12 @@ impl<'me, 'tcx> PlaceholderReplacer<'me, 'tcx> {
}
}
-impl<'tcx> TypeFolder<'tcx> for PlaceholderReplacer<'_, 'tcx> {
- fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for PlaceholderReplacer<'_, 'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.infcx.tcx
}
- fn fold_binder<T: TypeFoldable<'tcx>>(
+ fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
&mut self,
t: ty::Binder<'tcx, T>,
) -> ty::Binder<'tcx, T> {
@@ -888,7 +893,7 @@ impl<'tcx> TypeFolder<'tcx> for PlaceholderReplacer<'_, 'tcx> {
let db = ty::DebruijnIndex::from_usize(
self.universe_indices.len() - index + self.current_index.as_usize() - 1,
);
- self.tcx().mk_region(ty::ReLateBound(db, *replace_var))
+ self.interner().mk_re_late_bound(db, *replace_var)
}
None => r1,
}
@@ -915,7 +920,7 @@ impl<'tcx> TypeFolder<'tcx> for PlaceholderReplacer<'_, 'tcx> {
let db = ty::DebruijnIndex::from_usize(
self.universe_indices.len() - index + self.current_index.as_usize() - 1,
);
- self.tcx().mk_ty(ty::Bound(db, *replace_var))
+ self.interner().mk_bound(db, *replace_var)
}
None => ty,
}
@@ -939,7 +944,7 @@ impl<'tcx> TypeFolder<'tcx> for PlaceholderReplacer<'_, 'tcx> {
let db = ty::DebruijnIndex::from_usize(
self.universe_indices.len() - index + self.current_index.as_usize() - 1,
);
- self.tcx().mk_const(ty::ConstKind::Bound(db, *replace_var), ct.ty())
+ self.interner().mk_const(ty::ConstKind::Bound(db, *replace_var), ct.ty())
}
None => ct,
}
@@ -1170,7 +1175,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
/// paths you want to take. To make things worse, it was possible for
/// cycles to arise, where you basically had a setup like `<MyType<$0>
/// as Trait>::Foo == $0`. Here, normalizing `<MyType<$0> as
-/// Trait>::Foo> to `[type error]` would lead to an obligation of
+/// Trait>::Foo>` to `[type error]` would lead to an obligation of
/// `<MyType<[type error]> as Trait>::Foo`. We are supposed to report
/// an error for this obligation, but we legitimately should not,
/// because it contains `[type error]`. Yuck! (See issue #29857 for
@@ -1208,8 +1213,8 @@ struct Progress<'tcx> {
}
impl<'tcx> Progress<'tcx> {
- fn error(tcx: TyCtxt<'tcx>) -> Self {
- Progress { term: tcx.ty_error().into(), obligations: vec![] }
+ fn error(tcx: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> Self {
+ Progress { term: tcx.ty_error(guar).into(), obligations: vec![] }
}
fn with_addl_obligations(mut self, mut obligations: Vec<PredicateObligation<'tcx>>) -> Self {
@@ -1235,8 +1240,8 @@ fn project<'cx, 'tcx>(
)));
}
- if obligation.predicate.references_error() {
- return Ok(Projected::Progress(Progress::error(selcx.tcx())));
+ if let Err(guar) = obligation.predicate.error_reported() {
+ return Ok(Projected::Progress(Progress::error(selcx.tcx(), guar)));
}
let mut candidates = ProjectionCandidateSet::None;
@@ -1292,17 +1297,6 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, '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(obligation.predicate.def_id);
- // If we are trying to project an RPITIT with trait's default `Self` parameter,
- // then we must be within a default trait body.
- if obligation.predicate.self_ty()
- == ty::InternalSubsts::identity_for_item(tcx, obligation.predicate.def_id).type_at(0)
- && tcx.associated_item(trait_fn_def_id).defaultness(tcx).has_value()
- {
- candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(
- ImplTraitInTraitCandidate::Trait,
- ));
- return;
- }
let trait_def_id = tcx.parent(trait_fn_def_id);
let trait_substs =
@@ -1313,23 +1307,21 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
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(
- ImplTraitInTraitCandidate::Impl(data),
- ));
+ candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(data));
Ok(())
}
Ok(None) => {
candidate_set.mark_ambiguous();
- return Err(());
+ Err(())
}
Ok(Some(_)) => {
// Don't know enough about the impl to provide a useful signature
- return Err(());
+ Err(())
}
Err(e) => {
debug!(error = ?e, "selection error");
candidate_set.mark_error(e);
- return Err(());
+ Err(())
}
}
});
@@ -1605,6 +1597,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
| ty::Closure(..)
| ty::Generator(..)
| ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::Never
| ty::Tuple(..)
// Integers and floats always have `u8` as their discriminant.
@@ -1654,6 +1647,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
| ty::Closure(..)
| ty::Generator(..)
| ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::Never
// Extern types have unit metadata, according to RFC 2850
| ty::Foreign(_)
@@ -1775,18 +1769,9 @@ fn confirm_candidate<'cx, 'tcx>(
ProjectionCandidate::Select(impl_source) => {
confirm_select_candidate(selcx, obligation, impl_source)
}
- ProjectionCandidate::ImplTraitInTrait(ImplTraitInTraitCandidate::Impl(data)) => {
+ ProjectionCandidate::ImplTraitInTrait(data) => {
confirm_impl_trait_in_trait_candidate(selcx, obligation, data)
}
- // If we're projecting an RPITIT for a default trait body, that's just
- // the same def-id, but as an opaque type (with regular RPIT semantics).
- ProjectionCandidate::ImplTraitInTrait(ImplTraitInTraitCandidate::Trait) => Progress {
- term: selcx
- .tcx()
- .mk_opaque(obligation.predicate.def_id, obligation.predicate.substs)
- .into(),
- obligations: vec![],
- },
};
// When checking for cycle during evaluation, we compare predicates with
@@ -1921,7 +1906,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()].iter());
+ let substs = tcx.mk_substs(&[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();
@@ -2044,7 +2029,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>(
let cause = &obligation.cause;
let param_env = obligation.param_env;
- let cache_entry = infcx.replace_bound_vars_with_fresh_vars(
+ let cache_entry = infcx.instantiate_binder_with_fresh_vars(
cause.span,
LateBoundRegionConversionTime::HigherRankedType,
poly_cache_entry,
@@ -2112,8 +2097,9 @@ fn confirm_impl_candidate<'cx, 'tcx>(
let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap();
let param_env = obligation.param_env;
- let Ok(assoc_ty) = specialization_graph::assoc_def(tcx, impl_def_id, assoc_item_id) else {
- return Progress { term: tcx.ty_error().into(), obligations: nested };
+ let assoc_ty = match specialization_graph::assoc_def(tcx, impl_def_id, assoc_item_id) {
+ Ok(assoc_ty) => assoc_ty,
+ Err(guar) => return Progress::error(tcx, guar),
};
if !assoc_ty.item.defaultness(tcx).has_value() {
@@ -2125,7 +2111,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
"confirm_impl_candidate: no associated type {:?} for {:?}",
assoc_ty.item.name, obligation.predicate
);
- return Progress { term: tcx.ty_error().into(), obligations: nested };
+ return Progress { term: tcx.ty_error_misc().into(), obligations: nested };
}
// 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:
@@ -2136,7 +2122,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
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);
- let ty = tcx.bound_type_of(assoc_ty.item.def_id);
+ 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 identity_substs =
@@ -2147,7 +2133,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
} else {
ty.map_bound(|ty| ty.into())
};
- if !check_substs_compatible(tcx, &assoc_ty.item, substs) {
+ if !check_substs_compatible(tcx, assoc_ty.item, substs) {
let err = tcx.ty_error_with_message(
obligation.cause.span,
"impl item and trait item have different parameters",
@@ -2162,7 +2148,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
// Verify that the trait item and its implementation have compatible substs lists
fn check_substs_compatible<'tcx>(
tcx: TyCtxt<'tcx>,
- assoc_item: &ty::AssocItem,
+ assoc_item: ty::AssocItem,
substs: ty::SubstsRef<'tcx>,
) -> bool {
fn check_substs_compatible_inner<'tcx>(
@@ -2209,11 +2195,13 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
let mut obligations = data.nested;
let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.def_id);
- let Ok(leaf_def) = specialization_graph::assoc_def(tcx, data.impl_def_id, trait_fn_def_id) else {
- return Progress { term: tcx.ty_error().into(), obligations };
+ 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),
};
- if !leaf_def.item.defaultness(tcx).has_value() {
- return Progress { term: tcx.ty_error().into(), obligations };
+ // We don't support specialization for RPITITs anyways... yet.
+ if !leaf_def.is_final() {
+ return Progress { term: tcx.ty_error_misc().into(), obligations };
}
// Use the default `impl Trait` for the trait, e.g., for a default trait body
@@ -2236,7 +2224,7 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
leaf_def.defining_node,
);
- if !check_substs_compatible(tcx, &leaf_def.item, impl_fn_substs) {
+ if !check_substs_compatible(tcx, leaf_def.item, impl_fn_substs) {
let err = tcx.ty_error_with_message(
obligation.cause.span,
"impl method and trait method have different parameters",
@@ -2284,7 +2272,7 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
obligation.recursion_depth + 1,
tcx.bound_return_position_impl_trait_in_trait_tys(impl_fn_def_id)
.map_bound(|tys| {
- tys.map_or_else(|_| tcx.ty_error(), |tys| tys[&obligation.predicate.def_id])
+ tys.map_or_else(|guar| tcx.ty_error(guar), |tys| tys[&obligation.predicate.def_id])
})
.subst(tcx, impl_fn_substs),
&mut obligations,
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 0f21813bc..455b53bfb 100644
--- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
@@ -31,6 +31,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
| ty::FnPtr(_)
| ty::Char
| ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::RawPtr(_)
| ty::Ref(..)
| ty::Str
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 09b58894d..f183248f2 100644
--- a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
@@ -1,7 +1,9 @@
use rustc_middle::ty;
+use rustc_session::config::TraitSolver;
use crate::infer::canonical::OriginalQueryValues;
use crate::infer::InferCtxt;
+use crate::solve::{Certainty, Goal, InferCtxtEvalExt, MaybeCause};
use crate::traits::{EvaluationResult, OverflowError, PredicateObligation, SelectionContext};
pub trait InferCtxtExt<'tcx> {
@@ -77,12 +79,38 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
_ => obligation.param_env.without_const(),
};
- let c_pred = self
- .canonicalize_query_keep_static(param_env.and(obligation.predicate), &mut _orig_values);
- // Run canonical query. If overflow occurs, rerun from scratch but this time
- // in standard trait query mode so that overflow is handled appropriately
- // within `SelectionContext`.
- self.tcx.at(obligation.cause.span()).evaluate_obligation(c_pred)
+ if self.tcx.sess.opts.unstable_opts.trait_solver != TraitSolver::Next {
+ let c_pred = self.canonicalize_query_keep_static(
+ param_env.and(obligation.predicate),
+ &mut _orig_values,
+ );
+ self.tcx.at(obligation.cause.span()).evaluate_obligation(c_pred)
+ } else {
+ self.probe(|snapshot| {
+ if let Ok((_, certainty)) =
+ self.evaluate_root_goal(Goal::new(self.tcx, param_env, obligation.predicate))
+ {
+ match certainty {
+ Certainty::Yes => {
+ if self.opaque_types_added_in_snapshot(snapshot) {
+ Ok(EvaluationResult::EvaluatedToOkModuloOpaqueTypes)
+ } else if self.region_constraints_added_in_snapshot(snapshot).is_some()
+ {
+ Ok(EvaluationResult::EvaluatedToOkModuloRegions)
+ } else {
+ Ok(EvaluationResult::EvaluatedToOk)
+ }
+ }
+ Certainty::Maybe(MaybeCause::Ambiguity) => {
+ Ok(EvaluationResult::EvaluatedToAmbig)
+ }
+ Certainty::Maybe(MaybeCause::Overflow) => Err(OverflowError::Canonical),
+ }
+ } else {
+ Ok(EvaluationResult::EvaluatedToErr)
+ }
+ })
+ }
}
// Helper function that canonicalizes and runs the query. If an
@@ -92,6 +120,9 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
&self,
obligation: &PredicateObligation<'tcx>,
) -> EvaluationResult {
+ // Run canonical query. If overflow occurs, rerun from scratch but this time
+ // in standard trait query mode so that overflow is handled appropriately
+ // within `SelectionContext`.
match self.evaluate_obligation(obligation) {
Ok(result) => result,
Err(OverflowError::Canonical) => {
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index 27247271d..b0cec3ce7 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -12,7 +12,7 @@ use rustc_data_structures::sso::SsoHashMap;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_infer::traits::Normalized;
use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
-use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable};
+use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor};
use rustc_span::DUMMY_SP;
@@ -32,7 +32,7 @@ pub trait QueryNormalizeExt<'tcx> {
/// use [`TyCtxt::normalize_erasing_regions`], which wraps this procedure.
fn query_normalize<T>(&self, value: T) -> Result<Normalized<'tcx, T>, NoSolution>
where
- T: TypeFoldable<'tcx>;
+ T: TypeFoldable<TyCtxt<'tcx>>;
}
impl<'cx, 'tcx> QueryNormalizeExt<'tcx> for At<'cx, 'tcx> {
@@ -51,7 +51,7 @@ impl<'cx, 'tcx> QueryNormalizeExt<'tcx> for At<'cx, 'tcx> {
/// and other details are still "under development".
fn query_normalize<T>(&self, value: T) -> Result<Normalized<'tcx, T>, NoSolution>
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
debug!(
"normalize::<{}>(value={:?}, param_env={:?}, cause={:?})",
@@ -115,8 +115,8 @@ struct MaxEscapingBoundVarVisitor {
escaping: usize,
}
-impl<'tcx> TypeVisitor<'tcx> for MaxEscapingBoundVarVisitor {
- fn visit_binder<T: TypeVisitable<'tcx>>(
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MaxEscapingBoundVarVisitor {
+ fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
&mut self,
t: &ty::Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
@@ -170,14 +170,14 @@ struct QueryNormalizer<'cx, 'tcx> {
universes: Vec<Option<ty::UniverseIndex>>,
}
-impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
+impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx> {
type Error = NoSolution;
- fn tcx<'c>(&'c self) -> TyCtxt<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.infcx.tcx
}
- fn try_fold_binder<T: TypeFoldable<'tcx>>(
+ fn try_fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
&mut self,
t: ty::Binder<'tcx, T>,
) -> Result<ty::Binder<'tcx, T>, Self::Error> {
@@ -214,18 +214,22 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
Reveal::All => {
let substs = substs.try_fold_with(self)?;
- let recursion_limit = self.tcx().recursion_limit();
+ let recursion_limit = self.interner().recursion_limit();
if !recursion_limit.value_within_limit(self.anon_depth) {
- self.infcx.err_ctxt().report_overflow_error(
- &ty,
- self.cause.span,
- true,
- |_| {},
- );
+ // A closure or generator may have itself as in its upvars.
+ // This should be checked handled by the recursion check for opaque
+ // types, but we may end up here before that check can happen.
+ // In that case, we delay a bug to mark the trip, and continue without
+ // revealing the opaque.
+ self.infcx
+ .err_ctxt()
+ .build_overflow_error(&ty, self.cause.span, true)
+ .delay_as_bug();
+ return ty.try_super_fold_with(self);
}
- let generic_ty = self.tcx().bound_type_of(def_id);
- let concrete_ty = generic_ty.subst(self.tcx(), substs);
+ let generic_ty = self.interner().type_of(def_id);
+ let concrete_ty = generic_ty.subst(self.interner(), substs);
self.anon_depth += 1;
if concrete_ty == ty {
bug!(
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
index 97002b461..9e8bc8bce 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
@@ -54,8 +54,8 @@ pub struct TypeOpOutput<'tcx, Op: TypeOp<'tcx>> {
/// which produces the resulting query region constraints.
///
/// [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
-pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<'tcx> + 'tcx {
- type QueryResponse: TypeFoldable<'tcx>;
+pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<TyCtxt<'tcx>> + 'tcx {
+ type QueryResponse: TypeFoldable<TyCtxt<'tcx>>;
/// Give query the option for a simple fast path that never
/// actually hits the tcx cache lookup etc. Return `Some(r)` with
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs
index 8f0b4de31..5b216c076 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs
@@ -1,7 +1,7 @@
use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
use crate::traits::query::Fallible;
use rustc_middle::ty::fold::TypeFoldable;
-use rustc_middle::ty::{self, Lift, ParamEnvAnd, Ty, TyCtxt};
+use rustc_middle::ty::{self, Lift, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
use std::fmt;
pub use rustc_middle::traits::query::type_op::Normalize;
@@ -24,7 +24,7 @@ where
}
}
-pub trait Normalizable<'tcx>: fmt::Debug + TypeFoldable<'tcx> + Lift<'tcx> + Copy {
+pub trait Normalizable<'tcx>: fmt::Debug + TypeFoldable<TyCtxt<'tcx>> + Lift<'tcx> + Copy {
fn type_op_method(
tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
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 0d42cd825..21ef4e24f 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
@@ -21,11 +21,7 @@ impl<'tcx> super::QueryTypeOp<'tcx> for DropckOutlives<'tcx> {
tcx: TyCtxt<'tcx>,
key: &ParamEnvAnd<'tcx, Self>,
) -> Option<Self::QueryResponse> {
- if trivial_dropck_outlives(tcx, key.value.dropped_ty) {
- Some(DropckOutlivesResult::default())
- } else {
- None
- }
+ trivial_dropck_outlives(tcx, key.value.dropped_ty).then(DropckOutlivesResult::default)
}
fn perform_query(
diff --git a/compiler/rustc_trait_selection/src/traits/relationships.rs b/compiler/rustc_trait_selection/src/traits/relationships.rs
deleted file mode 100644
index 34b5fc489..000000000
--- a/compiler/rustc_trait_selection/src/traits/relationships.rs
+++ /dev/null
@@ -1,48 +0,0 @@
-use crate::infer::InferCtxt;
-use crate::traits::query::evaluate_obligation::InferCtxtExt;
-use crate::traits::PredicateObligation;
-use rustc_infer::traits::TraitEngine;
-use rustc_middle::ty;
-
-pub(crate) fn update<'tcx, T>(
- engine: &mut T,
- infcx: &InferCtxt<'tcx>,
- obligation: &PredicateObligation<'tcx>,
-) where
- T: TraitEngine<'tcx>,
-{
- // (*) binder skipped
- if let ty::PredicateKind::Clause(ty::Clause::Trait(tpred)) = obligation.predicate.kind().skip_binder()
- && let Some(ty) = infcx.shallow_resolve(tpred.self_ty()).ty_vid().map(|t| infcx.root_var(t))
- && infcx.tcx.lang_items().sized_trait().map_or(false, |st| st != tpred.trait_ref.def_id)
- {
- let new_self_ty = infcx.tcx.types.unit;
-
- // Then construct a new obligation with Self = () added
- // to the ParamEnv, and see if it holds.
- let o = obligation.with(infcx.tcx,
- obligation
- .predicate
- .kind()
- .rebind(
- // (*) binder moved here
- ty::PredicateKind::Clause(ty::Clause::Trait(tpred.with_self_ty(infcx.tcx, new_self_ty)))
- ),
- );
- // Don't report overflow errors. Otherwise equivalent to may_hold.
- if let Ok(result) = infcx.probe(|_| infcx.evaluate_obligation(&o)) && result.may_apply() {
- engine.relationships().entry(ty).or_default().self_in_trait = true;
- }
- }
-
- if let ty::PredicateKind::Clause(ty::Clause::Projection(predicate)) =
- obligation.predicate.kind().skip_binder()
- {
- // If the projection predicate (Foo::Bar == X) has X as a non-TyVid,
- // we need to make it into one.
- if let Some(vid) = predicate.term.ty().and_then(|ty| ty.ty_vid()) {
- debug!("relationship: {:?}.output = true", vid);
- engine.relationships().entry(vid).or_default().output = true;
- }
- }
-}
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 2733d9643..e91057356 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -9,7 +9,7 @@ use hir::LangItem;
use rustc_hir as hir;
use rustc_infer::traits::ObligationCause;
use rustc_infer::traits::{Obligation, SelectionError, TraitObligation};
-use rustc_middle::ty::{self, Ty, TypeVisitable};
+use rustc_middle::ty::{self, Ty, TypeVisitableExt};
use rustc_target::spec::abi::Abi;
use crate::traits;
@@ -94,7 +94,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
self.assemble_candidates_for_transmutability(obligation, &mut candidates);
} else if lang_items.tuple_trait() == Some(def_id) {
self.assemble_candidate_for_tuple(obligation, &mut candidates);
- } else if lang_items.pointer_sized() == Some(def_id) {
+ } else if lang_items.pointer_like() == Some(def_id) {
self.assemble_candidate_for_ptr_sized(obligation, &mut candidates);
} else {
if lang_items.clone_trait() == Some(def_id) {
@@ -174,8 +174,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.param_env
.caller_bounds()
.iter()
- .filter_map(|p| p.to_opt_poly_trait_pred())
- .filter(|p| !p.references_error());
+ .filter(|p| !p.references_error())
+ .filter_map(|p| p.to_opt_poly_trait_pred());
// Micro-optimization: filter out predicates relating to different traits.
let matching_bounds =
@@ -339,7 +339,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// Essentially any user-written impl will match with an error type,
// so creating `ImplCandidates` isn't useful. However, we might
- // end up finding a candidate elsewhere (e.g. a `BuiltinCandidate` for `Sized)
+ // end up finding a candidate elsewhere (e.g. a `BuiltinCandidate` for `Sized`)
// This helps us avoid overflow: see issue #72839
// Since compilation is already guaranteed to fail, this is just
// to try to show the 'nicest' possible errors to the user.
@@ -396,7 +396,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// still be provided by a manual implementation for
// this trait and type.
}
- ty::Param(..) | ty::Alias(ty::Projection, ..) => {
+ ty::Param(..)
+ | ty::Alias(ty::Projection, ..)
+ | ty::Placeholder(..)
+ | ty::Bound(..) => {
// In these cases, we don't know what the actual
// type is. Therefore, we cannot break it down
// into its constituent types. So we don't
@@ -448,6 +451,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
);
self.infcx.probe(|_snapshot| {
+ if obligation.has_non_region_late_bound() {
+ return;
+ }
+
// The code below doesn't care about regions, and the
// self-ty here doesn't escape this probe, so just erase
// any LBR.
@@ -466,7 +473,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
if let Some(principal) = data.principal() {
if !self.infcx.tcx.features().object_safe_for_dispatch {
principal.with_self_ty(self.tcx(), self_ty)
- } else if self.tcx().is_object_safe(principal.def_id()) {
+ } else if self.tcx().check_is_object_safe(principal.def_id()) {
principal.with_self_ty(self.tcx(), self_ty)
} else {
return;
@@ -488,7 +495,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);
let placeholder_trait_predicate =
- self.infcx.replace_bound_vars_with_placeholders(poly_trait_predicate);
+ self.infcx.instantiate_binder_with_placeholders(poly_trait_predicate);
// Count only those upcast versions that match the trait-ref
// we are looking for. Specifically, do not only check for the
@@ -765,7 +772,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::Closure(..)
| ty::Generator(..)
| ty::Tuple(_)
- | ty::GeneratorWitness(_) => {
+ | ty::GeneratorWitness(_)
+ | ty::GeneratorWitnessMIR(..) => {
// These are built-in, and cannot have a custom `impl const Destruct`.
candidates.vec.push(ConstDestructCandidate(None));
}
@@ -826,6 +834,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::Closure(_, _)
| ty::Generator(_, _, _)
| ty::GeneratorWitness(_)
+ | ty::GeneratorWitnessMIR(..)
| ty::Never
| ty::Alias(..)
| ty::Param(_)
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 82a59831b..21c158fd0 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -8,12 +8,11 @@
//! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_hir::lang_items::LangItem;
-use rustc_index::bit_set::GrowableBitSet;
use rustc_infer::infer::InferOk;
use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
use rustc_middle::ty::{
- self, Binder, GenericArg, GenericArgKind, GenericParamDefKind, InternalSubsts, SubstsRef,
- ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt,
+ self, Binder, GenericParamDefKind, InternalSubsts, SubstsRef, ToPolyTraitRef, ToPredicate,
+ TraitRef, Ty, TyCtxt, TypeVisitableExt,
};
use rustc_session::config::TraitSolver;
use rustc_span::def_id::DefId;
@@ -152,7 +151,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let trait_predicate = self.infcx.shallow_resolve(obligation.predicate);
let placeholder_trait_predicate =
- self.infcx.replace_bound_vars_with_placeholders(trait_predicate).trait_ref;
+ 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() {
@@ -337,7 +336,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let cause = obligation.derived_cause(BuiltinDerivedObligation);
let poly_trait_ref = obligation.predicate.to_poly_trait_ref();
- let trait_ref = self.infcx.replace_bound_vars_with_placeholders(poly_trait_ref);
+ let trait_ref = self.infcx.instantiate_binder_with_placeholders(poly_trait_ref);
let trait_obligations: Vec<PredicateObligation<'_>> = self.impl_or_trait_obligations(
&cause,
obligation.recursion_depth + 1,
@@ -428,7 +427,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let tcx = self.tcx();
debug!(?obligation, ?index, "confirm_object_candidate");
- let trait_predicate = self.infcx.replace_bound_vars_with_placeholders(obligation.predicate);
+ let trait_predicate = self.infcx.instantiate_binder_with_placeholders(obligation.predicate);
let self_ty = self.infcx.shallow_resolve(trait_predicate.self_ty());
let obligation_trait_ref = ty::Binder::dummy(trait_predicate.trait_ref);
let ty::Dynamic(data, ..) = *self_ty.kind() else {
@@ -438,7 +437,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let object_trait_ref = data.principal().unwrap_or_else(|| {
span_bug!(obligation.cause.span, "object candidate with no principal")
});
- let object_trait_ref = self.infcx.replace_bound_vars_with_fresh_vars(
+ let object_trait_ref = self.infcx.instantiate_binder_with_fresh_vars(
obligation.cause.span,
HigherRankedType,
object_trait_ref,
@@ -525,29 +524,29 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.kind
{
GenericParamDefKind::Type { .. } => {
- let kind = ty::BoundTyKind::Param(param.name);
+ let kind = ty::BoundTyKind::Param(param.def_id, param.name);
let bound_var = ty::BoundVariableKind::Ty(kind);
bound_vars.push(bound_var);
- tcx.mk_ty(ty::Bound(
+ tcx.mk_bound(
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);
- tcx.mk_region(ty::ReLateBound(
+ tcx.mk_re_late_bound(
ty::INNERMOST,
ty::BoundRegion {
var: ty::BoundVar::from_usize(bound_vars.len() - 1),
kind,
},
- ))
+ )
.into()
}
GenericParamDefKind::Const { .. } => {
@@ -558,15 +557,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ty::INNERMOST,
ty::BoundVar::from_usize(bound_vars.len() - 1),
),
- tcx.type_of(param.def_id),
+ 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.into_iter());
- let assoc_ty_substs = tcx.intern_substs(&substs);
-
- let bound_vars = tcx.mk_bound_variable_kinds(bound_vars.into_iter());
+ 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);
tcx.mk_predicate(ty::Binder::bind_with_vars(bound, bound_vars))
@@ -630,7 +629,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
// Confirm the `type Output: Sized;` bound that is present on `FnOnce`
- let output_ty = self.infcx.replace_bound_vars_with_placeholders(sig.output());
+ let output_ty = self.infcx.instantiate_binder_with_placeholders(sig.output());
let output_ty = normalize_with_depth_to(
self,
obligation.param_env,
@@ -653,7 +652,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
debug!(?obligation, "confirm_trait_alias_candidate");
let alias_def_id = obligation.predicate.def_id();
- let predicate = self.infcx.replace_bound_vars_with_placeholders(obligation.predicate);
+ 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;
@@ -822,6 +821,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
self.infcx
.at(&obligation.cause, obligation.param_env)
+ // needed for tests/ui/type-alias-impl-trait/assoc-projection-ice.rs
+ .define_opaque_types(true)
.sup(obligation_trait_ref, expected_trait_ref)
.map(|InferOk { mut obligations, .. }| {
obligations.extend(nested);
@@ -879,7 +880,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.map(ty::ExistentialPredicate::AutoTrait)
.map(ty::Binder::dummy),
);
- let existential_predicates = tcx.mk_poly_existential_predicates(iter);
+ let existential_predicates = tcx.mk_poly_existential_predicates_from_iter(iter);
let source_trait = tcx.mk_dynamic(existential_predicates, r_b, repr_a);
// Require that the traits involved in this upcast are **equal**;
@@ -978,7 +979,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.map(ty::ExistentialPredicate::AutoTrait)
.map(ty::Binder::dummy),
);
- let existential_predicates = tcx.mk_poly_existential_predicates(iter);
+ let existential_predicates = tcx.mk_poly_existential_predicates_from_iter(iter);
let source_trait = tcx.mk_dynamic(existential_predicates, r_b, dyn_a);
// Require that the traits involved in this upcast are **equal**;
@@ -1009,7 +1010,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// `T` -> `Trait`
(_, &ty::Dynamic(ref data, r, ty::Dyn)) => {
let mut object_dids = data.auto_traits().chain(data.principal_def_id());
- if let Some(did) = object_dids.find(|did| !tcx.is_object_safe(*did)) {
+ if let Some(did) = object_dids.find(|did| !tcx.check_is_object_safe(*did)) {
return Err(TraitNotObjectSafe(did));
}
@@ -1064,51 +1065,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// `Struct<T>` -> `Struct<U>`
(&ty::Adt(def, substs_a), &ty::Adt(_, substs_b)) => {
- let maybe_unsizing_param_idx = |arg: GenericArg<'tcx>| match arg.unpack() {
- GenericArgKind::Type(ty) => match ty.kind() {
- ty::Param(p) => Some(p.index),
- _ => None,
- },
-
- // Lifetimes aren't allowed to change during unsizing.
- GenericArgKind::Lifetime(_) => None,
-
- GenericArgKind::Const(ct) => match ct.kind() {
- ty::ConstKind::Param(p) => Some(p.index),
- _ => None,
- },
- };
-
- // FIXME(eddyb) cache this (including computing `unsizing_params`)
- // by putting it in a query; it would only need the `DefId` as it
- // looks at declared field types, not anything substituted.
-
- // The last field of the structure has to exist and contain type/const parameters.
- let (tail_field, prefix_fields) =
- def.non_enum_variant().fields.split_last().ok_or(Unimplemented)?;
- let tail_field_ty = tcx.bound_type_of(tail_field.did);
-
- let mut unsizing_params = GrowableBitSet::new_empty();
- for arg in tail_field_ty.0.walk() {
- if let Some(i) = maybe_unsizing_param_idx(arg) {
- unsizing_params.insert(i);
- }
- }
-
- // Ensure none of the other fields mention the parameters used
- // in unsizing.
- for field in prefix_fields {
- for arg in tcx.type_of(field.did).walk() {
- if let Some(i) = maybe_unsizing_param_idx(arg) {
- unsizing_params.remove(i);
- }
- }
- }
-
+ let unsizing_params = tcx.unsizing_params_for_adt(def.did());
if unsizing_params.is_empty() {
return Err(Unimplemented);
}
+ let tail_field = def
+ .non_enum_variant()
+ .fields
+ .last()
+ .expect("expected unsized ADT to have a tail field");
+ let tail_field_ty = tcx.type_of(tail_field.did);
+
// 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).
@@ -1131,7 +1099,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// Check that the source struct with the target's
// unsizing parameters is equal to the target.
- let substs = tcx.mk_substs(substs_a.iter().enumerate().map(|(i, k)| {
+ 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 = tcx.mk_adt(def, substs);
@@ -1163,7 +1131,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// Check that the source tuple with the target's
// last element is equal to the target.
- let new_tuple = tcx.mk_tup(a_mid.iter().copied().chain(iter::once(b_last)));
+ let new_tuple =
+ tcx.mk_tup_from_iter(a_mid.iter().copied().chain(iter::once(b_last)));
let InferOk { obligations, .. } = self
.infcx
.at(&obligation.cause, obligation.param_env)
@@ -1223,7 +1192,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let cause = obligation.derived_cause(|derived| {
ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
derived,
- impl_def_id,
+ impl_or_alias_def_id: impl_def_id,
+ impl_def_predicate_index: None,
span: obligation.cause.span,
}))
});
@@ -1285,6 +1255,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ty::GeneratorWitness(tys) => {
stack.extend(tcx.erase_late_bound_regions(tys).to_vec());
}
+ ty::GeneratorWitnessMIR(def_id, substs) => {
+ let tcx = self.tcx();
+ stack.extend(tcx.generator_hidden_types(def_id).map(|bty| {
+ let ty = bty.subst(tcx, substs);
+ debug_assert!(!ty.has_late_bound_regions());
+ ty
+ }))
+ }
// If we have a projection type, make sure to normalize it so we replace it
// with a fresh infer variable
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index f90da95d5..7f454fbb3 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -27,6 +27,7 @@ use super::{
use crate::infer::{InferCtxt, InferOk, TypeFreshener};
use crate::traits::error_reporting::TypeErrCtxtExt;
+use crate::traits::project::try_normalize_with_depth_to;
use crate::traits::project::ProjectAndUnifyResult;
use crate::traits::project::ProjectionCacheKeyExt;
use crate::traits::ProjectionCacheKey;
@@ -38,6 +39,8 @@ use rustc_errors::Diagnostic;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_infer::infer::LateBoundRegionConversionTime;
+use rustc_infer::traits::TraitEngine;
+use rustc_infer::traits::TraitEngineExt;
use rustc_middle::dep_graph::{DepKind, DepNodeIndex};
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
@@ -46,7 +49,8 @@ use rustc_middle::ty::fold::BottomUpFolder;
use rustc_middle::ty::relate::TypeRelation;
use rustc_middle::ty::SubstsRef;
use rustc_middle::ty::{self, EarlyBinder, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate};
-use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable, TypeVisitable};
+use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
+use rustc_session::config::TraitSolver;
use rustc_span::symbol::sym;
use std::cell::{Cell, RefCell};
@@ -147,7 +151,7 @@ struct TraitObligationStack<'prev, 'tcx> {
/// you don't want to cache that `B: AutoTrait` or `A: AutoTrait`
/// is `EvaluatedToOk`; this is because they were only considered
/// ok on the premise that if `A: AutoTrait` held, but we indeed
- /// encountered a problem (later on) with `A: AutoTrait. So we
+ /// encountered a problem (later on) with `A: AutoTrait`. So we
/// currently set a flag on the stack node for `B: AutoTrait` (as
/// well as the second instance of `A: AutoTrait`) to suppress
/// caching.
@@ -374,11 +378,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let self_ty = trait_ref.self_ty();
let (trait_desc, self_desc) = with_no_trimmed_paths!({
let trait_desc = trait_ref.print_only_trait_path().to_string();
- let self_desc = if self_ty.has_concrete_skeleton() {
- Some(self_ty.to_string())
- } else {
- None
- };
+ let self_desc =
+ self_ty.has_concrete_skeleton().then(|| self_ty.to_string());
(trait_desc, self_desc)
});
let cause = if let Conflict::Upstream = conflict {
@@ -544,10 +545,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation: &PredicateObligation<'tcx>,
) -> Result<EvaluationResult, OverflowError> {
self.evaluation_probe(|this| {
- this.evaluate_predicate_recursively(
- TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()),
- obligation.clone(),
- )
+ if this.tcx().sess.opts.unstable_opts.trait_solver != TraitSolver::Next {
+ this.evaluate_predicate_recursively(
+ TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()),
+ obligation.clone(),
+ )
+ } else {
+ this.evaluate_predicates_recursively_in_new_solver([obligation.clone()])
+ }
})
}
@@ -586,18 +591,40 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
where
I: IntoIterator<Item = PredicateObligation<'tcx>> + std::fmt::Debug,
{
- let mut result = EvaluatedToOk;
- for obligation in predicates {
- let eval = self.evaluate_predicate_recursively(stack, obligation.clone())?;
- if let EvaluatedToErr = eval {
- // fast-path - EvaluatedToErr is the top of the lattice,
- // so we don't need to look on the other predicates.
- return Ok(EvaluatedToErr);
- } else {
- result = cmp::max(result, eval);
+ if self.tcx().sess.opts.unstable_opts.trait_solver != TraitSolver::Next {
+ let mut result = EvaluatedToOk;
+ for obligation in predicates {
+ let eval = self.evaluate_predicate_recursively(stack, obligation.clone())?;
+ if let EvaluatedToErr = eval {
+ // fast-path - EvaluatedToErr is the top of the lattice,
+ // so we don't need to look on the other predicates.
+ return Ok(EvaluatedToErr);
+ } else {
+ result = cmp::max(result, eval);
+ }
}
+ Ok(result)
+ } else {
+ self.evaluate_predicates_recursively_in_new_solver(predicates)
}
- Ok(result)
+ }
+
+ /// Evaluates the predicates using the new solver when `-Ztrait-solver=next` is enabled
+ fn evaluate_predicates_recursively_in_new_solver(
+ &mut self,
+ predicates: impl IntoIterator<Item = PredicateObligation<'tcx>>,
+ ) -> Result<EvaluationResult, OverflowError> {
+ let mut fulfill_cx = crate::solve::FulfillmentCtxt::new();
+ fulfill_cx.register_predicate_obligations(self.infcx, predicates);
+ // True errors
+ if !fulfill_cx.select_where_possible(self.infcx).is_empty() {
+ return Ok(EvaluatedToErr);
+ }
+ if !fulfill_cx.select_all_or_error(self.infcx).is_empty() {
+ return Ok(EvaluatedToAmbig);
+ }
+ // Regions and opaques are handled in the `evaluation_probe` by looking at the snapshot
+ Ok(EvaluatedToOk)
}
#[instrument(
@@ -700,7 +727,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// Otherwise, we can say that `T: NonAutoTrait` is
// true.
// Let's imagine we have a predicate stack like
- // `Foo: Bar -> WF(T) -> T: NonAutoTrait -> T: Auto
+ // `Foo: Bar -> WF(T) -> T: NonAutoTrait -> T: Auto`
// depth ^1 ^2 ^3
// and the current predicate is `WF(T)`. `wf_args`
// would contain `(T, 1)`. We want to check all
@@ -768,7 +795,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
ty::PredicateKind::ObjectSafe(trait_def_id) => {
- if self.tcx().is_object_safe(trait_def_id) {
+ if self.tcx().check_is_object_safe(trait_def_id) {
Ok(EvaluatedToOk)
} else {
Ok(EvaluatedToErr)
@@ -962,7 +989,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ty::PredicateKind::TypeWellFormedFromEnv(..) => {
bug!("TypeWellFormedFromEnv is only used for chalk")
}
+ ty::PredicateKind::AliasEq(..) => {
+ bug!("AliasEq is only used for new solver")
+ }
ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig),
+ ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
+ match self.infcx.at(&obligation.cause, obligation.param_env).eq(ct.ty(), ty) {
+ Ok(inf_ok) => self.evaluate_predicates_recursively(
+ previous_stack,
+ inf_ok.into_obligations(),
+ ),
+ Err(_) => Ok(EvaluatedToErr),
+ }
+ }
}
})
}
@@ -1017,7 +1056,51 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
return Ok(cycle_result);
}
- let (result, dep_node) = self.in_task(|this| this.evaluate_stack(&stack));
+ let (result, dep_node) = self.in_task(|this| {
+ let mut result = this.evaluate_stack(&stack)?;
+
+ // fix issue #103563, we don't normalize
+ // nested obligations which produced by `TraitDef` candidate
+ // (i.e. using bounds on assoc items as assumptions).
+ // because we don't have enough information to
+ // normalize these obligations before evaluating.
+ // so we will try to normalize the obligation and evaluate again.
+ // we will replace it with new solver in the future.
+ if EvaluationResult::EvaluatedToErr == result
+ && fresh_trait_pred.has_projections()
+ && fresh_trait_pred.is_global()
+ {
+ let mut nested_obligations = Vec::new();
+ let predicate = try_normalize_with_depth_to(
+ this,
+ param_env,
+ obligation.cause.clone(),
+ obligation.recursion_depth + 1,
+ obligation.predicate,
+ &mut nested_obligations,
+ );
+ if predicate != obligation.predicate {
+ let mut nested_result = EvaluationResult::EvaluatedToOk;
+ for obligation in nested_obligations {
+ nested_result = cmp::max(
+ this.evaluate_predicate_recursively(previous_stack, obligation)?,
+ nested_result,
+ );
+ }
+
+ if nested_result.must_apply_modulo_regions() {
+ let obligation = obligation.with(this.tcx(), predicate);
+ result = cmp::max(
+ nested_result,
+ this.evaluate_trait_predicate_recursively(previous_stack, obligation)?,
+ );
+ }
+ }
+ }
+
+ Ok::<_, OverflowError>(result)
+ });
+
let result = result?;
if !result.must_apply_modulo_regions() {
@@ -1323,7 +1406,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
/// The weird return type of this function allows it to be used with the `try` (`?`)
/// operator within certain functions.
#[inline(always)]
- fn check_recursion_limit<T: Display + TypeFoldable<'tcx>, V>(
+ fn check_recursion_limit<T: Display + TypeFoldable<TyCtxt<'tcx>>, V>(
&self,
obligation: &Obligation<'tcx, T>,
error_obligation: &Obligation<'tcx, V>,
@@ -1589,7 +1672,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
) -> smallvec::SmallVec<[(usize, ty::BoundConstness); 2]> {
let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);
let placeholder_trait_predicate =
- self.infcx.replace_bound_vars_with_placeholders(poly_trait_predicate);
+ self.infcx.instantiate_binder_with_placeholders(poly_trait_predicate);
debug!(?placeholder_trait_predicate);
let tcx = self.infcx.tcx;
@@ -1669,7 +1752,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
});
self.infcx
.at(&obligation.cause, obligation.param_env)
- .define_opaque_types(false)
.sup(ty::Binder::dummy(placeholder_trait_ref), trait_bound)
.map(|InferOk { obligations: _, value: () }| {
// This method is called within a probe, so we can't have
@@ -1709,7 +1791,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
potentially_unnormalized_candidates: bool,
) -> ProjectionMatchesProjection {
let mut nested_obligations = Vec::new();
- let infer_predicate = self.infcx.replace_bound_vars_with_fresh_vars(
+ let infer_predicate = self.infcx.instantiate_binder_with_fresh_vars(
obligation.cause.span,
LateBoundRegionConversionTime::HigherRankedType,
env_predicate,
@@ -1732,7 +1814,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let is_match = self
.infcx
.at(&obligation.cause, obligation.param_env)
- .define_opaque_types(false)
.sup(obligation.predicate, infer_projection)
.map_or(false, |InferOk { obligations, value: () }| {
self.evaluate_predicates_recursively(
@@ -2037,6 +2118,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::Ref(..)
| ty::Generator(..)
| ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::Array(..)
| ty::Closure(..)
| ty::Never
@@ -2064,12 +2146,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}))
}
- ty::Alias(..) | ty::Param(_) => None,
+ ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => None,
ty::Infer(ty::TyVar(_)) => Ambiguous,
- ty::Placeholder(..)
- | ty::Bound(..)
- | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
+ // We can make this an ICE if/once we actually instantiate the trait obligation.
+ ty::Bound(..) => None,
+
+ ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
bug!("asked to assemble builtin bounds of unexpected type: {:?}", self_ty);
}
}
@@ -2147,12 +2230,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
}
// (*) binder moved here
- let all_vars = self.tcx().mk_bound_variable_kinds(
+ let all_vars = self.tcx().mk_bound_variable_kinds_from_iter(
obligation.predicate.bound_vars().iter().chain(binder.bound_vars().iter()),
);
Where(ty::Binder::bind_with_vars(witness_tys.to_vec(), all_vars))
}
+ ty::GeneratorWitnessMIR(def_id, ref substs) => {
+ let hidden_types = bind_generator_hidden_types_above(
+ self.infcx,
+ def_id,
+ substs,
+ obligation.predicate.bound_vars(),
+ );
+ Where(hidden_types)
+ }
+
ty::Closure(_, substs) => {
// (*) binder moved here
let ty = self.infcx.shallow_resolve(substs.as_closure().tupled_upvars_ty());
@@ -2207,12 +2300,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::Float(_)
| ty::FnDef(..)
| ty::FnPtr(_)
- | ty::Str
| ty::Error(_)
| ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
| ty::Never
| ty::Char => ty::Binder::dummy(Vec::new()),
+ // Treat this like `struct str([u8]);`
+ ty::Str => ty::Binder::dummy(vec![self.tcx().mk_slice(self.tcx().types.u8)]),
+
ty::Placeholder(..)
| ty::Dynamic(..)
| ty::Param(..)
@@ -2250,6 +2345,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, '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())
+ }
+
// For `PhantomData<T>`, we pass `T`.
ty::Adt(def, substs) if def.is_phantom_data() => t.rebind(substs.types().collect()),
@@ -2261,7 +2360,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, '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![self.tcx().bound_type_of(def_id).subst(self.tcx(), substs)])
+ t.rebind(vec![self.tcx().type_of(def_id).subst(self.tcx(), substs)])
}
}
}
@@ -2295,7 +2394,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.flat_map(|ty| {
let ty: ty::Binder<'tcx, Ty<'tcx>> = types.rebind(*ty); // <----/
- let placeholder_ty = self.infcx.replace_bound_vars_with_placeholders(ty);
+ let placeholder_ty = self.infcx.instantiate_binder_with_placeholders(ty);
let Normalized { value: normalized_ty, mut obligations } =
ensure_sufficient_stack(|| {
project::normalize_with_depth(
@@ -2346,7 +2445,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// the placeholder trait ref may fail due the Generalizer relation
// raising a CyclicalTy error due to a sub_root_var relation
// for a variable being generalized...
- self.infcx.tcx.sess.delay_span_bug(
+ let guar = self.infcx.tcx.sess.delay_span_bug(
obligation.cause.span,
&format!(
"Impl {:?} was matchable against {:?} but now is not",
@@ -2354,7 +2453,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
),
);
let value = self.infcx.fresh_substs_for_item(obligation.cause.span, impl_def_id);
- let err = self.tcx().ty_error();
+ let err = self.tcx().ty_error(guar);
let value = value.fold_with(&mut BottomUpFolder {
tcx: self.tcx(),
ty_op: |_| err,
@@ -2374,7 +2473,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation: &TraitObligation<'tcx>,
) -> Result<Normalized<'tcx, SubstsRef<'tcx>>, ()> {
let placeholder_obligation =
- self.infcx.replace_bound_vars_with_placeholders(obligation.predicate);
+ 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);
@@ -2408,9 +2507,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let InferOk { obligations, .. } = self
.infcx
.at(&cause, obligation.param_env)
- .define_opaque_types(false)
.eq(placeholder_obligation_trait_ref, impl_trait_ref)
- .map_err(|e| debug!("match_impl: failed eq_trait_refs due to `{e}`"))?;
+ .map_err(|e| {
+ debug!("match_impl: failed eq_trait_refs due to `{}`", e.to_string(self.tcx()))
+ })?;
nested_obligations.extend(obligations);
if !self.is_intercrate()
@@ -2457,11 +2557,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
) -> Result<Vec<PredicateObligation<'tcx>>, ()> {
self.infcx
.at(&obligation.cause, obligation.param_env)
- // We don't want predicates for opaque types to just match all other types,
- // if there is an obligation on the opaque type, then that obligation must be met
- // opaquely. Otherwise we'd match any obligation to the opaque type and then error
- // out later.
- .define_opaque_types(false)
.sup(obligation.predicate.to_poly_trait_ref(), poly_trait_ref)
.map(|InferOk { obligations, .. }| obligations)
.map_err(|_| ())
@@ -2562,11 +2657,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
assert_eq!(predicates.parent, None);
let predicates = predicates.instantiate_own(tcx, substs);
let mut obligations = Vec::with_capacity(predicates.len());
- for (predicate, span) in predicates {
+ for (index, (predicate, span)) in predicates.into_iter().enumerate() {
let cause = cause.clone().derived_cause(parent_trait_pred, |derived| {
ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
derived,
- impl_def_id: def_id,
+ impl_or_alias_def_id: def_id,
+ impl_def_predicate_index: Some(index),
span,
}))
});
@@ -2892,3 +2988,56 @@ pub enum ProjectionMatchesProjection {
Ambiguous,
No,
}
+
+/// Replace all regions inside the generator interior with late bound regions.
+/// Note that each region slot in the types gets a new fresh late bound region, which means that
+/// none of the regions inside relate to any other, even if typeck had previously found constraints
+/// that would cause them to be related.
+#[instrument(level = "trace", skip(infcx), ret)]
+fn bind_generator_hidden_types_above<'tcx>(
+ infcx: &InferCtxt<'tcx>,
+ def_id: DefId,
+ substs: ty::SubstsRef<'tcx>,
+ bound_vars: &ty::List<ty::BoundVariableKind>,
+) -> ty::Binder<'tcx, Vec<Ty<'tcx>>> {
+ let tcx = infcx.tcx;
+ let mut seen_tys = FxHashSet::default();
+
+ let considering_regions = infcx.considering_regions;
+
+ let num_bound_variables = bound_vars.len() as u32;
+ let mut counter = num_bound_variables;
+
+ let hidden_types: Vec<_> = tcx
+ .generator_hidden_types(def_id)
+ // Deduplicate tys to avoid repeated work.
+ .filter(|bty| seen_tys.insert(*bty))
+ .map(|bty| {
+ let mut ty = bty.subst(tcx, substs);
+
+ // Only remap erased regions if we use them.
+ if considering_regions {
+ ty = tcx.fold_regions(ty, |mut r, current_depth| {
+ if let ty::ReErased = r.kind() {
+ let br = ty::BoundRegion {
+ var: ty::BoundVar::from_u32(counter),
+ kind: ty::BrAnon(counter, None),
+ };
+ counter += 1;
+ r = tcx.mk_re_late_bound(current_depth, br);
+ }
+ r
+ })
+ }
+
+ ty
+ })
+ .collect();
+ if considering_regions {
+ debug_assert!(!hidden_types.has_erased_regions());
+ }
+ let bound_vars = tcx.mk_bound_variable_kinds_from_iter(bound_vars.iter().chain(
+ (num_bound_variables..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i, None))),
+ ));
+ ty::Binder::bind_with_vars(hidden_types, bound_vars)
+}
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index 3b796c623..d1d6a7a90 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -455,7 +455,13 @@ pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Opti
w.push('>');
}
- write!(w, " {} for {}", trait_ref.print_only_trait_path(), tcx.type_of(impl_def_id)).unwrap();
+ write!(
+ w,
+ " {} for {}",
+ trait_ref.print_only_trait_path(),
+ tcx.type_of(impl_def_id).subst_identity()
+ )
+ .unwrap();
// The predicates will contain default bounds like `T: Sized`. We need to
// remove these bounds, and add `T: ?Sized` to any untouched type parameters.
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 0f9196de4..61ed9ef2e 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
@@ -4,7 +4,7 @@ use crate::traits;
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams};
-use rustc_middle::ty::{self, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
pub use rustc_middle::traits::specialization_graph::*;
@@ -113,7 +113,7 @@ impl<'tcx> ChildrenExt<'tcx> for Children {
// Only report the `Self` type if it has at least
// some outer concrete shell; otherwise, it's
// not adding much information.
- self_ty: if self_ty.has_concrete_skeleton() { Some(self_ty) } else { None },
+ self_ty: self_ty.has_concrete_skeleton().then_some(self_ty),
intercrate_ambiguity_causes: overlap.intercrate_ambiguity_causes,
involves_placeholder: overlap.involves_placeholder,
}
@@ -399,7 +399,7 @@ pub(crate) fn assoc_def(
// If there is no such item in that impl, this function will fail with a
// cycle error if the specialization graph is currently being built.
if let Some(&impl_item_id) = tcx.impl_item_implementor_ids(impl_def_id).get(&assoc_def_id) {
- let &item = tcx.associated_item(impl_item_id);
+ let item = tcx.associated_item(impl_item_id);
let impl_node = Node::Impl(impl_def_id);
return Ok(LeafDef {
item,
diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs
index f398fb06c..e38ae9381 100644
--- a/compiler/rustc_trait_selection/src/traits/structural_match.rs
+++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs
@@ -78,7 +78,7 @@ impl<'tcx> Search<'tcx> {
}
}
-impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> {
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for Search<'tcx> {
type BreakTy = Ty<'tcx>;
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
@@ -101,7 +101,7 @@ impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> {
ty::Closure(..) => {
return ControlFlow::Break(ty);
}
- ty::Generator(..) | ty::GeneratorWitness(..) => {
+ ty::Generator(..) | ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) => {
return ControlFlow::Break(ty);
}
ty::FnDef(..) => {
@@ -110,7 +110,7 @@ impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> {
return ControlFlow::Continue(());
}
ty::Array(_, n)
- if { n.try_eval_usize(self.tcx, ty::ParamEnv::reveal_all()) == Some(0) } =>
+ if { n.try_eval_target_usize(self.tcx, ty::ParamEnv::reveal_all()) == Some(0) } =>
{
// rust-lang/rust#62336: ignore type of contents
// for empty array.
diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs
index b5df583e3..bcf63d5a6 100644
--- a/compiler/rustc_trait_selection/src/traits/util.rs
+++ b/compiler/rustc_trait_selection/src/traits/util.rs
@@ -4,7 +4,7 @@ use smallvec::SmallVec;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def_id::DefId;
-use rustc_middle::ty::{self, ImplSubject, ToPredicate, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{self, ImplSubject, ToPredicate, Ty, TyCtxt, TypeVisitableExt};
use rustc_middle::ty::{GenericArg, SubstsRef};
use super::NormalizeExt;
@@ -239,7 +239,7 @@ pub fn predicate_for_trait_def<'tcx>(
cause: ObligationCause<'tcx>,
trait_def_id: DefId,
recursion_depth: usize,
- params: impl IntoIterator<Item = impl Into<GenericArg<'tcx>>>,
+ params: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
) -> PredicateObligation<'tcx> {
let trait_ref = tcx.mk_trait_ref(trait_def_id, params);
predicate_for_trait_ref(tcx, cause, param_env, trait_ref, recursion_depth)
@@ -292,7 +292,7 @@ pub fn closure_trait_ref_and_return_type<'tcx>(
assert!(!self_ty.has_escaping_bound_vars());
let arguments_tuple = match tuple_arguments {
TupleArgumentsFlag::No => sig.skip_binder().inputs()[0],
- TupleArgumentsFlag::Yes => tcx.intern_tup(sig.skip_binder().inputs()),
+ TupleArgumentsFlag::Yes => tcx.mk_tup(sig.skip_binder().inputs()),
};
let trait_ref = tcx.mk_trait_ref(fn_trait_def_id, [self_ty, arguments_tuple]);
sig.map_bound(|sig| (trait_ref, sig.output()))
diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs
index 64daca714..a4e9928f8 100644
--- a/compiler/rustc_trait_selection/src/traits/vtable.rs
+++ b/compiler/rustc_trait_selection/src/traits/vtable.rs
@@ -4,7 +4,7 @@ use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
use rustc_infer::traits::util::PredicateSet;
use rustc_infer::traits::ImplSource;
-use rustc_middle::ty::visit::TypeVisitable;
+use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::InternalSubsts;
use rustc_middle::ty::{self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, VtblEntry};
use rustc_span::{sym, Span};
@@ -197,12 +197,12 @@ fn own_existential_vtable_entries(tcx: TyCtxt<'_>, trait_def_id: DefId) -> &[Def
.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| {
+ let own_entries = trait_methods.filter_map(move |&trait_method| {
debug!("own_existential_vtable_entry: trait_method={:?}", trait_method);
let def_id = trait_method.def_id;
// Some methods cannot be called on an object; skip those.
- if !is_vtable_safe_method(tcx, trait_def_id, &trait_method) {
+ if !is_vtable_safe_method(tcx, trait_def_id, trait_method) {
debug!("own_existential_vtable_entry: not vtable safe");
return None;
}
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 12d4cb4fc..d498af359 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -1,11 +1,11 @@
use crate::infer::InferCtxt;
use crate::traits;
use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable};
-use rustc_span::Span;
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
+use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
+use rustc_span::{Span, DUMMY_SP};
use std::iter;
/// Returns the set of obligations needed to make `arg` well-formed.
@@ -17,7 +17,7 @@ use std::iter;
pub fn obligations<'tcx>(
infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
- body_id: hir::HirId,
+ body_id: LocalDefId,
recursion_depth: usize,
arg: GenericArg<'tcx>,
span: Span,
@@ -75,6 +75,34 @@ pub fn obligations<'tcx>(
Some(result)
}
+/// Compute the predicates that are required for a type to be well-formed.
+///
+/// This is only intended to be used in the new solver, since it does not
+/// take into account recursion depth or proper error-reporting spans.
+pub fn unnormalized_obligations<'tcx>(
+ infcx: &InferCtxt<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ arg: GenericArg<'tcx>,
+) -> Option<Vec<traits::PredicateObligation<'tcx>>> {
+ if let ty::GenericArgKind::Lifetime(..) = arg.unpack() {
+ return Some(vec![]);
+ }
+
+ debug_assert_eq!(arg, infcx.resolve_vars_if_possible(arg));
+
+ let mut wf = WfPredicates {
+ tcx: infcx.tcx,
+ param_env,
+ body_id: CRATE_DEF_ID,
+ span: DUMMY_SP,
+ out: vec![],
+ recursion_depth: 0,
+ item: None,
+ };
+ wf.compute(arg);
+ Some(wf.out)
+}
+
/// Returns the obligations that make this trait reference
/// well-formed. For example, if there is a trait `Set` defined like
/// `trait Set<K:Eq>`, then the trait reference `Foo: Set<Bar>` is WF
@@ -82,7 +110,7 @@ pub fn obligations<'tcx>(
pub fn trait_obligations<'tcx>(
infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
- body_id: hir::HirId,
+ body_id: LocalDefId,
trait_pred: &ty::TraitPredicate<'tcx>,
span: Span,
item: &'tcx hir::Item<'tcx>,
@@ -105,7 +133,7 @@ pub fn trait_obligations<'tcx>(
pub fn predicate_obligations<'tcx>(
infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
- body_id: hir::HirId,
+ body_id: LocalDefId,
predicate: ty::Predicate<'tcx>,
span: Span,
) -> Vec<traits::PredicateObligation<'tcx>> {
@@ -135,6 +163,10 @@ pub fn predicate_obligations<'tcx>(
ty::TermKind::Const(c) => c.into(),
})
}
+ ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
+ wf.compute(ct.into());
+ wf.compute(ty.into());
+ }
ty::PredicateKind::WellFormed(arg) => {
wf.compute(arg);
}
@@ -159,6 +191,9 @@ pub fn predicate_obligations<'tcx>(
ty::PredicateKind::TypeWellFormedFromEnv(..) => {
bug!("TypeWellFormedFromEnv is only used for Chalk")
}
+ ty::PredicateKind::AliasEq(..) => {
+ bug!("We should only wf check where clauses and `AliasEq` is not a `Clause`")
+ }
}
wf.normalize(infcx)
@@ -167,7 +202,7 @@ pub fn predicate_obligations<'tcx>(
struct WfPredicates<'tcx> {
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
- body_id: hir::HirId,
+ body_id: LocalDefId,
span: Span,
out: Vec<traits::PredicateObligation<'tcx>>,
recursion_depth: usize,
@@ -523,6 +558,7 @@ impl<'tcx> WfPredicates<'tcx> {
| ty::Error(_)
| ty::Str
| ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::Never
| ty::Param(_)
| ty::Bound(..)
@@ -847,7 +883,7 @@ pub fn object_region_bounds<'tcx>(
// Since we don't actually *know* the self type for an object,
// this "open(err)" serves as a kind of dummy standin -- basically
// a placeholder type.
- let open_ty = tcx.mk_ty_infer(ty::FreshTy(0));
+ let open_ty = tcx.mk_fresh_ty(0);
let predicates = existential_predicates.iter().filter_map(|predicate| {
if let ty::ExistentialPredicate::Projection(_) = predicate.skip_binder() {
@@ -890,6 +926,7 @@ pub(crate) fn required_region_bounds<'tcx>(
match obligation.predicate.kind().skip_binder() {
ty::PredicateKind::Clause(ty::Clause::Projection(..))
| ty::PredicateKind::Clause(ty::Clause::Trait(..))
+ | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
| ty::PredicateKind::Subtype(..)
| ty::PredicateKind::Coerce(..)
| ty::PredicateKind::WellFormed(..)
@@ -899,6 +936,7 @@ pub(crate) fn required_region_bounds<'tcx>(
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::ConstEquate(..)
| ty::PredicateKind::Ambiguous
+ | ty::PredicateKind::AliasEq(..)
| ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate(
ref t,