Skip to content

Commit

Permalink
Suppress host effect predicates if underlying trait doesn't hold
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Dec 31, 2024
1 parent 0b63477 commit 899d9e6
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -538,23 +538,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}

ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(predicate)) => {
// 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 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)
self.report_host_effect_error(bound_predicate.rebind(predicate), obligation.param_env, span)
}

ty::PredicateKind::Subtype(predicate) => {
Expand Down Expand Up @@ -763,6 +747,41 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
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(
&self,
obligation: &PredicateObligation<'tcx>,
Expand Down
Original file line number Diff line number Diff line change
@@ -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() {}
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit 899d9e6

Please sign in to comment.