Semantic checks of impl restrictions#154661
Semantic checks of impl restrictions#154661CoCo-Japan-pan wants to merge 9 commits intorust-lang:mainfrom
impl restrictions#154661Conversation
|
Some changes occurred in compiler/rustc_passes/src/check_attr.rs cc @jdonszelmann, @JonathanBrouwer Some changes occurred in src/tools/clippy cc @rust-lang/clippy |
impl restriction checkimpl restrictions
| if restricted_to.krate == krate { | ||
| tcx.def_path_str(restricted_to) | ||
| } else { | ||
| tcx.crate_name(restricted_to.krate).to_ident_string() | ||
| } |
There was a problem hiding this comment.
This doesn't seems right. tcx.crate_name will only return the default crate name, but one can rename a crate when importing it, eg with extern crate serde as another_serde; or in Cargo.toml.
I think it would be safer to only call def_path_str here.
| impl external::TopLevel for LocalType {} //~ ERROR trait cannot be implemented outside `external_impl_restriction` | ||
| impl external::inner::Inner for LocalType {} //~ ERROR trait cannot be implemented outside `external_impl_restriction` |
There was a problem hiding this comment.
That's what I was talking about, the error here refers to external_impl_restriction instead of external.
| impl external::TopLevel for LocalType {} //~ ERROR trait cannot be implemented outside `external_impl_restriction` | |
| impl external::inner::Inner for LocalType {} //~ ERROR trait cannot be implemented outside `external_impl_restriction` | |
| impl external::TopLevel for LocalType {} //~ ERROR trait cannot be implemented outside `external` | |
| impl external::inner::Inner for LocalType {} //~ ERROR trait cannot be implemented outside `external` |
There was a problem hiding this comment.
When we use def_path_str for external crates, the second one will be inner instead of external::inner.
Maybe we should use with_no_trimmed_paths!?
There was a problem hiding this comment.
You can try with with_no_trimmed_paths!, though I'm surprised it gives you inner and not external::inner. I wonder if def_path_str is a bit confused with external definitions.
Looking at the different overrides maybe with_resolve_crate_name! would be better for us here, as it would avoid always printing the crate name when not necessary.
There was a problem hiding this comment.
with_resolve_crate_name!(tcx.def_path_str(restricted_to)) seems to output the same result as tcx.def_path_str(restricted_to) in these test cases, which gives us inner instead of external::inner.
rust/compiler/rustc_public_bridge/src/context/impls.rs
Lines 269 to 270 in 96893dc
Only using with_no_trimmed_paths! yields external::inner, while local items appear to omit the crate prefix (e.g., foo::bar).
On the other hand, with_resolve_crate_name!(with_no_trimmed_paths!(self.tcx.def_path_str(def_id))) does not omit the prefix for local items, but uses the crate name (e.g., impl_restriction_check::foo::bar) instead of crate.
Would it make sense to use with_no_trimmed_paths! and then explicitly add the crate prefix for local items?
Or maybe we should just use with_no_trimmed_paths! or with_resolve_crate_name!(with_no_trimmed_paths!(..))?
There was a problem hiding this comment.
Given your description it seems like we could with_crate_name! + with_no_trimmed_paths! to get crate:: prefix for local modules and full path for external modules.
It that doesn't work, let's just use with_no_trimmed_paths!. The most important being that we get the resolved crate name when pointing at external modules.
| pub(crate) impl(super) trait Bar {} | ||
| pub impl(crate) trait Baz {} | ||
| pub(crate) impl(in crate::foo::bar) trait Qux {} | ||
| pub(crate) impl(in crate::foo) trait FooBar {} |
There was a problem hiding this comment.
Can you add test case where it's impl(in crate::bar) here, so we can make sure it's not implementable here.
Same with a impl(in external).
There was a problem hiding this comment.
crate::bar would be an invalid path, and external is not an ancestor, so both cases should already result in errors during path resolution. Is that what you had in mind?
There was a problem hiding this comment.
Well mod bar {} would need to be created, but yes, I would like to have a test for those two cases.
In general, it's always good add tests for edge-case, even if they appear "impossible", you never know what users will throw at the compiler.
There was a problem hiding this comment.
For ancestor-related errors involving restrictions to other crates, it might make sense to add such cases to restriction_resolution_errors.rs
There was a problem hiding this comment.
I was pointing here since there is already an aux-build, but feel free to put it where you think it makes the most sense.
View all comments
This PR implements semantic checks for
implrestrictions proposed in the Restrictions RFC (Tracking Issue #105077), and linked to a GSOC idea/proposal.It lowers the resolved paths of
implrestrictions from the AST to HIR and intoTraitDef, and integrates the checks into the coherence phase by extendingcheck_impl. As parsing (#152943) and path resolution (#153556) have already been implemented, this PR provides a working implementation ofimplrestrictions.r? @Urgau
cc @jhpratt