Skip to content

Commit 9bdb488

Browse files
committed
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
2 parents 5fa73a7 + b8541eb commit 9bdb488

File tree

39 files changed

+258
-384
lines changed

39 files changed

+258
-384
lines changed

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

+7-14
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use rustc_span::hygiene::DesugaringKind;
2424
use rustc_span::symbol::{kw, sym};
2525
use rustc_span::{BytePos, Span, Symbol};
2626
use rustc_trait_selection::infer::InferCtxtExt;
27+
use rustc_trait_selection::traits::ObligationCtxt;
2728

2829
use crate::borrow_set::TwoPhaseActivation;
2930
use crate::borrowck_errors;
@@ -760,20 +761,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
760761
else { return; };
761762
// Try to find predicates on *generic params* that would allow copying `ty`
762763
let infcx = tcx.infer_ctxt().build();
763-
let copy_did = infcx.tcx.require_lang_item(LangItem::Copy, Some(span));
764-
let cause = ObligationCause::new(
765-
span,
766-
self.mir_def_id(),
767-
rustc_infer::traits::ObligationCauseCode::MiscObligation,
768-
);
769-
let errors = rustc_trait_selection::traits::fully_solve_bound(
770-
&infcx,
771-
cause,
772-
self.param_env,
773-
// Erase any region vids from the type, which may not be resolved
774-
infcx.tcx.erase_regions(ty),
775-
copy_did,
776-
);
764+
let ocx = ObligationCtxt::new(&infcx);
765+
let copy_did = tcx.require_lang_item(LangItem::Copy, Some(span));
766+
let cause = ObligationCause::misc(span, self.mir_def_id());
767+
768+
ocx.register_bound(cause, self.param_env, infcx.tcx.erase_regions(ty), copy_did);
769+
let errors = ocx.select_all_or_error();
777770

778771
// Only emit suggestion if all required predicates are on generic
779772
let predicates: Result<Vec<_>, _> = errors

compiler/rustc_borrowck/src/diagnostics/mod.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1078,7 +1078,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
10781078
self.param_env,
10791079
tcx.mk_imm_ref(tcx.lifetimes.re_erased, tcx.erase_regions(ty)),
10801080
def_id,
1081-
DUMMY_SP,
10821081
)
10831082
}
10841083
_ => false,

compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_middle::mir;
99
use rustc_middle::mir::*;
1010
use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty};
1111
use rustc_trait_selection::traits::{
12-
self, ImplSource, Obligation, ObligationCause, SelectionContext,
12+
self, ImplSource, Obligation, ObligationCause, ObligationCtxt, SelectionContext,
1313
};
1414

1515
use super::ConstCx;
@@ -184,7 +184,10 @@ impl Qualif for NeedsNonConstDrop {
184184
}
185185

186186
// If we had any errors, then it's bad
187-
!traits::fully_solve_obligations(&infcx, impl_src.nested_obligations()).is_empty()
187+
let ocx = ObligationCtxt::new(&infcx);
188+
ocx.register_obligations(impl_src.nested_obligations());
189+
let errors = ocx.select_all_or_error();
190+
!errors.is_empty()
188191
}
189192

190193
fn in_adt_inherently<'tcx>(

compiler/rustc_hir_analysis/src/check/intrinsic.rs

+1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ fn equate_intrinsic_type<'tcx>(
5959
require_same_types(
6060
tcx,
6161
&cause,
62+
ty::ParamEnv::empty(), // FIXME: do all intrinsics have an empty param env?
6263
tcx.mk_fn_ptr(tcx.fn_sig(it.owner_id).subst_identity()),
6364
fty,
6465
);

compiler/rustc_hir_analysis/src/coherence/builtin.rs

+18-15
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@ use rustc_hir::ItemKind;
1111
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
1212
use rustc_infer::infer::{self, RegionResolutionError};
1313
use rustc_infer::infer::{DefineOpaqueTypes, TyCtxtInferExt};
14+
use rustc_infer::traits::Obligation;
1415
use rustc_middle::ty::adjustment::CoerceUnsizedInfo;
1516
use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeVisitableExt};
1617
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
1718
use rustc_trait_selection::traits::misc::{
1819
type_allowed_to_implement_copy, CopyImplementationError, InfringingFieldsReason,
1920
};
20-
use rustc_trait_selection::traits::predicate_for_trait_def;
21+
use rustc_trait_selection::traits::ObligationCtxt;
2122
use rustc_trait_selection::traits::{self, ObligationCause};
2223
use std::collections::BTreeMap;
2324

@@ -334,19 +335,19 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
334335
))
335336
.emit();
336337
} else {
337-
let errors = traits::fully_solve_obligations(
338-
&infcx,
339-
coerced_fields.into_iter().map(|field| {
340-
predicate_for_trait_def(
341-
tcx,
342-
param_env,
343-
cause.clone(),
338+
let ocx = ObligationCtxt::new(&infcx);
339+
for field in coerced_fields {
340+
ocx.register_obligation(Obligation::new(
341+
tcx,
342+
cause.clone(),
343+
param_env,
344+
ty::Binder::dummy(tcx.mk_trait_ref(
344345
dispatch_from_dyn_trait,
345-
0,
346346
[field.ty(tcx, substs_a), field.ty(tcx, substs_b)],
347-
)
348-
}),
349-
);
347+
)),
348+
));
349+
}
350+
let errors = ocx.select_all_or_error();
350351
if !errors.is_empty() {
351352
infcx.err_ctxt().report_fulfillment_errors(&errors);
352353
}
@@ -580,10 +581,12 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
580581
};
581582

582583
// Register an obligation for `A: Trait<B>`.
584+
let ocx = ObligationCtxt::new(&infcx);
583585
let cause = traits::ObligationCause::misc(span, impl_did);
584-
let predicate =
585-
predicate_for_trait_def(tcx, param_env, cause, trait_def_id, 0, [source, target]);
586-
let errors = traits::fully_solve_obligation(&infcx, predicate);
586+
let obligation =
587+
Obligation::new(tcx, cause, param_env, tcx.mk_trait_ref(trait_def_id, [source, target]));
588+
ocx.register_obligation(obligation);
589+
let errors = ocx.select_all_or_error();
587590
if !errors.is_empty() {
588591
infcx.err_ctxt().report_fulfillment_errors(&errors);
589592
}

compiler/rustc_hir_analysis/src/hir_wf_check.rs

+21-21
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use rustc_infer::traits::{ObligationCause, WellFormedLoc};
77
use rustc_middle::ty::query::Providers;
88
use rustc_middle::ty::{self, Region, TyCtxt, TypeFoldable, TypeFolder};
99
use rustc_span::def_id::LocalDefId;
10-
use rustc_trait_selection::traits;
10+
use rustc_trait_selection::traits::{self, ObligationCtxt};
1111

1212
pub fn provide(providers: &mut Providers) {
1313
*providers = Providers { diagnostic_hir_wf_check, ..*providers };
@@ -66,35 +66,35 @@ fn diagnostic_hir_wf_check<'tcx>(
6666
impl<'tcx> Visitor<'tcx> for HirWfCheck<'tcx> {
6767
fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
6868
let infcx = self.tcx.infer_ctxt().build();
69+
let ocx = ObligationCtxt::new(&infcx);
70+
6971
let tcx_ty = self.icx.to_ty(ty).fold_with(&mut EraseAllBoundRegions { tcx: self.tcx });
7072
let cause = traits::ObligationCause::new(
7173
ty.span,
7274
self.def_id,
7375
traits::ObligationCauseCode::WellFormed(None),
7476
);
75-
let errors = traits::fully_solve_obligation(
76-
&infcx,
77-
traits::Obligation::new(
78-
self.tcx,
79-
cause,
80-
self.param_env,
81-
ty::Binder::dummy(ty::PredicateKind::WellFormed(tcx_ty.into())),
82-
),
83-
);
84-
if !errors.is_empty() {
85-
debug!("Wf-check got errors for {:?}: {:?}", ty, errors);
86-
for error in errors {
87-
if error.obligation.predicate == self.predicate {
88-
// Save the cause from the greatest depth - this corresponds
89-
// to picking more-specific types (e.g. `MyStruct<u8>`)
90-
// over less-specific types (e.g. `Option<MyStruct<u8>>`)
91-
if self.depth >= self.cause_depth {
92-
self.cause = Some(error.obligation.cause);
93-
self.cause_depth = self.depth
94-
}
77+
78+
ocx.register_obligation(traits::Obligation::new(
79+
self.tcx,
80+
cause,
81+
self.param_env,
82+
ty::PredicateKind::WellFormed(tcx_ty.into()),
83+
));
84+
85+
for error in ocx.select_all_or_error() {
86+
debug!("Wf-check got error for {:?}: {:?}", ty, error);
87+
if error.obligation.predicate == self.predicate {
88+
// Save the cause from the greatest depth - this corresponds
89+
// to picking more-specific types (e.g. `MyStruct<u8>`)
90+
// over less-specific types (e.g. `Option<MyStruct<u8>>`)
91+
if self.depth >= self.cause_depth {
92+
self.cause = Some(error.obligation.cause);
93+
self.cause_depth = self.depth
9594
}
9695
}
9796
}
97+
9898
self.depth += 1;
9999
intravisit::walk_ty(self, ty);
100100
self.depth -= 1;

compiler/rustc_hir_analysis/src/lib.rs

+16-17
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ use rustc_errors::ErrorGuaranteed;
102102
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
103103
use rustc_hir as hir;
104104
use rustc_hir::Node;
105-
use rustc_infer::infer::{DefineOpaqueTypes, InferOk, TyCtxtInferExt};
105+
use rustc_infer::infer::TyCtxtInferExt;
106106
use rustc_macros::fluent_messages;
107107
use rustc_middle::middle;
108108
use rustc_middle::ty::query::Providers;
@@ -113,7 +113,7 @@ use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
113113
use rustc_span::{symbol::sym, Span, DUMMY_SP};
114114
use rustc_target::spec::abi::Abi;
115115
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
116-
use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode};
116+
use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, ObligationCtxt};
117117

118118
use std::ops::Not;
119119

@@ -160,24 +160,21 @@ fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi
160160
fn require_same_types<'tcx>(
161161
tcx: TyCtxt<'tcx>,
162162
cause: &ObligationCause<'tcx>,
163+
param_env: ty::ParamEnv<'tcx>,
163164
expected: Ty<'tcx>,
164165
actual: Ty<'tcx>,
165-
) -> bool {
166+
) {
166167
let infcx = &tcx.infer_ctxt().build();
167-
let param_env = ty::ParamEnv::empty();
168-
let errors = match infcx.at(cause, param_env).eq(DefineOpaqueTypes::No, expected, actual) {
169-
Ok(InferOk { obligations, .. }) => traits::fully_solve_obligations(infcx, obligations),
168+
let ocx = ObligationCtxt::new(infcx);
169+
match ocx.eq(cause, param_env, expected, actual) {
170+
Ok(()) => {
171+
let errors = ocx.select_all_or_error();
172+
if !errors.is_empty() {
173+
infcx.err_ctxt().report_fulfillment_errors(&errors);
174+
}
175+
}
170176
Err(err) => {
171177
infcx.err_ctxt().report_mismatched_types(cause, expected, actual, err).emit();
172-
return false;
173-
}
174-
};
175-
176-
match &errors[..] {
177-
[] => true,
178-
errors => {
179-
infcx.err_ctxt().report_fulfillment_errors(errors);
180-
false
181178
}
182179
}
183180
}
@@ -296,6 +293,8 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
296293
return;
297294
}
298295

296+
// Main should have no WC, so empty param env is OK here.
297+
let param_env = ty::ParamEnv::empty();
299298
let expected_return_type;
300299
if let Some(term_did) = tcx.lang_items().termination() {
301300
let return_ty = main_fnsig.output();
@@ -306,8 +305,6 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
306305
}
307306
let return_ty = return_ty.skip_binder();
308307
let infcx = tcx.infer_ctxt().build();
309-
// Main should have no WC, so empty param env is OK here.
310-
let param_env = ty::ParamEnv::empty();
311308
let cause = traits::ObligationCause::new(
312309
return_ty_span,
313310
main_diagnostics_def_id,
@@ -343,6 +340,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
343340
main_diagnostics_def_id,
344341
ObligationCauseCode::MainFunctionType,
345342
),
343+
param_env,
346344
se_ty,
347345
tcx.mk_fn_ptr(main_fnsig),
348346
);
@@ -417,6 +415,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
417415
start_def_id,
418416
ObligationCauseCode::StartFunctionType,
419417
),
418+
ty::ParamEnv::empty(), // start should not have any where bounds.
420419
se_ty,
421420
tcx.mk_fn_ptr(tcx.fn_sig(start_def_id).subst_identity()),
422421
);

compiler/rustc_hir_typeck/src/callee.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
668668

669669
if !self.maybe_suggest_bad_array_definition(&mut err, call_expr, callee_expr) {
670670
if let Some((maybe_def, output_ty, _)) = self.extract_callable_info(callee_ty)
671-
&& !self.type_is_sized_modulo_regions(self.param_env, output_ty, callee_expr.span)
671+
&& !self.type_is_sized_modulo_regions(self.param_env, output_ty)
672672
{
673673
let descr = match maybe_def {
674674
DefIdOrName::DefId(def_id) => self.tcx.def_descr(def_id),

compiler/rustc_hir_typeck/src/cast.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
9696
let t = self.resolve_vars_if_possible(t);
9797
t.error_reported()?;
9898

99-
if self.type_is_sized_modulo_regions(self.param_env, t, span) {
99+
if self.type_is_sized_modulo_regions(self.param_env, t) {
100100
return Ok(Some(PointerKind::Thin));
101101
}
102102

@@ -722,7 +722,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
722722

723723
debug!("check_cast({}, {:?} as {:?})", self.expr.hir_id, self.expr_ty, self.cast_ty);
724724

725-
if !fcx.type_is_sized_modulo_regions(fcx.param_env, self.cast_ty, self.span)
725+
if !fcx.type_is_sized_modulo_regions(fcx.param_env, self.cast_ty)
726726
&& !self.cast_ty.has_infer_types()
727727
{
728728
self.report_cast_to_unsized_type(fcx);

compiler/rustc_hir_typeck/src/coercion.rs

+7-9
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ use rustc_hir::Expr;
4646
use rustc_hir_analysis::astconv::AstConv;
4747
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
4848
use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult};
49-
use rustc_infer::traits::Obligation;
49+
use rustc_infer::traits::{Obligation, PredicateObligation};
5050
use rustc_middle::lint::in_external_macro;
5151
use rustc_middle::ty::adjustment::{
5252
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast,
@@ -597,13 +597,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
597597
// and almost never more than 3. By using a SmallVec we avoid an
598598
// allocation, at the (very small) cost of (occasionally) having to
599599
// shift subsequent elements down when removing the front element.
600-
let mut queue: SmallVec<[_; 4]> = smallvec![traits::predicate_for_trait_def(
600+
let mut queue: SmallVec<[PredicateObligation<'tcx>; 4]> = smallvec![Obligation::new(
601601
self.tcx,
602-
self.fcx.param_env,
603602
cause,
604-
coerce_unsized_did,
605-
0,
606-
[coerce_source, coerce_target]
603+
self.fcx.param_env,
604+
self.tcx.mk_trait_ref(coerce_unsized_did, [coerce_source, coerce_target])
607605
)];
608606

609607
let mut has_unsized_tuple_coercion = false;
@@ -651,9 +649,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
651649
let self_ty = trait_pred.skip_binder().self_ty();
652650
let unsize_ty = trait_pred.skip_binder().trait_ref.substs[1].expect_ty();
653651
debug!("coerce_unsized: ambiguous unsize case for {:?}", trait_pred);
654-
match (&self_ty.kind(), &unsize_ty.kind()) {
655-
(ty::Infer(ty::TyVar(v)), ty::Dynamic(..))
656-
if self.type_var_is_sized(*v) =>
652+
match (self_ty.kind(), unsize_ty.kind()) {
653+
(&ty::Infer(ty::TyVar(v)), ty::Dynamic(..))
654+
if self.type_var_is_sized(v) =>
657655
{
658656
debug!("coerce_unsized: have sized infer {:?}", v);
659657
coercion.obligations.push(obligation);

compiler/rustc_hir_typeck/src/demand.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1480,7 +1480,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14801480

14811481
// For this suggestion to make sense, the type would need to be `Copy`,
14821482
// or we have to be moving out of a `Box<T>`
1483-
if self.type_is_copy_modulo_regions(self.param_env, expected, sp)
1483+
if self.type_is_copy_modulo_regions(self.param_env, expected)
14841484
// FIXME(compiler-errors): We can actually do this if the checked_ty is
14851485
// `steps` layers of boxes, not just one, but this is easier and most likely.
14861486
|| (checked_ty.is_box() && steps == 1)

compiler/rustc_hir_typeck/src/expr_use_visitor.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -867,10 +867,7 @@ fn copy_or_move<'a, 'tcx>(
867867
mc: &mc::MemCategorizationContext<'a, 'tcx>,
868868
place_with_id: &PlaceWithHirId<'tcx>,
869869
) -> ConsumeMode {
870-
if !mc.type_is_copy_modulo_regions(
871-
place_with_id.place.ty(),
872-
mc.tcx().hir().span(place_with_id.hir_id),
873-
) {
870+
if !mc.type_is_copy_modulo_regions(place_with_id.place.ty()) {
874871
ConsumeMode::Move
875872
} else {
876873
ConsumeMode::Copy

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -1011,11 +1011,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10111011
let mut suggest_copied_or_cloned = || {
10121012
let expr_inner_ty = substs.type_at(0);
10131013
let expected_inner_ty = expected_substs.type_at(0);
1014-
if let ty::Ref(_, ty, hir::Mutability::Not) = expr_inner_ty.kind()
1015-
&& self.can_eq(self.param_env, *ty, expected_inner_ty)
1014+
if let &ty::Ref(_, ty, hir::Mutability::Not) = expr_inner_ty.kind()
1015+
&& self.can_eq(self.param_env, ty, expected_inner_ty)
10161016
{
10171017
let def_path = self.tcx.def_path_str(adt_def.did());
1018-
if self.type_is_copy_modulo_regions(self.param_env, *ty, expr.span) {
1018+
if self.type_is_copy_modulo_regions(self.param_env, ty) {
10191019
diag.span_suggestion_verbose(
10201020
expr.span.shrink_to_hi(),
10211021
format!(
@@ -1029,9 +1029,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10291029
&& rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions(
10301030
self,
10311031
self.param_env,
1032-
*ty,
1032+
ty,
10331033
clone_did,
1034-
expr.span
10351034
)
10361035
{
10371036
diag.span_suggestion_verbose(

0 commit comments

Comments
 (0)