Skip to content

Commit bc78d0c

Browse files
Error on unconstrained lifetime in RPITIT
1 parent 6330daa commit bc78d0c

12 files changed

+188
-102
lines changed

compiler/rustc_hir_analysis/src/check/compare_impl_item.rs

+38-21
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,7 @@ pub(super) fn compare_impl_method<'tcx>(
4545
debug!("compare_impl_method(impl_trait_ref={:?})", impl_trait_ref);
4646

4747
let _: Result<_, ErrorGuaranteed> = try {
48-
compare_self_type(tcx, impl_m, trait_m, impl_trait_ref)?;
49-
compare_number_of_generics(tcx, impl_m, trait_m, false)?;
50-
compare_generic_param_kinds(tcx, impl_m, trait_m, false)?;
51-
compare_number_of_method_arguments(tcx, impl_m, trait_m)?;
52-
compare_synthetic_generics(tcx, impl_m, trait_m)?;
53-
compare_asyncness(tcx, impl_m, trait_m)?;
48+
check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, false)?;
5449
compare_method_predicate_entailment(
5550
tcx,
5651
impl_m,
@@ -61,6 +56,26 @@ pub(super) fn compare_impl_method<'tcx>(
6156
};
6257
}
6358

59+
/// Checks a bunch of different properties of the impl/trait methods for
60+
/// compatibility, such as asyncness, number of argument, self receiver kind,
61+
/// and number of early- and late-bound generics.
62+
fn check_method_is_structurally_compatible<'tcx>(
63+
tcx: TyCtxt<'tcx>,
64+
impl_m: ty::AssocItem,
65+
trait_m: ty::AssocItem,
66+
impl_trait_ref: ty::TraitRef<'tcx>,
67+
delay: bool,
68+
) -> Result<(), ErrorGuaranteed> {
69+
compare_self_type(tcx, impl_m, trait_m, impl_trait_ref, delay)?;
70+
compare_number_of_generics(tcx, impl_m, trait_m, delay)?;
71+
compare_generic_param_kinds(tcx, impl_m, trait_m, delay)?;
72+
compare_number_of_method_arguments(tcx, impl_m, trait_m, delay)?;
73+
compare_synthetic_generics(tcx, impl_m, trait_m, delay)?;
74+
compare_asyncness(tcx, impl_m, trait_m, delay)?;
75+
check_region_bounds_on_impl_item(tcx, impl_m, trait_m, delay)?;
76+
Ok(())
77+
}
78+
6479
/// This function is best explained by example. Consider a trait with it's implementation:
6580
///
6681
/// ```rust
@@ -177,9 +192,6 @@ fn compare_method_predicate_entailment<'tcx>(
177192
let impl_m_predicates = tcx.predicates_of(impl_m.def_id);
178193
let trait_m_predicates = tcx.predicates_of(trait_m.def_id);
179194

180-
// Check region bounds.
181-
check_region_bounds_on_impl_item(tcx, impl_m, trait_m, false)?;
182-
183195
// Create obligations for each predicate declared by the impl
184196
// definition in the context of the trait's parameter
185197
// environment. We can't just use `impl_env.caller_bounds`,
@@ -534,6 +546,7 @@ fn compare_asyncness<'tcx>(
534546
tcx: TyCtxt<'tcx>,
535547
impl_m: ty::AssocItem,
536548
trait_m: ty::AssocItem,
549+
delay: bool,
537550
) -> Result<(), ErrorGuaranteed> {
538551
if tcx.asyncness(trait_m.def_id) == hir::IsAsync::Async {
539552
match tcx.fn_sig(impl_m.def_id).skip_binder().skip_binder().output().kind() {
@@ -544,11 +557,14 @@ fn compare_asyncness<'tcx>(
544557
// We don't know if it's ok, but at least it's already an error.
545558
}
546559
_ => {
547-
return Err(tcx.sess.emit_err(crate::errors::AsyncTraitImplShouldBeAsync {
548-
span: tcx.def_span(impl_m.def_id),
549-
method_name: trait_m.name,
550-
trait_item_span: tcx.hir().span_if_local(trait_m.def_id),
551-
}));
560+
return Err(tcx
561+
.sess
562+
.create_err(crate::errors::AsyncTraitImplShouldBeAsync {
563+
span: tcx.def_span(impl_m.def_id),
564+
method_name: trait_m.name,
565+
trait_item_span: tcx.hir().span_if_local(trait_m.def_id),
566+
})
567+
.emit_unless(delay));
552568
}
553569
};
554570
}
@@ -602,9 +618,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
602618

603619
// First, check a few of the same things as `compare_impl_method`,
604620
// just so we don't ICE during substitution later.
605-
compare_number_of_generics(tcx, impl_m, trait_m, true)?;
606-
compare_generic_param_kinds(tcx, impl_m, trait_m, true)?;
607-
check_region_bounds_on_impl_item(tcx, impl_m, trait_m, true)?;
621+
check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, true)?;
608622

609623
let trait_to_impl_substs = impl_trait_ref.substs;
610624

@@ -1097,6 +1111,7 @@ fn compare_self_type<'tcx>(
10971111
impl_m: ty::AssocItem,
10981112
trait_m: ty::AssocItem,
10991113
impl_trait_ref: ty::TraitRef<'tcx>,
1114+
delay: bool,
11001115
) -> Result<(), ErrorGuaranteed> {
11011116
// Try to give more informative error messages about self typing
11021117
// mismatches. Note that any mismatch will also be detected
@@ -1145,7 +1160,7 @@ fn compare_self_type<'tcx>(
11451160
} else {
11461161
err.note_trait_signature(trait_m.name, trait_m.signature(tcx));
11471162
}
1148-
return Err(err.emit());
1163+
return Err(err.emit_unless(delay));
11491164
}
11501165

11511166
(true, false) => {
@@ -1166,7 +1181,7 @@ fn compare_self_type<'tcx>(
11661181
err.note_trait_signature(trait_m.name, trait_m.signature(tcx));
11671182
}
11681183

1169-
return Err(err.emit());
1184+
return Err(err.emit_unless(delay));
11701185
}
11711186
}
11721187

@@ -1352,6 +1367,7 @@ fn compare_number_of_method_arguments<'tcx>(
13521367
tcx: TyCtxt<'tcx>,
13531368
impl_m: ty::AssocItem,
13541369
trait_m: ty::AssocItem,
1370+
delay: bool,
13551371
) -> Result<(), ErrorGuaranteed> {
13561372
let impl_m_fty = tcx.fn_sig(impl_m.def_id);
13571373
let trait_m_fty = tcx.fn_sig(trait_m.def_id);
@@ -1422,7 +1438,7 @@ fn compare_number_of_method_arguments<'tcx>(
14221438
),
14231439
);
14241440

1425-
return Err(err.emit());
1441+
return Err(err.emit_unless(delay));
14261442
}
14271443

14281444
Ok(())
@@ -1432,6 +1448,7 @@ fn compare_synthetic_generics<'tcx>(
14321448
tcx: TyCtxt<'tcx>,
14331449
impl_m: ty::AssocItem,
14341450
trait_m: ty::AssocItem,
1451+
delay: bool,
14351452
) -> Result<(), ErrorGuaranteed> {
14361453
// FIXME(chrisvittal) Clean up this function, list of FIXME items:
14371454
// 1. Better messages for the span labels
@@ -1551,7 +1568,7 @@ fn compare_synthetic_generics<'tcx>(
15511568
}
15521569
_ => unreachable!(),
15531570
}
1554-
error_found = Some(err.emit());
1571+
error_found = Some(err.emit_unless(delay));
15551572
}
15561573
}
15571574
if let Some(reported) = error_found { Err(reported) } else { Ok(()) }

compiler/rustc_hir_analysis/src/impl_wf_check.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,23 @@ fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId)
106106
if item.defaultness(tcx).has_value() {
107107
cgp::parameters_for(&tcx.type_of(def_id).subst_identity(), true)
108108
} else {
109-
Vec::new()
109+
vec![]
110110
}
111111
}
112-
ty::AssocKind::Fn | ty::AssocKind::Const => Vec::new(),
112+
ty::AssocKind::Fn => {
113+
if !tcx.lower_impl_trait_in_trait_to_assoc_ty()
114+
&& item.defaultness(tcx).has_value()
115+
&& tcx.impl_method_has_trait_impl_trait_tys(item.def_id)
116+
&& let Ok(table) = tcx.collect_return_position_impl_trait_in_trait_tys(def_id)
117+
{
118+
table.values().copied().flat_map(|ty| {
119+
cgp::parameters_for(&ty.subst_identity(), true)
120+
}).collect()
121+
} else {
122+
vec![]
123+
}
124+
}
125+
ty::AssocKind::Const => vec![],
113126
}
114127
})
115128
.collect();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error[E0053]: method `early` has an incompatible type for trait
2+
--> $DIR/method-signature-matches.rs:58:27
3+
|
4+
LL | fn early<'late, T>(_: &'late ()) {}
5+
| - ^^^^^^^^^
6+
| | |
7+
| | expected type parameter `T`, found `()`
8+
| | help: change the parameter type to match the trait: `&'early T`
9+
| this type parameter
10+
|
11+
note: type in trait
12+
--> $DIR/method-signature-matches.rs:53:28
13+
|
14+
LL | fn early<'early, T>(x: &'early T) -> impl Sized;
15+
| ^^^^^^^^^
16+
= note: expected signature `fn(&'early T)`
17+
found signature `fn(&())`
18+
19+
error: aborting due to previous error
20+
21+
For more information about this error, try `rustc --explain E0053`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error[E0053]: method `owo` has an incompatible type for trait
2+
--> $DIR/method-signature-matches.rs:14:15
3+
|
4+
LL | fn owo(_: u8) {}
5+
| ^^
6+
| |
7+
| expected `()`, found `u8`
8+
| help: change the parameter type to match the trait: `()`
9+
|
10+
note: type in trait
11+
--> $DIR/method-signature-matches.rs:9:15
12+
|
13+
LL | fn owo(x: ()) -> impl Sized;
14+
| ^^
15+
= note: expected signature `fn(())`
16+
found signature `fn(u8)`
17+
18+
error: aborting due to previous error
19+
20+
For more information about this error, try `rustc --explain E0053`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error[E0053]: method `owo` has an incompatible type for trait
2+
--> $DIR/method-signature-matches.rs:25:21
3+
|
4+
LL | async fn owo(_: u8) {}
5+
| ^^
6+
| |
7+
| expected `()`, found `u8`
8+
| help: change the parameter type to match the trait: `()`
9+
|
10+
note: type in trait
11+
--> $DIR/method-signature-matches.rs:20:21
12+
|
13+
LL | async fn owo(x: ()) {}
14+
| ^^
15+
= note: expected signature `fn(()) -> _`
16+
found signature `fn(u8) -> _`
17+
18+
error: aborting due to previous error
19+
20+
For more information about this error, try `rustc --explain E0053`.
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,62 @@
11
// edition: 2021
2+
// revisions: mismatch mismatch_async too_many too_few lt
23

34
#![feature(return_position_impl_trait_in_trait, async_fn_in_trait)]
45
#![allow(incomplete_features)]
56

7+
#[cfg(mismatch)]
68
trait Uwu {
79
fn owo(x: ()) -> impl Sized;
810
}
911

12+
#[cfg(mismatch)]
1013
impl Uwu for () {
1114
fn owo(_: u8) {}
12-
//~^ ERROR method `owo` has an incompatible type for trait
15+
//[mismatch]~^ ERROR method `owo` has an incompatible type for trait
1316
}
1417

18+
#[cfg(mismatch_async)]
1519
trait AsyncUwu {
1620
async fn owo(x: ()) {}
1721
}
1822

23+
#[cfg(mismatch_async)]
1924
impl AsyncUwu for () {
2025
async fn owo(_: u8) {}
21-
//~^ ERROR method `owo` has an incompatible type for trait
26+
//[mismatch_async]~^ ERROR method `owo` has an incompatible type for trait
2227
}
2328

29+
#[cfg(too_many)]
2430
trait TooMuch {
2531
fn calm_down_please() -> impl Sized;
2632
}
2733

34+
#[cfg(too_many)]
2835
impl TooMuch for () {
2936
fn calm_down_please(_: (), _: (), _: ()) {}
30-
//~^ ERROR method `calm_down_please` has 3 parameters but the declaration in trait `TooMuch::calm_down_please` has 0
37+
//[too_many]~^ ERROR method `calm_down_please` has 3 parameters but the declaration in trait `TooMuch::calm_down_please` has 0
3138
}
3239

40+
#[cfg(too_few)]
3341
trait TooLittle {
3442
fn come_on_a_little_more_effort(_: (), _: (), _: ()) -> impl Sized;
3543
}
3644

45+
#[cfg(too_few)]
3746
impl TooLittle for () {
3847
fn come_on_a_little_more_effort() {}
39-
//~^ ERROR method `come_on_a_little_more_effort` has 0 parameters but the declaration in trait `TooLittle::come_on_a_little_more_effort` has 3
48+
//[too_few]~^ ERROR method `come_on_a_little_more_effort` has 0 parameters but the declaration in trait `TooLittle::come_on_a_little_more_effort` has 3
4049
}
4150

51+
#[cfg(lt)]
4252
trait Lifetimes {
4353
fn early<'early, T>(x: &'early T) -> impl Sized;
4454
}
4555

56+
#[cfg(lt)]
4657
impl Lifetimes for () {
4758
fn early<'late, T>(_: &'late ()) {}
48-
//~^ ERROR method `early` has an incompatible type for trait
59+
//[lt]~^ ERROR method `early` has an incompatible type for trait
4960
}
5061

5162
fn main() {}

tests/ui/impl-trait/in-trait/method-signature-matches.stderr

-74
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0050]: method `come_on_a_little_more_effort` has 0 parameters but the declaration in trait `TooLittle::come_on_a_little_more_effort` has 3
2+
--> $DIR/method-signature-matches.rs:47:5
3+
|
4+
LL | fn come_on_a_little_more_effort(_: (), _: (), _: ()) -> impl Sized;
5+
| ---------------- trait requires 3 parameters
6+
...
7+
LL | fn come_on_a_little_more_effort() {}
8+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 3 parameters, found 0
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0050`.

0 commit comments

Comments
 (0)