Suppress host effect predicates if underlying trait doesn't hold
This commit is contained in:
parent
0b63477350
commit
899d9e6769
3 changed files with 99 additions and 17 deletions
|
@ -538,23 +538,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(predicate)) => {
|
ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(predicate)) => {
|
||||||
// FIXME(const_trait_impl): We should recompute the predicate with `~const`
|
self.report_host_effect_error(bound_predicate.rebind(predicate), obligation.param_env, span)
|
||||||
// if it's `const`, and if it holds, explain that this bound only
|
|
||||||
// *conditionally* holds. If that fails, we should also do selection
|
|
||||||
// to drill this down to an impl or built-in source, so we can
|
|
||||||
// point at it and explain that while the trait *is* implemented,
|
|
||||||
// that implementation is not const.
|
|
||||||
let err_msg = self.get_standard_error_message(
|
|
||||||
bound_predicate.rebind(ty::TraitPredicate {
|
|
||||||
trait_ref: predicate.trait_ref,
|
|
||||||
polarity: ty::PredicatePolarity::Positive,
|
|
||||||
}),
|
|
||||||
None,
|
|
||||||
Some(predicate.constness),
|
|
||||||
None,
|
|
||||||
String::new(),
|
|
||||||
);
|
|
||||||
struct_span_code_err!(self.dcx(), span, E0277, "{}", err_msg)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::PredicateKind::Subtype(predicate) => {
|
ty::PredicateKind::Subtype(predicate) => {
|
||||||
|
@ -763,6 +747,41 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
applied_do_not_recommend
|
applied_do_not_recommend
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn report_host_effect_error(
|
||||||
|
&self,
|
||||||
|
predicate: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
span: Span,
|
||||||
|
) -> Diag<'a> {
|
||||||
|
// FIXME(const_trait_impl): We should recompute the predicate with `~const`
|
||||||
|
// if it's `const`, and if it holds, explain that this bound only
|
||||||
|
// *conditionally* holds. If that fails, we should also do selection
|
||||||
|
// to drill this down to an impl or built-in source, so we can
|
||||||
|
// point at it and explain that while the trait *is* implemented,
|
||||||
|
// that implementation is not const.
|
||||||
|
let trait_ref = predicate.map_bound(|predicate| ty::TraitPredicate {
|
||||||
|
trait_ref: predicate.trait_ref,
|
||||||
|
polarity: ty::PredicatePolarity::Positive,
|
||||||
|
});
|
||||||
|
let err_msg = self.get_standard_error_message(
|
||||||
|
trait_ref,
|
||||||
|
None,
|
||||||
|
Some(predicate.constness()),
|
||||||
|
None,
|
||||||
|
String::new(),
|
||||||
|
);
|
||||||
|
let mut diag = struct_span_code_err!(self.dcx(), span, E0277, "{}", err_msg);
|
||||||
|
if !self.predicate_may_hold(&Obligation::new(
|
||||||
|
self.tcx,
|
||||||
|
ObligationCause::dummy(),
|
||||||
|
param_env,
|
||||||
|
trait_ref,
|
||||||
|
)) {
|
||||||
|
diag.downgrade_to_delayed_bug();
|
||||||
|
}
|
||||||
|
diag
|
||||||
|
}
|
||||||
|
|
||||||
fn emit_specialized_closure_kind_error(
|
fn emit_specialized_closure_kind_error(
|
||||||
&self,
|
&self,
|
||||||
obligation: &PredicateObligation<'tcx>,
|
obligation: &PredicateObligation<'tcx>,
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
// Make sure we don't issue *two* error messages for the trait predicate *and* host predicate.
|
||||||
|
|
||||||
|
#![feature(const_trait_impl)]
|
||||||
|
|
||||||
|
#[const_trait]
|
||||||
|
trait Trait {
|
||||||
|
type Out;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn needs_const<T: ~const Trait>(_: &T) {}
|
||||||
|
|
||||||
|
const IN_CONST: () = {
|
||||||
|
needs_const(&());
|
||||||
|
//~^ ERROR the trait bound `(): Trait` is not satisfied
|
||||||
|
};
|
||||||
|
|
||||||
|
const fn conditionally_const() {
|
||||||
|
needs_const(&());
|
||||||
|
//~^ ERROR the trait bound `(): Trait` is not satisfied
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,41 @@
|
||||||
|
error[E0277]: the trait bound `(): Trait` is not satisfied
|
||||||
|
--> $DIR/double-error-for-unimplemented-trait.rs:13:15
|
||||||
|
|
|
||||||
|
LL | needs_const(&());
|
||||||
|
| ----------- ^^^ the trait `Trait` is not implemented for `()`
|
||||||
|
| |
|
||||||
|
| required by a bound introduced by this call
|
||||||
|
|
|
||||||
|
help: this trait has no implementations, consider adding one
|
||||||
|
--> $DIR/double-error-for-unimplemented-trait.rs:6:1
|
||||||
|
|
|
||||||
|
LL | trait Trait {
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
note: required by a bound in `needs_const`
|
||||||
|
--> $DIR/double-error-for-unimplemented-trait.rs:10:25
|
||||||
|
|
|
||||||
|
LL | const fn needs_const<T: ~const Trait>(_: &T) {}
|
||||||
|
| ^^^^^^^^^^^^ required by this bound in `needs_const`
|
||||||
|
|
||||||
|
error[E0277]: the trait bound `(): Trait` is not satisfied
|
||||||
|
--> $DIR/double-error-for-unimplemented-trait.rs:18:15
|
||||||
|
|
|
||||||
|
LL | needs_const(&());
|
||||||
|
| ----------- ^^^ the trait `Trait` is not implemented for `()`
|
||||||
|
| |
|
||||||
|
| required by a bound introduced by this call
|
||||||
|
|
|
||||||
|
help: this trait has no implementations, consider adding one
|
||||||
|
--> $DIR/double-error-for-unimplemented-trait.rs:6:1
|
||||||
|
|
|
||||||
|
LL | trait Trait {
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
note: required by a bound in `needs_const`
|
||||||
|
--> $DIR/double-error-for-unimplemented-trait.rs:10:25
|
||||||
|
|
|
||||||
|
LL | const fn needs_const<T: ~const Trait>(_: &T) {}
|
||||||
|
| ^^^^^^^^^^^^ required by this bound in `needs_const`
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
Loading…
Add table
Add a link
Reference in a new issue