Skip to content

Commit 053aecf

Browse files
committed
1 parent 0a689c1 commit 053aecf

File tree

4 files changed

+126
-6
lines changed

4 files changed

+126
-6
lines changed

compiler/rustc_hir_analysis/src/collect/generics_of.rs

+43-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
6565
// struct Foo<const N: usize = { .. }>;
6666
// ^^^ ^ ^^^^^^ def id of this anon const
6767
// ^ ^ param_id
68-
// ^ parent_def_id
68+
// ^ parent_def_id after
6969
//
7070
// then we only want to return generics for params to the left of `N`. If we don't do that we
7171
// end up with that const looking like: `ty::ConstKind::Unevaluated(def_id, args: [N#0])`.
@@ -85,6 +85,48 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
8585
// This has some implications for how we get the predicates available to the anon const
8686
// see `explicit_predicates_of` for more information on this
8787
let generics = tcx.generics_of(parent_def_id.to_def_id());
88+
let parent_node = tcx.hir().get_parent(hir_id);
89+
90+
// For expr in where predict.
91+
// Will panic If we directly obtain GenericParamDef from the generics params based on the index.
92+
// fn foo<T>() where for<const N: u8 = { T::<0>::A as u8 }> T: Default {}
93+
// ^^^^^^^^^^^^^^^^^^^ hir_id
94+
// ^ param_id
95+
// ^^^ parent_id after twice iterations
96+
// ^ generics of parent
97+
// Push GenericParamDef of 'N' in above example into params.
98+
if let hir::Node::GenericParam(
99+
GenericParam{
100+
hir_id: parent_hir_id,
101+
kind: GenericParamKind::Const {
102+
ty: ty_info,
103+
default: Some(anon_const) },
104+
name,
105+
def_id,
106+
pure_wrt_drop, ..}) = parent_node
107+
&& !generics.param_def_id_to_index.contains_key(&param_id.to_def_id())
108+
&& anon_const.hir_id == hir_id {
109+
let mut params = generics.params.to_vec();
110+
params.push(ty::GenericParamDef {
111+
name: name.ident().name,
112+
index: (params.len() + 1) as u32,
113+
def_id: def_id.to_def_id(),
114+
pure_wrt_drop: *pure_wrt_drop,
115+
kind: ty::GenericParamDefKind::Lifetime,
116+
});
117+
let param_def_id_to_index =
118+
params.iter().map(|param| (param.def_id, param.index)).collect();
119+
120+
return ty::Generics {
121+
parent: generics.parent,
122+
parent_count: generics.parent_count,
123+
params,
124+
param_def_id_to_index,
125+
has_self: generics.has_self,
126+
has_late_bound_regions: generics.has_late_bound_regions,
127+
host_effect_index: None,
128+
};
129+
}
88130
let param_def_idx = generics.param_def_id_to_index[&param_id.to_def_id()];
89131
// In the above example this would be .params[..N#0]
90132
let params = generics.params_to(param_def_idx as usize, tcx).to_owned();

compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs

+30-5
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ enum Scope<'a> {
126126
/// fn foo(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
127127
/// ```
128128
where_bound_origin: Option<hir::PredicateOrigin>,
129+
in_where_predict: bool,
129130
},
130131

131132
/// Lifetimes introduced by a fn are scoped to the call-site for that fn,
@@ -195,7 +196,7 @@ struct TruncatedScopeDebug<'a>(&'a Scope<'a>);
195196
impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
196197
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
197198
match self.0 {
198-
Scope::Binder { bound_vars, scope_type, hir_id, where_bound_origin, s: _ } => f
199+
Scope::Binder { bound_vars, scope_type, hir_id, where_bound_origin, s: _, .. } => f
199200
.debug_struct("Binder")
200201
.field("bound_vars", bound_vars)
201202
.field("scope_type", scope_type)
@@ -394,6 +395,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
394395
s: self.scope,
395396
scope_type,
396397
where_bound_origin: None,
398+
in_where_predict: false,
397399
};
398400
self.with(scope, |this| {
399401
walk_list!(this, visit_generic_param, trait_ref.bound_generic_params);
@@ -478,14 +480,14 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
478480
.unzip();
479481

480482
deny_non_region_late_bound(self.tcx, &mut bound_vars, "closures");
481-
482483
self.record_late_bound_vars(e.hir_id, binders);
483484
let scope = Scope::Binder {
484485
hir_id: e.hir_id,
485486
bound_vars,
486487
s: self.scope,
487488
scope_type: BinderScopeType::Normal,
488489
where_bound_origin: None,
490+
in_where_predict: false,
489491
};
490492

491493
self.with(scope, |this| {
@@ -577,6 +579,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
577579
s: this.scope,
578580
scope_type: BinderScopeType::Normal,
579581
where_bound_origin: None,
582+
in_where_predict: false,
580583
};
581584
this.with(scope, |this| {
582585
let scope = Scope::TraitRefBoundary { s: this.scope };
@@ -630,14 +633,14 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
630633
.unzip();
631634

632635
deny_non_region_late_bound(self.tcx, &mut bound_vars, "function pointer types");
633-
634636
self.record_late_bound_vars(ty.hir_id, binders);
635637
let scope = Scope::Binder {
636638
hir_id: ty.hir_id,
637639
bound_vars,
638640
s: self.scope,
639641
scope_type: BinderScopeType::Normal,
640642
where_bound_origin: None,
643+
in_where_predict: false,
641644
};
642645
self.with(scope, |this| {
643646
// a bare fn has no bounds, so everything
@@ -907,6 +910,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
907910
s: self.scope,
908911
scope_type: BinderScopeType::Normal,
909912
where_bound_origin: Some(origin),
913+
in_where_predict: true,
910914
};
911915
self.with(scope, |this| {
912916
walk_list!(this, visit_generic_param, bound_generic_params);
@@ -963,14 +967,14 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
963967
// of "if there isn't a Binder scope above us, add one", but I
964968
// imagine there's a better way to go about this.
965969
let (binders, scope_type) = self.poly_trait_ref_binder_info();
966-
967970
self.record_late_bound_vars(*hir_id, binders);
968971
let scope = Scope::Binder {
969972
hir_id: *hir_id,
970973
bound_vars: FxIndexMap::default(),
971974
s: self.scope,
972975
scope_type,
973976
where_bound_origin: None,
977+
in_where_predict: false,
974978
};
975979
self.with(scope, |this| {
976980
intravisit::walk_param_bound(this, bound);
@@ -992,6 +996,26 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
992996

993997
fn visit_generic_param(&mut self, p: &'tcx GenericParam<'tcx>) {
994998
match p.kind {
999+
GenericParamKind::Const { ty, default: Some(default) } => {
1000+
self.resolve_type_ref(p.def_id, p.hir_id);
1001+
1002+
// For expr in default of Const expr in where predict.
1003+
// We may get unexpected bound var resolution when converts a hir id
1004+
// corresponding to a type parameter to a early-bound `ty::Param` or late-bound `ty::Bound`
1005+
// fn foo<T>() where for<const N: u8 = { T::<0>::A as u8 }> T: Default {}
1006+
// ^ generic param ty
1007+
// ^^^^^^ hir_id
1008+
// ^^^^^^^^^^^^^^^^^^^ default
1009+
// ^^^ parent_id after twice iterations
1010+
// ^ generics of parent
1011+
if let Scope::Binder {in_where_predict, .. } = self.scope && *in_where_predict {
1012+
let BoundVarContext { tcx, map, .. } = self;
1013+
let wrap_scope = Scope::LateBoundary { s: self.scope, what: "constant" };
1014+
let mut this = BoundVarContext { tcx: *tcx, map, scope: &wrap_scope };
1015+
this.visit_id(default.hir_id);
1016+
this.visit_nested_body(default.body);
1017+
}
1018+
}
9951019
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
9961020
self.resolve_type_ref(p.def_id, p.hir_id);
9971021
}
@@ -1144,6 +1168,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
11441168
s: self.scope,
11451169
scope_type: BinderScopeType::Normal,
11461170
where_bound_origin: None,
1171+
in_where_predict: false,
11471172
};
11481173
self.with(scope, walk);
11491174
}
@@ -1160,6 +1185,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
11601185
s: self.scope,
11611186
scope_type: BinderScopeType::Normal,
11621187
where_bound_origin: None,
1188+
in_where_predict: false,
11631189
};
11641190
self.with(scope, |this| {
11651191
let scope = Scope::TraitRefBoundary { s: this.scope };
@@ -1369,7 +1395,6 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
13691395
let mut late_depth = 0;
13701396
let mut scope = self.scope;
13711397
let mut crossed_late_boundary = None;
1372-
13731398
let result = loop {
13741399
match *scope {
13751400
Scope::Body { s, .. } => {

tests/ui/traits/issue-115497.rs

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#![feature(generic_const_exprs)]
2+
//~^ WARN the feature `generic_const_exprs` is incomplete
3+
#![feature(non_lifetime_binders)]
4+
//~^ WARN the feature `non_lifetime_binders` is incomplete
5+
6+
fn foo<T>() where for<const N: u8 = { T::<0>::A as u8 }> T: Default {}
7+
//~^ ERROR const arguments are not allowed on type parameter `T`
8+
//~| ERROR no associated item named `A` found for type parameter `T` in the current scope
9+
10+
fn main() {}

tests/ui/traits/issue-115497.stderr

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
2+
--> $DIR/issue-115497.rs:1:12
3+
|
4+
LL | #![feature(generic_const_exprs)]
5+
| ^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
8+
= note: `#[warn(incomplete_features)]` on by default
9+
10+
warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
11+
--> $DIR/issue-115497.rs:3:12
12+
|
13+
LL | #![feature(non_lifetime_binders)]
14+
| ^^^^^^^^^^^^^^^^^^^^
15+
|
16+
= note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
17+
18+
error[E0109]: const arguments are not allowed on type parameter `T`
19+
--> $DIR/issue-115497.rs:6:43
20+
|
21+
LL | fn foo<T>() where for<const N: u8 = { T::<0>::A as u8 }> T: Default {}
22+
| - ^ const argument not allowed
23+
| |
24+
| not allowed on type parameter `T`
25+
|
26+
note: type parameter `T` defined here
27+
--> $DIR/issue-115497.rs:6:8
28+
|
29+
LL | fn foo<T>() where for<const N: u8 = { T::<0>::A as u8 }> T: Default {}
30+
| ^
31+
32+
error[E0599]: no associated item named `A` found for type parameter `T` in the current scope
33+
--> $DIR/issue-115497.rs:6:47
34+
|
35+
LL | fn foo<T>() where for<const N: u8 = { T::<0>::A as u8 }> T: Default {}
36+
| - ^ associated item not found in `T`
37+
| |
38+
| associated item `A` not found for this type parameter
39+
40+
error: aborting due to 2 previous errors; 2 warnings emitted
41+
42+
Some errors have detailed explanations: E0109, E0599.
43+
For more information about an error, try `rustc --explain E0109`.

0 commit comments

Comments
 (0)