Skip to content

Commit b4ec830

Browse files
committed
Ensure const parameters' types cannot depend on type parameters
1 parent c71d1f5 commit b4ec830

File tree

2 files changed

+60
-16
lines changed

2 files changed

+60
-16
lines changed

src/librustc_resolve/diagnostics.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1652,6 +1652,17 @@ fn main() {
16521652
```
16531653
"##,
16541654

1655+
E0668: r##"
1656+
Const parameters cannot depend on type parameters.
1657+
The following is therefore invalid:
1658+
1659+
```
1660+
fn const_id<T, const N: T>() -> T {
1661+
N
1662+
}
1663+
```
1664+
"##,
1665+
16551666
}
16561667

16571668
register_diagnostics! {

src/librustc_resolve/lib.rs

Lines changed: 49 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,8 @@ impl Ord for BindingError {
133133
}
134134

135135
enum ResolutionError<'a> {
136-
/// error E0401: can't use type parameters from outer function
137-
TypeParametersFromOuterFunction(Def),
136+
/// error E0401: can't use type or const parameters from outer function
137+
ParametersFromOuterFunction(Def),
138138
/// error E0403: the name is already used for a type or const parameter in this type parameter list
139139
NameAlreadyUsedInParameterList(Name, &'a Span),
140140
/// error E0407: method is not a member of trait
@@ -170,7 +170,9 @@ enum ResolutionError<'a> {
170170
/// error E0530: X bindings cannot shadow Ys
171171
BindingShadowsSomethingUnacceptable(&'a str, Name, &'a NameBinding<'a>),
172172
/// error E0128: type parameters with a default cannot use forward declared identifiers
173-
ForwardDeclaredTyParam,
173+
ForwardDeclaredTyParam, // FIXME(const_generics:defaults)
174+
/// error E0668: const parameter cannot depend on type parameter
175+
ConstParamDependentOnTypeParam,
174176
}
175177

176178
/// Combines an error with provided span and emits it
@@ -188,12 +190,12 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
188190
resolution_error: ResolutionError<'a>)
189191
-> DiagnosticBuilder<'sess> {
190192
match resolution_error {
191-
ResolutionError::TypeParametersFromOuterFunction(outer_def) => {
193+
ResolutionError::ParametersFromOuterFunction(outer_def) => {
192194
let mut err = struct_span_err!(resolver.session,
193-
span,
194-
E0401,
195-
"can't use type parameters from outer function");
196-
err.span_label(span, "use of type variable from outer function");
195+
span,
196+
E0401,
197+
"can't use type or const parameters from outer function");
198+
err.span_label(span, "use of type or const variable from outer function");
197199

198200
let cm = resolver.session.source_map();
199201
match outer_def {
@@ -206,7 +208,7 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
206208
}
207209
Def::TyParam(typaram_defid) => {
208210
if let Some(typaram_span) = resolver.definitions.opt_span(typaram_defid) {
209-
err.span_label(typaram_span, "type variable from outer function");
211+
err.span_label(typaram_span, "type or const variable from outer function");
210212
}
211213
}
212214
_ => {
@@ -217,16 +219,17 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
217219

218220
// Try to retrieve the span of the function signature and generate a new message with
219221
// a local type parameter
220-
let sugg_msg = "try using a local type parameter instead";
222+
let sugg_msg = "try using a local type or const parameter instead";
221223
if let Some((sugg_span, new_snippet)) = cm.generate_local_type_param_snippet(span) {
222224
// Suggest the modification to the user
223225
err.span_suggestion(sugg_span,
224226
sugg_msg,
225227
new_snippet);
226228
} else if let Some(sp) = cm.generate_fn_name_span(span) {
227-
err.span_label(sp, "try adding a local type parameter in this method instead");
229+
err.span_label(sp,
230+
"try adding a local type or const parameter in this method instead");
228231
} else {
229-
err.help("try using a local type parameter instead");
232+
err.help("try using a local type or const parameter instead");
230233
}
231234

232235
err
@@ -405,6 +408,12 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
405408
span, "defaulted type parameters cannot be forward declared".to_string());
406409
err
407410
}
411+
ResolutionError::ConstParamDependentOnTypeParam => {
412+
let mut err = struct_span_err!(resolver.session, span, E0668,
413+
"const parameters cannot depend on type parameters");
414+
err.span_label(span, format!("const parameter depends on type parameter"));
415+
err
416+
}
408417
}
409418
}
410419

@@ -833,6 +842,16 @@ impl<'a, 'tcx, 'cl> Visitor<'tcx> for Resolver<'a, 'cl> {
833842
}
834843
}));
835844

845+
// We also ban access to type parameters for use as the types of const parameters.
846+
let mut const_ty_param_ban_rib = Rib::new(TyParamAsConstParamTy);
847+
const_ty_param_ban_rib.bindings.extend(generics.params.iter()
848+
.filter(|param| if let GenericParamKind::Type { .. } = param.kind {
849+
true
850+
} else {
851+
false
852+
})
853+
.map(|param| (Ident::with_empty_ctxt(param.ident.name), Def::Err)));
854+
836855
for param in &generics.params {
837856
match param.kind {
838857
GenericParamKind::Lifetime { .. } => self.visit_generic_param(param),
@@ -851,13 +870,15 @@ impl<'a, 'tcx, 'cl> Visitor<'tcx> for Resolver<'a, 'cl> {
851870
default_ban_rib.bindings.remove(&Ident::with_empty_ctxt(param.ident.name));
852871
}
853872
GenericParamKind::Const { ref ty } => {
873+
self.ribs[TypeNS].push(const_ty_param_ban_rib);
874+
854875
for bound in &param.bounds {
855876
self.visit_param_bound(bound);
856877
}
857878

858879
self.visit_ty(ty);
859880

860-
// TODO(const_generics): do we need to do thing banning here too?
881+
const_ty_param_ban_rib = self.ribs[TypeNS].pop().unwrap();
861882
}
862883
}
863884
}
@@ -910,6 +931,9 @@ enum RibKind<'a> {
910931
/// from the default of a type parameter because they're not declared
911932
/// before said type parameter. Also see the `visit_generics` override.
912933
ForwardTyParamBanRibKind,
934+
935+
/// We forbid the use of type parameters as the types of const parameters.
936+
TyParamAsConstParamTy,
913937
}
914938

915939
/// One local scope.
@@ -3739,6 +3763,15 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
37393763
return Def::Err;
37403764
}
37413765

3766+
// An invalid use of a type parameter as the type of a const parameter.
3767+
if let TyParamAsConstParamTy = self.ribs[ns][rib_index].kind {
3768+
if record_used {
3769+
resolve_error(self, span, ResolutionError::ConstParamDependentOnTypeParam);
3770+
}
3771+
assert_eq!(def, Def::Err);
3772+
return Def::Err;
3773+
}
3774+
37423775
match def {
37433776
Def::Upvar(..) => {
37443777
span_bug!(span, "unexpected {:?} in bindings", def)
@@ -3747,7 +3780,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
37473780
for rib in ribs {
37483781
match rib.kind {
37493782
NormalRibKind | ModuleRibKind(..) | MacroDefinition(..) |
3750-
ForwardTyParamBanRibKind => {
3783+
ForwardTyParamBanRibKind | TyParamAsConstParamTy => {
37513784
// Nothing to do. Continue.
37523785
}
37533786
ClosureRibKind(function_id) => {
@@ -3800,15 +3833,15 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
38003833
match rib.kind {
38013834
NormalRibKind | TraitOrImplItemRibKind | ClosureRibKind(..) |
38023835
ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind |
3803-
ConstantItemRibKind => {
3836+
ConstantItemRibKind | TyParamAsConstParamTy => {
38043837
// Nothing to do. Continue.
38053838
}
38063839
ItemRibKind => {
38073840
// This was an attempt to use a type parameter outside
38083841
// its scope.
38093842
if record_used {
38103843
resolve_error(self, span,
3811-
ResolutionError::TypeParametersFromOuterFunction(def));
3844+
ResolutionError::ParametersFromOuterFunction(def));
38123845
}
38133846
return Def::Err;
38143847
}

0 commit comments

Comments
 (0)