-
Notifications
You must be signed in to change notification settings - Fork 13k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto merge of #53851 - oli-obk:local_promotion, r=eddyb
Limit the promotion of const fns to the libstd and the `rustc_promotable` attribute There are so many questions around promoting const fn calls... it seems saner to try to limit automatic promotion to const fns which were explicitly opted in for promotion. I added the attribute to all public stable const fns that were already promotable (e.g. not Cell::new) in order to not cause any breakage r? @eddyb cc @nikomatsakis
- Loading branch information
Showing
45 changed files
with
484 additions
and
335 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
use ty::query::Providers; | ||
use hir::def_id::DefId; | ||
use hir; | ||
use ty::TyCtxt; | ||
use syntax_pos::symbol::Symbol; | ||
use hir::map::blocks::FnLikeNode; | ||
use syntax::attr; | ||
use rustc_target::spec::abi; | ||
|
||
impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { | ||
/// Whether the `def_id` counts as const fn in your current crate, considering all active | ||
/// feature gates | ||
pub fn is_const_fn(self, def_id: DefId) -> bool { | ||
self.is_const_fn_raw(def_id) && match self.lookup_stability(def_id) { | ||
Some(stab) => match stab.const_stability { | ||
// has a `rustc_const_unstable` attribute, check whether the user enabled the | ||
// corresponding feature gate | ||
Some(feature_name) => self.features() | ||
.declared_lib_features | ||
.iter() | ||
.any(|&(sym, _)| sym == feature_name), | ||
// the function has no stability attribute, it is stable as const fn or the user | ||
// needs to use feature gates to use the function at all | ||
None => true, | ||
}, | ||
// functions without stability are either stable user written const fn or the user is | ||
// using feature gates and we thus don't care what they do | ||
None => true, | ||
} | ||
} | ||
|
||
/// Whether the `def_id` is an unstable const fn and what feature gate is necessary to enable it | ||
pub fn is_unstable_const_fn(self, def_id: DefId) -> Option<Symbol> { | ||
if self.is_const_fn_raw(def_id) { | ||
self.lookup_stability(def_id)?.const_stability | ||
} else { | ||
None | ||
} | ||
} | ||
|
||
/// Returns true if this function must conform to `min_const_fn` | ||
pub fn is_min_const_fn(self, def_id: DefId) -> bool { | ||
if self.features().staged_api { | ||
// some intrinsics are waved through if called inside the | ||
// standard library. Users never need to call them directly | ||
if let abi::Abi::RustIntrinsic = self.fn_sig(def_id).abi() { | ||
assert!(!self.is_const_fn(def_id)); | ||
match &self.item_name(def_id).as_str()[..] { | ||
| "size_of" | ||
| "min_align_of" | ||
| "needs_drop" | ||
=> return true, | ||
_ => {}, | ||
} | ||
} | ||
// in order for a libstd function to be considered min_const_fn | ||
// it needs to be stable and have no `rustc_const_unstable` attribute | ||
match self.lookup_stability(def_id) { | ||
// stable functions with unstable const fn aren't `min_const_fn` | ||
Some(&attr::Stability { const_stability: Some(_), .. }) => false, | ||
// unstable functions don't need to conform | ||
Some(&attr::Stability { ref level, .. }) if level.is_unstable() => false, | ||
// everything else needs to conform, because it would be callable from | ||
// other `min_const_fn` functions | ||
_ => true, | ||
} | ||
} else { | ||
// users enabling the `const_fn` can do what they want | ||
!self.sess.features_untracked().const_fn | ||
} | ||
} | ||
} | ||
|
||
|
||
pub fn provide<'tcx>(providers: &mut Providers<'tcx>) { | ||
/// only checks whether the function has a `const` modifier | ||
fn is_const_fn_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> bool { | ||
let node_id = tcx.hir.as_local_node_id(def_id) | ||
.expect("Non-local call to local provider is_const_fn"); | ||
|
||
if let Some(fn_like) = FnLikeNode::from_node(tcx.hir.get(node_id)) { | ||
fn_like.constness() == hir::Constness::Const | ||
} else { | ||
false | ||
} | ||
} | ||
|
||
fn is_promotable_const_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> bool { | ||
tcx.is_const_fn(def_id) && match tcx.lookup_stability(def_id) { | ||
Some(stab) => { | ||
if cfg!(debug_assertions) && stab.promotable { | ||
let sig = tcx.fn_sig(def_id); | ||
assert_eq!( | ||
sig.unsafety(), | ||
hir::Unsafety::Normal, | ||
"don't mark const unsafe fns as promotable", | ||
// /~https://github.com/rust-lang/rust/pull/53851#issuecomment-418760682 | ||
); | ||
} | ||
stab.promotable | ||
}, | ||
None => false, | ||
} | ||
} | ||
|
||
*providers = Providers { | ||
is_const_fn_raw, | ||
is_promotable_const_fn, | ||
..*providers | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.