adt_const_params: check referred-to types when checking impls of ConstParamTy on refs#120127
adt_const_params: check referred-to types when checking impls of ConstParamTy on refs#120127sjwang05 wants to merge 3 commits intorust-lang:masterfrom
adt_const_params: check referred-to types when checking impls of ConstParamTy on refs#120127Conversation
|
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 typeUsing 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.
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.
| 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.
| 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::Uint(_) | ty::Int(_) | ty::Bool | ty::Char | ty::Str => return Ok(()), | ||
|
|
||
| &ty::Adt(adt, args) => (adt, args), | ||
| &ty::Adt(adt, args) => adts_and_args.push((adt, args)), |
There was a problem hiding this comment.
| &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.
| 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.
| 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
ConstParamTyon refs actually implementedConstParamTyintype_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
ConstParamTyand were not const-evaluatable (#119299).This PR modifies
type_allowed_to_implement_const_param_tyto check if the referred-to type and all of its fields implementConstParamTy. It additionally adds a new variant to theConstParamTyImplementationErrorenum and a new error in the case the referenced-to type does not implementConstParamTy.cc @rust-lang/project-const-generics
Fixes #112124