summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_hir_analysis/src/check/wfcheck.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs (renamed from compiler/rustc_typeck/src/check/wfcheck.rs)367
1 files changed, 192 insertions, 175 deletions
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index d0334cd0d..a23575004 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1,5 +1,5 @@
-use crate::check::regionck::OutlivesEnvironmentExt;
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};
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
@@ -10,22 +10,21 @@ use rustc_hir::ItemKind;
use rustc_infer::infer::outlives::env::{OutlivesEnvironment, RegionBoundPairs};
use rustc_infer::infer::outlives::obligations::TypeOutlives;
use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
-use rustc_infer::traits::Normalized;
+use rustc_middle::mir::ConstraintCategory;
use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst};
use rustc_middle::ty::trait_def::TraitSpecializationKind;
use rustc_middle::ty::{
self, AdtKind, DefIdTree, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable,
TypeSuperVisitable, TypeVisitable, TypeVisitor,
};
+use rustc_middle::ty::{GenericArgKind, InternalSubsts};
use rustc_session::parse::feature_err;
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
use rustc_trait_selection::autoderef::Autoderef;
-use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
+use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
+use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
-use rustc_trait_selection::traits::query::normalize::AtExt;
-use rustc_trait_selection::traits::query::NoSolution;
use rustc_trait_selection::traits::{
self, ObligationCause, ObligationCauseCode, ObligationCtxt, WellFormedLoc,
};
@@ -72,9 +71,11 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
) {
let cause =
traits::ObligationCause::new(span, self.body_id, ObligationCauseCode::WellFormed(loc));
+ // for a type to be WF, we do not need to check if const trait predicates satisfy.
+ let param_env = self.param_env.without_const();
self.ocx.register_obligation(traits::Obligation::new(
cause,
- self.param_env,
+ param_env,
ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)).to_predicate(self.tcx()),
));
}
@@ -86,31 +87,35 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
body_def_id: LocalDefId,
f: F,
) where
- F: for<'a> FnOnce(&WfCheckingCtxt<'a, 'tcx>) -> FxHashSet<Ty<'tcx>>,
+ F: for<'a> FnOnce(&WfCheckingCtxt<'a, 'tcx>),
{
let param_env = tcx.param_env(body_def_id);
let body_id = tcx.hir().local_def_id_to_hir_id(body_def_id);
- tcx.infer_ctxt().enter(|ref infcx| {
- let ocx = ObligationCtxt::new(infcx);
- let mut wfcx = WfCheckingCtxt { ocx, span, body_id, param_env };
+ let infcx = &tcx.infer_ctxt().build();
+ let ocx = ObligationCtxt::new(infcx);
- if !tcx.features().trivial_bounds {
- wfcx.check_false_global_bounds()
- }
- let wf_tys = f(&mut wfcx);
- let errors = wfcx.select_all_or_error();
- if !errors.is_empty() {
- infcx.report_fulfillment_errors(&errors, None, false);
- return;
- }
+ let assumed_wf_types = ocx.assumed_wf_types(param_env, span, body_def_id);
- let mut outlives_environment = OutlivesEnvironment::new(param_env);
- outlives_environment.add_implied_bounds(infcx, wf_tys, body_id);
- infcx.check_region_obligations_and_report_errors(body_def_id, &outlives_environment);
- })
+ let mut wfcx = WfCheckingCtxt { ocx, span, body_id, param_env };
+
+ if !tcx.features().trivial_bounds {
+ wfcx.check_false_global_bounds()
+ }
+ f(&mut wfcx);
+ let errors = wfcx.select_all_or_error();
+ if !errors.is_empty() {
+ infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
+ return;
+ }
+
+ let implied_bounds = infcx.implied_bounds_tys(param_env, body_id, assumed_wf_types);
+ let outlives_environment =
+ OutlivesEnvironment::with_bounds(param_env, Some(infcx), implied_bounds);
+
+ infcx.check_region_obligations_and_report_errors(body_def_id, &outlives_environment);
}
-fn check_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
+fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) {
let node = tcx.hir().expect_owner(def_id);
match node {
hir::OwnerNode::Crate(_) => {}
@@ -142,10 +147,10 @@ fn check_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
/// the types first.
#[instrument(skip(tcx), level = "debug")]
fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
- let def_id = item.def_id;
+ let def_id = item.owner_id.def_id;
debug!(
- ?item.def_id,
+ ?item.owner_id,
item.name = ? tcx.def_path_str(def_id.to_def_id())
);
@@ -169,7 +174,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
// for `T`
hir::ItemKind::Impl(ref impl_) => {
let is_auto = tcx
- .impl_trait_ref(item.def_id)
+ .impl_trait_ref(def_id)
.map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.def_id));
if let (hir::Defaultness::Default { .. }, true) = (impl_.defaultness, is_auto) {
let sp = impl_.of_trait.as_ref().map_or(item.span, |t| t.path.span);
@@ -205,13 +210,13 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
}
}
hir::ItemKind::Fn(ref sig, ..) => {
- check_item_fn(tcx, item.def_id, item.ident, item.span, sig.decl);
+ check_item_fn(tcx, def_id, item.ident, item.span, sig.decl);
}
hir::ItemKind::Static(ty, ..) => {
- check_item_type(tcx, item.def_id, ty.span, false);
+ check_item_type(tcx, def_id, ty.span, false);
}
hir::ItemKind::Const(ty, ..) => {
- check_item_type(tcx, item.def_id, ty.span, false);
+ check_item_type(tcx, def_id, ty.span, false);
}
hir::ItemKind::Struct(ref struct_def, ref ast_generics) => {
check_type_defn(tcx, item, false, |wfcx| vec![wfcx.non_enum_variant(struct_def)]);
@@ -241,24 +246,24 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
}
fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) {
- let def_id = item.def_id;
+ let def_id = item.owner_id.def_id;
debug!(
- ?item.def_id,
+ ?item.owner_id,
item.name = ? tcx.def_path_str(def_id.to_def_id())
);
match item.kind {
hir::ForeignItemKind::Fn(decl, ..) => {
- check_item_fn(tcx, item.def_id, item.ident, item.span, decl)
+ check_item_fn(tcx, def_id, item.ident, item.span, decl)
}
- hir::ForeignItemKind::Static(ty, ..) => check_item_type(tcx, item.def_id, ty.span, true),
+ hir::ForeignItemKind::Static(ty, ..) => check_item_type(tcx, def_id, ty.span, true),
hir::ForeignItemKind::Type => (),
}
}
fn check_trait_item(tcx: TyCtxt<'_>, trait_item: &hir::TraitItem<'_>) {
- let def_id = trait_item.def_id;
+ let def_id = trait_item.owner_id.def_id;
let (method_sig, span) = match trait_item.kind {
hir::TraitItemKind::Fn(ref sig, _) => (Some(sig), trait_item.span),
@@ -266,11 +271,11 @@ fn check_trait_item(tcx: TyCtxt<'_>, trait_item: &hir::TraitItem<'_>) {
_ => (None, trait_item.span),
};
check_object_unsafe_self_trait_by_name(tcx, trait_item);
- check_associated_item(tcx, trait_item.def_id, span, method_sig);
+ check_associated_item(tcx, def_id, span, method_sig);
let encl_trait_def_id = tcx.local_parent(def_id);
let encl_trait = tcx.hir().expect_item(encl_trait_def_id);
- let encl_trait_def_id = encl_trait.def_id.to_def_id();
+ let encl_trait_def_id = encl_trait.owner_id.to_def_id();
let fn_lang_item_name = if Some(encl_trait_def_id) == tcx.lang_items().fn_trait() {
Some("fn")
} else if Some(encl_trait_def_id) == tcx.lang_items().fn_mut_trait() {
@@ -343,7 +348,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
loop {
let mut should_continue = false;
for gat_item in associated_items {
- let gat_def_id = gat_item.id.def_id;
+ let gat_def_id = gat_item.id.owner_id;
let gat_item = tcx.associated_item(gat_def_id);
// If this item is not an assoc ty, or has no substs, then it's not a GAT
if gat_item.kind != ty::AssocKind::Type {
@@ -360,7 +365,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
// constrains the GAT with individually.
let mut new_required_bounds: Option<FxHashSet<ty::Predicate<'_>>> = None;
for item in associated_items {
- let item_def_id = item.id.def_id;
+ let item_def_id = item.id.owner_id;
// Skip our own GAT, since it does not constrain itself at all.
if item_def_id == gat_def_id {
continue;
@@ -383,11 +388,11 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
tcx,
param_env,
item_hir_id,
- sig.output(),
+ sig.inputs_and_output,
// We also assume that all of the function signature's parameter types
// are well formed.
&sig.inputs().iter().copied().collect(),
- gat_def_id,
+ gat_def_id.def_id,
gat_generics,
)
}
@@ -410,7 +415,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
.copied()
.collect::<Vec<_>>(),
&FxHashSet::default(),
- gat_def_id,
+ gat_def_id.def_id,
gat_generics,
)
}
@@ -450,7 +455,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
}
for (gat_def_id, required_bounds) in required_bounds_by_item {
- let gat_item_hir = tcx.hir().expect_trait_item(gat_def_id);
+ let gat_item_hir = tcx.hir().expect_trait_item(gat_def_id.def_id);
debug!(?required_bounds);
let param_env = tcx.param_env(gat_def_id);
let gat_hir = gat_item_hir.hir_id();
@@ -658,7 +663,7 @@ fn ty_known_to_outlive<'tcx>(
resolve_regions_with_wf_tys(tcx, id, param_env, &wf_tys, |infcx, region_bound_pairs| {
let origin = infer::RelateParamBound(DUMMY_SP, ty, None);
let outlives = &mut TypeOutlives::new(infcx, tcx, region_bound_pairs, None, param_env);
- outlives.type_must_outlive(origin, ty, region);
+ outlives.type_must_outlive(origin, ty, region, ConstraintCategory::BoringNoLocation);
})
}
@@ -676,7 +681,12 @@ fn region_known_to_outlive<'tcx>(
use rustc_infer::infer::outlives::obligations::TypeOutlivesDelegate;
let origin = infer::RelateRegionParamBound(DUMMY_SP);
// `region_a: region_b` -> `region_b <= region_a`
- infcx.push_sub_region_constraint(origin, region_b, region_a);
+ infcx.push_sub_region_constraint(
+ origin,
+ region_b,
+ region_a,
+ ConstraintCategory::BoringNoLocation,
+ );
})
}
@@ -688,26 +698,32 @@ fn resolve_regions_with_wf_tys<'tcx>(
id: hir::HirId,
param_env: ty::ParamEnv<'tcx>,
wf_tys: &FxHashSet<Ty<'tcx>>,
- add_constraints: impl for<'a> FnOnce(&'a InferCtxt<'a, 'tcx>, &'a RegionBoundPairs<'tcx>),
+ add_constraints: impl for<'a> FnOnce(&'a InferCtxt<'tcx>, &'a RegionBoundPairs<'tcx>),
) -> bool {
// Unfortunately, we have to use a new `InferCtxt` each call, because
// region constraints get added and solved there and we need to test each
// call individually.
- tcx.infer_ctxt().enter(|infcx| {
- let mut outlives_environment = OutlivesEnvironment::new(param_env);
- outlives_environment.add_implied_bounds(&infcx, wf_tys.clone(), id);
- let region_bound_pairs = outlives_environment.region_bound_pairs();
+ 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);
+ add_constraints(&infcx, region_bound_pairs);
- let errors = infcx.resolve_regions(&outlives_environment);
+ infcx.process_registered_region_obligations(
+ outlives_environment.region_bound_pairs(),
+ param_env,
+ );
+ let errors = infcx.resolve_regions(&outlives_environment);
- debug!(?errors, "errors");
+ debug!(?errors, "errors");
- // If we were able to prove that the type outlives the region without
- // an error, it must be because of the implied or explicit bounds...
- errors.is_empty()
- })
+ // If we were able to prove that the type outlives the region without
+ // an error, it must be because of the implied or explicit bounds...
+ errors.is_empty()
}
/// TypeVisitor that looks for uses of GATs like
@@ -761,7 +777,7 @@ impl<'tcx> TypeVisitor<'tcx> for GATSubstCollector<'tcx> {
fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool {
match ty.kind {
hir::TyKind::TraitObject([trait_ref], ..) => match trait_ref.trait_ref.path.segments {
- [s] => s.res.and_then(|r| r.opt_def_id()) == Some(trait_def_id.to_def_id()),
+ [s] => s.res.opt_def_id() == Some(trait_def_id.to_def_id()),
_ => false,
},
_ => false,
@@ -772,9 +788,9 @@ fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool {
/// When this is done, suggest using `Self` instead.
fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem<'_>) {
let (trait_name, trait_def_id) =
- match tcx.hir().get_by_def_id(tcx.hir().get_parent_item(item.hir_id())) {
+ match tcx.hir().get_by_def_id(tcx.hir().get_parent_item(item.hir_id()).def_id) {
hir::Node::Item(item) => match item.kind {
- hir::ItemKind::Trait(..) => (item.ident, item.def_id),
+ hir::ItemKind::Trait(..) => (item.ident, item.owner_id),
_ => return,
},
_ => return,
@@ -782,18 +798,18 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem
let mut trait_should_be_self = vec![];
match &item.kind {
hir::TraitItemKind::Const(ty, _) | hir::TraitItemKind::Type(_, Some(ty))
- if could_be_self(trait_def_id, ty) =>
+ if could_be_self(trait_def_id.def_id, ty) =>
{
trait_should_be_self.push(ty.span)
}
hir::TraitItemKind::Fn(sig, _) => {
for ty in sig.decl.inputs {
- if could_be_self(trait_def_id, ty) {
+ if could_be_self(trait_def_id.def_id, ty) {
trait_should_be_self.push(ty.span);
}
}
match sig.decl.output {
- hir::FnRetTy::Return(ty) if could_be_self(trait_def_id, ty) => {
+ hir::FnRetTy::Return(ty) if could_be_self(trait_def_id.def_id, ty) => {
trait_should_be_self.push(ty.span);
}
_ => {}
@@ -822,16 +838,14 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem
}
fn check_impl_item(tcx: TyCtxt<'_>, impl_item: &hir::ImplItem<'_>) {
- let def_id = impl_item.def_id;
-
let (method_sig, span) = match impl_item.kind {
hir::ImplItemKind::Fn(ref sig, _) => (Some(sig), impl_item.span),
// Constrain binding and overflow error spans to `<Ty>` in `type foo = <Ty>`.
- hir::ImplItemKind::TyAlias(ty) if ty.span != DUMMY_SP => (None, ty.span),
+ hir::ImplItemKind::Type(ty) if ty.span != DUMMY_SP => (None, ty.span),
_ => (None, impl_item.span),
};
- check_associated_item(tcx, def_id, span, method_sig);
+ check_associated_item(tcx, impl_item.owner_id.def_id, span, method_sig);
}
fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
@@ -965,7 +979,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
}
}
-#[tracing::instrument(level = "debug", skip(tcx, span, sig_if_method))]
+#[instrument(level = "debug", skip(tcx, span, sig_if_method))]
fn check_associated_item(
tcx: TyCtxt<'_>,
item_id: LocalDefId,
@@ -976,15 +990,9 @@ fn check_associated_item(
enter_wf_checking_ctxt(tcx, span, item_id, |wfcx| {
let item = tcx.associated_item(item_id);
- let (mut implied_bounds, self_ty) = match item.container {
- ty::TraitContainer => (FxHashSet::default(), tcx.types.self_param),
- ty::ImplContainer => {
- let def_id = item.container_id(tcx);
- (
- impl_implied_bounds(tcx, wfcx.param_env, def_id.expect_local(), span),
- tcx.type_of(def_id),
- )
- }
+ let self_ty = match item.container {
+ ty::TraitContainer => tcx.types.self_param,
+ ty::ImplContainer => tcx.type_of(item.container_id(tcx)),
};
match item.kind {
@@ -1002,7 +1010,6 @@ fn check_associated_item(
sig,
hir_sig.decl,
item.def_id.expect_local(),
- &mut implied_bounds,
);
check_method_receiver(wfcx, hir_sig, item, self_ty);
}
@@ -1017,8 +1024,6 @@ fn check_associated_item(
}
}
}
-
- implied_bounds
})
}
@@ -1040,9 +1045,11 @@ fn check_type_defn<'tcx, F>(
) where
F: FnMut(&WfCheckingCtxt<'_, 'tcx>) -> Vec<AdtVariant<'tcx>>,
{
- enter_wf_checking_ctxt(tcx, item.span, item.def_id, |wfcx| {
+ let _ = tcx.representability(item.owner_id.def_id);
+
+ enter_wf_checking_ctxt(tcx, item.span, item.owner_id.def_id, |wfcx| {
let variants = lookup_fields(wfcx);
- let packed = tcx.adt_def(item.def_id).repr().packed();
+ let packed = tcx.adt_def(item.owner_id).repr().packed();
for variant in &variants {
// All field types must be well-formed.
@@ -1066,7 +1073,7 @@ fn check_type_defn<'tcx, F>(
// Just treat unresolved type expression as if it needs drop.
true
} else {
- ty.needs_drop(tcx, tcx.param_env(item.def_id))
+ ty.needs_drop(tcx, tcx.param_env(item.owner_id))
}
}
};
@@ -1098,8 +1105,6 @@ fn check_type_defn<'tcx, F>(
// Explicit `enum` discriminant values must const-evaluate successfully.
if let Some(discr_def_id) = variant.explicit_discr {
- let discr_substs = InternalSubsts::identity_for_item(tcx, discr_def_id.to_def_id());
-
let cause = traits::ObligationCause::new(
tcx.def_span(discr_def_id),
wfcx.body_id,
@@ -1108,31 +1113,28 @@ fn check_type_defn<'tcx, F>(
wfcx.register_obligation(traits::Obligation::new(
cause,
wfcx.param_env,
- ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ty::Unevaluated::new(
- ty::WithOptConstParam::unknown(discr_def_id.to_def_id()),
- discr_substs,
- )))
+ ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(
+ ty::Const::from_anon_const(tcx, discr_def_id),
+ ))
.to_predicate(tcx),
));
}
}
- check_where_clauses(wfcx, item.span, item.def_id);
-
- // No implied bounds in a struct definition.
- FxHashSet::default()
+ check_where_clauses(wfcx, item.span, item.owner_id.def_id);
});
}
#[instrument(skip(tcx, item))]
fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
- debug!(?item.def_id);
+ debug!(?item.owner_id);
- let trait_def = tcx.trait_def(item.def_id);
+ let def_id = item.owner_id.def_id;
+ let trait_def = tcx.trait_def(def_id);
if trait_def.is_marker
|| matches!(trait_def.specialization_kind, TraitSpecializationKind::Marker)
{
- for associated_def_id in &*tcx.associated_item_def_ids(item.def_id) {
+ for associated_def_id in &*tcx.associated_item_def_ids(def_id) {
struct_span_err!(
tcx.sess,
tcx.def_span(*associated_def_id),
@@ -1143,10 +1145,8 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
}
}
- enter_wf_checking_ctxt(tcx, item.span, item.def_id, |wfcx| {
- check_where_clauses(wfcx, item.span, item.def_id);
-
- FxHashSet::default()
+ enter_wf_checking_ctxt(tcx, item.span, def_id, |wfcx| {
+ check_where_clauses(wfcx, item.span, def_id)
});
// Only check traits, don't check trait aliases
@@ -1186,9 +1186,7 @@ fn check_item_fn(
) {
enter_wf_checking_ctxt(tcx, span, def_id, |wfcx| {
let sig = tcx.fn_sig(def_id);
- let mut implied_bounds = FxHashSet::default();
- check_fn_or_method(wfcx, ident.span, sig, decl, def_id, &mut implied_bounds);
- implied_bounds
+ check_fn_or_method(wfcx, ident.span, sig, decl, def_id);
})
}
@@ -1231,13 +1229,10 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: LocalDefId, ty_span: Span, allow_fo
tcx.require_lang_item(LangItem::Sync, Some(ty_span)),
);
}
-
- // No implied bounds in a const, etc.
- FxHashSet::default()
});
}
-#[tracing::instrument(level = "debug", skip(tcx, ast_self_ty, ast_trait_ref))]
+#[instrument(level = "debug", skip(tcx, ast_self_ty, ast_trait_ref))]
fn check_impl<'tcx>(
tcx: TyCtxt<'tcx>,
item: &'tcx hir::Item<'tcx>,
@@ -1245,13 +1240,13 @@ fn check_impl<'tcx>(
ast_trait_ref: &Option<hir::TraitRef<'_>>,
constness: hir::Constness,
) {
- enter_wf_checking_ctxt(tcx, item.span, item.def_id, |wfcx| {
+ enter_wf_checking_ctxt(tcx, item.span, item.owner_id.def_id, |wfcx| {
match *ast_trait_ref {
Some(ref ast_trait_ref) => {
// `#[rustc_reservation_impl]` impls are not real impls and
// therefore don't need to be WF (the trait's `Self: Trait` predicate
// won't hold).
- let trait_ref = tcx.impl_trait_ref(item.def_id).unwrap();
+ let trait_ref = tcx.impl_trait_ref(item.owner_id).unwrap();
let trait_ref = wfcx.normalize(ast_trait_ref.path.span, None, trait_ref);
let trait_pred = ty::TraitPredicate {
trait_ref,
@@ -1273,19 +1268,21 @@ fn check_impl<'tcx>(
wfcx.register_obligations(obligations);
}
None => {
- let self_ty = tcx.type_of(item.def_id);
- let self_ty = wfcx.normalize(item.span, None, self_ty);
+ let self_ty = tcx.type_of(item.owner_id);
+ let self_ty = wfcx.normalize(
+ item.span,
+ Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),
+ self_ty,
+ );
wfcx.register_wf_obligation(
ast_self_ty.span,
- Some(WellFormedLoc::Ty(item.hir_id().expect_owner())),
+ Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),
self_ty.into(),
);
}
}
- check_where_clauses(wfcx, item.span, item.def_id);
-
- impl_implied_bounds(tcx, wfcx.param_env, item.def_id, item.span)
+ check_where_clauses(wfcx, item.span, item.owner_id.def_id);
});
}
@@ -1321,7 +1318,11 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
// parameter includes another (e.g., `<T, U = T>`). In those cases, we can't
// be sure if it will error or not as user might always specify the other.
if !ty.needs_subst() {
- wfcx.register_wf_obligation(tcx.def_span(param.def_id), None, ty.into());
+ wfcx.register_wf_obligation(
+ tcx.def_span(param.def_id),
+ Some(WellFormedLoc::Ty(param.def_id.expect_local())),
+ ty.into(),
+ );
}
}
}
@@ -1426,9 +1427,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
let substituted_pred = predicates.rebind(pred).subst(tcx, substs);
// Don't check non-defaulted params, dependent defaults (including lifetimes)
// or preds with multiple params.
- if substituted_pred.has_param_types_or_consts()
- || param_count.params.len() > 1
- || has_region
+ if substituted_pred.has_non_region_param() || param_count.params.len() > 1 || has_region
{
None
} else if predicates.0.predicates.iter().any(|&(p, _)| p == substituted_pred) {
@@ -1465,21 +1464,26 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
assert_eq!(predicates.predicates.len(), predicates.spans.len());
let wf_obligations =
iter::zip(&predicates.predicates, &predicates.spans).flat_map(|(&p, &sp)| {
- traits::wf::predicate_obligations(infcx, wfcx.param_env, wfcx.body_id, p, sp)
+ traits::wf::predicate_obligations(
+ infcx,
+ wfcx.param_env.without_const(),
+ wfcx.body_id,
+ p,
+ sp,
+ )
});
let obligations: Vec<_> = wf_obligations.chain(default_obligations).collect();
wfcx.register_obligations(obligations);
}
-#[tracing::instrument(level = "debug", skip(wfcx, span, hir_decl))]
+#[instrument(level = "debug", skip(wfcx, span, hir_decl))]
fn check_fn_or_method<'tcx>(
wfcx: &WfCheckingCtxt<'_, 'tcx>,
span: Span,
sig: ty::PolyFnSig<'tcx>,
hir_decl: &hir::FnDecl<'_>,
def_id: LocalDefId,
- implied_bounds: &mut FxHashSet<Ty<'tcx>>,
) {
let tcx = wfcx.tcx();
let sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig);
@@ -1521,23 +1525,66 @@ fn check_fn_or_method<'tcx>(
);
}
- implied_bounds.extend(sig.inputs());
-
- wfcx.register_wf_obligation(hir_decl.output.span(), None, sig.output().into());
+ wfcx.register_wf_obligation(
+ hir_decl.output.span(),
+ Some(WellFormedLoc::Param {
+ function: def_id,
+ param_idx: sig.inputs().len().try_into().unwrap(),
+ }),
+ sig.output().into(),
+ );
- // FIXME(#27579) return types should not be implied bounds
- implied_bounds.insert(sig.output());
+ check_where_clauses(wfcx, span, def_id);
- debug!(?implied_bounds);
+ check_return_position_impl_trait_in_trait_bounds(
+ tcx,
+ wfcx,
+ def_id,
+ sig.output(),
+ hir_decl.output.span(),
+ );
+}
- check_where_clauses(wfcx, span, def_id);
+/// Basically `check_associated_type_bounds`, but separated for now and should be
+/// deduplicated when RPITITs get lowered into real associated items.
+fn check_return_position_impl_trait_in_trait_bounds<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ wfcx: &WfCheckingCtxt<'_, 'tcx>,
+ fn_def_id: LocalDefId,
+ fn_output: Ty<'tcx>,
+ span: Span,
+) {
+ 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::Projection(proj) = ty.kind()
+ && tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder
+ && tcx.impl_trait_in_trait_parent(proj.item_def_id) == fn_def_id.to_def_id()
+ {
+ let bounds = wfcx.tcx().explicit_item_bounds(proj.item_def_id);
+ let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| {
+ let normalized_bound = wfcx.normalize(span, None, bound);
+ traits::wf::predicate_obligations(
+ wfcx.infcx,
+ wfcx.param_env,
+ wfcx.body_id,
+ normalized_bound,
+ bound_span,
+ )
+ });
+ wfcx.register_obligations(wf_obligations);
+ }
+ }
+ }
}
const HELP_FOR_SELF_TYPE: &str = "consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, \
`self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one \
of the previous types except `Self`)";
-#[tracing::instrument(level = "debug", skip(wfcx))]
+#[instrument(level = "debug", skip(wfcx))]
fn check_method_receiver<'tcx>(
wfcx: &WfCheckingCtxt<'_, 'tcx>,
fn_sig: &hir::FnSig<'_>,
@@ -1629,7 +1676,7 @@ fn receiver_is_valid<'tcx>(
// `self: Self` is always valid.
if can_eq_self(receiver_ty) {
if let Err(err) = wfcx.equate_types(&cause, wfcx.param_env, self_ty, receiver_ty) {
- infcx.report_mismatched_types(&cause, self_ty, receiver_ty, err).emit();
+ infcx.err_ctxt().report_mismatched_types(&cause, self_ty, receiver_ty, err).emit();
}
return true;
}
@@ -1661,7 +1708,10 @@ fn receiver_is_valid<'tcx>(
if let Err(err) =
wfcx.equate_types(&cause, wfcx.param_env, self_ty, potential_self_ty)
{
- infcx.report_mismatched_types(&cause, self_ty, potential_self_ty, err).emit();
+ infcx
+ .err_ctxt()
+ .report_mismatched_types(&cause, self_ty, potential_self_ty, err)
+ .emit();
}
break;
@@ -1728,14 +1778,14 @@ fn check_variances_for_type_defn<'tcx>(
item: &hir::Item<'tcx>,
hir_generics: &hir::Generics<'_>,
) {
- let ty = tcx.type_of(item.def_id);
+ let ty = tcx.type_of(item.owner_id);
if tcx.has_error_field(ty) {
return;
}
- let ty_predicates = tcx.predicates_of(item.def_id);
+ let ty_predicates = tcx.predicates_of(item.owner_id);
assert_eq!(ty_predicates.parent, None);
- let variances = tcx.variances_of(item.def_id);
+ let variances = tcx.variances_of(item.owner_id);
let mut constrained_parameters: FxHashSet<_> = variances
.iter()
@@ -1748,7 +1798,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.def_id.to_def_id());
+ let icx = crate::collect::ItemCtxt::new(tcx, item.owner_id.to_def_id());
hir_generics
.predicates
.iter()
@@ -1817,6 +1867,7 @@ fn report_bivariance(
impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
/// Feature gates RFC 2056 -- trivial bounds, checking for global bounds that
/// aren't true.
+ #[instrument(level = "debug", skip(self))]
fn check_false_global_bounds(&mut self) {
let tcx = self.ocx.infcx.tcx;
let mut span = self.span;
@@ -1868,10 +1919,10 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalDefId) {
let items = tcx.hir_module_items(module);
- items.par_items(|item| tcx.ensure().check_well_formed(item.def_id));
- items.par_impl_items(|item| tcx.ensure().check_well_formed(item.def_id));
- items.par_trait_items(|item| tcx.ensure().check_well_formed(item.def_id));
- items.par_foreign_items(|item| tcx.ensure().check_well_formed(item.def_id));
+ items.par_items(|item| tcx.ensure().check_well_formed(item.owner_id));
+ items.par_impl_items(|item| tcx.ensure().check_well_formed(item.owner_id));
+ items.par_trait_items(|item| tcx.ensure().check_well_formed(item.owner_id));
+ items.par_foreign_items(|item| tcx.ensure().check_well_formed(item.owner_id));
}
///////////////////////////////////////////////////////////////////////////
@@ -1924,40 +1975,6 @@ impl<'a, 'tcx> WfCheckingCtxt<'a, 'tcx> {
}
}
-pub fn impl_implied_bounds<'tcx>(
- tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
- impl_def_id: LocalDefId,
- span: Span,
-) -> FxHashSet<Ty<'tcx>> {
- // We completely ignore any obligations caused by normalizing the types
- // we assume to be well formed. Considering that the user of the implied
- // bounds will also normalize them, we leave it to them to emit errors
- // which should result in better causes and spans.
- tcx.infer_ctxt().enter(|infcx| {
- let cause = ObligationCause::misc(span, tcx.hir().local_def_id_to_hir_id(impl_def_id));
- match tcx.impl_trait_ref(impl_def_id) {
- Some(trait_ref) => {
- // Trait impl: take implied bounds from all types that
- // appear in the trait reference.
- match infcx.at(&cause, param_env).normalize(trait_ref) {
- Ok(Normalized { value, obligations: _ }) => value.substs.types().collect(),
- Err(NoSolution) => FxHashSet::default(),
- }
- }
-
- None => {
- // Inherent impl: take implied bounds from the `self` type.
- let self_ty = tcx.type_of(impl_def_id);
- match infcx.at(&cause, param_env).normalize(self_ty) {
- Ok(Normalized { value, obligations: _ }) => FxHashSet::from_iter([value]),
- Err(NoSolution) => FxHashSet::default(),
- }
- }
- }
- })
-}
-
fn error_392(
tcx: TyCtxt<'_>,
span: Span,