summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_hir_analysis/src/check/wfcheck.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_hir_analysis/src/check/wfcheck.rs')
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs125
1 files changed, 81 insertions, 44 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 4cccdf30c..53197bc84 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1,7 +1,6 @@
use crate::autoderef::Autoderef;
use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
-use hir::def::DefKind;
use rustc_ast as ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
@@ -111,16 +110,13 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
let errors = wfcx.select_all_or_error();
if !errors.is_empty() {
- infcx.err_ctxt().report_fulfillment_errors(&errors, None);
+ infcx.err_ctxt().report_fulfillment_errors(&errors);
return;
}
- let outlives_environment =
- OutlivesEnvironment::with_bounds(param_env, Some(infcx), implied_bounds);
+ let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
- let _ = infcx
- .err_ctxt()
- .check_region_obligations_and_report_errors(body_def_id, &outlives_environment);
+ let _ = wfcx.ocx.resolve_regions_and_report_errors(body_def_id, &outlives_env);
}
fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) {
@@ -676,19 +672,13 @@ fn resolve_regions_with_wf_tys<'tcx>(
let infcx = tcx.infer_ctxt().build();
let outlives_environment = OutlivesEnvironment::with_bounds(
param_env,
- Some(&infcx),
infcx.implied_bounds_tys(param_env, id, wf_tys.clone()),
);
let region_bound_pairs = outlives_environment.region_bound_pairs();
add_constraints(&infcx, region_bound_pairs);
- infcx.process_registered_region_obligations(
- outlives_environment.region_bound_pairs(),
- param_env,
- );
let errors = infcx.resolve_regions(&outlives_environment);
-
debug!(?errors, "errors");
// If we were able to prove that the type outlives the region without
@@ -1033,7 +1023,7 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b
// intermediate types must be sized.
let needs_drop_copy = || {
packed && {
- let ty = tcx.type_of(variant.fields.last().unwrap().did).subst_identity();
+ let ty = tcx.type_of(variant.fields.raw.last().unwrap().did).subst_identity();
let ty = tcx.erase_regions(ty);
if ty.needs_infer() {
tcx.sess
@@ -1049,7 +1039,7 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b
let all_sized = all_sized || variant.fields.is_empty() || needs_drop_copy();
let unsized_len = if all_sized { 0 } else { 1 };
for (idx, field) in
- variant.fields[..variant.fields.len() - unsized_len].iter().enumerate()
+ variant.fields.raw[..variant.fields.len() - unsized_len].iter().enumerate()
{
let last = idx == variant.fields.len() - 1;
let field_id = field.did.expect_local();
@@ -1545,31 +1535,81 @@ fn check_return_position_impl_trait_in_trait_bounds<'tcx>(
span: Span,
) {
let tcx = wfcx.tcx();
- if let Some(assoc_item) = tcx.opt_associated_item(fn_def_id.to_def_id())
- && assoc_item.container == ty::AssocItemContainer::TraitContainer
- {
- for arg in fn_output.walk() {
- if let ty::GenericArgKind::Type(ty) = arg.unpack()
- && let ty::Alias(ty::Opaque, proj) = ty.kind()
- && tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder
- && tcx.impl_trait_in_trait_parent(proj.def_id) == fn_def_id.to_def_id()
+ let Some(assoc_item) = tcx.opt_associated_item(fn_def_id.to_def_id()) else {
+ return;
+ };
+ if assoc_item.container != ty::AssocItemContainer::TraitContainer {
+ return;
+ }
+ fn_output.visit_with(&mut ImplTraitInTraitFinder {
+ wfcx,
+ fn_def_id,
+ depth: ty::INNERMOST,
+ seen: FxHashSet::default(),
+ });
+}
+
+// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): Even with the new lowering
+// strategy, we can't just call `check_associated_item` on the new RPITITs,
+// because tests like `tests/ui/async-await/in-trait/implied-bounds.rs` will fail.
+// That's because we need to check that the bounds of the RPITIT hold using
+// the special substs that we create during opaque type lowering, otherwise we're
+// getting a bunch of early bound and free regions mixed up... Haven't looked too
+// deep into this, though.
+struct ImplTraitInTraitFinder<'a, 'tcx> {
+ wfcx: &'a WfCheckingCtxt<'a, 'tcx>,
+ fn_def_id: LocalDefId,
+ depth: ty::DebruijnIndex,
+ seen: FxHashSet<DefId>,
+}
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
+ type BreakTy = !;
+
+ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<!> {
+ let tcx = self.wfcx.tcx();
+ if let ty::Alias(ty::Opaque, unshifted_opaque_ty) = *ty.kind()
+ && self.seen.insert(unshifted_opaque_ty.def_id)
+ && let Some(opaque_def_id) = unshifted_opaque_ty.def_id.as_local()
+ && let opaque = tcx.hir().expect_item(opaque_def_id).expect_opaque_ty()
+ && let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = opaque.origin
+ && source == self.fn_def_id
+ {
+ let opaque_ty = tcx.fold_regions(unshifted_opaque_ty, |re, depth| {
+ if let ty::ReLateBound(index, bv) = re.kind() {
+ if depth != ty::INNERMOST {
+ return tcx.mk_re_error_with_message(
+ DUMMY_SP,
+ "we shouldn't walk non-predicate binders with `impl Trait`...",
+ );
+ }
+ tcx.mk_re_late_bound(index.shifted_out_to_binder(self.depth), bv)
+ } else {
+ re
+ }
+ });
+ for (bound, bound_span) in tcx
+ .bound_explicit_item_bounds(opaque_ty.def_id)
+ .subst_iter_copied(tcx, opaque_ty.substs)
{
- let span = tcx.def_span(proj.def_id);
- let bounds = wfcx.tcx().explicit_item_bounds(proj.def_id);
- let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| {
- let bound = ty::EarlyBinder(bound).subst(tcx, proj.substs);
- let normalized_bound = wfcx.normalize(span, None, bound);
- traits::wf::predicate_obligations(
- wfcx.infcx,
- wfcx.param_env,
- wfcx.body_def_id,
- normalized_bound,
- bound_span,
- )
- });
- wfcx.register_obligations(wf_obligations);
+ let bound = self.wfcx.normalize(bound_span, None, bound);
+ self.wfcx.register_obligations(traits::wf::predicate_obligations(
+ self.wfcx.infcx,
+ self.wfcx.param_env,
+ self.wfcx.body_def_id,
+ bound,
+ bound_span,
+ ));
+ // Set the debruijn index back to innermost here, since we already eagerly
+ // shifted the substs that we use to generate these bounds. This is unfortunately
+ // subtly different behavior than the `ImplTraitInTraitFinder` we use in `param_env`,
+ // but that function doesn't actually need to normalize the bound it's visiting
+ // (whereas we have to do so here)...
+ let old_depth = std::mem::replace(&mut self.depth, ty::INNERMOST);
+ bound.visit_with(self);
+ self.depth = old_depth;
}
}
+ ty.super_visit_with(self)
}
}
@@ -1784,7 +1824,7 @@ fn check_variances_for_type_defn<'tcx>(
// Lazily calculated because it is only needed in case of an error.
let explicitly_bounded_params = LazyCell::new(|| {
- let icx = crate::collect::ItemCtxt::new(tcx, item.owner_id.to_def_id());
+ let icx = crate::collect::ItemCtxt::new(tcx, item.owner_id.def_id);
hir_generics
.predicates
.iter()
@@ -1861,16 +1901,15 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
let predicates_with_span = tcx.predicates_of(self.body_def_id).predicates.iter().copied();
// Check elaborated bounds.
- let implied_obligations = traits::elaborate_predicates_with_span(tcx, predicates_with_span);
+ let implied_obligations = traits::elaborate(tcx, predicates_with_span);
- for obligation in implied_obligations {
+ for (pred, obligation_span) in implied_obligations {
// We lower empty bounds like `Vec<dyn Copy>:` as
// `WellFormed(Vec<dyn Copy>)`, which will later get checked by
// regular WF checking
- if let ty::PredicateKind::WellFormed(..) = obligation.predicate.kind().skip_binder() {
+ if let ty::PredicateKind::WellFormed(..) = pred.kind().skip_binder() {
continue;
}
- let pred = obligation.predicate;
// Match the existing behavior.
if pred.is_global() && !pred.has_late_bound_vars() {
let pred = self.normalize(span, None, pred);
@@ -1881,8 +1920,6 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
if let Some(hir::Generics { predicates, .. }) =
hir_node.and_then(|node| node.generics())
{
- let obligation_span = obligation.cause.span();
-
span = predicates
.iter()
// There seems to be no better way to find out which predicate we are in