Skip to content

Commit 9ba54ca

Browse files
Rollup merge of #113071 - compiler-errors:no-parent-non-lifetime-args-in-apit, r=eholk
Account for late-bound vars from parent arg-position impl trait We should be reporting an error like we do for late-bound args coming from a parent APIT. Fixes #113016
2 parents ae30e8c + 724f3ff commit 9ba54ca

File tree

7 files changed

+114
-15
lines changed

7 files changed

+114
-15
lines changed

compiler/rustc_hir_analysis/messages.ftl

+9
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,15 @@ hir_analysis_invalid_union_field =
9999
hir_analysis_invalid_union_field_sugg =
100100
wrap the field type in `ManuallyDrop<...>`
101101
102+
hir_analysis_late_bound_const_in_apit = `impl Trait` can only mention const parameters from an fn or impl
103+
.label = const parameter declared here
104+
105+
hir_analysis_late_bound_lifetime_in_apit = `impl Trait` can only mention lifetimes from an fn or impl
106+
.label = lifetime declared here
107+
108+
hir_analysis_late_bound_type_in_apit = `impl Trait` can only mention type parameters from an fn or impl
109+
.label = type parameter declared here
110+
102111
hir_analysis_lifetimes_or_bounds_mismatch_on_trait =
103112
lifetime parameters or bounds on {$item_kind} `{$ident}` do not match the trait declaration
104113
.label = lifetimes do not match {$item_kind} in trait

compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs

+49-6
Original file line numberDiff line numberDiff line change
@@ -1344,12 +1344,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
13441344
Scope::Binder {
13451345
where_bound_origin: Some(hir::PredicateOrigin::ImplTrait), ..
13461346
} => {
1347-
let mut err = self.tcx.sess.struct_span_err(
1348-
lifetime_ref.ident.span,
1349-
"`impl Trait` can only mention lifetimes bound at the fn or impl level",
1350-
);
1351-
err.span_note(self.tcx.def_span(region_def_id), "lifetime declared here");
1352-
err.emit();
1347+
self.tcx.sess.emit_err(errors::LateBoundInApit::Lifetime {
1348+
span: lifetime_ref.ident.span,
1349+
param_span: self.tcx.def_span(region_def_id),
1350+
});
13531351
return;
13541352
}
13551353
Scope::Root { .. } => break,
@@ -1379,6 +1377,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
13791377
let mut late_depth = 0;
13801378
let mut scope = self.scope;
13811379
let mut crossed_anon_const = false;
1380+
13821381
let result = loop {
13831382
match *scope {
13841383
Scope::Body { s, .. } => {
@@ -1446,6 +1445,50 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
14461445
return;
14471446
}
14481447

1448+
// We may fail to resolve higher-ranked ty/const vars that are mentioned by APIT.
1449+
// AST-based resolution does not care for impl-trait desugaring, which are the
1450+
// responsibility of lowering. This may create a mismatch between the resolution
1451+
// AST found (`param_def_id`) which points to HRTB, and what HIR allows.
1452+
// ```
1453+
// fn foo(x: impl for<T> Trait<Assoc = impl Trait2<T>>) {}
1454+
// ```
1455+
//
1456+
// In such case, walk back the binders to diagnose it properly.
1457+
let mut scope = self.scope;
1458+
loop {
1459+
match *scope {
1460+
Scope::Binder {
1461+
where_bound_origin: Some(hir::PredicateOrigin::ImplTrait), ..
1462+
} => {
1463+
let guar = self.tcx.sess.emit_err(match self.tcx.def_kind(param_def_id) {
1464+
DefKind::TyParam => errors::LateBoundInApit::Type {
1465+
span: self.tcx.hir().span(hir_id),
1466+
param_span: self.tcx.def_span(param_def_id),
1467+
},
1468+
DefKind::ConstParam => errors::LateBoundInApit::Const {
1469+
span: self.tcx.hir().span(hir_id),
1470+
param_span: self.tcx.def_span(param_def_id),
1471+
},
1472+
kind => {
1473+
bug!("unexpected def-kind: {}", kind.descr(param_def_id.to_def_id()))
1474+
}
1475+
});
1476+
self.map.defs.insert(hir_id, ResolvedArg::Error(guar));
1477+
return;
1478+
}
1479+
Scope::Root { .. } => break,
1480+
Scope::Binder { s, .. }
1481+
| Scope::Body { s, .. }
1482+
| Scope::Elision { s, .. }
1483+
| Scope::ObjectLifetimeDefault { s, .. }
1484+
| Scope::Supertrait { s, .. }
1485+
| Scope::TraitRefBoundary { s, .. }
1486+
| Scope::AnonConstBoundary { s } => {
1487+
scope = s;
1488+
}
1489+
}
1490+
}
1491+
14491492
self.tcx.sess.delay_span_bug(
14501493
self.tcx.hir().span(hir_id),
14511494
format!("could not resolve {param_def_id:?}"),

compiler/rustc_hir_analysis/src/errors.rs

+25
Original file line numberDiff line numberDiff line change
@@ -875,3 +875,28 @@ pub(crate) enum ReturnTypeNotationIllegalParam {
875875
param_span: Span,
876876
},
877877
}
878+
879+
#[derive(Diagnostic)]
880+
pub(crate) enum LateBoundInApit {
881+
#[diag(hir_analysis_late_bound_type_in_apit)]
882+
Type {
883+
#[primary_span]
884+
span: Span,
885+
#[label]
886+
param_span: Span,
887+
},
888+
#[diag(hir_analysis_late_bound_const_in_apit)]
889+
Const {
890+
#[primary_span]
891+
span: Span,
892+
#[label]
893+
param_span: Span,
894+
},
895+
#[diag(hir_analysis_late_bound_lifetime_in_apit)]
896+
Lifetime {
897+
#[primary_span]
898+
span: Span,
899+
#[label]
900+
param_span: Span,
901+
},
902+
}

tests/ui/impl-trait/universal_wrong_hrtb.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@ trait Trait<'a> {
33
}
44

55
fn test_argument_position(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
6-
//~^ ERROR `impl Trait` can only mention lifetimes bound at the fn or impl level
6+
//~^ ERROR `impl Trait` can only mention lifetimes from an fn or impl
77

88
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,8 @@
1-
error: `impl Trait` can only mention lifetimes bound at the fn or impl level
1+
error: `impl Trait` can only mention lifetimes from an fn or impl
22
--> $DIR/universal_wrong_hrtb.rs:5:73
33
|
44
LL | fn test_argument_position(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
5-
| ^^
6-
|
7-
note: lifetime declared here
8-
--> $DIR/universal_wrong_hrtb.rs:5:39
9-
|
10-
LL | fn test_argument_position(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
11-
| ^^
5+
| -- lifetime declared here ^^
126

137
error: aborting due to previous error
148

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#![feature(non_lifetime_binders)]
2+
//~^ WARN the feature `non_lifetime_binders` is incomplete
3+
4+
trait Trait<Input> {
5+
type Assoc;
6+
}
7+
8+
fn uwu(_: impl for<T> Trait<(), Assoc = impl Trait<T>>) {}
9+
//~^ ERROR `impl Trait` can only mention type parameters from an fn or impl
10+
11+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
2+
--> $DIR/nested-apit-mentioning-outer-bound-var.rs:1:12
3+
|
4+
LL | #![feature(non_lifetime_binders)]
5+
| ^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
8+
= note: `#[warn(incomplete_features)]` on by default
9+
10+
error: `impl Trait` can only mention type parameters from an fn or impl
11+
--> $DIR/nested-apit-mentioning-outer-bound-var.rs:8:52
12+
|
13+
LL | fn uwu(_: impl for<T> Trait<(), Assoc = impl Trait<T>>) {}
14+
| - type parameter declared here ^
15+
16+
error: aborting due to previous error; 1 warning emitted
17+

0 commit comments

Comments
 (0)