Skip to content

Commit cbf4d4e

Browse files
Deny capturing late-bound non-lifetime param in anon const
1 parent b583ede commit cbf4d4e

File tree

5 files changed

+121
-5
lines changed

5 files changed

+121
-5
lines changed

compiler/rustc_hir_analysis/locales/en-US.ftl

+8
Original file line numberDiff line numberDiff line change
@@ -147,3 +147,11 @@ hir_analysis_main_function_generic_parameters = `main` function is not allowed t
147147
148148
hir_analysis_variadic_function_compatible_convention = C-variadic function must have a compatible calling convention, like {$conventions}
149149
.label = C-variadic function must have a compatible calling convention
150+
151+
hir_analysis_cannot_capture_late_bound_ty_in_anon_const =
152+
cannot capture late-bound type parameter in a constant
153+
.label = parameter defined here
154+
155+
hir_analysis_cannot_capture_late_bound_const_in_anon_const =
156+
cannot capture late-bound const parameter in a constant
157+
.label = parameter defined here

compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs

+57-5
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ use rustc_span::symbol::{sym, Ident};
2424
use rustc_span::Span;
2525
use std::fmt;
2626

27+
use crate::errors;
28+
2729
trait RegionExt {
2830
fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg);
2931

@@ -161,6 +163,15 @@ enum Scope<'a> {
161163
s: ScopeRef<'a>,
162164
},
163165

166+
/// Disallows capturing non-lifetime binders from parent scopes.
167+
///
168+
/// This is necessary for something like `for<T> [(); { /* references T */ }]:`,
169+
/// since we don't do something more correct like replacing any captured
170+
/// late-bound vars with early-bound params in the const's own generics.
171+
AnonConstBoundary {
172+
s: ScopeRef<'a>,
173+
},
174+
164175
Root {
165176
opt_parent_item: Option<LocalDefId>,
166177
},
@@ -211,6 +222,7 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
211222
.field("s", &"..")
212223
.finish(),
213224
Scope::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(),
225+
Scope::AnonConstBoundary { s: _ } => f.debug_struct("AnonConstBoundary").finish(),
214226
Scope::Root { opt_parent_item } => {
215227
f.debug_struct("Root").field("opt_parent_item", &opt_parent_item).finish()
216228
}
@@ -312,7 +324,9 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
312324
break (vec![], BinderScopeType::Normal);
313325
}
314326

315-
Scope::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } => {
327+
Scope::Elision { s, .. }
328+
| Scope::ObjectLifetimeDefault { s, .. }
329+
| Scope::AnonConstBoundary { s } => {
316330
scope = s;
317331
}
318332

@@ -1029,6 +1043,12 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
10291043
fn visit_poly_trait_ref(&mut self, trait_ref: &'tcx hir::PolyTraitRef<'tcx>) {
10301044
self.visit_poly_trait_ref_inner(trait_ref, NonLifetimeBinderAllowed::Allow);
10311045
}
1046+
1047+
fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
1048+
self.with(Scope::AnonConstBoundary { s: self.scope }, |this| {
1049+
intravisit::walk_anon_const(this, c);
1050+
});
1051+
}
10321052
}
10331053

10341054
fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: DefId) -> ObjectLifetimeDefault {
@@ -1267,7 +1287,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
12671287
Scope::Elision { s, .. }
12681288
| Scope::ObjectLifetimeDefault { s, .. }
12691289
| Scope::Supertrait { s, .. }
1270-
| Scope::TraitRefBoundary { s, .. } => {
1290+
| Scope::TraitRefBoundary { s, .. }
1291+
| Scope::AnonConstBoundary { s } => {
12711292
scope = s;
12721293
}
12731294
}
@@ -1332,7 +1353,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
13321353
| Scope::Elision { s, .. }
13331354
| Scope::ObjectLifetimeDefault { s, .. }
13341355
| Scope::Supertrait { s, .. }
1335-
| Scope::TraitRefBoundary { s, .. } => {
1356+
| Scope::TraitRefBoundary { s, .. }
1357+
| Scope::AnonConstBoundary { s } => {
13361358
scope = s;
13371359
}
13381360
}
@@ -1351,6 +1373,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
13511373
// search.
13521374
let mut late_depth = 0;
13531375
let mut scope = self.scope;
1376+
let mut crossed_anon_const = false;
13541377
let result = loop {
13551378
match *scope {
13561379
Scope::Body { s, .. } => {
@@ -1384,10 +1407,36 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
13841407
| Scope::TraitRefBoundary { s, .. } => {
13851408
scope = s;
13861409
}
1410+
1411+
Scope::AnonConstBoundary { s } => {
1412+
crossed_anon_const = true;
1413+
scope = s;
1414+
}
13871415
}
13881416
};
13891417

13901418
if let Some(def) = result {
1419+
if let ResolvedArg::LateBound(..) = def && crossed_anon_const {
1420+
let use_span = self.tcx.hir().span(hir_id);
1421+
let def_span = self.tcx.def_span(param_def_id);
1422+
match self.tcx.def_kind(param_def_id) {
1423+
DefKind::ConstParam => {
1424+
self.tcx.sess.emit_err(errors::CannotCaptureLateBoundInAnonConst::Const {
1425+
use_span,
1426+
def_span,
1427+
});
1428+
}
1429+
DefKind::TyParam => {
1430+
self.tcx.sess.emit_err(errors::CannotCaptureLateBoundInAnonConst::Type {
1431+
use_span,
1432+
def_span,
1433+
});
1434+
}
1435+
_ => unreachable!(),
1436+
}
1437+
return;
1438+
}
1439+
13911440
self.map.defs.insert(hir_id, def);
13921441
return;
13931442
}
@@ -1465,7 +1514,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
14651514
| Scope::Elision { s, .. }
14661515
| Scope::ObjectLifetimeDefault { s, .. }
14671516
| Scope::Supertrait { s, .. }
1468-
| Scope::TraitRefBoundary { s, .. } => {
1517+
| Scope::TraitRefBoundary { s, .. }
1518+
| Scope::AnonConstBoundary { s } => {
14691519
scope = s;
14701520
}
14711521
}
@@ -1701,7 +1751,9 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
17011751

17021752
Scope::ObjectLifetimeDefault { lifetime: Some(l), .. } => break l,
17031753

1704-
Scope::Supertrait { s, .. } | Scope::TraitRefBoundary { s, .. } => {
1754+
Scope::Supertrait { s, .. }
1755+
| Scope::TraitRefBoundary { s, .. }
1756+
| Scope::AnonConstBoundary { s } => {
17051757
scope = s;
17061758
}
17071759
}

compiler/rustc_hir_analysis/src/errors.rs

+18
Original file line numberDiff line numberDiff line change
@@ -381,3 +381,21 @@ pub(crate) struct VariadicFunctionCompatibleConvention<'a> {
381381
pub span: Span,
382382
pub conventions: &'a str,
383383
}
384+
385+
#[derive(Diagnostic)]
386+
pub(crate) enum CannotCaptureLateBoundInAnonConst {
387+
#[diag(hir_analysis_cannot_capture_late_bound_ty_in_anon_const)]
388+
Type {
389+
#[primary_span]
390+
use_span: Span,
391+
#[label]
392+
def_span: Span,
393+
},
394+
#[diag(hir_analysis_cannot_capture_late_bound_const_in_anon_const)]
395+
Const {
396+
#[primary_span]
397+
use_span: Span,
398+
#[label]
399+
def_span: Span,
400+
},
401+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#![feature(non_lifetime_binders, generic_const_exprs)]
2+
//~^ WARN the feature `non_lifetime_binders` is incomplete
3+
//~| WARN the feature `generic_const_exprs` is incomplete
4+
5+
fn foo() -> usize
6+
where
7+
for<T> [i32; { let _: T = todo!(); 0 }]:,
8+
//~^ ERROR cannot capture late-bound type parameter in a constant
9+
{}
10+
11+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
2+
--> $DIR/late-bound-in-anon-ct.rs:1:12
3+
|
4+
LL | #![feature(non_lifetime_binders, generic_const_exprs)]
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+
warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
11+
--> $DIR/late-bound-in-anon-ct.rs:1:34
12+
|
13+
LL | #![feature(non_lifetime_binders, generic_const_exprs)]
14+
| ^^^^^^^^^^^^^^^^^^^
15+
|
16+
= note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
17+
18+
error: cannot capture late-bound type parameter in a constant
19+
--> $DIR/late-bound-in-anon-ct.rs:7:27
20+
|
21+
LL | for<T> [i32; { let _: T = todo!(); 0 }]:,
22+
| - ^
23+
| |
24+
| parameter defined here
25+
26+
error: aborting due to previous error; 2 warnings emitted
27+

0 commit comments

Comments
 (0)