-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
adt_const_params
: check referred-to types when checking impls of ConstParamTy on refs
#120127
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