remove some trait solver helpers
they add more complexity then they are worth. It's confusing which of these helpers should be used in which context.
This commit is contained in:
parent
84c47b8279
commit
791ce0b7b5
@ -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);
|
||||
}
|
||||
@ -583,10 +584,12 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
|
||||
};
|
||||
|
||||
// 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() {
|
||||
|
@ -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,23 @@ 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,
|
||||
// FIXME: using the empty param env is wrong, should use the one from `body_id`.
|
||||
ty::ParamEnv::empty(),
|
||||
// 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,
|
||||
@ -2440,15 +2440,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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user