- 
                Notifications
    You must be signed in to change notification settings 
- Fork 13.9k
          Implement the min_const_fn feature gate
          #53604
        
          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
Conversation
      
        
              This comment has been minimized.
        
        
      
    
  This comment has been minimized.
        
          
                src/libsyntax/feature_gate.rs
              
                Outdated
          
        
      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.
We will need to ensure that the standard library has not enabled #![feature(const_fn)]; this includes libstd, liballoc, libcore.
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.
Well, we will want it for NonZero::new_unchecked, right?
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.
Hmm... I was hoping on using the stabilization of min_const_fn but exclusion of const_fn from libstd so that standard library functions could be const-ified en masse instead of piecemeal. This kinda relies on not having #![feature(const_fn)] enabled so that accidental things don't happen.
Could we handle new_unchecked through some other internal means instead temporarily?
EDIT: like rustc_const_stable or something...
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.
I'd say:
- const fnwithout- #[rustc_const_unstable]is stable if it passes- min_const_fn
- const fnnot passing- min_const_fncan be forced stable with- #[rustc_const_fn_force_stable]
This way the active feature gates have no influence on stability, but we're checking the right thing and can't accidentally do anything wrong.
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.
@oli-obk this sounds good to me :)
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.
What is const_raw_ptr_deref?
Can't we somehow check unsafety, instead of trying to get an exhaustive list of unsafe behavior?
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.
If it aint possible to detect this in MIR perhaps do it in HIR instead?
EDIT: Add a test with an empty unsafe { ... } block in it
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.
AFAIK MIR has some unsafety information; we do some unsafety checks in MIR.
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.
done
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.
Done as in, the reference to const_raw_ptr_deref is gone? If not, please mention the filename where that function is defined...^^
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.
As in there's a test. And const_raw_ptr_deref is a feature gate.
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.
Oh, I see. That's not clear.^^
But the feature is ruled out independent of whether that gate is set...?
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.
well... it's additionally prevented in min_const_fn due to its unsafety. The same doesn't hold for casting *const T to usize. I'll add some more sanity checks. This will annoy the heck out of nightly users since they are now getting a lot of messages twice in different wording (already happening with a bunch of things in this PR)
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.
That's a consequence of doing multiple analyses, right?
I do not think that is the right approach... even if we have separate analyses, we should only call one.
| Is it really better to have all that code duplicated into a second analysis, than changing the existing analysis to qualify every  | 
| 
 The existing analysis is supposed to be split up into three separate analyses. Me adding a fourth one to be split out in the future would not help the process. | 
| Three?!? I can see that promotion is separate, but other than that everything else should be just "const checking", which should (eventually) be the same for  | 
| 
 The checks for  | 
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.
fun side effect: the two cases below which are future compat lints are hard errors inside const fns
      
        
              This comment has been minimized.
        
        
      
    
  This comment has been minimized.
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.
Some more tests... :)
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.
I specifically do want a test here that ensures that even without access, const fn no_inner_fn_ptr2(x: Hide) { } is banned.
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.
That requires a lot of code... I'll impl it, but I don't think it's a good addition to rustc
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.
So you already have the erroring tests:
const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {}
const fn no_fn_ptrs(_x: fn()) {}This is good, because it leaves open the possibility that this means &dyn const std::fmt::Debug or const fn(); If we didn't reject this, then users could pass in values where you don't have a const implementation of std::fmt::Debug, and so we wouldn't be able to change this in the future. However, as for situations where you have:
struct Hide<'a>(&'a dyn Debug);
const fn foo(_x: Hide) {}... this would only prevent a situation in the future where we decided to split up our nominal type universe into one for the const restriction and one for impure... This seems like a very unlikely future... as such... I think the tests you have currently are sufficient.
So you don't need to implement it.
      
        
              This comment has been minimized.
        
        
      
    
  This comment has been minimized.
| Should be fine to merge once the tests pass. :) | 
      
        
              This comment has been minimized.
        
        
      
    
  This comment has been minimized.
      
        
              This comment has been minimized.
        
        
      
    
  This comment has been minimized.
      
        
              This comment has been minimized.
        
        
      
    
  This comment has been minimized.
| @Centril this is ready now I think | 
| So... while I could actually implement a check that validates the MIR of constants in  Can we just decide to treat  Alternatively I can rewrite the entire  | 
| I am perfectly fine with treating  | 
| @oli-obk I'm fine with this; I guess T-libs will just be a bit more careful with respect to  | 
| @bors r=Centril,varkor | 
| 📌 Commit 2839f4f has been approved by  | 
Implement the `min_const_fn` feature gate cc @RalfJung @eddyb r? @Centril implements the feature gate for #53555 I added a hack so the `const_fn` feature gate also enables the `min_const_fn` feature gate. This ensures that nightly users of `const_fn` don't have to touch their code at all. The `min_const_fn` checks are run first, and if they succeeded, the `const_fn` checks are run additionally to ensure we didn't miss anything.
| ☀️ Test successful - status-appveyor, status-travis | 
| I had this code in a PR I was working on, how should I write this now? impl<T> UnsafeList<T> {
    pub const fn new() -> Self {
        unsafe {
            UnsafeList {
                head_tail: NonNull::new_unchecked(1 as _),
                head_tail_entry: None
            }
        }
    }
} | 
| Minimal repro on playground: #![feature(staged_api, const_fn)]
use std::ptr::NonNull;
pub struct UnsafeList<T>(NonNull<T>);
impl<T> UnsafeList<T> {
    pub const fn new() -> Self {
        unsafe {
            UnsafeList(NonNull::new_unchecked(1 as _))
        }
    }
}The only way to get around this is to add an  | 
| @jethrogb Is this for a PR to the standard library or the compiler, or is this for code outside of that? | 
| PR for  | 
| @jethrogb if  | 
| @Centril that is not sufficient. You also need to add an  | 
| @jethrogb  | 
cc @RalfJung @eddyb
r? @Centril
implements the feature gate for #53555
I added a hack so the
const_fnfeature gate also enables themin_const_fnfeature gate. This ensures that nightly users ofconst_fndon't have to touch their code at all.The
min_const_fnchecks are run first, and if they succeeded, theconst_fnchecks are run additionally to ensure we didn't miss anything.