Report the selection error when possible
This commit is contained in:
parent
cccf4b2fc3
commit
12397ab48b
13 changed files with 107 additions and 37 deletions
|
@ -14,6 +14,7 @@ use rustc_middle::ty::{self, adjustment::PointerCast, Instance, InstanceDef, Ty,
|
||||||
use rustc_middle::ty::{Binder, TraitPredicate, TraitRef};
|
use rustc_middle::ty::{Binder, TraitPredicate, TraitRef};
|
||||||
use rustc_mir_dataflow::{self, Analysis};
|
use rustc_mir_dataflow::{self, Analysis};
|
||||||
use rustc_span::{sym, Span, Symbol};
|
use rustc_span::{sym, Span, Symbol};
|
||||||
|
use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
|
||||||
use rustc_trait_selection::traits::SelectionContext;
|
use rustc_trait_selection::traits::SelectionContext;
|
||||||
|
|
||||||
use std::mem;
|
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 trait_ref = TraitRef::from_method(tcx, trait_id, substs);
|
||||||
let obligation = Obligation::new(
|
let poly_trait_pred = Binder::dummy(TraitPredicate {
|
||||||
ObligationCause::dummy(),
|
|
||||||
param_env,
|
|
||||||
Binder::dummy(TraitPredicate {
|
|
||||||
trait_ref,
|
trait_ref,
|
||||||
constness: ty::BoundConstness::NotConst,
|
constness: ty::BoundConstness::ConstIfConst,
|
||||||
polarity: ty::ImplPolarity::Positive,
|
polarity: ty::ImplPolarity::Positive,
|
||||||
}),
|
});
|
||||||
);
|
let obligation =
|
||||||
|
Obligation::new(ObligationCause::dummy(), param_env, poly_trait_pred);
|
||||||
|
|
||||||
let implsrc = tcx.infer_ctxt().enter(|infcx| {
|
let implsrc = tcx.infer_ctxt().enter(|infcx| {
|
||||||
let mut selcx = SelectionContext::new(&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
|
// #[default_method_body_is_const], and the callee is in the same
|
||||||
// trait.
|
// trait.
|
||||||
let callee_trait = tcx.trait_of_item(callee);
|
let callee_trait = tcx.trait_of_item(callee);
|
||||||
if callee_trait.is_some() {
|
if callee_trait.is_some()
|
||||||
if tcx.has_attr(caller, sym::default_method_body_is_const) {
|
&& tcx.has_attr(caller, sym::default_method_body_is_const)
|
||||||
if tcx.trait_of_item(caller) == callee_trait {
|
&& 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;
|
nonconst_call_permission = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !nonconst_call_permission {
|
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 {
|
self.check_op(ops::FnCallNonConst {
|
||||||
caller,
|
caller,
|
||||||
callee,
|
callee,
|
||||||
|
|
|
@ -22,7 +22,8 @@ pub const fn add_i32(a: i32, b: i32) -> i32 {
|
||||||
|
|
||||||
pub const fn add_u32(a: u32, b: u32) -> u32 {
|
pub const fn add_u32(a: u32, b: u32) -> u32 {
|
||||||
a.plus(b)
|
a.plus(b)
|
||||||
//~^ ERROR cannot call non-const fn
|
//~^ ERROR the trait bound
|
||||||
|
//~| ERROR cannot call non-const fn
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
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
|
error[E0015]: cannot call non-const fn `<u32 as Plus>::plus` in constant functions
|
||||||
--> $DIR/call-const-trait-method-fail.rs:24:7
|
--> $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
|
= 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`.
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
|
|
||||||
pub const fn equals_self<T: PartialEq>(t: &T) -> bool {
|
pub const fn equals_self<T: PartialEq>(t: &T) -> bool {
|
||||||
*t == *t
|
*t == *t
|
||||||
//~^ ERROR cannot call non-const operator
|
//~^ ERROR can't compare
|
||||||
|
//~| ERROR cannot call non-const
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
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
|
error[E0015]: cannot call non-const operator in constant functions
|
||||||
--> $DIR/call-generic-method-fail.rs:5:5
|
--> $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: PartialEq + ~const std::cmp::PartialEq>(t: &T) -> bool {
|
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`.
|
||||||
|
|
|
@ -23,7 +23,8 @@ impl const ConstDefaultFn for ConstImpl {
|
||||||
|
|
||||||
const fn test() {
|
const fn test() {
|
||||||
NonConstImpl.a();
|
NonConstImpl.a();
|
||||||
//~^ ERROR cannot call non-const fn
|
//~^ ERROR the trait bound
|
||||||
|
//~| ERROR cannot call non-const fn
|
||||||
ConstImpl.a();
|
ConstImpl.a();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
error[E0015]: cannot call non-const fn `<NonConstImpl as ConstDefaultFn>::a` in constant functions
|
||||||
--> $DIR/const-default-method-bodies.rs:25:18
|
--> $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
|
= 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`.
|
||||||
|
|
|
@ -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
|
error[E0015]: cannot call non-const fn `<cross_crate::NonConst as cross_crate::MyTrait>::func` in constant functions
|
||||||
--> $DIR/cross-crate.rs:15:14
|
--> $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
|
= 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`.
|
||||||
|
|
|
@ -12,8 +12,8 @@ fn non_const_context() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const fn const_context() {
|
const fn const_context() {
|
||||||
NonConst.func();
|
NonConst.func(); //~ ERROR: cannot call non-const fn
|
||||||
//~^ ERROR: cannot call non-const fn
|
//[gated]~^ ERROR: the trait bound
|
||||||
Const.func();
|
Const.func();
|
||||||
//[stock]~^ ERROR: cannot call non-const fn
|
//[stock]~^ ERROR: cannot call non-const fn
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,8 @@ pub trait Tr {
|
||||||
#[default_method_body_is_const]
|
#[default_method_body_is_const]
|
||||||
fn b(&self) {
|
fn b(&self) {
|
||||||
().a()
|
().a()
|
||||||
//~^ ERROR calls in constant functions are limited
|
//~^ ERROR the trait bound
|
||||||
|
//~| ERROR cannot call
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,18 @@
|
||||||
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
error[E0277]: the trait bound `(): ~const Tr` is not satisfied
|
||||||
--> $DIR/default-method-body-is-const-same-trait-ck.rs:10:9
|
--> $DIR/default-method-body-is-const-same-trait-ck.rs:10:12
|
||||||
|
|
|
|
||||||
LL | ().a()
|
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
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0015`.
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0015, E0277.
|
||||||
|
For more information about an error, try `rustc --explain E0015`.
|
||||||
|
|
|
@ -7,7 +7,8 @@ pub trait A {
|
||||||
|
|
||||||
pub const fn foo<T: A>() -> bool {
|
pub const fn foo<T: A>() -> bool {
|
||||||
T::assoc()
|
T::assoc()
|
||||||
//~^ ERROR cannot call non-const fn
|
//~^ ERROR the trait bound
|
||||||
|
//~| ERROR cannot call non-const fn
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -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
|
error[E0015]: cannot call non-const fn `<T as A>::assoc` in constant functions
|
||||||
--> $DIR/issue-88155.rs:9:5
|
--> $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
|
= 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`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue