summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_hir_analysis/src/check
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:39 +0000
commit1376c5a617be5c25655d0d7cb63e3beaa5a6e026 (patch)
tree3bb8d61aee02bc7a15eab3f36e3b921afc2075d0 /compiler/rustc_hir_analysis/src/check
parentReleasing progress-linux version 1.69.0+dfsg1-1~progress7.99u1. (diff)
downloadrustc-1376c5a617be5c25655d0d7cb63e3beaa5a6e026.tar.xz
rustc-1376c5a617be5c25655d0d7cb63e3beaa5a6e026.zip
Merging upstream version 1.70.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_hir_analysis/src/check')
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs81
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs204
-rw-r--r--compiler/rustc_hir_analysis/src/check/dropck.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs30
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsicck.rs9
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs9
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs125
7 files changed, 256 insertions, 210 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 848828175..0bb98fdf2 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -1,5 +1,5 @@
use crate::check::intrinsicck::InlineAsmCtxt;
-use crate::errors::LinkageType;
+use crate::errors::{self, LinkageType};
use super::compare_impl_item::check_type_bounds;
use super::compare_impl_item::{compare_impl_method, compare_impl_ty};
@@ -22,12 +22,12 @@ use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::util::{Discr, IntTypeExt};
use rustc_middle::ty::{
- self, AdtDef, DefIdTree, ParamEnv, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
- TypeVisitableExt,
+ self, AdtDef, ParamEnv, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
};
use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS};
use rustc_span::symbol::sym;
use rustc_span::{self, Span};
+use rustc_target::abi::FieldIdx;
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedDirective;
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
@@ -115,9 +115,11 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b
allowed_union_field(*elem, tcx, param_env)
}
_ => {
- // Fallback case: allow `ManuallyDrop` and things that are `Copy`.
+ // Fallback case: allow `ManuallyDrop` and things that are `Copy`,
+ // also no need to report an error if the type is unresolved.
ty.ty_adt_def().is_some_and(|adt_def| adt_def.is_manually_drop())
|| ty.is_copy_modulo_regions(tcx, param_env)
+ || ty.references_error()
}
}
}
@@ -132,26 +134,14 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b
Some(Node::Field(field)) => (field.span, field.ty.span),
_ => unreachable!("mir field has to correspond to hir field"),
};
- struct_span_err!(
- tcx.sess,
+ tcx.sess.emit_err(errors::InvalidUnionField {
field_span,
- E0740,
- "unions cannot contain fields that may need dropping"
- )
- .note(
- "a type is guaranteed not to need dropping \
- when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type",
- )
- .multipart_suggestion_verbose(
- "when the type does not implement `Copy`, \
- wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped",
- vec![
- (ty_span.shrink_to_lo(), "std::mem::ManuallyDrop<".into()),
- (ty_span.shrink_to_hi(), ">".into()),
- ],
- Applicability::MaybeIncorrect,
- )
- .emit();
+ sugg: errors::InvalidUnionFieldSuggestion {
+ lo: ty_span.shrink_to_lo(),
+ hi: ty_span.shrink_to_hi(),
+ },
+ note: (),
+ });
return false;
} else if field_ty.needs_drop(tcx, param_env) {
// This should never happen. But we can get here e.g. in case of name resolution errors.
@@ -222,7 +212,7 @@ fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) {
return;
}
- let substs = InternalSubsts::identity_for_item(tcx, item.owner_id.to_def_id());
+ let substs = InternalSubsts::identity_for_item(tcx, item.owner_id);
let span = tcx.def_span(item.owner_id.def_id);
if !tcx.features().impl_trait_projections {
@@ -315,8 +305,8 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
..
}) = item.kind
{
- let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
- let opaque_identity_ty = if in_trait {
+ let substs = InternalSubsts::identity_for_item(tcx, def_id);
+ let opaque_identity_ty = if in_trait && !tcx.lower_impl_trait_in_trait_to_assoc_ty() {
tcx.mk_projection(def_id.to_def_id(), substs)
} else {
tcx.mk_opaque(def_id.to_def_id(), substs)
@@ -455,18 +445,15 @@ fn check_opaque_meets_bounds<'tcx>(
// version.
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
- infcx.err_ctxt().report_fulfillment_errors(&errors, None);
+ infcx.err_ctxt().report_fulfillment_errors(&errors);
}
match origin {
// Checked when type checking the function containing them.
hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {}
// Can have different predicates to their defining use
hir::OpaqueTyOrigin::TyAlias => {
- let outlives_environment = OutlivesEnvironment::new(param_env);
- let _ = infcx.err_ctxt().check_region_obligations_and_report_errors(
- defining_use_anchor,
- &outlives_environment,
- );
+ let outlives_env = OutlivesEnvironment::new(param_env);
+ let _ = ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env);
}
}
// Clean up after ourselves
@@ -485,7 +472,7 @@ fn is_enum_of_nonnullable_ptr<'tcx>(
let [var_one, var_two] = &adt_def.variants().raw[..] else {
return false;
};
- let (([], [field]) | ([field], [])) = (&var_one.fields[..], &var_two.fields[..]) else {
+ let (([], [field]) | ([field], [])) = (&var_one.fields.raw[..], &var_two.fields.raw[..]) else {
return false;
};
matches!(field.ty(tcx, substs).kind(), ty::FnPtr(..) | ty::Ref(..))
@@ -546,7 +533,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
}
ty::AssocKind::Type if assoc_item.defaultness(tcx).has_value() => {
let trait_substs =
- InternalSubsts::identity_for_item(tcx, id.owner_id.to_def_id());
+ InternalSubsts::identity_for_item(tcx, id.owner_id);
let _: Result<_, rustc_errors::ErrorGuaranteed> = check_type_bounds(
tcx,
assoc_item,
@@ -565,10 +552,18 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
check_union(tcx, id.owner_id.def_id);
}
DefKind::OpaqueTy => {
- check_opaque(tcx, id);
+ let opaque = tcx.hir().expect_item(id.owner_id.def_id).expect_opaque_ty();
+ if let hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id) = opaque.origin
+ && let hir::Node::TraitItem(trait_item) = tcx.hir().get_by_def_id(fn_def_id)
+ && let (_, hir::TraitFn::Required(..)) = trait_item.expect_fn()
+ {
+ // Skip opaques from RPIT in traits with no default body.
+ } else {
+ check_opaque(tcx, id);
+ }
}
DefKind::ImplTraitPlaceholder => {
- let parent = tcx.impl_trait_in_trait_parent(id.owner_id.to_def_id());
+ let parent = tcx.impl_trait_in_trait_parent_fn(id.owner_id.to_def_id());
// Only check the validity of this opaque type if the function has a default body
if let hir::Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)),
@@ -896,7 +891,7 @@ pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
struct_span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty").emit();
return;
}
- let e = fields[0].ty(tcx, substs);
+ let e = fields[FieldIdx::from_u32(0)].ty(tcx, substs);
if !fields.iter().all(|f| f.ty(tcx, substs) == e) {
struct_span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous")
.span_label(sp, "SIMD elements must have the same type")
@@ -1172,7 +1167,7 @@ fn check_enum(tcx: TyCtxt<'_>, def_id: LocalDefId) {
def.destructor(tcx); // force the destructor to be evaluated
if def.variants().is_empty() {
- if let Some(attr) = tcx.get_attrs(def_id.to_def_id(), sym::repr).next() {
+ if let Some(attr) = tcx.get_attrs(def_id, sym::repr).next() {
struct_span_err!(
tcx.sess,
attr.span,
@@ -1511,6 +1506,14 @@ fn opaque_type_cycle_error(
{
label_match(interior_ty.ty, interior_ty.span);
}
+ if tcx.sess.opts.unstable_opts.drop_tracking_mir
+ && let DefKind::Generator = tcx.def_kind(closure_def_id)
+ {
+ let generator_layout = tcx.mir_generator_witnesses(closure_def_id);
+ for interior_ty in &generator_layout.field_tys {
+ label_match(interior_ty.ty, interior_ty.source_info.span);
+ }
+ }
}
}
}
@@ -1548,6 +1551,6 @@ pub(super) fn check_generator_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) {
let errors = fulfillment_cx.select_all_or_error(&infcx);
debug!(?errors);
if !errors.is_empty() {
- infcx.err_ctxt().report_fulfillment_errors(&errors, None);
+ infcx.err_ctxt().report_fulfillment_errors(&errors);
}
}
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 691d3f8d9..5d119a773 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -16,8 +16,7 @@ use rustc_infer::traits::util;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::util::ExplicitSelf;
use rustc_middle::ty::{
- self, DefIdTree, InternalSubsts, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable,
- TypeVisitableExt,
+ self, InternalSubsts, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
};
use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt};
use rustc_span::Span;
@@ -321,7 +320,7 @@ fn compare_method_predicate_entailment<'tcx>(
});
}
CheckImpliedWfMode::Skip => {
- let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None);
+ let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
return Err(reported);
}
}
@@ -331,13 +330,8 @@ fn compare_method_predicate_entailment<'tcx>(
// lifetime parameters.
let outlives_env = OutlivesEnvironment::with_bounds(
param_env,
- Some(infcx),
infcx.implied_bounds_tys(param_env, impl_m_def_id, wf_tys.clone()),
);
- infcx.process_registered_region_obligations(
- outlives_env.region_bound_pairs(),
- outlives_env.param_env,
- );
let errors = infcx.resolve_regions(&outlives_env);
if !errors.is_empty() {
// FIXME(compiler-errors): This can be simplified when IMPLIED_BOUNDS_ENTAILMENT
@@ -584,13 +578,13 @@ fn compare_asyncness<'tcx>(
#[instrument(skip(tcx), level = "debug", ret)]
pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
tcx: TyCtxt<'tcx>,
- def_id: DefId,
+ impl_m_def_id: LocalDefId,
) -> Result<&'tcx FxHashMap<DefId, Ty<'tcx>>, ErrorGuaranteed> {
- let impl_m = tcx.opt_associated_item(def_id).unwrap();
+ let impl_m = tcx.opt_associated_item(impl_m_def_id.to_def_id()).unwrap();
let trait_m = tcx.opt_associated_item(impl_m.trait_item_def_id.unwrap()).unwrap();
let impl_trait_ref =
tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap().subst_identity();
- let param_env = tcx.param_env(def_id);
+ let param_env = tcx.param_env(impl_m_def_id);
// First, check a few of the same things as `compare_impl_method`,
// just so we don't ICE during substitution later.
@@ -600,7 +594,6 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
let trait_to_impl_substs = impl_trait_ref.substs;
- let impl_m_def_id = impl_m.def_id.expect_local();
let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m_def_id);
let return_span = tcx.hir().fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span();
let cause = ObligationCause::new(
@@ -721,23 +714,22 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
// RPITs.
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
- let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None);
+ let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
return Err(reported);
}
+ let collected_types = collector.types;
+
// Finally, resolve all regions. This catches wily misuses of
// lifetime parameters.
- let outlives_environment = OutlivesEnvironment::with_bounds(
+ let outlives_env = OutlivesEnvironment::with_bounds(
param_env,
- Some(infcx),
infcx.implied_bounds_tys(param_env, impl_m_def_id, wf_tys),
);
- infcx
- .err_ctxt()
- .check_region_obligations_and_report_errors(impl_m_def_id, &outlives_environment)?;
+ ocx.resolve_regions_and_report_errors(impl_m_def_id, &outlives_env)?;
let mut collected_tys = FxHashMap::default();
- for (def_id, (ty, substs)) in collector.types {
+ for (def_id, (ty, substs)) in collected_types {
match infcx.fully_resolve(ty) {
Ok(ty) => {
// `ty` contains free regions that we created earlier while liberating the
@@ -831,7 +823,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx> {
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
if let ty::Alias(ty::Projection, proj) = ty.kind()
- && self.interner().def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder
+ && self.interner().is_impl_trait_in_trait(proj.def_id)
{
if let Some((ty, _)) = self.types.get(&proj.def_id) {
return *ty;
@@ -1206,6 +1198,17 @@ fn compare_number_of_generics<'tcx>(
return Ok(());
}
+ // We never need to emit a separate error for RPITITs, since if an RPITIT
+ // has mismatched type or const generic arguments, then the method that it's
+ // inheriting the generics from will also have mismatched arguments, and
+ // we'll report an error for that instead. Delay a bug for safety, though.
+ if tcx.opt_rpitit_info(trait_.def_id).is_some() {
+ return Err(tcx.sess.delay_span_bug(
+ rustc_span::DUMMY_SP,
+ "errors comparing numbers of generics of trait/impl functions were not emitted",
+ ));
+ }
+
let matchings = [
("type", trait_own_counts.types, impl_own_counts.types),
("const", trait_own_counts.consts, impl_own_counts.consts),
@@ -1732,14 +1735,11 @@ pub(super) fn compare_impl_const_raw(
// version.
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
- return Err(infcx.err_ctxt().report_fulfillment_errors(&errors, None));
+ return Err(infcx.err_ctxt().report_fulfillment_errors(&errors));
}
- let outlives_environment = OutlivesEnvironment::new(param_env);
- infcx
- .err_ctxt()
- .check_region_obligations_and_report_errors(impl_const_item_def, &outlives_environment)?;
- Ok(())
+ let outlives_env = OutlivesEnvironment::new(param_env);
+ ocx.resolve_regions_and_report_errors(impl_const_item_def, &outlives_env)
}
pub(super) fn compare_impl_ty<'tcx>(
@@ -1832,19 +1832,14 @@ fn compare_type_predicate_entailment<'tcx>(
// version.
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
- let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None);
+ let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
return Err(reported);
}
// Finally, resolve all regions. This catches wily misuses of
// lifetime parameters.
- let outlives_environment = OutlivesEnvironment::new(param_env);
- infcx.err_ctxt().check_region_obligations_and_report_errors(
- impl_ty.def_id.expect_local(),
- &outlives_environment,
- )?;
-
- Ok(())
+ let outlives_env = OutlivesEnvironment::new(param_env);
+ ocx.resolve_regions_and_report_errors(impl_ty_def_id, &outlives_env)
}
/// Validate that `ProjectionCandidate`s created for this associated type will
@@ -1867,14 +1862,17 @@ pub(super) fn check_type_bounds<'tcx>(
impl_ty: ty::AssocItem,
impl_trait_ref: ty::TraitRef<'tcx>,
) -> Result<(), ErrorGuaranteed> {
+ let param_env = tcx.param_env(impl_ty.def_id);
+ let container_id = impl_ty.container_id(tcx);
// Given
//
// impl<A, B> Foo<u32> for (A, B) {
- // type Bar<C> =...
+ // type Bar<C> = Wrapper<A, B, C>
// }
//
// - `impl_trait_ref` would be `<(A, B) as Foo<u32>>`
- // - `impl_ty_substs` would be `[A, B, ^0.0]` (`^0.0` here is the bound var with db 0 and index 0)
+ // - `normalize_impl_ty_substs` would be `[A, B, ^0.0]` (`^0.0` here is the bound var with db 0 and index 0)
+ // - `normalize_impl_ty` would be `Wrapper<A, B, ^0.0>`
// - `rebased_substs` would be `[(A, B), u32, ^0.0]`, combining the substs from
// the *trait* with the generic associated type parameters (as bound vars).
//
@@ -1903,56 +1901,46 @@ pub(super) fn check_type_bounds<'tcx>(
// Member<C: Eq> = .... That type would fail a well-formedness check that we ought to be doing
// elsewhere, which would check that any <T as Family>::Member<X> meets the bounds declared in
// the trait (notably, that X: Eq and T: Family).
- let defs: &ty::Generics = tcx.generics_of(impl_ty.def_id);
- let mut substs = smallvec::SmallVec::with_capacity(defs.count());
- if let Some(def_id) = defs.parent {
- let parent_defs = tcx.generics_of(def_id);
- InternalSubsts::fill_item(&mut substs, tcx, parent_defs, &mut |param, _| {
- tcx.mk_param_from_def(param)
- });
- }
let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> =
- smallvec::SmallVec::with_capacity(defs.count());
- InternalSubsts::fill_single(&mut substs, defs, &mut |param, _| match param.kind {
- GenericParamDefKind::Type { .. } => {
- let kind = ty::BoundTyKind::Param(param.def_id, param.name);
- let bound_var = ty::BoundVariableKind::Ty(kind);
- bound_vars.push(bound_var);
- tcx.mk_bound(
- ty::INNERMOST,
- ty::BoundTy { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind },
- )
- .into()
- }
- GenericParamDefKind::Lifetime => {
- let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name);
- let bound_var = ty::BoundVariableKind::Region(kind);
- bound_vars.push(bound_var);
- tcx.mk_re_late_bound(
- ty::INNERMOST,
- ty::BoundRegion { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind },
- )
- .into()
- }
- GenericParamDefKind::Const { .. } => {
- let bound_var = ty::BoundVariableKind::Const;
- bound_vars.push(bound_var);
- tcx.mk_const(
- ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_usize(bound_vars.len() - 1)),
- tcx.type_of(param.def_id).subst_identity(),
- )
- .into()
- }
- });
- let bound_vars = tcx.mk_bound_variable_kinds(&bound_vars);
- let impl_ty_substs = tcx.mk_substs(&substs);
- let container_id = impl_ty.container_id(tcx);
-
- let rebased_substs = impl_ty_substs.rebase_onto(tcx, container_id, impl_trait_ref.substs);
- let impl_ty_value = tcx.type_of(impl_ty.def_id).subst_identity();
-
- let param_env = tcx.param_env(impl_ty.def_id);
-
+ smallvec::SmallVec::with_capacity(tcx.generics_of(impl_ty.def_id).params.len());
+ // Extend the impl's identity substs with late-bound GAT vars
+ let normalize_impl_ty_substs = ty::InternalSubsts::identity_for_item(tcx, container_id)
+ .extend_to(tcx, impl_ty.def_id, |param, _| match param.kind {
+ GenericParamDefKind::Type { .. } => {
+ let kind = ty::BoundTyKind::Param(param.def_id, param.name);
+ let bound_var = ty::BoundVariableKind::Ty(kind);
+ bound_vars.push(bound_var);
+ tcx.mk_bound(
+ ty::INNERMOST,
+ ty::BoundTy { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind },
+ )
+ .into()
+ }
+ GenericParamDefKind::Lifetime => {
+ let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name);
+ let bound_var = ty::BoundVariableKind::Region(kind);
+ bound_vars.push(bound_var);
+ tcx.mk_re_late_bound(
+ ty::INNERMOST,
+ ty::BoundRegion { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind },
+ )
+ .into()
+ }
+ GenericParamDefKind::Const { .. } => {
+ let bound_var = ty::BoundVariableKind::Const;
+ bound_vars.push(bound_var);
+ tcx.mk_const(
+ ty::ConstKind::Bound(
+ ty::INNERMOST,
+ ty::BoundVar::from_usize(bound_vars.len() - 1),
+ ),
+ tcx.type_of(param.def_id)
+ .no_bound_vars()
+ .expect("const parameter types cannot be generic"),
+ )
+ .into()
+ }
+ });
// When checking something like
//
// trait X { type Y: PartialEq<<Self as X>::Y> }
@@ -1962,9 +1950,13 @@ pub(super) fn check_type_bounds<'tcx>(
// we want <T as X>::Y to normalize to S. This is valid because we are
// checking the default value specifically here. Add this equality to the
// ParamEnv for normalization specifically.
+ let normalize_impl_ty = tcx.type_of(impl_ty.def_id).subst(tcx, normalize_impl_ty_substs);
+ let rebased_substs =
+ normalize_impl_ty_substs.rebase_onto(tcx, container_id, impl_trait_ref.substs);
+ let bound_vars = tcx.mk_bound_variable_kinds(&bound_vars);
let normalize_param_env = {
let mut predicates = param_env.caller_bounds().iter().collect::<Vec<_>>();
- match impl_ty_value.kind() {
+ match normalize_impl_ty.kind() {
ty::Alias(ty::Projection, proj)
if proj.def_id == trait_ty.def_id && proj.substs == rebased_substs =>
{
@@ -1978,7 +1970,7 @@ pub(super) fn check_type_bounds<'tcx>(
ty::Binder::bind_with_vars(
ty::ProjectionPredicate {
projection_ty: tcx.mk_alias_ty(trait_ty.def_id, rebased_substs),
- term: impl_ty_value.into(),
+ term: normalize_impl_ty.into(),
},
bound_vars,
)
@@ -1996,13 +1988,20 @@ pub(super) fn check_type_bounds<'tcx>(
let infcx = tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(&infcx);
- let impl_ty_span = match tcx.hir().get_by_def_id(impl_ty_def_id) {
- hir::Node::TraitItem(hir::TraitItem {
- kind: hir::TraitItemKind::Type(_, Some(ty)),
- ..
- }) => ty.span,
- hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Type(ty), .. }) => ty.span,
- _ => bug!(),
+ // A synthetic impl Trait for RPITIT desugaring has no HIR, which we currently use to get the
+ // span for an impl's associated type. Instead, for these, use the def_span for the synthesized
+ // associated type.
+ let impl_ty_span = if tcx.opt_rpitit_info(impl_ty.def_id).is_some() {
+ tcx.def_span(impl_ty_def_id)
+ } else {
+ match tcx.hir().get_by_def_id(impl_ty_def_id) {
+ hir::Node::TraitItem(hir::TraitItem {
+ kind: hir::TraitItemKind::Type(_, Some(ty)),
+ ..
+ }) => ty.span,
+ hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Type(ty), .. }) => ty.span,
+ _ => bug!(),
+ }
};
let assumed_wf_types = ocx.assumed_wf_types(param_env, impl_ty_span, impl_ty_def_id);
@@ -2023,7 +2022,7 @@ pub(super) fn check_type_bounds<'tcx>(
ObligationCause::new(impl_ty_span, impl_ty_def_id, code)
};
- let obligations = tcx
+ let obligations: Vec<_> = tcx
.bound_explicit_item_bounds(trait_ty.def_id)
.subst_iter_copied(tcx, rebased_substs)
.map(|(concrete_ty_bound, span)| {
@@ -2033,7 +2032,7 @@ pub(super) fn check_type_bounds<'tcx>(
.collect();
debug!("check_type_bounds: item_bounds={:?}", obligations);
- for mut obligation in util::elaborate_obligations(tcx, obligations) {
+ for mut obligation in util::elaborate(tcx, obligations) {
let normalized_predicate =
ocx.normalize(&normalize_cause, normalize_param_env, obligation.predicate);
debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate);
@@ -2045,22 +2044,15 @@ pub(super) fn check_type_bounds<'tcx>(
// version.
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
- let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None);
+ let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
return Err(reported);
}
// Finally, resolve all regions. This catches wily misuses of
// lifetime parameters.
let implied_bounds = infcx.implied_bounds_tys(param_env, impl_ty_def_id, assumed_wf_types);
- let outlives_environment =
- OutlivesEnvironment::with_bounds(param_env, Some(&infcx), implied_bounds);
-
- infcx.err_ctxt().check_region_obligations_and_report_errors(
- impl_ty.def_id.expect_local(),
- &outlives_environment,
- )?;
-
- Ok(())
+ let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
+ ocx.resolve_regions_and_report_errors(impl_ty_def_id, &outlives_env)
}
fn assoc_item_kind_str(impl_item: &ty::AssocItem) -> &'static str {
diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs
index 2bb724138..111bf5e54 100644
--- a/compiler/rustc_hir_analysis/src/check/dropck.rs
+++ b/compiler/rustc_hir_analysis/src/check/dropck.rs
@@ -253,10 +253,6 @@ impl<'tcx> TypeRelation<'tcx> for SimpleEqRelation<'tcx> {
self.tcx
}
- fn intercrate(&self) -> bool {
- false
- }
-
fn param_env(&self) -> ty::ParamEnv<'tcx> {
self.param_env
}
@@ -269,10 +265,6 @@ impl<'tcx> TypeRelation<'tcx> for SimpleEqRelation<'tcx> {
true
}
- fn mark_ambiguous(&mut self) {
- bug!()
- }
-
fn relate_with_variance<T: Relate<'tcx>>(
&mut self,
_: ty::Variance,
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 054284cce..854974d16 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -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,
);
@@ -138,14 +139,14 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
let name_str = intrinsic_name.as_str();
let bound_vars = tcx.mk_bound_variable_kinds(&[
- ty::BoundVariableKind::Region(ty::BrAnon(0, None)),
+ ty::BoundVariableKind::Region(ty::BrAnon(None)),
ty::BoundVariableKind::Region(ty::BrEnv),
]);
let mk_va_list_ty = |mutbl| {
tcx.lang_items().va_list().map(|did| {
let region = tcx.mk_re_late_bound(
ty::INNERMOST,
- ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) },
+ ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(None) },
);
let env_region = tcx.mk_re_late_bound(
ty::INNERMOST,
@@ -222,6 +223,21 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
],
tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
),
+ sym::option_payload_ptr => {
+ let option_def_id = tcx.require_lang_item(hir::LangItem::Option, None);
+ let p0 = param(0);
+ (
+ 1,
+ vec![tcx.mk_ptr(ty::TypeAndMut {
+ ty: tcx.mk_adt(
+ tcx.adt_def(option_def_id),
+ tcx.mk_substs_from_iter([ty::GenericArg::from(p0)].into_iter()),
+ ),
+ mutbl: hir::Mutability::Not,
+ })],
+ tcx.mk_ptr(ty::TypeAndMut { ty: p0, mutbl: hir::Mutability::Not }),
+ )
+ }
sym::ptr_mask => (
1,
vec![
@@ -300,6 +316,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
sym::nearbyintf64 => (0, vec![tcx.types.f64], tcx.types.f64),
sym::roundf32 => (0, vec![tcx.types.f32], tcx.types.f32),
sym::roundf64 => (0, vec![tcx.types.f64], tcx.types.f64),
+ sym::roundevenf32 => (0, vec![tcx.types.f32], tcx.types.f32),
+ sym::roundevenf64 => (0, vec![tcx.types.f64], tcx.types.f64),
sym::volatile_load | sym::unaligned_volatile_load => {
(1, vec![tcx.mk_imm_ptr(param(0))], param(0))
@@ -361,14 +379,15 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
sym::likely => (0, vec![tcx.types.bool], tcx.types.bool),
sym::unlikely => (0, vec![tcx.types.bool], tcx.types.bool),
+ sym::read_via_copy => (1, vec![tcx.mk_imm_ptr(param(0))], param(0)),
+
sym::discriminant_value => {
let assoc_items = tcx.associated_item_def_ids(
tcx.require_lang_item(hir::LangItem::DiscriminantKind, None),
);
let discriminant_def_id = assoc_items[0];
- let br =
- ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) };
+ let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(None) };
(
1,
vec![tcx.mk_imm_ref(tcx.mk_re_late_bound(ty::INNERMOST, br), param(0))],
@@ -420,8 +439,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
sym::nontemporal_store => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),
sym::raw_eq => {
- let br =
- ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) };
+ let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(None) };
let param_ty = tcx.mk_imm_ref(tcx.mk_re_late_bound(ty::INNERMOST, br), param(0));
(1, vec![param_ty; 2], tcx.types.bool)
}
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
index b1d5a27be..0d482b53a 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
@@ -1,10 +1,11 @@
use rustc_ast::InlineAsmTemplatePiece;
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir;
use rustc_middle::ty::{self, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy};
use rustc_session::lint;
use rustc_span::def_id::LocalDefId;
use rustc_span::{Symbol, DUMMY_SP};
+use rustc_target::abi::FieldIdx;
use rustc_target::asm::{InlineAsmReg, InlineAsmRegClass, InlineAsmRegOrRegClass, InlineAsmType};
pub struct InlineAsmCtxt<'a, 'tcx> {
@@ -51,7 +52,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
template: &[InlineAsmTemplatePiece],
is_input: bool,
tied_input: Option<(&'tcx hir::Expr<'tcx>, Option<InlineAsmType>)>,
- target_features: &FxHashSet<Symbol>,
+ target_features: &FxIndexSet<Symbol>,
) -> Option<InlineAsmType> {
let ty = (self.get_operand_ty)(expr);
if ty.has_non_region_infer() {
@@ -82,7 +83,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
}
ty::Adt(adt, substs) if adt.repr().simd() => {
let fields = &adt.non_enum_variant().fields;
- let elem_ty = fields[0].ty(self.tcx, substs);
+ let elem_ty = fields[FieldIdx::from_u32(0)].ty(self.tcx, substs);
match elem_ty.kind() {
ty::Never | ty::Error(_) => return None,
ty::Int(IntTy::I8) | ty::Uint(UintTy::U8) => {
@@ -201,7 +202,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
// (!). In that case we still need the earlier check to verify that the
// register class is usable at all.
if let Some(feature) = feature {
- if !target_features.contains(&feature) {
+ if !target_features.contains(feature) {
let msg = &format!("`{}` target feature is not enabled", feature);
let mut err = self.tcx.sess.struct_span_err(expr.span, msg);
err.note(&format!(
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 9acfc1b3d..8fe4c44fc 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -109,8 +109,8 @@ pub fn provide(providers: &mut Providers) {
};
}
-fn adt_destructor(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::Destructor> {
- tcx.calculate_dtor(def_id, dropck::check_drop_impl)
+fn adt_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::Destructor> {
+ tcx.calculate_dtor(def_id.to_def_id(), dropck::check_drop_impl)
}
/// Given a `DefId` for an opaque type in return position, find its parent item's return
@@ -202,8 +202,11 @@ fn missing_items_err(
missing_items: &[ty::AssocItem],
full_impl_span: Span,
) {
+ let missing_items =
+ missing_items.iter().filter(|trait_item| tcx.opt_rpitit_info(trait_item.def_id).is_none());
+
let missing_items_msg = missing_items
- .iter()
+ .clone()
.map(|trait_item| trait_item.name.to_string())
.collect::<Vec<_>>()
.join("`, `");
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