diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 2fd814c129c2a..095c8f84f41ad 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -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; @@ -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); @@ -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 `::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, diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs index 5f55d61f5fdcd..24b9235bb9a76 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs @@ -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() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr index b5680c04a65a3..ee30d7a88405a 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr @@ -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 `::plus` in constant functions --> $DIR/call-const-trait-method-fail.rs:24:7 | @@ -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`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs index e3de75ea51943..e81e0d1e571c3 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs @@ -3,7 +3,8 @@ pub const fn equals_self(t: &T) -> bool { *t == *t - //~^ ERROR cannot call non-const operator + //~^ ERROR can't compare + //~| ERROR cannot call non-const } fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr index d50100d033e51..2c9ee48ef6de2 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr @@ -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 | @@ -10,6 +16,7 @@ help: consider further restricting this bound LL | pub const fn equals_self(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`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.rs b/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.rs index 4b685b3b2b75a..3e87787a09195 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.rs @@ -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(); } diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr index 853fa3d64781f..060d1ea53e3fc 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr @@ -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 `::a` in constant functions --> $DIR/const-default-method-bodies.rs:25:18 | @@ -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`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gated.stderr b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gated.stderr index df960902133f3..b145cd3db676f 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gated.stderr +++ b/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 `::func` in constant functions --> $DIR/cross-crate.rs:15:14 | @@ -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`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.rs b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.rs index 670d06b85f281..fa049ab86ff49 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.rs @@ -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 } diff --git a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.rs b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.rs index cccb856c2f675..4d087b5180be4 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.rs @@ -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 } } diff --git a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr index 91f4d2fd4b0e8..338563287a289 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr @@ -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`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-88155.rs b/src/test/ui/rfc-2632-const-trait-impl/issue-88155.rs index e4fc65e3cb353..cbe3fe0ce5f3f 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/issue-88155.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/issue-88155.rs @@ -7,7 +7,8 @@ pub trait A { pub const fn foo() -> bool { T::assoc() - //~^ ERROR cannot call non-const fn + //~^ ERROR the trait bound + //~| ERROR cannot call non-const fn } fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-88155.stderr b/src/test/ui/rfc-2632-const-trait-impl/issue-88155.stderr index b94d655a9ffa2..eed15ab98beab 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/issue-88155.stderr +++ b/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 `::assoc` in constant functions --> $DIR/issue-88155.rs:9:5 | @@ -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`.