Skip to content

Commit

Permalink
Auto merge of #51570 - oli-obk:demotion, r=<try>
Browse files Browse the repository at this point in the history
Do not promote constants that contain unpromotable code

r? @eddyb

cc @nikomatsakis

I'll add more tests, just getting this out for a crater run
  • Loading branch information
bors committed Jun 18, 2018
2 parents c45ae9e + 1030037 commit ba92154
Show file tree
Hide file tree
Showing 25 changed files with 457 additions and 154 deletions.
8 changes: 7 additions & 1 deletion src/librustc/hir/map/blocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ impl MaybeFnLike for ast::Item {
}
}

impl MaybeFnLike for ast::ImplItem {
fn is_fn_like(&self) -> bool {
match self.node { ast::ImplItemKind::Method(..) => true, _ => false, }
}
}

impl MaybeFnLike for ast::TraitItem {
fn is_fn_like(&self) -> bool {
match self.node {
Expand Down Expand Up @@ -144,7 +150,7 @@ impl<'a> FnLikeNode<'a> {
let fn_like = match node {
map::NodeItem(item) => item.is_fn_like(),
map::NodeTraitItem(tm) => tm.is_fn_like(),
map::NodeImplItem(_) => true,
map::NodeImplItem(it) => it.is_fn_like(),
map::NodeExpr(e) => e.is_fn_like(),
_ => false
};
Expand Down
5 changes: 5 additions & 0 deletions src/librustc/ty/steal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ impl<T> Steal<T> {
})
}

/// In case of cyclic queries, use this function to break the cycle
pub fn try_borrow(&self) -> ReadGuard<Option<T>> {
self.value.borrow()
}

pub fn steal(&self) -> T {
let value_ref = &mut *self.value.try_write().expect("stealing value which is locked");
let value = mem::replace(value_ref, None);
Expand Down
14 changes: 11 additions & 3 deletions src/librustc_metadata/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -415,9 +415,9 @@ impl<'tcx> EntryKind<'tcx> {
EntryKind::ForeignMutStatic => Def::Static(did, true),
EntryKind::Struct(_, _) => Def::Struct(did),
EntryKind::Union(_, _) => Def::Union(did),
EntryKind::Fn(_) |
EntryKind::Fn(..) |
EntryKind::ForeignFn(_) => Def::Fn(did),
EntryKind::Method(_) => Def::Method(did),
EntryKind::Method(..) => Def::Method(did),
EntryKind::Type => Def::TyAlias(did),
EntryKind::AssociatedType(_) => Def::AssociatedTy(did),
EntryKind::Mod(_) => Def::Mod(did),
Expand Down Expand Up @@ -765,7 +765,13 @@ impl<'a, 'tcx> CrateMetadata {
match self.entry(id).kind {
EntryKind::AssociatedConst(_, data, _) |
EntryKind::Const(data, _) => data.ast_promotable,
_ => bug!(),
EntryKind::Fn(ref data) => {
data.decode(self).qualif.map_or(false, |q| q.ast_promotable)
},
EntryKind::Method(ref data) => {
data.decode(self).fn_data.qualif.map_or(false, |q| q.ast_promotable)
},
_ => bug!("{:?}", id),
}
}

Expand All @@ -791,6 +797,8 @@ impl<'a, 'tcx> CrateMetadata {
EntryKind::AssociatedConst(AssociatedContainer::ImplFinal, qualif, _) => {
qualif.mir
}
EntryKind::Method(data) => data.decode(self).fn_data.qualif.map_or(0, |q| q.mir),
EntryKind::Fn(data) => data.decode(self).qualif.map_or(0, |q| q.mir),
_ => bug!(),
}
}
Expand Down
27 changes: 22 additions & 5 deletions src/librustc_metadata/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -827,6 +827,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
constness: hir::Constness::NotConst,
arg_names,
sig: self.lazy(&tcx.fn_sig(def_id)),
qualif: None,
}
} else {
bug!()
Expand Down Expand Up @@ -880,6 +881,20 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
!self.tcx.sess.opts.output_types.should_codegen()
}

fn const_fn_qualif(
&self,
def_id: DefId,
body_id: hir::BodyId,
span: Span,
) -> Option<ConstQualif> {
if self.tcx.is_const_fn(def_id) {
let mir = self.tcx.at(span).mir_const_qualif(def_id).0;
Some(self.const_qualif(mir, body_id))
} else {
None
}
}

fn const_qualif(&self, mir: u8, body_id: hir::BodyId) -> ConstQualif {
let body_owner_def_id = self.tcx.hir.body_owner_def_id(body_id);
let ast_promotable = self.tcx.const_is_rvalue_promotable_to_static(body_owner_def_id);
Expand Down Expand Up @@ -915,11 +930,12 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
}
}
ty::AssociatedKind::Method => {
let fn_data = if let hir::ImplItemKind::Method(ref sig, body) = ast_item.node {
let fn_data = if let hir::ImplItemKind::Method(ref sig, body_id) = ast_item.node {
FnData {
constness: sig.constness,
arg_names: self.encode_fn_arg_names_for_body(body),
arg_names: self.encode_fn_arg_names_for_body(body_id),
sig: self.lazy(&tcx.fn_sig(def_id)),
qualif: self.const_fn_qualif(def_id, body_id, ast_item.span),
}
} else {
bug!()
Expand Down Expand Up @@ -1045,13 +1061,13 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
self.encode_rendered_const_for_body(body_id)
)
}
hir::ItemFn(_, _, constness, .., body) => {
hir::ItemFn(_, _, constness, .., body_id) => {
let data = FnData {
constness,
arg_names: self.encode_fn_arg_names_for_body(body),
arg_names: self.encode_fn_arg_names_for_body(body_id),
sig: self.lazy(&tcx.fn_sig(def_id)),
qualif: self.const_fn_qualif(def_id, body_id, item.span),
};

EntryKind::Fn(self.lazy(&data))
}
hir::ItemMod(ref m) => {
Expand Down Expand Up @@ -1565,6 +1581,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
constness: hir::Constness::NotConst,
arg_names: self.encode_fn_arg_names(names),
sig: self.lazy(&tcx.fn_sig(def_id)),
qualif: None,
};
EntryKind::ForeignFn(self.lazy(&data))
}
Expand Down
3 changes: 2 additions & 1 deletion src/librustc_metadata/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -434,9 +434,10 @@ pub struct FnData<'tcx> {
pub constness: hir::Constness,
pub arg_names: LazySeq<ast::Name>,
pub sig: Lazy<ty::PolyFnSig<'tcx>>,
pub qualif: Option<ConstQualif>,
}

impl_stable_hash_for!(struct FnData<'tcx> { constness, arg_names, sig });
impl_stable_hash_for!(struct FnData<'tcx> { constness, arg_names, sig, qualif });

#[derive(RustcEncodable, RustcDecodable)]
pub struct VariantData<'tcx> {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/build/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ use util as mir_util;

/// Construct the MIR for a given def-id.
pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'tcx> {
let id = tcx.hir.as_local_node_id(def_id).unwrap();
let id = tcx.hir.as_local_node_id(def_id).expect("can't build non-local MIR");
let unsupported = || {
span_bug!(tcx.hir.span(id), "can't build MIR for {:?}", def_id);
};
Expand Down
4 changes: 4 additions & 0 deletions src/librustc_mir/transform/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,10 @@ fn mir_validated<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx
// Ensure that we compute the `mir_const_qualif` for constants at
// this point, before we steal the mir-const result.
let _ = tcx.mir_const_qualif(def_id);
} else if tcx.is_const_fn(def_id) {
// Ensure that we compute the `mir_const_qualif` for const fns at
// this point, before we steal the mir-const result.
let _ = tcx.mir_const_qualif(def_id);
}

let mut mir = tcx.mir_const(def_id).steal();
Expand Down
Loading

0 comments on commit ba92154

Please sign in to comment.