Skip to content

Commit 912bc72

Browse files
committed
Don't promote calls to const fns containing non-promotable content
1 parent e76172c commit 912bc72

17 files changed

+356
-50
lines changed

src/librustc/hir/map/blocks.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ impl MaybeFnLike for ast::Item {
5252
}
5353
}
5454

55+
impl MaybeFnLike for ast::ImplItem {
56+
fn is_fn_like(&self) -> bool {
57+
match self.node { ast::ImplItemKind::Method(..) => true, _ => false, }
58+
}
59+
}
60+
5561
impl MaybeFnLike for ast::TraitItem {
5662
fn is_fn_like(&self) -> bool {
5763
match self.node {
@@ -144,7 +150,7 @@ impl<'a> FnLikeNode<'a> {
144150
let fn_like = match node {
145151
map::NodeItem(item) => item.is_fn_like(),
146152
map::NodeTraitItem(tm) => tm.is_fn_like(),
147-
map::NodeImplItem(_) => true,
153+
map::NodeImplItem(it) => it.is_fn_like(),
148154
map::NodeExpr(e) => e.is_fn_like(),
149155
_ => false
150156
};

src/librustc/ty/steal.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ impl<T> Steal<T> {
4949
})
5050
}
5151

52+
/// In case of cyclic queries, use this function to break the cycle
53+
pub fn try_borrow(&self) -> ReadGuard<Option<T>> {
54+
self.value.borrow()
55+
}
56+
5257
pub fn steal(&self) -> T {
5358
let value_ref = &mut *self.value.try_write().expect("stealing value which is locked");
5459
let value = mem::replace(value_ref, None);

src/librustc_metadata/decoder.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -415,9 +415,9 @@ impl<'tcx> EntryKind<'tcx> {
415415
EntryKind::ForeignMutStatic => Def::Static(did, true),
416416
EntryKind::Struct(_, _) => Def::Struct(did),
417417
EntryKind::Union(_, _) => Def::Union(did),
418-
EntryKind::Fn(_) |
418+
EntryKind::Fn(..) |
419419
EntryKind::ForeignFn(_) => Def::Fn(did),
420-
EntryKind::Method(_) => Def::Method(did),
420+
EntryKind::Method(..) => Def::Method(did),
421421
EntryKind::Type => Def::TyAlias(did),
422422
EntryKind::AssociatedType(_) => Def::AssociatedTy(did),
423423
EntryKind::Mod(_) => Def::Mod(did),
@@ -765,7 +765,13 @@ impl<'a, 'tcx> CrateMetadata {
765765
match self.entry(id).kind {
766766
EntryKind::AssociatedConst(_, data, _) |
767767
EntryKind::Const(data, _) => data.ast_promotable,
768-
_ => bug!(),
768+
EntryKind::Fn(ref data) => {
769+
data.decode(self).qualif.map_or(false, |q| q.ast_promotable)
770+
},
771+
EntryKind::Method(ref data) => {
772+
data.decode(self).fn_data.qualif.map_or(false, |q| q.ast_promotable)
773+
},
774+
_ => bug!("{:?}", id),
769775
}
770776
}
771777

@@ -791,6 +797,8 @@ impl<'a, 'tcx> CrateMetadata {
791797
EntryKind::AssociatedConst(AssociatedContainer::ImplFinal, qualif, _) => {
792798
qualif.mir
793799
}
800+
EntryKind::Method(data) => data.decode(self).fn_data.qualif.map_or(0, |q| q.mir),
801+
EntryKind::Fn(data) => data.decode(self).qualif.map_or(0, |q| q.mir),
794802
_ => bug!(),
795803
}
796804
}

src/librustc_metadata/encoder.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
827827
constness: hir::Constness::NotConst,
828828
arg_names,
829829
sig: self.lazy(&tcx.fn_sig(def_id)),
830+
qualif: None,
830831
}
831832
} else {
832833
bug!()
@@ -880,6 +881,15 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
880881
!self.tcx.sess.opts.output_types.should_codegen()
881882
}
882883

884+
fn const_fn_qualif(&self, def_id: DefId, body_id: hir::BodyId, span: Span) -> Option<ConstQualif> {
885+
if self.tcx.is_const_fn(def_id) {
886+
let mir = self.tcx.at(span).mir_const_qualif(def_id).0;
887+
Some(self.const_qualif(mir, body_id))
888+
} else {
889+
None
890+
}
891+
}
892+
883893
fn const_qualif(&self, mir: u8, body_id: hir::BodyId) -> ConstQualif {
884894
let body_owner_def_id = self.tcx.hir.body_owner_def_id(body_id);
885895
let ast_promotable = self.tcx.const_is_rvalue_promotable_to_static(body_owner_def_id);
@@ -915,11 +925,12 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
915925
}
916926
}
917927
ty::AssociatedKind::Method => {
918-
let fn_data = if let hir::ImplItemKind::Method(ref sig, body) = ast_item.node {
928+
let fn_data = if let hir::ImplItemKind::Method(ref sig, body_id) = ast_item.node {
919929
FnData {
920930
constness: sig.constness,
921-
arg_names: self.encode_fn_arg_names_for_body(body),
931+
arg_names: self.encode_fn_arg_names_for_body(body_id),
922932
sig: self.lazy(&tcx.fn_sig(def_id)),
933+
qualif: self.const_fn_qualif(def_id, body_id, ast_item.span),
923934
}
924935
} else {
925936
bug!()
@@ -1045,13 +1056,13 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
10451056
self.encode_rendered_const_for_body(body_id)
10461057
)
10471058
}
1048-
hir::ItemFn(_, _, constness, .., body) => {
1059+
hir::ItemFn(_, _, constness, .., body_id) => {
10491060
let data = FnData {
10501061
constness,
1051-
arg_names: self.encode_fn_arg_names_for_body(body),
1062+
arg_names: self.encode_fn_arg_names_for_body(body_id),
10521063
sig: self.lazy(&tcx.fn_sig(def_id)),
1064+
qualif: self.const_fn_qualif(def_id, body_id, item.span),
10531065
};
1054-
10551066
EntryKind::Fn(self.lazy(&data))
10561067
}
10571068
hir::ItemMod(ref m) => {
@@ -1565,6 +1576,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
15651576
constness: hir::Constness::NotConst,
15661577
arg_names: self.encode_fn_arg_names(names),
15671578
sig: self.lazy(&tcx.fn_sig(def_id)),
1579+
qualif: None,
15681580
};
15691581
EntryKind::ForeignFn(self.lazy(&data))
15701582
}

src/librustc_metadata/schema.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,9 +434,10 @@ pub struct FnData<'tcx> {
434434
pub constness: hir::Constness,
435435
pub arg_names: LazySeq<ast::Name>,
436436
pub sig: Lazy<ty::PolyFnSig<'tcx>>,
437+
pub qualif: Option<ConstQualif>,
437438
}
438439

439-
impl_stable_hash_for!(struct FnData<'tcx> { constness, arg_names, sig });
440+
impl_stable_hash_for!(struct FnData<'tcx> { constness, arg_names, sig, qualif });
440441

441442
#[derive(RustcEncodable, RustcDecodable)]
442443
pub struct VariantData<'tcx> {

src/librustc_mir/build/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use util as mir_util;
3535

3636
/// Construct the MIR for a given def-id.
3737
pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'tcx> {
38-
let id = tcx.hir.as_local_node_id(def_id).unwrap();
38+
let id = tcx.hir.as_local_node_id(def_id).expect("can't build non-local MIR");
3939
let unsupported = || {
4040
span_bug!(tcx.hir.span(id), "can't build MIR for {:?}", def_id);
4141
};

src/librustc_mir/transform/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,10 @@ fn mir_validated<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx
210210
// Ensure that we compute the `mir_const_qualif` for constants at
211211
// this point, before we steal the mir-const result.
212212
let _ = tcx.mir_const_qualif(def_id);
213+
} else if tcx.is_const_fn(def_id) {
214+
// Ensure that we compute the `mir_const_qualif` for const fns at
215+
// this point, before we steal the mir-const result.
216+
let _ = tcx.mir_const_qualif(def_id);
213217
}
214218

215219
let mut mir = tcx.mir_const(def_id).steal();

0 commit comments

Comments
 (0)