-
Notifications
You must be signed in to change notification settings - Fork 13.4k
adt_const_params
: check referred-to types when checking impls of ConstParamTy on refs
#120127
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Conversation
r? @TaKO8Ki (rustbot has picked a reviewer for you, use r? to override) |
I swear I remember writing a review that we needed to check this on the original PR 😦 |
Could you also do this:
|
7c61a9d
to
f98b06f
Compare
Done. I split the logic into its own closure that gets called in the relevant branches, but otherwise the logic is the same as before. I also tweaked the error message slightly. @rustbot review |
Could you add the following two test cases: // check-pass
struct Bar;
struct Foo(Bar);
impl ConstParamTy for Bar
where
Foo: ConstParamTy {}
// impl checks means that this impl is only valid if `Bar: ConstParamTy` whic
// is only valid if `Foo: ConstParamTy` holds
impl ConstParamTy for Foo {} // check that we actually take into account region constraints for `ConstParamTy` impl checks
#![feature(adt_const_params)]
use std::marker::ConstParamTy;
struct Foo<'a>(&'a u32);
struct Bar<T>(T);
impl ConstParamTy for Foo<'static> {}
impl<'a> ConstParamTy for Bar<Foo<'a>> {}
// ~^ ERROR: the trait `ConstParamTy` cannot be implemented for this type Using an Could you move the inside of the nested loop in You can then use that function in |
Thanks for the PR 😃 that issue has been open so long lol 😳 |
8d29ae2
to
eb36660
Compare
29fb9ce
to
3025f6d
Compare
3025f6d
to
486c90d
Compare
Thanks for the help! I added the tests and fixed the @rustbot review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There shouldn't be any need to call type_allowed_to_implement_const_param_ty
(or do equivalent logic) recursively, so most of the code in the match arms should be able to be removed. I think the following changes ought to work. For impl ConstParamTy for MyType
we just check all the fields implement ConstParamTy
rather than checking all the fields could implement ConstParamTy
so I think doing the same thing for [T]/&T/(T,)
where we require T: ConstParamTy
rather than T
potentially being able to implement it, is okay.
let ty = ty.peel_refs(); | ||
if !ty.has_concrete_skeleton() { | ||
continue; | ||
} | ||
|
||
if let &ty::Adt(adt, args) = ty.kind() { | ||
adts_and_args.push((adt, args)); | ||
inner_tys.push((ty, adt.did())); | ||
} else { | ||
type_allowed_to_implement_const_param_ty(tcx, param_env, ty, parent_cause)?; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let ty = ty.peel_refs(); | |
if !ty.has_concrete_skeleton() { | |
continue; | |
} | |
if let &ty::Adt(adt, args) = ty.kind() { | |
adts_and_args.push((adt, args)); | |
inner_tys.push((ty, adt.did())); | |
} else { | |
type_allowed_to_implement_const_param_ty(tcx, param_env, ty, parent_cause)?; | |
} | |
} | |
inner_tys.push(ty); |
let ty = ty.peel_refs(); | ||
if !ty.has_concrete_skeleton() { | ||
return Ok(()); | ||
} | ||
|
||
if let &ty::Adt(adt, args) = ty.kind() { | ||
adts_and_args.push((adt, args)); | ||
inner_tys.push((ty, adt.did())); | ||
} else { | ||
type_allowed_to_implement_const_param_ty(tcx, param_env, ty, parent_cause)?; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let ty = ty.peel_refs(); | |
if !ty.has_concrete_skeleton() { | |
return Ok(()); | |
} | |
if let &ty::Adt(adt, args) = ty.kind() { | |
adts_and_args.push((adt, args)); | |
inner_tys.push((ty, adt.did())); | |
} else { | |
type_allowed_to_implement_const_param_ty(tcx, param_env, ty, parent_cause)?; | |
} | |
inner_tys.push(ty); |
|
||
&ty::Adt(adt, args) => (adt, args), | ||
&ty::Adt(adt, args) => adts_and_args.push((adt, args)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
&ty::Adt(adt, args) => adts_and_args.push((adt, args)), | |
&ty::Adt(adt, args) => { | |
all_fields_implement_trait( | |
tcx, | |
param_env, | |
self_type, | |
adt, | |
args, | |
parent_cause, | |
hir::LangItem::ConstParamTy, | |
) | |
.map_err(ConstParamTyImplementationError::InfrigingFields)?; | |
} | |
for (adt, args) in adts_and_args { | ||
all_fields_implement_trait( | ||
tcx, | ||
param_env, | ||
self_type, | ||
adt, | ||
args, | ||
parent_cause, | ||
hir::LangItem::ConstParamTy, | ||
) | ||
.map_err(ConstParamTyImplementationError::InfrigingFields)?; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for (adt, args) in adts_and_args { | |
all_fields_implement_trait( | |
tcx, | |
param_env, | |
self_type, | |
adt, | |
args, | |
parent_cause, | |
hir::LangItem::ConstParamTy, | |
) | |
.map_err(ConstParamTyImplementationError::InfrigingFields)?; | |
} |
for (ty, def_id) in inner_tys { | ||
let span = tcx.def_span(def_id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for (ty, def_id) in inner_tys { | |
let span = tcx.def_span(def_id); | |
for ty in inner_tys { | |
let span = match ty.kind() { | |
TyKind::Adt(def, _) => tcx.def_span(def_id), | |
_ => parent_cause.span, | |
}; |
☔ The latest upstream changes (presumably #121018) made this pull request unmergeable. Please resolve the merge conflicts. |
@sjwang05 FYI: when a PR is ready for review, send a message containing Or if you're not going to continue, please close it. Thank you! |
I'm just going to close this, this PR has been afk for months and also I think we are going to move in the direction of forbidding references |
Previously, we didn't check if referenced-to types of impls of
ConstParamTy
on refs actually implementedConstParamTy
intype_allowed_to_implement_const_param_ty
, leading to code like the following compiling without error (#112124):This would lead to ICEs when the inner referenced type had fields that were not
ConstParamTy
and were not const-evaluatable (#119299).This PR modifies
type_allowed_to_implement_const_param_ty
to check if the referred-to type and all of its fields implementConstParamTy
. It additionally adds a new variant to theConstParamTyImplementationError
enum and a new error in the case the referenced-to type does not implementConstParamTy
.cc @rust-lang/project-const-generics
Fixes #112124