impl_m_span,
impl_m_hir_id,
ObligationCauseCode::CompareImplMethodObligation {
- item_name: impl_m.ident.name,
impl_item_def_id: impl_m.def_id,
trait_item_def_id: trait_m.def_id,
},
let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_hir_id);
let param_env =
ty::ParamEnv::new(tcx.intern_predicates(&hybrid_preds.predicates), Reveal::UserFacing);
- let param_env = traits::normalize_param_env_or_error(
- tcx,
- impl_m.def_id,
- param_env,
- normalize_cause.clone(),
- );
+ let param_env =
+ traits::normalize_param_env_or_error(tcx, impl_m.def_id, param_env, normalize_cause);
tcx.infer_ctxt().enter(|infcx| {
let inh = Inherited::new(infcx, impl_m.def_id.expect_local());
let mut selcx = traits::SelectionContext::new(&infcx);
let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_placeholder_substs);
- for predicate in impl_m_own_bounds.predicates {
+ for (predicate, span) in iter::zip(impl_m_own_bounds.predicates, impl_m_own_bounds.spans) {
+ let normalize_cause = traits::ObligationCause::misc(span, impl_m_hir_id);
let traits::Normalized { value: predicate, obligations } =
- traits::normalize(&mut selcx, param_env, normalize_cause.clone(), predicate);
+ traits::normalize(&mut selcx, param_env, normalize_cause, predicate);
inh.register_predicates(obligations);
- inh.register_predicate(traits::Obligation::new(cause.clone(), param_env, predicate));
+ let mut cause = cause.clone();
+ cause.make_mut().span = span;
+ inh.register_predicate(traits::Obligation::new(cause, param_env, predicate));
}
// We now need to check that the signature of the impl method is
let sub_result = infcx.at(&cause, param_env).sup(trait_fty, impl_fty).map(
|InferOk { obligations, .. }| {
+ // FIXME: We'd want to keep more accurate spans than "the method signature" when
+ // processing the comparison between the trait and impl fn, but we sadly lose them
+ // and point at the whole signature when a trait bound or specific input or output
+ // type would be more appropriate. In other places we have a `Vec<Span>`
+ // corresponding to their `Vec<Predicate>`, but we don't have that here.
+ // Fixing this would improve the output of test `issue-83765.rs`.
inh.register_predicates(obligations);
},
);
// Check that all obligations are satisfied by the implementation's
// version.
- if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
- infcx.report_fulfillment_errors(errors, None, false);
+ let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx);
+ if !errors.is_empty() {
+ infcx.report_fulfillment_errors(&errors, None, false);
return Err(ErrorReported);
}
Ok(())
}
+#[instrument(level = "debug", skip(infcx))]
fn extract_spans_for_error_reporting<'a, 'tcx>(
infcx: &infer::InferCtxt<'a, 'tcx>,
terr: &TypeError<'_>,
.params
.iter()
.filter_map(|p| match p.kind {
- GenericParamKind::Type {
- synthetic: Some(hir::SyntheticTyParamKind::ImplTrait),
- ..
- } => Some(p.span),
+ GenericParamKind::Type { synthetic: true, .. } => Some(p.span),
_ => None,
})
.collect();
.params
.iter()
.filter_map(|p| match p.kind {
- GenericParamKind::Type {
- synthetic: Some(hir::SyntheticTyParamKind::ImplTrait),
- ..
- } => Some(p.span),
+ GenericParamKind::Type { synthetic: true, .. } => Some(p.span),
_ => None,
})
.collect();
match (impl_synthetic, trait_synthetic) {
// The case where the impl method uses `impl Trait` but the trait method uses
// explicit generics
- (Some(hir::SyntheticTyParamKind::ImplTrait), None) => {
+ (true, false) => {
err.span_label(impl_span, "expected generic parameter, found `impl Trait`");
(|| {
// try taking the name from the trait impl
}
// The case where the trait method uses `impl Trait`, but the impl method uses
// explicit generics.
- (None, Some(hir::SyntheticTyParamKind::ImplTrait)) => {
+ (false, true) => {
err.span_label(impl_span, "expected `impl Trait`, found generic parameter");
(|| {
let impl_m = impl_m.def_id.as_local()?;
// Check that all obligations are satisfied by the implementation's
// version.
- if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
- infcx.report_fulfillment_errors(errors, None, false);
+ let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx);
+ if !errors.is_empty() {
+ infcx.report_fulfillment_errors(&errors, None, false);
return;
}
impl_ty_span,
impl_ty_hir_id,
ObligationCauseCode::CompareImplTypeObligation {
- item_name: impl_ty.ident.name,
impl_item_def_id: impl_ty.def_id,
trait_item_def_id: trait_ty.def_id,
},
// Check that all obligations are satisfied by the implementation's
// version.
- if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
- infcx.report_fulfillment_errors(errors, None, false);
+ let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx);
+ if !errors.is_empty() {
+ infcx.report_fulfillment_errors(&errors, None, false);
return Err(ErrorReported);
}
let impl_ty_hir_id = tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local());
let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_hir_id);
- let mk_cause = |span| {
- ObligationCause::new(
- impl_ty_span,
- impl_ty_hir_id,
- ObligationCauseCode::BindingObligation(trait_ty.def_id, span),
- )
+ let mk_cause = |span: Span| {
+ let code = if span.is_dummy() {
+ traits::MiscObligation
+ } else {
+ traits::BindingObligation(trait_ty.def_id, span)
+ };
+ ObligationCause::new(impl_ty_span, impl_ty_hir_id, code)
};
let obligations = tcx
// Check that all obligations are satisfied by the implementation's
// version.
- if let Err(ref errors) =
- inh.fulfillment_cx.borrow_mut().select_all_with_constness_or_error(&infcx, constness)
- {
- infcx.report_fulfillment_errors(errors, None, false);
+ let errors =
+ inh.fulfillment_cx.borrow_mut().select_all_with_constness_or_error(&infcx, constness);
+ if !errors.is_empty() {
+ infcx.report_fulfillment_errors(&errors, None, false);
return Err(ErrorReported);
}