Skip to content

Commit

Permalink
Report the selection error when possible
Browse files Browse the repository at this point in the history
  • Loading branch information
fee1-dead committed Feb 12, 2022
1 parent cccf4b2 commit 12397ab
Show file tree
Hide file tree
Showing 13 changed files with 107 additions and 37 deletions.
51 changes: 36 additions & 15 deletions compiler/rustc_const_eval/src/transform/check_consts/check.rs
Expand Up @@ -14,6 +14,7 @@ use rustc_middle::ty::{self, adjustment::PointerCast, Instance, InstanceDef, Ty,
use rustc_middle::ty::{Binder, TraitPredicate, TraitRef};
use rustc_mir_dataflow::{self, Analysis};
use rustc_span::{sym, Span, Symbol};
use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
use rustc_trait_selection::traits::SelectionContext;

use std::mem;
Expand Down Expand Up @@ -808,15 +809,13 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
}

let trait_ref = TraitRef::from_method(tcx, trait_id, substs);
let obligation = Obligation::new(
ObligationCause::dummy(),
param_env,
Binder::dummy(TraitPredicate {
trait_ref,
constness: ty::BoundConstness::NotConst,
polarity: ty::ImplPolarity::Positive,
}),
);
let poly_trait_pred = Binder::dummy(TraitPredicate {
trait_ref,
constness: ty::BoundConstness::ConstIfConst,
polarity: ty::ImplPolarity::Positive,
});
let obligation =
Obligation::new(ObligationCause::dummy(), param_env, poly_trait_pred);

let implsrc = tcx.infer_ctxt().enter(|infcx| {
let mut selcx = SelectionContext::new(&infcx);
Expand Down Expand Up @@ -860,15 +859,37 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
// #[default_method_body_is_const], and the callee is in the same
// trait.
let callee_trait = tcx.trait_of_item(callee);
if callee_trait.is_some() {
if tcx.has_attr(caller, sym::default_method_body_is_const) {
if tcx.trait_of_item(caller) == callee_trait {
nonconst_call_permission = true;
}
}
if callee_trait.is_some()
&& tcx.has_attr(caller, sym::default_method_body_is_const)
&& callee_trait == tcx.trait_of_item(caller)
// Can only call methods when it's `<Self as TheTrait>::f`.
&& tcx.types.self_param == substs.type_at(0)
{
nonconst_call_permission = true;
}

if !nonconst_call_permission {
let obligation = Obligation::new(
ObligationCause::dummy_with_span(*fn_span),
param_env,
tcx.mk_predicate(
poly_trait_pred.map_bound(ty::PredicateKind::Trait),
),
);

// improve diagnostics by showing what failed. Our requirements are stricter this time
// as we are going to error again anyways.
tcx.infer_ctxt().enter(|infcx| {
if let Err(e) = implsrc {
infcx.report_selection_error(
obligation.clone(),
&obligation,
&e,
false,
);
}
});

self.check_op(ops::FnCallNonConst {
caller,
callee,
Expand Down
Expand Up @@ -22,7 +22,8 @@ pub const fn add_i32(a: i32, b: i32) -> i32 {

pub const fn add_u32(a: u32, b: u32) -> u32 {
a.plus(b)
//~^ ERROR cannot call non-const fn
//~^ ERROR the trait bound
//~| ERROR cannot call non-const fn
}

fn main() {}
@@ -1,3 +1,9 @@
error[E0277]: the trait bound `u32: ~const Plus` is not satisfied
--> $DIR/call-const-trait-method-fail.rs:24:7
|
LL | a.plus(b)
| ^^^^^^^ the trait `~const Plus` is not implemented for `u32`

error[E0015]: cannot call non-const fn `<u32 as Plus>::plus` in constant functions
--> $DIR/call-const-trait-method-fail.rs:24:7
|
Expand All @@ -6,6 +12,7 @@ LL | a.plus(b)
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants

error: aborting due to previous error
error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0015`.
Some errors have detailed explanations: E0015, E0277.
For more information about an error, try `rustc --explain E0015`.
Expand Up @@ -3,7 +3,8 @@

pub const fn equals_self<T: PartialEq>(t: &T) -> bool {
*t == *t
//~^ ERROR cannot call non-const operator
//~^ ERROR can't compare
//~| ERROR cannot call non-const
}

fn main() {}
@@ -1,3 +1,9 @@
error[E0277]: can't compare `T` with `T` in const contexts
--> $DIR/call-generic-method-fail.rs:5:5
|
LL | *t == *t
| ^^^^^^^^ no implementation for `T == T`

error[E0015]: cannot call non-const operator in constant functions
--> $DIR/call-generic-method-fail.rs:5:5
|
Expand All @@ -10,6 +16,7 @@ help: consider further restricting this bound
LL | pub const fn equals_self<T: PartialEq + ~const std::cmp::PartialEq>(t: &T) -> bool {
| ++++++++++++++++++++++++++++

error: aborting due to previous error
error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0015`.
Some errors have detailed explanations: E0015, E0277.
For more information about an error, try `rustc --explain E0015`.
Expand Up @@ -23,7 +23,8 @@ impl const ConstDefaultFn for ConstImpl {

const fn test() {
NonConstImpl.a();
//~^ ERROR cannot call non-const fn
//~^ ERROR the trait bound
//~| ERROR cannot call non-const fn
ConstImpl.a();
}

Expand Down
@@ -1,3 +1,9 @@
error[E0277]: the trait bound `NonConstImpl: ~const ConstDefaultFn` is not satisfied
--> $DIR/const-default-method-bodies.rs:25:18
|
LL | NonConstImpl.a();
| ^^^ the trait `~const ConstDefaultFn` is not implemented for `NonConstImpl`

error[E0015]: cannot call non-const fn `<NonConstImpl as ConstDefaultFn>::a` in constant functions
--> $DIR/const-default-method-bodies.rs:25:18
|
Expand All @@ -6,6 +12,7 @@ LL | NonConstImpl.a();
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants

error: aborting due to previous error
error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0015`.
Some errors have detailed explanations: E0015, E0277.
For more information about an error, try `rustc --explain E0015`.
11 changes: 9 additions & 2 deletions src/test/ui/rfc-2632-const-trait-impl/cross-crate.gated.stderr
@@ -1,3 +1,9 @@
error[E0277]: the trait bound `cross_crate::NonConst: ~const cross_crate::MyTrait` is not satisfied
--> $DIR/cross-crate.rs:15:14
|
LL | NonConst.func();
| ^^^^^^ the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`

error[E0015]: cannot call non-const fn `<cross_crate::NonConst as cross_crate::MyTrait>::func` in constant functions
--> $DIR/cross-crate.rs:15:14
|
Expand All @@ -6,6 +12,7 @@ LL | NonConst.func();
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants

error: aborting due to previous error
error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0015`.
Some errors have detailed explanations: E0015, E0277.
For more information about an error, try `rustc --explain E0015`.
4 changes: 2 additions & 2 deletions src/test/ui/rfc-2632-const-trait-impl/cross-crate.rs
Expand Up @@ -12,8 +12,8 @@ fn non_const_context() {
}

const fn const_context() {
NonConst.func();
//~^ ERROR: cannot call non-const fn
NonConst.func(); //~ ERROR: cannot call non-const fn
//[gated]~^ ERROR: the trait bound
Const.func();
//[stock]~^ ERROR: cannot call non-const fn
}
Expand Down
Expand Up @@ -8,7 +8,8 @@ pub trait Tr {
#[default_method_body_is_const]
fn b(&self) {
().a()
//~^ ERROR calls in constant functions are limited
//~^ ERROR the trait bound
//~| ERROR cannot call
}
}

Expand Down
@@ -1,9 +1,18 @@
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
--> $DIR/default-method-body-is-const-same-trait-ck.rs:10:9
error[E0277]: the trait bound `(): ~const Tr` is not satisfied
--> $DIR/default-method-body-is-const-same-trait-ck.rs:10:12
|
LL | ().a()
| ^^^^^^
| ^^^ the trait `~const Tr` is not implemented for `()`

error: aborting due to previous error
error[E0015]: cannot call non-const fn `<() as Tr>::a` in constant functions
--> $DIR/default-method-body-is-const-same-trait-ck.rs:10:12
|
LL | ().a()
| ^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0015`.
Some errors have detailed explanations: E0015, E0277.
For more information about an error, try `rustc --explain E0015`.
3 changes: 2 additions & 1 deletion src/test/ui/rfc-2632-const-trait-impl/issue-88155.rs
Expand Up @@ -7,7 +7,8 @@ pub trait A {

pub const fn foo<T: A>() -> bool {
T::assoc()
//~^ ERROR cannot call non-const fn
//~^ ERROR the trait bound
//~| ERROR cannot call non-const fn
}

fn main() {}
11 changes: 9 additions & 2 deletions src/test/ui/rfc-2632-const-trait-impl/issue-88155.stderr
@@ -1,3 +1,9 @@
error[E0277]: the trait bound `T: ~const A` is not satisfied
--> $DIR/issue-88155.rs:9:5
|
LL | T::assoc()
| ^^^^^^^^^^ the trait `~const A` is not implemented for `T`

error[E0015]: cannot call non-const fn `<T as A>::assoc` in constant functions
--> $DIR/issue-88155.rs:9:5
|
Expand All @@ -6,6 +12,7 @@ LL | T::assoc()
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants

error: aborting due to previous error
error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0015`.
Some errors have detailed explanations: E0015, E0277.
For more information about an error, try `rustc --explain E0015`.

0 comments on commit 12397ab

Please sign in to comment.