Skip to content

Commit 680ba90

Browse files
authored
Rollup merge of #104295 - compiler-errors:rpitit-generics-parity, r=eholk
Check generics parity before collecting return-position `impl Trait`s in trait The only thing is that this duplicates the error message for number of generics mismatch, but we already deduplicate that error message in Cargo. I could add a flag to delay the error if the reviewer cares. Fixes #104281 Also drive-by adds a few comments to the `collect_trait_impl_trait_tys` method, and removes an unused argument from `compare_number_of_generics`.
2 parents a78c9be + df5f247 commit 680ba90

File tree

3 files changed

+65
-32
lines changed

3 files changed

+65
-32
lines changed

Diff for: compiler/rustc_hir_analysis/src/check/compare_method.rs

+36-32
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,8 @@ use rustc_infer::traits::util;
1414
use rustc_middle::ty::error::{ExpectedFound, TypeError};
1515
use rustc_middle::ty::util::ExplicitSelf;
1616
use rustc_middle::ty::{
17-
self, AssocItem, DefIdTree, TraitRef, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable,
18-
TypeVisitable,
17+
self, DefIdTree, InternalSubsts, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable,
1918
};
20-
use rustc_middle::ty::{FnSig, InternalSubsts};
2119
use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt};
2220
use rustc_span::Span;
2321
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
@@ -51,11 +49,11 @@ pub(crate) fn compare_impl_method<'tcx>(
5149
return;
5250
}
5351

54-
if let Err(_) = compare_number_of_generics(tcx, impl_m, impl_m_span, trait_m, trait_item_span) {
52+
if let Err(_) = compare_number_of_generics(tcx, impl_m, trait_m, trait_item_span, false) {
5553
return;
5654
}
5755

58-
if let Err(_) = compare_generic_param_kinds(tcx, impl_m, trait_m) {
56+
if let Err(_) = compare_generic_param_kinds(tcx, impl_m, trait_m, false) {
5957
return;
6058
}
6159

@@ -144,9 +142,9 @@ pub(crate) fn compare_impl_method<'tcx>(
144142
#[instrument(level = "debug", skip(tcx, impl_m_span, impl_trait_ref))]
145143
fn compare_predicate_entailment<'tcx>(
146144
tcx: TyCtxt<'tcx>,
147-
impl_m: &AssocItem,
145+
impl_m: &ty::AssocItem,
148146
impl_m_span: Span,
149-
trait_m: &AssocItem,
147+
trait_m: &ty::AssocItem,
150148
impl_trait_ref: ty::TraitRef<'tcx>,
151149
) -> Result<(), ErrorGuaranteed> {
152150
let trait_to_impl_substs = impl_trait_ref.substs;
@@ -157,8 +155,7 @@ fn compare_predicate_entailment<'tcx>(
157155
// FIXME(@lcnr): remove that after removing `cause.body_id` from
158156
// obligations.
159157
let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
160-
// We sometimes modify the span further down.
161-
let mut cause = ObligationCause::new(
158+
let cause = ObligationCause::new(
162159
impl_m_span,
163160
impl_m_hir_id,
164161
ObligationCauseCode::CompareImplItemObligation {
@@ -307,14 +304,13 @@ fn compare_predicate_entailment<'tcx>(
307304
debug!(?terr, "sub_types failed: impl ty {:?}, trait ty {:?}", impl_fty, trait_fty);
308305

309306
let emitted = report_trait_method_mismatch(
310-
tcx,
311-
&mut cause,
312307
&infcx,
308+
cause,
313309
terr,
314310
(trait_m, trait_fty),
315311
(impl_m, impl_fty),
316-
&trait_sig,
317-
&impl_trait_ref,
312+
trait_sig,
313+
impl_trait_ref,
318314
);
319315
return Err(emitted);
320316
}
@@ -352,11 +348,15 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
352348
let impl_trait_ref = tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap();
353349
let param_env = tcx.param_env(def_id);
354350

351+
// First, check a few of the same thing as `compare_impl_method`, just so we don't ICE during substitutions later.
352+
compare_number_of_generics(tcx, impl_m, trait_m, tcx.hir().span_if_local(impl_m.def_id), true)?;
353+
compare_generic_param_kinds(tcx, impl_m, trait_m, true)?;
354+
355355
let trait_to_impl_substs = impl_trait_ref.substs;
356356

357357
let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
358358
let return_span = tcx.hir().fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span();
359-
let mut cause = ObligationCause::new(
359+
let cause = ObligationCause::new(
360360
return_span,
361361
impl_m_hir_id,
362362
ObligationCauseCode::CompareImplItemObligation {
@@ -376,6 +376,7 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
376376
let infcx = &tcx.infer_ctxt().build();
377377
let ocx = ObligationCtxt::new(infcx);
378378

379+
// Normalize the impl signature with fresh variables for lifetime inference.
379380
let norm_cause = ObligationCause::misc(return_span, impl_m_hir_id);
380381
let impl_sig = ocx.normalize(
381382
norm_cause.clone(),
@@ -388,6 +389,10 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
388389
);
389390
let impl_return_ty = impl_sig.output();
390391

392+
// Normalize the trait signature with liberated bound vars, passing it through
393+
// the ImplTraitInTraitCollector, which gathers all of the RPITITs and replaces
394+
// them with inference variables.
395+
// We will use these inference variables to collect the hidden types of RPITITs.
391396
let mut collector = ImplTraitInTraitCollector::new(&ocx, return_span, param_env, impl_m_hir_id);
392397
let unnormalized_trait_sig = tcx
393398
.liberate_late_bound_regions(
@@ -448,14 +453,13 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
448453
// emit an error now because `compare_predicate_entailment` will not report the error
449454
// when normalization fails.
450455
let emitted = report_trait_method_mismatch(
451-
tcx,
452-
&mut cause,
453456
infcx,
457+
cause,
454458
terr,
455459
(trait_m, trait_fty),
456460
(impl_m, impl_fty),
457-
&trait_sig,
458-
&impl_trait_ref,
461+
trait_sig,
462+
impl_trait_ref,
459463
);
460464
return Err(emitted);
461465
}
@@ -625,23 +629,21 @@ impl<'tcx> TypeFolder<'tcx> for ImplTraitInTraitCollector<'_, 'tcx> {
625629
}
626630

627631
fn report_trait_method_mismatch<'tcx>(
628-
tcx: TyCtxt<'tcx>,
629-
cause: &mut ObligationCause<'tcx>,
630632
infcx: &InferCtxt<'tcx>,
633+
mut cause: ObligationCause<'tcx>,
631634
terr: TypeError<'tcx>,
632-
(trait_m, trait_fty): (&AssocItem, Ty<'tcx>),
633-
(impl_m, impl_fty): (&AssocItem, Ty<'tcx>),
634-
trait_sig: &FnSig<'tcx>,
635-
impl_trait_ref: &TraitRef<'tcx>,
635+
(trait_m, trait_fty): (&ty::AssocItem, Ty<'tcx>),
636+
(impl_m, impl_fty): (&ty::AssocItem, Ty<'tcx>),
637+
trait_sig: ty::FnSig<'tcx>,
638+
impl_trait_ref: ty::TraitRef<'tcx>,
636639
) -> ErrorGuaranteed {
640+
let tcx = infcx.tcx;
637641
let (impl_err_span, trait_err_span) =
638642
extract_spans_for_error_reporting(&infcx, terr, &cause, impl_m, trait_m);
639643

640-
cause.span = impl_err_span;
641-
642644
let mut diag = struct_span_err!(
643645
tcx.sess,
644-
cause.span(),
646+
impl_err_span,
645647
E0053,
646648
"method `{}` has an incompatible type for trait",
647649
trait_m.name
@@ -712,6 +714,7 @@ fn report_trait_method_mismatch<'tcx>(
712714
_ => {}
713715
}
714716

717+
cause.span = impl_err_span;
715718
infcx.err_ctxt().note_type_err(
716719
&mut diag,
717720
&cause,
@@ -922,9 +925,9 @@ fn compare_self_type<'tcx>(
922925
fn compare_number_of_generics<'tcx>(
923926
tcx: TyCtxt<'tcx>,
924927
impl_: &ty::AssocItem,
925-
_impl_span: Span,
926928
trait_: &ty::AssocItem,
927929
trait_span: Option<Span>,
930+
delay: bool,
928931
) -> Result<(), ErrorGuaranteed> {
929932
let trait_own_counts = tcx.generics_of(trait_.def_id).own_counts();
930933
let impl_own_counts = tcx.generics_of(impl_.def_id).own_counts();
@@ -1054,7 +1057,7 @@ fn compare_number_of_generics<'tcx>(
10541057
err.span_label(*span, "`impl Trait` introduces an implicit type parameter");
10551058
}
10561059

1057-
let reported = err.emit();
1060+
let reported = err.emit_unless(delay);
10581061
err_occurred = Some(reported);
10591062
}
10601063
}
@@ -1306,6 +1309,7 @@ fn compare_generic_param_kinds<'tcx>(
13061309
tcx: TyCtxt<'tcx>,
13071310
impl_item: &ty::AssocItem,
13081311
trait_item: &ty::AssocItem,
1312+
delay: bool,
13091313
) -> Result<(), ErrorGuaranteed> {
13101314
assert_eq!(impl_item.kind, trait_item.kind);
13111315

@@ -1363,7 +1367,7 @@ fn compare_generic_param_kinds<'tcx>(
13631367
err.span_label(impl_header_span, "");
13641368
err.span_label(param_impl_span, make_param_message("found", param_impl));
13651369

1366-
let reported = err.emit();
1370+
let reported = err.emit_unless(delay);
13671371
return Err(reported);
13681372
}
13691373
}
@@ -1489,9 +1493,9 @@ pub(crate) fn compare_ty_impl<'tcx>(
14891493
debug!("compare_impl_type(impl_trait_ref={:?})", impl_trait_ref);
14901494

14911495
let _: Result<(), ErrorGuaranteed> = (|| {
1492-
compare_number_of_generics(tcx, impl_ty, impl_ty_span, trait_ty, trait_item_span)?;
1496+
compare_number_of_generics(tcx, impl_ty, trait_ty, trait_item_span, false)?;
14931497

1494-
compare_generic_param_kinds(tcx, impl_ty, trait_ty)?;
1498+
compare_generic_param_kinds(tcx, impl_ty, trait_ty, false)?;
14951499

14961500
let sp = tcx.def_span(impl_ty.def_id);
14971501
compare_type_predicate_entailment(tcx, impl_ty, sp, trait_ty, impl_trait_ref)?;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#![feature(return_position_impl_trait_in_trait)]
2+
#![allow(incomplete_features)]
3+
4+
struct S;
5+
6+
trait Foo {
7+
fn bar<T>() -> impl Sized;
8+
}
9+
10+
impl Foo for S {
11+
fn bar() -> impl Sized {}
12+
//~^ ERROR method `bar` has 0 type parameters but its trait declaration has 1 type parameter
13+
}
14+
15+
fn main() {
16+
S::bar();
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0049]: method `bar` has 0 type parameters but its trait declaration has 1 type parameter
2+
--> $DIR/trait-more-generics-than-impl.rs:11:11
3+
|
4+
LL | fn bar<T>() -> impl Sized;
5+
| - expected 1 type parameter
6+
...
7+
LL | fn bar() -> impl Sized {}
8+
| ^ found 0 type parameters
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0049`.

0 commit comments

Comments
 (0)