Skip to content

Commit 9c369bc

Browse files
committed
Add parent_contains_impl_trait function to check for impl trait syntax in parent paths
1 parent f3bfb47 commit 9c369bc

13 files changed

+66
-107
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/// Returns `true` if the parent path contains impl trait syntax:
2+
/// For example given `impl Bla<impl Foo>`, this function would
3+
/// return true for the path for `impl Foo`
4+
pub(crate) fn parent_contains_impl_trait(cx: &LoweringContext<'_>, path: &ast::Path) -> bool {
5+
let ast::Path { span: path_span, segments, tokens: _ } = path;
6+
7+
if let Some(parent_path_span) = path_span.parent_callsite() {
8+
return matches!(cx.source_map().span_to_snippet(parent_path_span), Ok(s) if s.starts_with("impl "));
9+
}
10+
11+
// This can be from a parameter list:
12+
// like in `fn foo(a: impl Bla<impl Foo<T>..`) somewhere
13+
// in a block or other nested context.
14+
let parent_node = cx.source_map().span_to_enclosing_node(*path_span).next();
15+
16+
if let Some(node) = parent_node {
17+
let content_str = cx.source_map().span_to_snippet(node.span).unwrap_or_default();
18+
let segments_strs =
19+
segments.iter().map(|s| cx.source_map().span_to_snippet(s.span()).unwrap_or_default());
20+
21+
let path_str = segments_strs.collect::<Vec<_>>().join("::");
22+
// Check if parent contains "impl Trait", except for the current path:
23+
let impl_trait_pattern = format!("impl {}", path_str);
24+
if content_str.contains("impl") && content_str.contains(&impl_trait_pattern) {
25+
return true;
26+
}
27+
}
28+
29+
false
30+
}

compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1312,8 +1312,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
13121312
deny_late_types_and_consts,
13131313
} => {
13141314
// For debugging purposes
1315-
println!(
1316-
"DEBUG: LateBoundary in resolve_type_ref - what: {}, deny_late_types_and_consts: {}",
1315+
debug!(
1316+
"LateBoundary in resolve_type_ref - what: {}, deny_late_types_and_consts: {}",
13171317
what, deny_late_types_and_consts
13181318
);
13191319
if deny_late_types_and_consts {
@@ -1542,8 +1542,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
15421542
deny_late_types_and_consts,
15431543
} => {
15441544
// For debugging purposes
1545-
println!(
1546-
"DEBUG: LateBoundary in resolve_type_ref - what: {}, deny_late_types_and_consts: {}",
1545+
debug!(
1546+
"LateBoundary in resolve_type_ref - what: {}, deny_late_types_and_consts: {}",
15471547
what, deny_late_types_and_consts
15481548
);
15491549
if deny_late_types_and_consts {

compiler/rustc_hir_analysis/src/errors.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -647,24 +647,24 @@ pub(crate) struct VariadicFunctionCompatibleConvention<'a> {
647647

648648
#[derive(Diagnostic)]
649649
pub(crate) enum CannotCaptureLateBound {
650-
#[diag(hir_analysis_cannot_capture_late_bound_ty)]
651-
Type {
650+
#[diag(hir_analysis_cannot_capture_late_bound_lifetime)]
651+
Lifetime {
652652
#[primary_span]
653653
use_span: Span,
654654
#[label]
655655
def_span: Span,
656656
what: &'static str,
657657
},
658-
#[diag(hir_analysis_cannot_capture_late_bound_const)]
659-
Const {
658+
#[diag(hir_analysis_cannot_capture_late_bound_ty)]
659+
Type {
660660
#[primary_span]
661661
use_span: Span,
662662
#[label]
663663
def_span: Span,
664664
what: &'static str,
665665
},
666-
#[diag(hir_analysis_cannot_capture_late_bound_lifetime)]
667-
Lifetime {
666+
#[diag(hir_analysis_cannot_capture_late_bound_const)]
667+
Const {
668668
#[primary_span]
669669
use_span: Span,
670670
#[label]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//@ revisions: cfail
2+
//@ should-ice
3+
//@ compile-flags: --edition=2021
4+
//@ error-pattern: assertion failed
5+
6+
#![feature(non_lifetime_binders)]
7+
#![feature(associated_type_defaults)]
8+
#![allow(incomplete_features)]
9+
10+
trait Trait<T: ?Sized> {
11+
type Assoc<'a> = i32;
12+
}
13+
14+
fn produce() -> impl for<T> Trait<(), Assoc = impl Trait<T>> {
15+
16
16+
}
17+
18+
fn main() {}

tests/ui/impl-trait/in-bindings/escaping-bound-var.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@ impl<'a> Foo<'a> for () {
1010

1111
fn main() {
1212
let x: &dyn for<'a> Foo<'a, Out = impl Sized + 'a> = &();
13-
//~^ ERROR cannot capture late-bound lifetime in `impl Trait` in binding
13+
//~^ ERROR cannot capture late-bound lifetime in nested `impl Trait`
1414
}

tests/ui/impl-trait/in-bindings/escaping-bound-var.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: cannot capture late-bound lifetime in `impl Trait` in binding
1+
error: cannot capture late-bound lifetime in nested `impl Trait`
22
--> $DIR/escaping-bound-var.rs:12:52
33
|
44
LL | let x: &dyn for<'a> Foo<'a, Out = impl Sized + 'a> = &();

tests/ui/traits/non_lifetime_binders/type-alias-impl-trait/non-lifetime-binder-in-constraint.rs

-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ fn produce() -> impl for<T> Trait<(), Assoc = impl Trait<T>> {
77
//~^ ERROR associated type `Assoc` not found for `Trait`
88
//~| ERROR associated type `Assoc` not found for `Trait`
99
//~| the trait bound `{integer}: Trait<()>` is not satisfied
10-
//~| ERROR cannot capture late-bound type parameter in nested `impl Trait`
1110
16
1211
}
1312

tests/ui/traits/non_lifetime_binders/type-alias-impl-trait/non-lifetime-binder-in-constraint.stderr

+1-7
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,3 @@
1-
error: cannot capture late-bound type parameter in nested `impl Trait`
2-
--> $DIR/non-lifetime-binder-in-constraint.rs:6:58
3-
|
4-
LL | fn produce() -> impl for<T> Trait<(), Assoc = impl Trait<T>> {
5-
| - parameter defined here ^
6-
71
error[E0220]: associated type `Assoc` not found for `Trait`
82
--> $DIR/non-lifetime-binder-in-constraint.rs:6:39
93
|
@@ -33,7 +27,7 @@ help: this trait has no implementations, consider adding one
3327
LL | trait Trait<T: ?Sized> {}
3428
| ^^^^^^^^^^^^^^^^^^^^^^
3529

36-
error: aborting due to 4 previous errors
30+
error: aborting due to 3 previous errors
3731

3832
Some errors have detailed explanations: E0220, E0277.
3933
For more information about an error, try `rustc --explain E0220`.

tests/ui/traits/non_lifetime_binders/type-alias-impl-trait/non-lifetime-binder-in-nested-impl-trait.rs

-21
This file was deleted.

tests/ui/traits/non_lifetime_binders/type-alias-impl-trait/non-lifetime-binder-in-nested-impl-trait.stderr

-52
This file was deleted.

tests/ui/traits/non_lifetime_binders/type-alias-impl-trait/non-lifetime-binder-nested.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ trait Trait<T> {}
55

66
fn f() -> impl for<T> Trait<impl Trait<T>> {
77
//~^ ERROR nested `impl Trait` is not allowed
8-
//~| ERROR cannot capture late-bound type parameter in nested `impl Trait`
8+
//~| ERROR the trait bound `(): Trait<impl Trait<T>>` is not satisfied
99
()
1010
}
1111

tests/ui/traits/non_lifetime_binders/type-alias-impl-trait/non-lifetime-binder.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ trait Trait<T> {}
55

66
fn f() -> impl for<T> Trait<impl Trait<T>> {}
77
//~^ ERROR nested `impl Trait` is not allowed
8-
//~| ERROR the trait bound `(): Trait<impl Trait<{type error}>>` is not satisfied
9-
//~| ERROR cannot capture late-bound type parameter in nested `impl Trait`
8+
//~| ERROR the trait bound `(): Trait<impl Trait<T>>` is not satisfied
109

1110
fn main() {}

tests/ui/traits/non_lifetime_binders/type-alias-impl-trait/non-lifetime-binder.stderr

+3-11
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,19 @@ LL | fn f() -> impl for<T> Trait<impl Trait<T>> {}
77
| | nested `impl Trait` here
88
| outer `impl Trait`
99

10-
error: cannot capture late-bound type parameter in nested `impl Trait`
11-
--> $DIR/non-lifetime-binder.rs:6:40
12-
|
13-
LL | fn f() -> impl for<T> Trait<impl Trait<T>> {}
14-
| - ^
15-
| |
16-
| parameter defined here
17-
18-
error[E0277]: the trait bound `(): Trait<impl Trait<{type error}>>` is not satisfied
10+
error[E0277]: the trait bound `(): Trait<impl Trait<T>>` is not satisfied
1911
--> $DIR/non-lifetime-binder.rs:6:11
2012
|
2113
LL | fn f() -> impl for<T> Trait<impl Trait<T>> {}
22-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<impl Trait<{type error}>>` is not implemented for `()`
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<impl Trait<T>>` is not implemented for `()`
2315
|
2416
help: this trait has no implementations, consider adding one
2517
--> $DIR/non-lifetime-binder.rs:4:1
2618
|
2719
LL | trait Trait<T> {}
2820
| ^^^^^^^^^^^^^^
2921

30-
error: aborting due to 3 previous errors
22+
error: aborting due to 2 previous errors
3123

3224
Some errors have detailed explanations: E0277, E0666.
3325
For more information about an error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)