only check cg defaults wf once instantiated

This commit is contained in:
lcnr 2021-07-08 22:57:10 +02:00
parent d0485c7986
commit 4a53b11518
6 changed files with 31 additions and 38 deletions

View File

@ -738,15 +738,19 @@ fn check_where_clauses<'tcx, 'fcx>(
}
}
GenericParamDefKind::Const { .. } => {
// FIXME(const_generics_defaults): Figure out if this
// is the behavior we want, see the comment further below.
if is_our_default(&param) {
// FIXME(const_generics_defaults): This
// is incorrect when dealing with unused substs, for example
// for `struct Foo<const N: usize, const M: usize = { 1 - 2 }>`
// we should eagerly error.
let default_ct = tcx.const_param_default(param.def_id);
fcx.register_wf_obligation(
default_ct.into(),
tcx.def_span(param.def_id),
ObligationCauseCode::MiscObligation,
);
if !default_ct.needs_subst() {
fcx.register_wf_obligation(
default_ct.into(),
tcx.def_span(param.def_id),
ObligationCauseCode::MiscObligation,
);
}
}
}
// Doesn't have defaults.
@ -783,14 +787,6 @@ fn check_where_clauses<'tcx, 'fcx>(
tcx.mk_param_from_def(param)
}
GenericParamDefKind::Const { .. } => {
// FIXME(const_generics_defaults): I(@lcnr) feel like always
// using the const parameter is the right choice here, even
// if it needs substs.
//
// Before stabilizing this we probably want to get some tests
// where this makes a difference and figure out what's the exact
// behavior we want here.
// If the param has a default, ...
if is_our_default(param) {
let default_ct = tcx.const_param_default(param.def_id);

View File

@ -2308,6 +2308,16 @@ fn const_evaluatable_predicates_of<'tcx>(
));
}
}
fn visit_const_param_default(&mut self, _param: HirId, _ct: &'tcx hir::AnonConst) {
// Do not look into const param defaults,
// these get checked when they are actually instantiated.
//
// We do not want the following to error:
//
// struct Foo<const N: usize, const M: usize = { N + 1 }>;
// struct Bar<const N: usize>(Foo<N, 3>);
}
}
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);

View File

@ -0,0 +1,6 @@
// check-pass
#![feature(const_generics, const_evaluatable_checked, const_generics_defaults)]
#![allow(incomplete_features)]
struct Foo<const N: usize, const M: usize = { N + 1 }>;
struct Bar<const N: usize>(Foo<N, 3>);
fn main() {}

View File

@ -1,18 +0,0 @@
error: constant expression depends on a generic parameter
--> $DIR/complex-generic-default-expr.rs:6:34
|
LL | struct Foo<const N: usize, const M: usize = { N + 1 }>;
| ^
|
= note: this may fail depending on what value the parameter takes
error: constant expression depends on a generic parameter
--> $DIR/complex-generic-default-expr.rs:10:21
|
LL | struct Bar<T, const TYPE_SIZE: usize = { std::mem::size_of::<T>() }>(T);
| ^^^^^^^^^
|
= note: this may fail depending on what value the parameter takes
error: aborting due to 2 previous errors

View File

@ -1,5 +1,5 @@
error: generic parameters may not be used in const operations
--> $DIR/complex-generic-default-expr.rs:6:47
--> $DIR/complex-generic-default-expr.rs:7:47
|
LL | struct Foo<const N: usize, const M: usize = { N + 1 }>;
| ^ cannot perform const operation using `N`

View File

@ -1,14 +1,13 @@
// revisions: full min
//[full] check-pass
#![cfg_attr(full, feature(const_generics))]
#![feature(const_generics_defaults)]
#![allow(incomplete_features)]
struct Foo<const N: usize, const M: usize = { N + 1 }>;
//[full]~^ ERROR constant expression depends on a generic parameter
//[min]~^^ ERROR generic parameters may not be used in const operations
//[min]~^ ERROR generic parameters may not be used in const operations
struct Bar<T, const TYPE_SIZE: usize = { std::mem::size_of::<T>() }>(T);
//[full]~^ ERROR constant expression depends on a generic parameter
//[min]~^^ ERROR generic parameters may not be used in const operations
//[min]~^ ERROR generic parameters may not be used in const operations
fn main() {}