Auto merge of #109119 - lcnr:trait-system-cleanup, r=compiler-errors
a general type system cleanup removes the helper functions `traits::fully_solve_X` as they add more complexity then they are worth. It's confusing which of these helpers should be used in which context. changes the way we deal with overflow to always add depth in `evaluate_predicates_recursively`. It may make sense to actually fully transition to not have `recursion_depth` on obligations but that's probably a bit too much for this PR. also removes some other small - and imo unnecessary - helpers. r? types
This commit is contained in:
commit
9bdb4881c7
@ -24,6 +24,7 @@ use rustc_span::hygiene::DesugaringKind;
|
||||
use rustc_span::symbol::{kw, sym};
|
||||
use rustc_span::{BytePos, Span, Symbol};
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::ObligationCtxt;
|
||||
|
||||
use crate::borrow_set::TwoPhaseActivation;
|
||||
use crate::borrowck_errors;
|
||||
@ -760,20 +761,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
else { return; };
|
||||
// Try to find predicates on *generic params* that would allow copying `ty`
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let copy_did = infcx.tcx.require_lang_item(LangItem::Copy, Some(span));
|
||||
let cause = ObligationCause::new(
|
||||
span,
|
||||
self.mir_def_id(),
|
||||
rustc_infer::traits::ObligationCauseCode::MiscObligation,
|
||||
);
|
||||
let errors = rustc_trait_selection::traits::fully_solve_bound(
|
||||
&infcx,
|
||||
cause,
|
||||
self.param_env,
|
||||
// Erase any region vids from the type, which may not be resolved
|
||||
infcx.tcx.erase_regions(ty),
|
||||
copy_did,
|
||||
);
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
let copy_did = tcx.require_lang_item(LangItem::Copy, Some(span));
|
||||
let cause = ObligationCause::misc(span, self.mir_def_id());
|
||||
|
||||
ocx.register_bound(cause, self.param_env, infcx.tcx.erase_regions(ty), copy_did);
|
||||
let errors = ocx.select_all_or_error();
|
||||
|
||||
// Only emit suggestion if all required predicates are on generic
|
||||
let predicates: Result<Vec<_>, _> = errors
|
||||
|
@ -1078,7 +1078,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
self.param_env,
|
||||
tcx.mk_imm_ref(tcx.lifetimes.re_erased, tcx.erase_regions(ty)),
|
||||
def_id,
|
||||
DUMMY_SP,
|
||||
)
|
||||
}
|
||||
_ => false,
|
||||
|
@ -9,7 +9,7 @@ use rustc_middle::mir;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty};
|
||||
use rustc_trait_selection::traits::{
|
||||
self, ImplSource, Obligation, ObligationCause, SelectionContext,
|
||||
self, ImplSource, Obligation, ObligationCause, ObligationCtxt, SelectionContext,
|
||||
};
|
||||
|
||||
use super::ConstCx;
|
||||
@ -184,7 +184,10 @@ impl Qualif for NeedsNonConstDrop {
|
||||
}
|
||||
|
||||
// If we had any errors, then it's bad
|
||||
!traits::fully_solve_obligations(&infcx, impl_src.nested_obligations()).is_empty()
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
ocx.register_obligations(impl_src.nested_obligations());
|
||||
let errors = ocx.select_all_or_error();
|
||||
!errors.is_empty()
|
||||
}
|
||||
|
||||
fn in_adt_inherently<'tcx>(
|
||||
|
@ -59,6 +59,7 @@ fn equate_intrinsic_type<'tcx>(
|
||||
require_same_types(
|
||||
tcx,
|
||||
&cause,
|
||||
ty::ParamEnv::empty(), // FIXME: do all intrinsics have an empty param env?
|
||||
tcx.mk_fn_ptr(tcx.fn_sig(it.owner_id).subst_identity()),
|
||||
fty,
|
||||
);
|
||||
|
@ -11,13 +11,14 @@ use rustc_hir::ItemKind;
|
||||
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
||||
use rustc_infer::infer::{self, RegionResolutionError};
|
||||
use rustc_infer::infer::{DefineOpaqueTypes, TyCtxtInferExt};
|
||||
use rustc_infer::traits::Obligation;
|
||||
use rustc_middle::ty::adjustment::CoerceUnsizedInfo;
|
||||
use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
|
||||
use rustc_trait_selection::traits::misc::{
|
||||
type_allowed_to_implement_copy, CopyImplementationError, InfringingFieldsReason,
|
||||
};
|
||||
use rustc_trait_selection::traits::predicate_for_trait_def;
|
||||
use rustc_trait_selection::traits::ObligationCtxt;
|
||||
use rustc_trait_selection::traits::{self, ObligationCause};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
@ -334,19 +335,19 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
|
||||
))
|
||||
.emit();
|
||||
} else {
|
||||
let errors = traits::fully_solve_obligations(
|
||||
&infcx,
|
||||
coerced_fields.into_iter().map(|field| {
|
||||
predicate_for_trait_def(
|
||||
tcx,
|
||||
param_env,
|
||||
cause.clone(),
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
for field in coerced_fields {
|
||||
ocx.register_obligation(Obligation::new(
|
||||
tcx,
|
||||
cause.clone(),
|
||||
param_env,
|
||||
ty::Binder::dummy(tcx.mk_trait_ref(
|
||||
dispatch_from_dyn_trait,
|
||||
0,
|
||||
[field.ty(tcx, substs_a), field.ty(tcx, substs_b)],
|
||||
)
|
||||
}),
|
||||
);
|
||||
)),
|
||||
));
|
||||
}
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
infcx.err_ctxt().report_fulfillment_errors(&errors);
|
||||
}
|
||||
@ -580,10 +581,12 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
|
||||
};
|
||||
|
||||
// Register an obligation for `A: Trait<B>`.
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
let cause = traits::ObligationCause::misc(span, impl_did);
|
||||
let predicate =
|
||||
predicate_for_trait_def(tcx, param_env, cause, trait_def_id, 0, [source, target]);
|
||||
let errors = traits::fully_solve_obligation(&infcx, predicate);
|
||||
let obligation =
|
||||
Obligation::new(tcx, cause, param_env, tcx.mk_trait_ref(trait_def_id, [source, target]));
|
||||
ocx.register_obligation(obligation);
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
infcx.err_ctxt().report_fulfillment_errors(&errors);
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ use rustc_infer::traits::{ObligationCause, WellFormedLoc};
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::ty::{self, Region, TyCtxt, TypeFoldable, TypeFolder};
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_trait_selection::traits;
|
||||
use rustc_trait_selection::traits::{self, ObligationCtxt};
|
||||
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
*providers = Providers { diagnostic_hir_wf_check, ..*providers };
|
||||
@ -66,35 +66,35 @@ fn diagnostic_hir_wf_check<'tcx>(
|
||||
impl<'tcx> Visitor<'tcx> for HirWfCheck<'tcx> {
|
||||
fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
|
||||
let infcx = self.tcx.infer_ctxt().build();
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
|
||||
let tcx_ty = self.icx.to_ty(ty).fold_with(&mut EraseAllBoundRegions { tcx: self.tcx });
|
||||
let cause = traits::ObligationCause::new(
|
||||
ty.span,
|
||||
self.def_id,
|
||||
traits::ObligationCauseCode::WellFormed(None),
|
||||
);
|
||||
let errors = traits::fully_solve_obligation(
|
||||
&infcx,
|
||||
traits::Obligation::new(
|
||||
self.tcx,
|
||||
cause,
|
||||
self.param_env,
|
||||
ty::Binder::dummy(ty::PredicateKind::WellFormed(tcx_ty.into())),
|
||||
),
|
||||
);
|
||||
if !errors.is_empty() {
|
||||
debug!("Wf-check got errors for {:?}: {:?}", ty, errors);
|
||||
for error in errors {
|
||||
if error.obligation.predicate == self.predicate {
|
||||
// Save the cause from the greatest depth - this corresponds
|
||||
// to picking more-specific types (e.g. `MyStruct<u8>`)
|
||||
// over less-specific types (e.g. `Option<MyStruct<u8>>`)
|
||||
if self.depth >= self.cause_depth {
|
||||
self.cause = Some(error.obligation.cause);
|
||||
self.cause_depth = self.depth
|
||||
}
|
||||
|
||||
ocx.register_obligation(traits::Obligation::new(
|
||||
self.tcx,
|
||||
cause,
|
||||
self.param_env,
|
||||
ty::PredicateKind::WellFormed(tcx_ty.into()),
|
||||
));
|
||||
|
||||
for error in ocx.select_all_or_error() {
|
||||
debug!("Wf-check got error for {:?}: {:?}", ty, error);
|
||||
if error.obligation.predicate == self.predicate {
|
||||
// Save the cause from the greatest depth - this corresponds
|
||||
// to picking more-specific types (e.g. `MyStruct<u8>`)
|
||||
// over less-specific types (e.g. `Option<MyStruct<u8>>`)
|
||||
if self.depth >= self.cause_depth {
|
||||
self.cause = Some(error.obligation.cause);
|
||||
self.cause_depth = self.depth
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.depth += 1;
|
||||
intravisit::walk_ty(self, ty);
|
||||
self.depth -= 1;
|
||||
|
@ -102,7 +102,7 @@ use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::Node;
|
||||
use rustc_infer::infer::{DefineOpaqueTypes, InferOk, TyCtxtInferExt};
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_macros::fluent_messages;
|
||||
use rustc_middle::middle;
|
||||
use rustc_middle::ty::query::Providers;
|
||||
@ -113,7 +113,7 @@ use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
|
||||
use rustc_span::{symbol::sym, Span, DUMMY_SP};
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
|
||||
use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode};
|
||||
use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, ObligationCtxt};
|
||||
|
||||
use std::ops::Not;
|
||||
|
||||
@ -160,24 +160,21 @@ fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi
|
||||
fn require_same_types<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
expected: Ty<'tcx>,
|
||||
actual: Ty<'tcx>,
|
||||
) -> bool {
|
||||
) {
|
||||
let infcx = &tcx.infer_ctxt().build();
|
||||
let param_env = ty::ParamEnv::empty();
|
||||
let errors = match infcx.at(cause, param_env).eq(DefineOpaqueTypes::No, expected, actual) {
|
||||
Ok(InferOk { obligations, .. }) => traits::fully_solve_obligations(infcx, obligations),
|
||||
let ocx = ObligationCtxt::new(infcx);
|
||||
match ocx.eq(cause, param_env, expected, actual) {
|
||||
Ok(()) => {
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
infcx.err_ctxt().report_fulfillment_errors(&errors);
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
infcx.err_ctxt().report_mismatched_types(cause, expected, actual, err).emit();
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
match &errors[..] {
|
||||
[] => true,
|
||||
errors => {
|
||||
infcx.err_ctxt().report_fulfillment_errors(errors);
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -296,6 +293,8 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Main should have no WC, so empty param env is OK here.
|
||||
let param_env = ty::ParamEnv::empty();
|
||||
let expected_return_type;
|
||||
if let Some(term_did) = tcx.lang_items().termination() {
|
||||
let return_ty = main_fnsig.output();
|
||||
@ -306,8 +305,6 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
|
||||
}
|
||||
let return_ty = return_ty.skip_binder();
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
// Main should have no WC, so empty param env is OK here.
|
||||
let param_env = ty::ParamEnv::empty();
|
||||
let cause = traits::ObligationCause::new(
|
||||
return_ty_span,
|
||||
main_diagnostics_def_id,
|
||||
@ -343,6 +340,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
|
||||
main_diagnostics_def_id,
|
||||
ObligationCauseCode::MainFunctionType,
|
||||
),
|
||||
param_env,
|
||||
se_ty,
|
||||
tcx.mk_fn_ptr(main_fnsig),
|
||||
);
|
||||
@ -417,6 +415,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
|
||||
start_def_id,
|
||||
ObligationCauseCode::StartFunctionType,
|
||||
),
|
||||
ty::ParamEnv::empty(), // start should not have any where bounds.
|
||||
se_ty,
|
||||
tcx.mk_fn_ptr(tcx.fn_sig(start_def_id).subst_identity()),
|
||||
);
|
||||
|
@ -668,7 +668,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
if !self.maybe_suggest_bad_array_definition(&mut err, call_expr, callee_expr) {
|
||||
if let Some((maybe_def, output_ty, _)) = self.extract_callable_info(callee_ty)
|
||||
&& !self.type_is_sized_modulo_regions(self.param_env, output_ty, callee_expr.span)
|
||||
&& !self.type_is_sized_modulo_regions(self.param_env, output_ty)
|
||||
{
|
||||
let descr = match maybe_def {
|
||||
DefIdOrName::DefId(def_id) => self.tcx.def_descr(def_id),
|
||||
|
@ -96,7 +96,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let t = self.resolve_vars_if_possible(t);
|
||||
t.error_reported()?;
|
||||
|
||||
if self.type_is_sized_modulo_regions(self.param_env, t, span) {
|
||||
if self.type_is_sized_modulo_regions(self.param_env, t) {
|
||||
return Ok(Some(PointerKind::Thin));
|
||||
}
|
||||
|
||||
@ -722,7 +722,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||
|
||||
debug!("check_cast({}, {:?} as {:?})", self.expr.hir_id, self.expr_ty, self.cast_ty);
|
||||
|
||||
if !fcx.type_is_sized_modulo_regions(fcx.param_env, self.cast_ty, self.span)
|
||||
if !fcx.type_is_sized_modulo_regions(fcx.param_env, self.cast_ty)
|
||||
&& !self.cast_ty.has_infer_types()
|
||||
{
|
||||
self.report_cast_to_unsized_type(fcx);
|
||||
|
@ -46,7 +46,7 @@ use rustc_hir::Expr;
|
||||
use rustc_hir_analysis::astconv::AstConv;
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult};
|
||||
use rustc_infer::traits::Obligation;
|
||||
use rustc_infer::traits::{Obligation, PredicateObligation};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_middle::ty::adjustment::{
|
||||
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast,
|
||||
@ -597,13 +597,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||
// and almost never more than 3. By using a SmallVec we avoid an
|
||||
// allocation, at the (very small) cost of (occasionally) having to
|
||||
// shift subsequent elements down when removing the front element.
|
||||
let mut queue: SmallVec<[_; 4]> = smallvec![traits::predicate_for_trait_def(
|
||||
let mut queue: SmallVec<[PredicateObligation<'tcx>; 4]> = smallvec![Obligation::new(
|
||||
self.tcx,
|
||||
self.fcx.param_env,
|
||||
cause,
|
||||
coerce_unsized_did,
|
||||
0,
|
||||
[coerce_source, coerce_target]
|
||||
self.fcx.param_env,
|
||||
self.tcx.mk_trait_ref(coerce_unsized_did, [coerce_source, coerce_target])
|
||||
)];
|
||||
|
||||
let mut has_unsized_tuple_coercion = false;
|
||||
@ -651,9 +649,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||
let self_ty = trait_pred.skip_binder().self_ty();
|
||||
let unsize_ty = trait_pred.skip_binder().trait_ref.substs[1].expect_ty();
|
||||
debug!("coerce_unsized: ambiguous unsize case for {:?}", trait_pred);
|
||||
match (&self_ty.kind(), &unsize_ty.kind()) {
|
||||
(ty::Infer(ty::TyVar(v)), ty::Dynamic(..))
|
||||
if self.type_var_is_sized(*v) =>
|
||||
match (self_ty.kind(), unsize_ty.kind()) {
|
||||
(&ty::Infer(ty::TyVar(v)), ty::Dynamic(..))
|
||||
if self.type_var_is_sized(v) =>
|
||||
{
|
||||
debug!("coerce_unsized: have sized infer {:?}", v);
|
||||
coercion.obligations.push(obligation);
|
||||
|
@ -1480,7 +1480,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
// For this suggestion to make sense, the type would need to be `Copy`,
|
||||
// or we have to be moving out of a `Box<T>`
|
||||
if self.type_is_copy_modulo_regions(self.param_env, expected, sp)
|
||||
if self.type_is_copy_modulo_regions(self.param_env, expected)
|
||||
// FIXME(compiler-errors): We can actually do this if the checked_ty is
|
||||
// `steps` layers of boxes, not just one, but this is easier and most likely.
|
||||
|| (checked_ty.is_box() && steps == 1)
|
||||
|
@ -867,10 +867,7 @@ fn copy_or_move<'a, 'tcx>(
|
||||
mc: &mc::MemCategorizationContext<'a, 'tcx>,
|
||||
place_with_id: &PlaceWithHirId<'tcx>,
|
||||
) -> ConsumeMode {
|
||||
if !mc.type_is_copy_modulo_regions(
|
||||
place_with_id.place.ty(),
|
||||
mc.tcx().hir().span(place_with_id.hir_id),
|
||||
) {
|
||||
if !mc.type_is_copy_modulo_regions(place_with_id.place.ty()) {
|
||||
ConsumeMode::Move
|
||||
} else {
|
||||
ConsumeMode::Copy
|
||||
|
@ -1011,11 +1011,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let mut suggest_copied_or_cloned = || {
|
||||
let expr_inner_ty = substs.type_at(0);
|
||||
let expected_inner_ty = expected_substs.type_at(0);
|
||||
if let ty::Ref(_, ty, hir::Mutability::Not) = expr_inner_ty.kind()
|
||||
&& self.can_eq(self.param_env, *ty, expected_inner_ty)
|
||||
if let &ty::Ref(_, ty, hir::Mutability::Not) = expr_inner_ty.kind()
|
||||
&& self.can_eq(self.param_env, ty, expected_inner_ty)
|
||||
{
|
||||
let def_path = self.tcx.def_path_str(adt_def.did());
|
||||
if self.type_is_copy_modulo_regions(self.param_env, *ty, expr.span) {
|
||||
if self.type_is_copy_modulo_regions(self.param_env, ty) {
|
||||
diag.span_suggestion_verbose(
|
||||
expr.span.shrink_to_hi(),
|
||||
format!(
|
||||
@ -1029,9 +1029,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
&& rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions(
|
||||
self,
|
||||
self.param_env,
|
||||
*ty,
|
||||
ty,
|
||||
clone_did,
|
||||
expr.span
|
||||
)
|
||||
{
|
||||
diag.span_suggestion_verbose(
|
||||
|
@ -120,8 +120,8 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
|
||||
self.infcx.tcx
|
||||
}
|
||||
|
||||
pub(crate) fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>, span: Span) -> bool {
|
||||
self.infcx.type_is_copy_modulo_regions(self.param_env, ty, span)
|
||||
pub(crate) fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>) -> bool {
|
||||
self.infcx.type_is_copy_modulo_regions(self.param_env, ty)
|
||||
}
|
||||
|
||||
fn resolve_vars_if_possible<T>(&self, value: T) -> T
|
||||
|
@ -21,7 +21,7 @@ use rustc_span::symbol::{sym, Ident};
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt as _;
|
||||
use rustc_trait_selection::traits::{self, FulfillmentError};
|
||||
use rustc_trait_selection::traits::{self, FulfillmentError, ObligationCtxt};
|
||||
use rustc_type_ir::sty::TyKind::*;
|
||||
|
||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
@ -434,7 +434,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
if self.type_is_copy_modulo_regions(
|
||||
self.param_env,
|
||||
*lhs_deref_ty,
|
||||
lhs_expr.span,
|
||||
) {
|
||||
suggest_deref_binop(*lhs_deref_ty);
|
||||
}
|
||||
@ -776,7 +775,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
(None, Some(trait_did)) => {
|
||||
let (obligation, _) =
|
||||
self.obligation_for_method(cause, trait_did, lhs_ty, Some(input_types));
|
||||
Err(rustc_trait_selection::traits::fully_solve_obligation(self, obligation))
|
||||
// FIXME: This should potentially just add the obligation to the `FnCtxt`
|
||||
let ocx = ObligationCtxt::new(&self.infcx);
|
||||
ocx.register_obligation(obligation);
|
||||
Err(ocx.select_all_or_error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -424,7 +424,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// closures. We want to make sure any adjustment that might make us move the place into
|
||||
// the closure gets handled.
|
||||
let (place, capture_kind) =
|
||||
restrict_precision_for_drop_types(self, place, capture_kind, usage_span);
|
||||
restrict_precision_for_drop_types(self, place, capture_kind);
|
||||
|
||||
capture_info.capture_kind = capture_kind;
|
||||
(place, capture_info)
|
||||
@ -1822,9 +1822,8 @@ fn restrict_precision_for_drop_types<'a, 'tcx>(
|
||||
fcx: &'a FnCtxt<'a, 'tcx>,
|
||||
mut place: Place<'tcx>,
|
||||
mut curr_mode: ty::UpvarCapture,
|
||||
span: Span,
|
||||
) -> (Place<'tcx>, ty::UpvarCapture) {
|
||||
let is_copy_type = fcx.infcx.type_is_copy_modulo_regions(fcx.param_env, place.ty(), span);
|
||||
let is_copy_type = fcx.infcx.type_is_copy_modulo_regions(fcx.param_env, place.ty());
|
||||
|
||||
if let (false, UpvarCapture::ByValue) = (is_copy_type, curr_mode) {
|
||||
for i in 0..place.projections.len() {
|
||||
|
@ -8,6 +8,8 @@ mod project;
|
||||
mod structural_impls;
|
||||
pub mod util;
|
||||
|
||||
use std::cmp;
|
||||
|
||||
use hir::def_id::LocalDefId;
|
||||
use rustc_hir as hir;
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
@ -139,6 +141,14 @@ impl<'tcx, O> Obligation<'tcx, O> {
|
||||
Self::with_depth(tcx, cause, 0, param_env, predicate)
|
||||
}
|
||||
|
||||
/// We often create nested obligations without setting the correct depth.
|
||||
///
|
||||
/// To deal with this evaluate and fulfill explicitly update the depth
|
||||
/// of nested obligations using this function.
|
||||
pub fn set_depth_from_parent(&mut self, parent_depth: usize) {
|
||||
self.recursion_depth = cmp::max(parent_depth + 1, self.recursion_depth);
|
||||
}
|
||||
|
||||
pub fn with_depth(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
cause: ObligationCause<'tcx>,
|
||||
|
@ -11,6 +11,7 @@ use rustc_hir as hir;
|
||||
use rustc_infer::{infer::TyCtxtInferExt, traits::ObligationCause};
|
||||
use rustc_middle::ty::{self, List};
|
||||
use rustc_span::{sym, Span};
|
||||
use rustc_trait_selection::traits::ObligationCtxt;
|
||||
|
||||
declare_lint! {
|
||||
/// The `for_loops_over_fallibles` lint checks for `for` loops over `Option` or `Result` values.
|
||||
@ -136,20 +137,22 @@ fn suggest_question_mark<'tcx>(
|
||||
|
||||
let ty = substs.type_at(0);
|
||||
let infcx = cx.tcx.infer_ctxt().build();
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
|
||||
let body_def_id = cx.tcx.hir().body_owner_def_id(body_id);
|
||||
let cause = ObligationCause::new(
|
||||
span,
|
||||
body_def_id,
|
||||
rustc_infer::traits::ObligationCauseCode::MiscObligation,
|
||||
);
|
||||
let errors = rustc_trait_selection::traits::fully_solve_bound(
|
||||
&infcx,
|
||||
|
||||
ocx.register_bound(
|
||||
cause,
|
||||
ty::ParamEnv::empty(),
|
||||
cx.param_env,
|
||||
// Erase any region vids from the type, which may not be resolved
|
||||
infcx.tcx.erase_regions(ty),
|
||||
into_iterator_did,
|
||||
);
|
||||
|
||||
errors.is_empty()
|
||||
ocx.select_all_or_error().is_empty()
|
||||
}
|
||||
|
@ -1128,6 +1128,13 @@ impl<'tcx, T> ToPredicate<'tcx, T> for T {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx> for PredicateKind<'tcx> {
|
||||
#[inline(always)]
|
||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
||||
ty::Binder::dummy(self).to_predicate(tcx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> {
|
||||
#[inline(always)]
|
||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
||||
@ -1142,6 +1149,13 @@ impl<'tcx> ToPredicate<'tcx> for Clause<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> {
|
||||
#[inline(always)]
|
||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
||||
ty::Binder::dummy(self).to_predicate(tcx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> {
|
||||
#[inline(always)]
|
||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
||||
|
@ -5,7 +5,7 @@ use crate::build::Builder;
|
||||
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
|
||||
impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
@ -66,7 +66,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
pub(crate) fn consume_by_copy_or_move(&self, place: Place<'tcx>) -> Operand<'tcx> {
|
||||
let tcx = self.tcx;
|
||||
let ty = place.ty(&self.local_decls, tcx).ty;
|
||||
if !self.infcx.type_is_copy_modulo_regions(self.param_env, ty, DUMMY_SP) {
|
||||
if !self.infcx.type_is_copy_modulo_regions(self.param_env, ty) {
|
||||
Operand::Move(place)
|
||||
} else {
|
||||
Operand::Copy(place)
|
||||
|
@ -1,14 +1,14 @@
|
||||
use rustc_hir as hir;
|
||||
use rustc_index::vec::Idx;
|
||||
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
|
||||
use rustc_infer::traits::Obligation;
|
||||
use rustc_middle::mir::{self, Field};
|
||||
use rustc_middle::thir::{FieldPat, Pat, PatKind};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_session::lint;
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::traits::predicate_for_trait_def;
|
||||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::{self, ObligationCause, PredicateObligation};
|
||||
use rustc_trait_selection::traits::{self, ObligationCause};
|
||||
|
||||
use std::cell::Cell;
|
||||
|
||||
@ -189,17 +189,15 @@ impl<'tcx> ConstToPat<'tcx> {
|
||||
// using `PartialEq::eq` in this scenario in the past.)
|
||||
let partial_eq_trait_id =
|
||||
self.tcx().require_lang_item(hir::LangItem::PartialEq, Some(self.span));
|
||||
let obligation: PredicateObligation<'_> = predicate_for_trait_def(
|
||||
let partial_eq_obligation = Obligation::new(
|
||||
self.tcx(),
|
||||
ObligationCause::dummy(),
|
||||
self.param_env,
|
||||
ObligationCause::misc(self.span, self.id.owner.def_id),
|
||||
partial_eq_trait_id,
|
||||
0,
|
||||
[ty, ty],
|
||||
self.tcx().mk_trait_ref(partial_eq_trait_id, [ty, ty]),
|
||||
);
|
||||
// FIXME: should this call a `predicate_must_hold` variant instead?
|
||||
|
||||
let has_impl = self.infcx.predicate_may_hold(&obligation);
|
||||
// FIXME: should this call a `predicate_must_hold` variant instead?
|
||||
let has_impl = self.infcx.predicate_may_hold(&partial_eq_obligation);
|
||||
|
||||
// Note: To fix rust-lang/rust#65466, we could just remove this type
|
||||
// walk hack for function pointers, and unconditionally error
|
||||
|
@ -8,26 +8,16 @@ use rustc_middle::infer::canonical::{Canonical, CanonicalQueryResponse, QueryRes
|
||||
use rustc_middle::traits::query::Fallible;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
|
||||
use rustc_middle::ty::{GenericArg, ToPredicate};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_span::DUMMY_SP;
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
pub use rustc_infer::infer::*;
|
||||
|
||||
pub trait InferCtxtExt<'tcx> {
|
||||
fn type_is_copy_modulo_regions(
|
||||
&self,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
) -> bool;
|
||||
fn type_is_copy_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool;
|
||||
|
||||
fn type_is_sized_modulo_regions(
|
||||
&self,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
) -> bool;
|
||||
fn type_is_sized_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool;
|
||||
|
||||
/// Check whether a `ty` implements given trait(trait_def_id).
|
||||
/// The inputs are:
|
||||
@ -46,13 +36,9 @@ pub trait InferCtxtExt<'tcx> {
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> traits::EvaluationResult;
|
||||
}
|
||||
|
||||
impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
|
||||
fn type_is_copy_modulo_regions(
|
||||
&self,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
) -> bool {
|
||||
fn type_is_copy_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool {
|
||||
let ty = self.resolve_vars_if_possible(ty);
|
||||
|
||||
if !(param_env, ty).needs_infer() {
|
||||
@ -65,17 +51,12 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
|
||||
// rightly refuses to work with inference variables, but
|
||||
// moves_by_default has a cache, which we want to use in other
|
||||
// cases.
|
||||
traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id, span)
|
||||
traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id)
|
||||
}
|
||||
|
||||
fn type_is_sized_modulo_regions(
|
||||
&self,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
) -> bool {
|
||||
fn type_is_sized_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool {
|
||||
let lang_item = self.tcx.require_lang_item(LangItem::Sized, None);
|
||||
traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, lang_item, span)
|
||||
traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, lang_item)
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self, params), ret)]
|
||||
|
@ -180,8 +180,9 @@ impl<'tcx> AutoTraitFinder<'tcx> {
|
||||
// At this point, we already have all of the bounds we need. FulfillmentContext is used
|
||||
// to store all of the necessary region/lifetime bounds in the InferContext, as well as
|
||||
// an additional sanity check.
|
||||
let errors =
|
||||
super::fully_solve_bound(&infcx, ObligationCause::dummy(), full_env, ty, trait_did);
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
ocx.register_bound(ObligationCause::dummy(), full_env, ty, trait_did);
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
panic!("Unable to fulfill trait {:?} for '{:?}': {:?}", trait_did, ty, errors);
|
||||
}
|
||||
|
@ -383,7 +383,10 @@ fn resolve_negative_obligation<'tcx>(
|
||||
};
|
||||
|
||||
let param_env = o.param_env;
|
||||
if !super::fully_solve_obligation(&infcx, o).is_empty() {
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
ocx.register_obligation(o);
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ use rustc_middle::ty::fold::TypeFoldable;
|
||||
use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
|
||||
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeSuperVisitable};
|
||||
use rustc_middle::ty::{InternalSubsts, SubstsRef};
|
||||
use rustc_span::def_id::{DefId, CRATE_DEF_ID};
|
||||
use rustc_span::def_id::DefId;
|
||||
use rustc_span::Span;
|
||||
|
||||
use std::fmt::Debug;
|
||||
@ -63,9 +63,7 @@ pub use self::util::{
|
||||
elaborate_trait_ref, elaborate_trait_refs,
|
||||
};
|
||||
pub use self::util::{expand_trait_aliases, TraitAliasExpander};
|
||||
pub use self::util::{
|
||||
get_vtable_index_of_object_method, impl_item_is_final, predicate_for_trait_def, upcast_choices,
|
||||
};
|
||||
pub use self::util::{get_vtable_index_of_object_method, impl_item_is_final, upcast_choices};
|
||||
pub use self::util::{
|
||||
supertrait_def_ids, supertraits, transitive_bounds, transitive_bounds_that_define_assoc_type,
|
||||
SupertraitDefIds, Supertraits,
|
||||
@ -131,29 +129,23 @@ pub fn type_known_to_meet_bound_modulo_regions<'tcx>(
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
def_id: DefId,
|
||||
span: Span,
|
||||
) -> bool {
|
||||
let trait_ref = ty::Binder::dummy(infcx.tcx.mk_trait_ref(def_id, [ty]));
|
||||
pred_known_to_hold_modulo_regions(infcx, param_env, trait_ref.without_const(), span)
|
||||
pred_known_to_hold_modulo_regions(infcx, param_env, trait_ref.without_const())
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(infcx, param_env, span, pred), ret)]
|
||||
/// FIXME(@lcnr): this function doesn't seem right and shouldn't exist?
|
||||
///
|
||||
/// Ping me on zulip if you want to use this method and need help with finding
|
||||
/// an appropriate replacement.
|
||||
#[instrument(level = "debug", skip(infcx, param_env, pred), ret)]
|
||||
fn pred_known_to_hold_modulo_regions<'tcx>(
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
pred: impl ToPredicate<'tcx> + TypeVisitable<TyCtxt<'tcx>>,
|
||||
span: Span,
|
||||
) -> bool {
|
||||
let has_non_region_infer = pred.has_non_region_infer();
|
||||
let obligation = Obligation {
|
||||
param_env,
|
||||
// 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, CRATE_DEF_ID),
|
||||
recursion_depth: 0,
|
||||
predicate: pred.to_predicate(infcx.tcx),
|
||||
};
|
||||
let obligation = Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, pred);
|
||||
|
||||
let result = infcx.evaluate_obligation_no_overflow(&obligation);
|
||||
debug!(?result);
|
||||
@ -166,14 +158,13 @@ fn pred_known_to_hold_modulo_regions<'tcx>(
|
||||
// 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);
|
||||
|
||||
match &errors[..] {
|
||||
let ocx = ObligationCtxt::new(infcx);
|
||||
ocx.register_obligation(obligation);
|
||||
let errors = ocx.select_all_or_error();
|
||||
match errors.as_slice() {
|
||||
[] => true,
|
||||
errors => {
|
||||
debug!(?errors);
|
||||
@ -389,43 +380,6 @@ where
|
||||
Ok(resolved_value)
|
||||
}
|
||||
|
||||
/// Process an obligation (and any nested obligations that come from it) to
|
||||
/// completion, returning any errors
|
||||
pub fn fully_solve_obligation<'tcx>(
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
obligation: PredicateObligation<'tcx>,
|
||||
) -> Vec<FulfillmentError<'tcx>> {
|
||||
fully_solve_obligations(infcx, [obligation])
|
||||
}
|
||||
|
||||
/// Process a set of obligations (and any nested obligations that come from them)
|
||||
/// to completion
|
||||
pub fn fully_solve_obligations<'tcx>(
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
obligations: impl IntoIterator<Item = PredicateObligation<'tcx>>,
|
||||
) -> Vec<FulfillmentError<'tcx>> {
|
||||
let ocx = ObligationCtxt::new(infcx);
|
||||
ocx.register_obligations(obligations);
|
||||
ocx.select_all_or_error()
|
||||
}
|
||||
|
||||
/// Process a bound (and any nested obligations that come from it) to completion.
|
||||
/// This is a convenience function for traits that have no generic arguments, such
|
||||
/// as auto traits, and builtin traits like Copy or Sized.
|
||||
pub fn fully_solve_bound<'tcx>(
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
cause: ObligationCause<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
bound: DefId,
|
||||
) -> Vec<FulfillmentError<'tcx>> {
|
||||
let tcx = infcx.tcx;
|
||||
let trait_ref = tcx.mk_trait_ref(bound, [ty]);
|
||||
let obligation = Obligation::new(tcx, cause, param_env, ty::Binder::dummy(trait_ref));
|
||||
|
||||
fully_solve_obligation(infcx, obligation)
|
||||
}
|
||||
|
||||
/// Normalizes the predicates and checks whether they hold in an empty environment. If this
|
||||
/// returns true, then either normalize encountered an error or one of the predicates did not
|
||||
/// hold. Used when creating vtables to check for unsatisfiable methods.
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::infer::InferCtxt;
|
||||
use crate::traits::query::type_op::{self, TypeOp, TypeOpOutput};
|
||||
use crate::traits::query::NoSolution;
|
||||
use crate::traits::ObligationCause;
|
||||
use crate::traits::{ObligationCause, ObligationCtxt};
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_middle::ty::{self, ParamEnv, Ty};
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
@ -71,22 +71,23 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> {
|
||||
|
||||
if let Some(constraints) = constraints {
|
||||
debug!(?constraints);
|
||||
// Instantiation may have produced new inference variables and constraints on those
|
||||
// variables. Process these constraints.
|
||||
let cause = ObligationCause::misc(span, body_id);
|
||||
let errors = super::fully_solve_obligations(
|
||||
self,
|
||||
constraints.outlives.iter().map(|constraint| {
|
||||
self.query_outlives_constraint_to_obligation(
|
||||
*constraint,
|
||||
cause.clone(),
|
||||
param_env,
|
||||
)
|
||||
}),
|
||||
);
|
||||
if !constraints.member_constraints.is_empty() {
|
||||
span_bug!(span, "{:#?}", constraints.member_constraints);
|
||||
}
|
||||
|
||||
// Instantiation may have produced new inference variables and constraints on those
|
||||
// variables. Process these constraints.
|
||||
let ocx = ObligationCtxt::new(self);
|
||||
let cause = ObligationCause::misc(span, body_id);
|
||||
for &constraint in &constraints.outlives {
|
||||
ocx.register_obligation(self.query_outlives_constraint_to_obligation(
|
||||
constraint,
|
||||
cause.clone(),
|
||||
param_env,
|
||||
));
|
||||
}
|
||||
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
self.tcx.sess.delay_span_bug(
|
||||
span,
|
||||
|
@ -1,8 +1,8 @@
|
||||
use crate::infer::canonical::query_response;
|
||||
use crate::infer::{InferCtxt, InferOk};
|
||||
use crate::traits;
|
||||
use crate::traits::query::type_op::TypeOpOutput;
|
||||
use crate::traits::query::Fallible;
|
||||
use crate::traits::ObligationCtxt;
|
||||
use rustc_infer::infer::region_constraints::RegionConstraintData;
|
||||
use rustc_span::source_map::DUMMY_SP;
|
||||
|
||||
@ -73,7 +73,9 @@ pub fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>(
|
||||
);
|
||||
|
||||
let InferOk { value, obligations } = infcx.commit_if_ok(|_| op())?;
|
||||
let errors = traits::fully_solve_obligations(infcx, obligations);
|
||||
let ocx = ObligationCtxt::new(infcx);
|
||||
ocx.register_obligations(obligations);
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
infcx.tcx.sess.diagnostic().delay_span_bug(
|
||||
DUMMY_SP,
|
||||
@ -82,9 +84,7 @@ pub fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>(
|
||||
}
|
||||
|
||||
let region_obligations = infcx.take_registered_region_obligations();
|
||||
|
||||
let region_constraint_data = infcx.take_and_reset_region_constraints();
|
||||
|
||||
let region_constraints = query_response::make_query_region_constraints(
|
||||
infcx.tcx,
|
||||
region_obligations
|
||||
|
@ -18,7 +18,7 @@ use rustc_session::config::TraitSolver;
|
||||
use rustc_span::def_id::DefId;
|
||||
|
||||
use crate::traits::project::{normalize_with_depth, normalize_with_depth_to};
|
||||
use crate::traits::util::{self, closure_trait_ref_and_return_type, predicate_for_trait_def};
|
||||
use crate::traits::util::{self, closure_trait_ref_and_return_type};
|
||||
use crate::traits::vtable::{
|
||||
count_own_vtable_entries, prepare_vtable_segments, vtable_trait_first_method_offset,
|
||||
VtblSegment,
|
||||
@ -253,15 +253,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
};
|
||||
|
||||
let cause = obligation.derived_cause(BuiltinDerivedObligation);
|
||||
ensure_sufficient_stack(|| {
|
||||
self.collect_predicates_for_types(
|
||||
obligation.param_env,
|
||||
cause,
|
||||
obligation.recursion_depth + 1,
|
||||
trait_def,
|
||||
nested,
|
||||
)
|
||||
})
|
||||
self.collect_predicates_for_types(
|
||||
obligation.param_env,
|
||||
cause,
|
||||
obligation.recursion_depth + 1,
|
||||
trait_def,
|
||||
nested,
|
||||
)
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
@ -1118,14 +1116,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
nested.extend(obligations);
|
||||
|
||||
// Construct the nested `TailField<T>: Unsize<TailField<U>>` predicate.
|
||||
nested.push(predicate_for_trait_def(
|
||||
let tail_unsize_obligation = obligation.with(
|
||||
tcx,
|
||||
obligation.param_env,
|
||||
obligation.cause.clone(),
|
||||
obligation.predicate.def_id(),
|
||||
obligation.recursion_depth + 1,
|
||||
[source_tail, target_tail],
|
||||
));
|
||||
tcx.mk_trait_ref(obligation.predicate.def_id(), [source_tail, target_tail]),
|
||||
);
|
||||
nested.push(tail_unsize_obligation);
|
||||
}
|
||||
|
||||
// `(.., T)` -> `(.., U)`
|
||||
@ -1147,17 +1142,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
.map_err(|_| Unimplemented)?;
|
||||
nested.extend(obligations);
|
||||
|
||||
// Construct the nested `T: Unsize<U>` predicate.
|
||||
nested.push(ensure_sufficient_stack(|| {
|
||||
predicate_for_trait_def(
|
||||
tcx,
|
||||
obligation.param_env,
|
||||
obligation.cause.clone(),
|
||||
obligation.predicate.def_id(),
|
||||
obligation.recursion_depth + 1,
|
||||
[a_last, b_last],
|
||||
)
|
||||
}));
|
||||
// Add a nested `T: Unsize<U>` predicate.
|
||||
let last_unsize_obligation = obligation
|
||||
.with(tcx, tcx.mk_trait_ref(obligation.predicate.def_id(), [a_last, b_last]));
|
||||
nested.push(last_unsize_obligation);
|
||||
}
|
||||
|
||||
_ => bug!("source: {source}, target: {target}"),
|
||||
|
@ -17,7 +17,7 @@ use super::project;
|
||||
use super::project::normalize_with_depth_to;
|
||||
use super::project::ProjectionTyObligation;
|
||||
use super::util;
|
||||
use super::util::{closure_trait_ref_and_return_type, predicate_for_trait_def};
|
||||
use super::util::closure_trait_ref_and_return_type;
|
||||
use super::wf;
|
||||
use super::{
|
||||
ErrorReporting, ImplDerivedObligation, ImplDerivedObligationCause, Normalized, Obligation,
|
||||
@ -595,7 +595,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
self.evaluate_predicates_recursively_in_new_solver(predicates)
|
||||
} else {
|
||||
let mut result = EvaluatedToOk;
|
||||
for obligation in predicates {
|
||||
for mut obligation in predicates {
|
||||
obligation.set_depth_from_parent(stack.depth());
|
||||
let eval = self.evaluate_predicate_recursively(stack, obligation.clone())?;
|
||||
if let EvaluatedToErr = eval {
|
||||
// fast-path - EvaluatedToErr is the top of the lattice,
|
||||
@ -661,12 +662,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
let p = bound_predicate.rebind(p);
|
||||
// Does this code ever run?
|
||||
match self.infcx.subtype_predicate(&obligation.cause, obligation.param_env, p) {
|
||||
Ok(Ok(InferOk { mut obligations, .. })) => {
|
||||
self.add_depth(obligations.iter_mut(), obligation.recursion_depth);
|
||||
self.evaluate_predicates_recursively(
|
||||
previous_stack,
|
||||
obligations.into_iter(),
|
||||
)
|
||||
Ok(Ok(InferOk { obligations, .. })) => {
|
||||
self.evaluate_predicates_recursively(previous_stack, obligations)
|
||||
}
|
||||
Ok(Err(_)) => Ok(EvaluatedToErr),
|
||||
Err(..) => Ok(EvaluatedToAmbig),
|
||||
@ -677,12 +674,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
let p = bound_predicate.rebind(p);
|
||||
// Does this code ever run?
|
||||
match self.infcx.coerce_predicate(&obligation.cause, obligation.param_env, p) {
|
||||
Ok(Ok(InferOk { mut obligations, .. })) => {
|
||||
self.add_depth(obligations.iter_mut(), obligation.recursion_depth);
|
||||
self.evaluate_predicates_recursively(
|
||||
previous_stack,
|
||||
obligations.into_iter(),
|
||||
)
|
||||
Ok(Ok(InferOk { obligations, .. })) => {
|
||||
self.evaluate_predicates_recursively(previous_stack, obligations)
|
||||
}
|
||||
Ok(Err(_)) => Ok(EvaluatedToErr),
|
||||
Err(..) => Ok(EvaluatedToAmbig),
|
||||
@ -755,9 +748,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
arg,
|
||||
obligation.cause.span,
|
||||
) {
|
||||
Some(mut obligations) => {
|
||||
self.add_depth(obligations.iter_mut(), obligation.recursion_depth);
|
||||
|
||||
Some(obligations) => {
|
||||
cache.wf_args.borrow_mut().push((arg, previous_stack.depth()));
|
||||
let result =
|
||||
self.evaluate_predicates_recursively(previous_stack, obligations);
|
||||
@ -826,10 +817,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
self.add_depth(
|
||||
subobligations.iter_mut(),
|
||||
obligation.recursion_depth,
|
||||
);
|
||||
// Need to explicitly set the depth of nested goals here as
|
||||
// projection obligations can cycle by themselves and in
|
||||
// `evaluate_predicates_recursively` we only add the depth
|
||||
// for parent trait goals because only these get added to the
|
||||
// `TraitObligationStackList`.
|
||||
for subobligation in subobligations.iter_mut() {
|
||||
subobligation.set_depth_from_parent(obligation.recursion_depth);
|
||||
}
|
||||
let res = self.evaluate_predicates_recursively(
|
||||
previous_stack,
|
||||
subobligations,
|
||||
@ -909,38 +904,28 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
if a.def.did == b.def.did
|
||||
&& tcx.def_kind(a.def.did) == DefKind::AssocConst =>
|
||||
{
|
||||
if let Ok(new_obligations) = self
|
||||
if let Ok(InferOk { obligations, value: () }) = self
|
||||
.infcx
|
||||
.at(&obligation.cause, obligation.param_env)
|
||||
.trace(c1, c2)
|
||||
.eq(DefineOpaqueTypes::No, a.substs, b.substs)
|
||||
{
|
||||
let mut obligations = new_obligations.obligations;
|
||||
self.add_depth(
|
||||
obligations.iter_mut(),
|
||||
obligation.recursion_depth,
|
||||
);
|
||||
return self.evaluate_predicates_recursively(
|
||||
previous_stack,
|
||||
obligations.into_iter(),
|
||||
obligations,
|
||||
);
|
||||
}
|
||||
}
|
||||
(_, Unevaluated(_)) | (Unevaluated(_), _) => (),
|
||||
(_, _) => {
|
||||
if let Ok(new_obligations) = self
|
||||
if let Ok(InferOk { obligations, value: () }) = self
|
||||
.infcx
|
||||
.at(&obligation.cause, obligation.param_env)
|
||||
.eq(DefineOpaqueTypes::No, c1, c2)
|
||||
{
|
||||
let mut obligations = new_obligations.obligations;
|
||||
self.add_depth(
|
||||
obligations.iter_mut(),
|
||||
obligation.recursion_depth,
|
||||
);
|
||||
return self.evaluate_predicates_recursively(
|
||||
previous_stack,
|
||||
obligations.into_iter(),
|
||||
obligations,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1366,24 +1351,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
self.infcx.evaluation_cache.insert((param_env, trait_pred), dep_node, result);
|
||||
}
|
||||
|
||||
/// For various reasons, it's possible for a subobligation
|
||||
/// to have a *lower* recursion_depth than the obligation used to create it.
|
||||
/// Projection sub-obligations may be returned from the projection cache,
|
||||
/// which results in obligations with an 'old' `recursion_depth`.
|
||||
/// Additionally, methods like `InferCtxt.subtype_predicate` produce
|
||||
/// subobligations without taking in a 'parent' depth, causing the
|
||||
/// generated subobligations to have a `recursion_depth` of `0`.
|
||||
///
|
||||
/// To ensure that obligation_depth never decreases, we force all subobligations
|
||||
/// to have at least the depth of the original obligation.
|
||||
fn add_depth<T: 'cx, I: Iterator<Item = &'cx mut Obligation<'tcx, T>>>(
|
||||
&self,
|
||||
it: I,
|
||||
min_depth: usize,
|
||||
) {
|
||||
it.for_each(|o| o.recursion_depth = cmp::max(min_depth, o.recursion_depth) + 1);
|
||||
}
|
||||
|
||||
fn check_recursion_depth<T>(
|
||||
&self,
|
||||
depth: usize,
|
||||
@ -2440,15 +2407,14 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
||||
placeholder_ty,
|
||||
)
|
||||
});
|
||||
let placeholder_obligation = predicate_for_trait_def(
|
||||
|
||||
let obligation = Obligation::new(
|
||||
self.tcx(),
|
||||
param_env,
|
||||
cause.clone(),
|
||||
trait_def_id,
|
||||
recursion_depth,
|
||||
[normalized_ty],
|
||||
param_env,
|
||||
self.tcx().mk_trait_ref(trait_def_id, [normalized_ty]),
|
||||
);
|
||||
obligations.push(placeholder_obligation);
|
||||
obligations.push(obligation);
|
||||
obligations
|
||||
})
|
||||
.collect()
|
||||
|
@ -1,11 +1,11 @@
|
||||
use super::NormalizeExt;
|
||||
use super::{Obligation, ObligationCause, PredicateObligation, SelectionContext};
|
||||
use super::{ObligationCause, PredicateObligation, SelectionContext};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::Diagnostic;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_infer::infer::InferOk;
|
||||
use rustc_middle::ty::SubstsRef;
|
||||
use rustc_middle::ty::{self, ImplSubject, ToPredicate, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_middle::ty::{GenericArg, SubstsRef};
|
||||
use rustc_span::Span;
|
||||
use smallvec::SmallVec;
|
||||
|
||||
@ -218,33 +218,6 @@ pub fn impl_subject_and_oblig<'a, 'tcx>(
|
||||
(subject, impl_obligations)
|
||||
}
|
||||
|
||||
pub fn predicate_for_trait_ref<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
cause: ObligationCause<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
trait_ref: ty::TraitRef<'tcx>,
|
||||
recursion_depth: usize,
|
||||
) -> PredicateObligation<'tcx> {
|
||||
Obligation {
|
||||
cause,
|
||||
param_env,
|
||||
recursion_depth,
|
||||
predicate: ty::Binder::dummy(trait_ref).without_const().to_predicate(tcx),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn predicate_for_trait_def<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
cause: ObligationCause<'tcx>,
|
||||
trait_def_id: DefId,
|
||||
recursion_depth: usize,
|
||||
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)
|
||||
}
|
||||
|
||||
/// Casts a trait reference into a reference to one of its super
|
||||
/// traits; returns `None` if `target_trait_def_id` is not a
|
||||
/// supertrait.
|
||||
|
@ -3,7 +3,6 @@
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_span::DUMMY_SP;
|
||||
use rustc_trait_selection::traits;
|
||||
|
||||
fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
|
||||
@ -30,7 +29,7 @@ fn is_item_raw<'tcx>(
|
||||
let (param_env, ty) = query.into_parts();
|
||||
let trait_def_id = tcx.require_lang_item(item, None);
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
traits::type_known_to_meet_bound_modulo_regions(&infcx, param_env, ty, trait_def_id, DUMMY_SP)
|
||||
traits::type_known_to_meet_bound_modulo_regions(&infcx, param_env, ty, trait_def_id)
|
||||
}
|
||||
|
||||
pub(crate) fn provide(providers: &mut ty::query::Providers) {
|
||||
|
@ -9,7 +9,7 @@ use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::{sym, Span};
|
||||
use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt;
|
||||
use rustc_trait_selection::traits::{self, FulfillmentError};
|
||||
use rustc_trait_selection::traits::{self, FulfillmentError, ObligationCtxt};
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
@ -79,8 +79,10 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
|
||||
let send_trait = cx.tcx.get_diagnostic_item(sym::Send).unwrap();
|
||||
let span = decl.output.span();
|
||||
let infcx = cx.tcx.infer_ctxt().build();
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
let cause = traits::ObligationCause::misc(span, fn_def_id);
|
||||
let send_errors = traits::fully_solve_bound(&infcx, cause, cx.param_env, ret_ty, send_trait);
|
||||
ocx.register_bound(cause, cx.param_env, ret_ty, send_trait);
|
||||
let send_errors = ocx.select_all_or_error();
|
||||
if !send_errors.is_empty() {
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
// Regression for #93775, needs build-pass to test it.
|
||||
|
||||
#![recursion_limit = "1000"]
|
||||
#![recursion_limit = "1001"]
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
|
@ -1,15 +1,10 @@
|
||||
error[E0275]: overflow evaluating the requirement `K: Send`
|
||||
error[E0275]: overflow evaluating the requirement `J: Send`
|
||||
--> $DIR/recursion_limit.rs:34:5
|
||||
|
|
||||
LL | is_send::<A>();
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` attribute to your crate (`recursion_limit`)
|
||||
note: required because it appears within the type `J`
|
||||
--> $DIR/recursion_limit.rs:24:9
|
||||
|
|
||||
LL | link! { J, K }
|
||||
| ^
|
||||
note: required because it appears within the type `I`
|
||||
--> $DIR/recursion_limit.rs:23:9
|
||||
|
|
||||
|
@ -11,7 +11,7 @@ note: required for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<
|
||||
LL | impl<T> Foo for T where Bar<T>: Foo {}
|
||||
| ^^^ ^ --- unsatisfied trait bound introduced here
|
||||
= note: the full type name has been written to '$TEST_BUILD_DIR/error-codes/E0275/E0275.long-type-hash.txt'
|
||||
= note: 127 redundant requirements hidden
|
||||
= note: 126 redundant requirements hidden
|
||||
= note: required for `Bar<T>` to implement `Foo`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -20,51 +20,51 @@ note: required for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoDa
|
||||
LL | impl<T> Foo for T where NoData<T>: Foo {
|
||||
| ^^^ ^ --- unsatisfied trait bound introduced here
|
||||
= note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-20413/issue-20413.long-type-hash.txt'
|
||||
= note: 127 redundant requirements hidden
|
||||
= note: 126 redundant requirements hidden
|
||||
= note: required for `NoData<T>` to implement `Foo`
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<...>>>>>>>: Baz`
|
||||
error[E0275]: overflow evaluating the requirement `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<...>>>>>>>: Bar`
|
||||
--> $DIR/issue-20413.rs:28:42
|
||||
|
|
||||
LL | impl<T> Bar for T where EvenLessData<T>: Baz {
|
||||
| ^^^
|
||||
|
|
||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`)
|
||||
note: required for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<...>>>>>>>` to implement `Bar`
|
||||
--> $DIR/issue-20413.rs:28:9
|
||||
|
|
||||
LL | impl<T> Bar for T where EvenLessData<T>: Baz {
|
||||
| ^^^ ^ --- unsatisfied trait bound introduced here
|
||||
= note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-20413/issue-20413.long-type-hash.txt'
|
||||
note: required for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<...>>>>>>>` to implement `Baz`
|
||||
--> $DIR/issue-20413.rs:35:9
|
||||
|
|
||||
LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
|
||||
| ^^^ ^ --- unsatisfied trait bound introduced here
|
||||
= note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-20413/issue-20413.long-type-hash.txt'
|
||||
= note: 126 redundant requirements hidden
|
||||
note: required for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<...>>>>>>>` to implement `Bar`
|
||||
--> $DIR/issue-20413.rs:28:9
|
||||
|
|
||||
LL | impl<T> Bar for T where EvenLessData<T>: Baz {
|
||||
| ^^^ ^ --- unsatisfied trait bound introduced here
|
||||
= note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-20413/issue-20413.long-type-hash.txt'
|
||||
= note: 125 redundant requirements hidden
|
||||
= note: required for `EvenLessData<T>` to implement `Baz`
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<...>>>>>>>: Bar`
|
||||
error[E0275]: overflow evaluating the requirement `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<...>>>>>>>: Baz`
|
||||
--> $DIR/issue-20413.rs:35:42
|
||||
|
|
||||
LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
|
||||
| ^^^
|
||||
|
|
||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`)
|
||||
note: required for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<...>>>>>>>` to implement `Baz`
|
||||
--> $DIR/issue-20413.rs:35:9
|
||||
|
|
||||
LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
|
||||
| ^^^ ^ --- unsatisfied trait bound introduced here
|
||||
= note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-20413/issue-20413.long-type-hash.txt'
|
||||
note: required for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<...>>>>>>>` to implement `Bar`
|
||||
--> $DIR/issue-20413.rs:28:9
|
||||
|
|
||||
LL | impl<T> Bar for T where EvenLessData<T>: Baz {
|
||||
| ^^^ ^ --- unsatisfied trait bound introduced here
|
||||
= note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-20413/issue-20413.long-type-hash.txt'
|
||||
= note: 126 redundant requirements hidden
|
||||
note: required for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<...>>>>>>>` to implement `Baz`
|
||||
--> $DIR/issue-20413.rs:35:9
|
||||
|
|
||||
LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
|
||||
| ^^^ ^ --- unsatisfied trait bound introduced here
|
||||
= note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-20413/issue-20413.long-type-hash.txt'
|
||||
= note: 125 redundant requirements hidden
|
||||
= note: required for `AlmostNoData<T>` to implement `Bar`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
@ -1,22 +1,9 @@
|
||||
error[E0275]: overflow evaluating the requirement `SalsaStorage: RefUnwindSafe`
|
||||
error[E0275]: overflow evaluating the requirement `RootDatabase: RefUnwindSafe`
|
||||
--> $DIR/cycle-cache-err-60010.rs:27:13
|
||||
|
|
||||
LL | _parse: <ParseQuery as Query<RootDatabase>>::Data,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: required because it appears within the type `PhantomData<SalsaStorage>`
|
||||
= note: required because it appears within the type `Unique<SalsaStorage>`
|
||||
= note: required because it appears within the type `Box<SalsaStorage>`
|
||||
note: required because it appears within the type `Runtime<RootDatabase>`
|
||||
--> $DIR/cycle-cache-err-60010.rs:23:8
|
||||
|
|
||||
LL | struct Runtime<DB: Database> {
|
||||
| ^^^^^^^
|
||||
note: required because it appears within the type `RootDatabase`
|
||||
--> $DIR/cycle-cache-err-60010.rs:20:8
|
||||
|
|
||||
LL | struct RootDatabase {
|
||||
| ^^^^^^^^^^^^
|
||||
note: required for `RootDatabase` to implement `SourceDatabase`
|
||||
--> $DIR/cycle-cache-err-60010.rs:44:9
|
||||
|
|
||||
|
@ -1,6 +1,6 @@
|
||||
// build-fail
|
||||
// compile-flags: -Zinline-mir=no
|
||||
// error-pattern: overflow evaluating the requirement `(): Sized`
|
||||
// error-pattern: overflow evaluating the requirement `<std::iter::Empty<()> as Iterator>::Item == ()`
|
||||
// error-pattern: function cannot return without recursing
|
||||
// normalize-stderr-test: "long-type-\d+" -> "long-type-hash"
|
||||
|
||||
|
@ -12,11 +12,17 @@ LL | recurse(IteratorOfWrapped(elements).map(|t| t.0))
|
||||
= help: a `loop` may express intention better if this is on purpose
|
||||
= note: `#[warn(unconditional_recursion)]` on by default
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `(): Sized`
|
||||
error[E0275]: overflow evaluating the requirement `<std::iter::Empty<()> as Iterator>::Item == ()`
|
||||
|
|
||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "512"]` attribute to your crate (`issue_91949_hangs_on_recursion`)
|
||||
= note: required for `std::iter::Empty<()>` to implement `Iterator`
|
||||
= note: 171 redundant requirements hidden
|
||||
note: required for `IteratorOfWrapped<(), std::iter::Empty<()>>` to implement `Iterator`
|
||||
--> $DIR/issue-91949-hangs-on-recursion.rs:16:32
|
||||
|
|
||||
LL | impl<T, I: Iterator<Item = T>> Iterator for IteratorOfWrapped<T, I> {
|
||||
| -------- ^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| unsatisfied trait bound introduced here
|
||||
= note: 256 redundant requirements hidden
|
||||
= note: required for `IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<..., ...>>, ...>>, ...>>` to implement `Iterator`
|
||||
= note: the full type name has been written to '$TEST_BUILD_DIR/traits/issue-91949-hangs-on-recursion/issue-91949-hangs-on-recursion.long-type-hash.txt'
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user