Skip to content

Commit

Permalink
Enable effects for libcore
Browse files Browse the repository at this point in the history
  • Loading branch information
fee1-dead committed Aug 13, 2023
1 parent cb0c299 commit f7c0ba5
Show file tree
Hide file tree
Showing 29 changed files with 271 additions and 191 deletions.
6 changes: 5 additions & 1 deletion compiler/rustc_codegen_ssa/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,11 @@ pub fn build_langcall<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
) -> (Bx::FnAbiOfResult, Bx::Value) {
let tcx = bx.tcx();
let def_id = tcx.require_lang_item(li, span);
let instance = ty::Instance::mono(tcx, def_id);
let instance = if li == LangItem::Panic {
ty::Instance::new(def_id, tcx.mk_args(&[tcx.consts.true_.into()]))
} else {
ty::Instance::mono(tcx, def_id)
};
(bx.fn_abi_of_instance(instance, ty::List::empty()), bx.get_fn_addr(instance))
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir/src/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ language_item_table! {
// in the sense that a crate is not required to have it defined to use it, but a final product
// is required to define it somewhere. Additionally, there are restrictions on crates that use
// a weak lang item, but do not have it defined.
Panic, sym::panic, panic_fn, Target::Fn, GenericRequirement::Exact(0);
Panic, sym::panic, panic_fn, Target::Fn, GenericRequirement::Minimum(0);
PanicNounwind, sym::panic_nounwind, panic_nounwind, Target::Fn, GenericRequirement::Exact(0);
PanicFmt, sym::panic_fmt, panic_fmt, Target::Fn, GenericRequirement::None;
PanicDisplay, sym::panic_display, panic_display, Target::Fn, GenericRequirement::None;
Expand Down
8 changes: 7 additions & 1 deletion compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -525,8 +525,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
_ => self.instantiate_value_path(segs, opt_ty, res, expr.span, expr.hir_id).0,
};

if let ty::FnDef(did, ..) = *ty.kind() {
if let ty::FnDef(did, callee_args) = *ty.kind() {
let fn_sig = ty.fn_sig(tcx);

// HACK: whenever we get a FnDef in a non-const context, enforce effects to get the
// default `host = true` to avoid inference errors later.
if tcx.hir().body_const_context(self.body_id).is_none() {
self.enforce_context_effects(expr.hir_id, qpath.span(), did, callee_args);
}
if tcx.fn_sig(did).skip_binder().abi() == RustIntrinsic
&& tcx.item_name(did) == sym::transmute
{
Expand Down
19 changes: 14 additions & 5 deletions compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,11 +274,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
//
// This check is here because there is currently no way to express a trait bound for `FnDef` types only.
if is_const_eval_select && (1..=2).contains(&idx) {
if let ty::FnDef(def_id, _) = checked_ty.kind() {
if idx == 1 && !self.tcx.is_const_fn_raw(*def_id) {
self.tcx
.sess
.emit_err(errors::ConstSelectMustBeConst { span: provided_arg.span });
if let ty::FnDef(def_id, args) = *checked_ty.kind() {
if idx == 1 {
if !self.tcx.is_const_fn_raw(def_id) {
self.tcx.sess.emit_err(errors::ConstSelectMustBeConst {
span: provided_arg.span,
});
} else {
self.enforce_context_effects(
provided_arg.hir_id,
provided_arg.span,
def_id,
args,
)
}
}
} else {
self.tcx.sess.emit_err(errors::ConstSelectMustBeFn {
Expand Down
7 changes: 4 additions & 3 deletions compiler/rustc_metadata/src/rmeta/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -846,7 +846,7 @@ fn should_encode_span(def_kind: DefKind) -> bool {
}
}

fn should_encode_attrs(def_kind: DefKind) -> bool {
fn should_encode_attrs(def_kind: DefKind, def_id: DefId, tcx: TyCtxt<'_>) -> bool {
match def_kind {
DefKind::Mod
| DefKind::Struct
Expand All @@ -871,8 +871,9 @@ fn should_encode_attrs(def_kind: DefKind) -> bool {
// https://github.com/model-checking/kani and is not a performance
// or maintenance issue for us.
DefKind::Closure => true,
// encode the host param attr
DefKind::ConstParam => tcx.has_attr(def_id, sym::rustc_host),
DefKind::TyParam
| DefKind::ConstParam
| DefKind::Ctor(..)
| DefKind::ExternCrate
| DefKind::Use
Expand Down Expand Up @@ -1329,7 +1330,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
let def_span = tcx.def_span(local_id);
record!(self.tables.def_span[def_id] <- def_span);
}
if should_encode_attrs(def_kind) {
if should_encode_attrs(def_kind, def_id, tcx) {
self.encode_attrs(local_id);
}
if should_encode_expn_that_defined(def_kind) {
Expand Down
13 changes: 9 additions & 4 deletions compiler/rustc_monomorphize/src/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -767,11 +767,16 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
}
}
mir::TerminatorKind::Assert { ref msg, .. } => {
let lang_item = match &**msg {
mir::AssertKind::BoundsCheck { .. } => LangItem::PanicBoundsCheck,
_ => LangItem::Panic,
let (lang_item, has_host_effect) = match &**msg {
mir::AssertKind::BoundsCheck { .. } => (LangItem::PanicBoundsCheck, false),
_ => (LangItem::Panic, true),
};
let def_id = tcx.require_lang_item(lang_item, Some(source));
let instance = if has_host_effect {
Instance::new(def_id, tcx.mk_args(&[tcx.consts.true_.into()]))
} else {
Instance::mono(tcx, def_id)
};
let instance = Instance::mono(tcx, tcx.require_lang_item(lang_item, Some(source)));
if should_codegen_locally(tcx, &instance) {
self.output.push(create_fn_mono_item(tcx, instance, source));
}
Expand Down
1 change: 1 addition & 0 deletions library/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@
//
// Language features:
// tidy-alphabetical-start
#![cfg_attr(not(bootstrap), feature(effects))]
#![feature(abi_unadjusted)]
#![feature(adt_const_params)]
#![feature(allow_internal_unsafe)]
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -966,7 +966,7 @@ marker_impls! {
#[lang = "destruct"]
#[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)]
#[rustc_deny_explicit_impl(implement_via_object = false)]
#[const_trait]
// FIXME(effects) #[const_trait]
pub trait Destruct {}

/// A marker for tuple types.
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/ops/drop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@
/// [nomicon]: ../../nomicon/phantom-data.html#an-exception-the-special-case-of-the-standard-library-and-its-unstable-may_dangle
#[lang = "drop"]
#[stable(feature = "rust1", since = "1.0.0")]
#[const_trait]
// FIXME(effects) #[const_trait]
pub trait Drop {
/// Executes the destructor for this type.
///
Expand Down
6 changes: 3 additions & 3 deletions library/core/src/ops/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ use crate::marker::Tuple;
)]
#[fundamental] // so that regex can rely that `&str: !FnMut`
#[must_use = "closures are lazy and do nothing unless called"]
#[const_trait]
// FIXME(effects) #[const_trait]
pub trait Fn<Args: Tuple>: FnMut<Args> {
/// Performs the call operation.
#[unstable(feature = "fn_traits", issue = "29625")]
Expand Down Expand Up @@ -159,7 +159,7 @@ pub trait Fn<Args: Tuple>: FnMut<Args> {
)]
#[fundamental] // so that regex can rely that `&str: !FnMut`
#[must_use = "closures are lazy and do nothing unless called"]
#[const_trait]
// FIXME(effects) #[const_trait]
pub trait FnMut<Args: Tuple>: FnOnce<Args> {
/// Performs the call operation.
#[unstable(feature = "fn_traits", issue = "29625")]
Expand Down Expand Up @@ -238,7 +238,7 @@ pub trait FnMut<Args: Tuple>: FnOnce<Args> {
)]
#[fundamental] // so that regex can rely that `&str: !FnMut`
#[must_use = "closures are lazy and do nothing unless called"]
#[const_trait]
// FIXME(effects) #[const_trait]
pub trait FnOnce<Args: Tuple> {
/// The returned type after the call operator is used.
#[lang = "fn_once_output"]
Expand Down
9 changes: 3 additions & 6 deletions tests/ui/consts/const-block-const-bound.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
error[E0493]: destructor of `T` cannot be evaluated at compile-time
--> $DIR/const-block-const-bound.rs:8:32
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/const-block-const-bound.rs:8:22
|
LL | const fn f<T: ~const Destruct>(x: T) {}
| ^ - value is dropped here
| |
| the destructor for this type cannot be evaluated in constant functions
| ^^^^^^^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0493`.
86 changes: 85 additions & 1 deletion tests/ui/consts/fn_trait_refs.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,90 @@ error[E0635]: unknown feature `const_cmp`
LL | #![feature(const_cmp)]
| ^^^^^^^^^

error: aborting due to 2 previous errors
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:15:15
|
LL | T: ~const Fn<()> + ~const Destruct,
| ^^^^^^

error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:15:31
|
LL | T: ~const Fn<()> + ~const Destruct,
| ^^^^^^^^

error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:15:15
|
LL | T: ~const Fn<()> + ~const Destruct,
| ^^^^^^

error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:22:15
|
LL | T: ~const FnMut<()> + ~const Destruct,
| ^^^^^^^^^

error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:22:34
|
LL | T: ~const FnMut<()> + ~const Destruct,
| ^^^^^^^^

error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:22:15
|
LL | T: ~const FnMut<()> + ~const Destruct,
| ^^^^^^^^^

error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:29:15
|
LL | T: ~const FnOnce<()>,
| ^^^^^^^^^^

error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:29:15
|
LL | T: ~const FnOnce<()>,
| ^^^^^^^^^^

error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:36:15
|
LL | T: ~const Fn<()> + ~const Destruct,
| ^^^^^^

error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:36:31
|
LL | T: ~const Fn<()> + ~const Destruct,
| ^^^^^^^^

error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:36:15
|
LL | T: ~const Fn<()> + ~const Destruct,
| ^^^^^^

error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:50:15
|
LL | T: ~const FnMut<()> + ~const Destruct,
| ^^^^^^^^^

error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:50:34
|
LL | T: ~const FnMut<()> + ~const Destruct,
| ^^^^^^^^

error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:50:15
|
LL | T: ~const FnMut<()> + ~const Destruct,
| ^^^^^^^^^

error: aborting due to 16 previous errors

For more information about this error, try `rustc --explain E0635`.
8 changes: 5 additions & 3 deletions tests/ui/consts/unstable-const-fn-in-libcore.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// known-bug: #110395
// FIXME check-pass
// This is a non-regression test for const-qualification of unstable items in libcore
// as explained in issue #67053.
// const-qualification could miss some `const fn`s if they were unstable and the feature
Expand All @@ -15,12 +17,12 @@ impl<T> Opt<T> {
#[rustc_const_unstable(feature = "foo", issue = "none")]
#[stable(feature = "rust1", since = "1.0.0")]
const fn unwrap_or_else<F: ~const FnOnce() -> T>(self, f: F) -> T {
//~^ ERROR destructor of
//~| ERROR destructor of
//FIXME ~^ ERROR destructor of
//FIXME ~| ERROR destructor of
match self {
Opt::Some(t) => t,
Opt::None => f(),
//~^ ERROR cannot call
//FIXME ~^ ERROR cannot call
}
}
}
Expand Down
34 changes: 4 additions & 30 deletions tests/ui/consts/unstable-const-fn-in-libcore.stderr
Original file line number Diff line number Diff line change
@@ -1,34 +1,8 @@
error[E0015]: cannot call non-const closure in constant functions
--> $DIR/unstable-const-fn-in-libcore.rs:22:26
|
LL | Opt::None => f(),
| ^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
help: consider further restricting this bound
|
LL | const fn unwrap_or_else<F: ~const FnOnce() -> T + ~const std::ops::FnOnce<()>>(self, f: F) -> T {
| +++++++++++++++++++++++++++++

error[E0493]: destructor of `F` cannot be evaluated at compile-time
--> $DIR/unstable-const-fn-in-libcore.rs:17:60
|
LL | const fn unwrap_or_else<F: ~const FnOnce() -> T>(self, f: F) -> T {
| ^ the destructor for this type cannot be evaluated in constant functions
...
LL | }
| - value is dropped here

error[E0493]: destructor of `Opt<T>` cannot be evaluated at compile-time
--> $DIR/unstable-const-fn-in-libcore.rs:17:54
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/unstable-const-fn-in-libcore.rs:19:39
|
LL | const fn unwrap_or_else<F: ~const FnOnce() -> T>(self, f: F) -> T {
| ^^^^ the destructor for this type cannot be evaluated in constant functions
...
LL | }
| - value is dropped here
| ^^^^^^^^^^^^^

error: aborting due to 3 previous errors
error: aborting due to previous error

Some errors have detailed explanations: E0015, E0493.
For more information about an error, try `rustc --explain E0015`.
25 changes: 7 additions & 18 deletions tests/ui/impl-trait/normalize-tait-in-const.stderr
Original file line number Diff line number Diff line change
@@ -1,25 +1,14 @@
error[E0015]: cannot call non-const closure in constant functions
--> $DIR/normalize-tait-in-const.rs:26:5
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/normalize-tait-in-const.rs:25:42
|
LL | fun(filter_positive());
| ^^^^^^^^^^^^^^^^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
help: consider further restricting this bound
|
LL | const fn with_positive<F: ~const for<'a> Fn(&'a Alias<'a>) + ~const Destruct + ~const std::ops::Fn<(&Alias<'_>,)>>(fun: F) {
| ++++++++++++++++++++++++++++++++++++
LL | const fn with_positive<F: ~const for<'a> Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) {
| ^^^^^^^^^^^^^^^^^

error[E0493]: destructor of `F` cannot be evaluated at compile-time
--> $DIR/normalize-tait-in-const.rs:25:79
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/normalize-tait-in-const.rs:25:69
|
LL | const fn with_positive<F: ~const for<'a> Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) {
| ^^^ the destructor for this type cannot be evaluated in constant functions
LL | fun(filter_positive());
LL | }
| - value is dropped here
| ^^^^^^^^

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0015, E0493.
For more information about an error, try `rustc --explain E0015`.
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// check-pass
// known-bug: #110395
// FIXME check-pass

#![feature(const_trait_impl, const_closures)]
#![allow(incomplete_features)]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/const-closure-parse-not-item.rs:7:32
|
LL | const fn test() -> impl ~const Fn() {
| ^^^^

error: aborting due to previous error

0 comments on commit f7c0ba5

Please sign in to comment.