Skip to content

Commit 68791ef

Browse files
authored
Rollup merge of #134951 - compiler-errors:double-trait-err-msg, r=davidtwco
Suppress host effect predicates if underlying trait doesn't hold Don't report two errors for when the (`HostEffectPredicate`) `T: const Trait` isn't implemented because (`TraitPredicate`) `T: Trait` doesn't even hold.
2 parents 44c6e83 + 62d6ee3 commit 68791ef

File tree

3 files changed

+101
-19
lines changed

3 files changed

+101
-19
lines changed

compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs

+38-19
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
114114
//
115115
// We rely on a few heuristics to identify cases where this root
116116
// obligation is more important than the leaf obligation:
117-
let (main_trait_predicate, o) = if let ty::PredicateKind::Clause(
117+
let (main_trait_predicate, main_obligation) = if let ty::PredicateKind::Clause(
118118
ty::ClauseKind::Trait(root_pred)
119119
) = root_obligation.predicate.kind().skip_binder()
120120
&& !leaf_trait_predicate.self_ty().skip_binder().has_escaping_bound_vars()
@@ -199,7 +199,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
199199
notes,
200200
parent_label,
201201
append_const_msg,
202-
} = self.on_unimplemented_note(main_trait_predicate, o, &mut long_ty_file);
202+
} = self.on_unimplemented_note(main_trait_predicate, main_obligation, &mut long_ty_file);
203203

204204
let have_alt_message = message.is_some() || label.is_some();
205205
let is_try_conversion = self.is_try_conversion(span, main_trait_ref.def_id());
@@ -538,23 +538,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
538538
}
539539

540540
ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(predicate)) => {
541-
// FIXME(const_trait_impl): We should recompute the predicate with `~const`
542-
// if it's `const`, and if it holds, explain that this bound only
543-
// *conditionally* holds. If that fails, we should also do selection
544-
// to drill this down to an impl or built-in source, so we can
545-
// point at it and explain that while the trait *is* implemented,
546-
// that implementation is not const.
547-
let err_msg = self.get_standard_error_message(
548-
bound_predicate.rebind(ty::TraitPredicate {
549-
trait_ref: predicate.trait_ref,
550-
polarity: ty::PredicatePolarity::Positive,
551-
}),
552-
None,
553-
Some(predicate.constness),
554-
None,
555-
String::new(),
556-
);
557-
struct_span_code_err!(self.dcx(), span, E0277, "{}", err_msg)
541+
self.report_host_effect_error(bound_predicate.rebind(predicate), obligation.param_env, span)
558542
}
559543

560544
ty::PredicateKind::Subtype(predicate) => {
@@ -763,6 +747,41 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
763747
applied_do_not_recommend
764748
}
765749

750+
fn report_host_effect_error(
751+
&self,
752+
predicate: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
753+
param_env: ty::ParamEnv<'tcx>,
754+
span: Span,
755+
) -> Diag<'a> {
756+
// FIXME(const_trait_impl): We should recompute the predicate with `~const`
757+
// if it's `const`, and if it holds, explain that this bound only
758+
// *conditionally* holds. If that fails, we should also do selection
759+
// to drill this down to an impl or built-in source, so we can
760+
// point at it and explain that while the trait *is* implemented,
761+
// that implementation is not const.
762+
let trait_ref = predicate.map_bound(|predicate| ty::TraitPredicate {
763+
trait_ref: predicate.trait_ref,
764+
polarity: ty::PredicatePolarity::Positive,
765+
});
766+
let err_msg = self.get_standard_error_message(
767+
trait_ref,
768+
None,
769+
Some(predicate.constness()),
770+
None,
771+
String::new(),
772+
);
773+
let mut diag = struct_span_code_err!(self.dcx(), span, E0277, "{}", err_msg);
774+
if !self.predicate_may_hold(&Obligation::new(
775+
self.tcx,
776+
ObligationCause::dummy(),
777+
param_env,
778+
trait_ref,
779+
)) {
780+
diag.downgrade_to_delayed_bug();
781+
}
782+
diag
783+
}
784+
766785
fn emit_specialized_closure_kind_error(
767786
&self,
768787
obligation: &PredicateObligation<'tcx>,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Make sure we don't issue *two* error messages for the trait predicate *and* host predicate.
2+
3+
#![feature(const_trait_impl)]
4+
5+
#[const_trait]
6+
trait Trait {
7+
type Out;
8+
}
9+
10+
const fn needs_const<T: ~const Trait>(_: &T) {}
11+
12+
const IN_CONST: () = {
13+
needs_const(&());
14+
//~^ ERROR the trait bound `(): Trait` is not satisfied
15+
};
16+
17+
const fn conditionally_const() {
18+
needs_const(&());
19+
//~^ ERROR the trait bound `(): Trait` is not satisfied
20+
}
21+
22+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
error[E0277]: the trait bound `(): Trait` is not satisfied
2+
--> $DIR/double-error-for-unimplemented-trait.rs:13:15
3+
|
4+
LL | needs_const(&());
5+
| ----------- ^^^ the trait `Trait` is not implemented for `()`
6+
| |
7+
| required by a bound introduced by this call
8+
|
9+
help: this trait has no implementations, consider adding one
10+
--> $DIR/double-error-for-unimplemented-trait.rs:6:1
11+
|
12+
LL | trait Trait {
13+
| ^^^^^^^^^^^
14+
note: required by a bound in `needs_const`
15+
--> $DIR/double-error-for-unimplemented-trait.rs:10:25
16+
|
17+
LL | const fn needs_const<T: ~const Trait>(_: &T) {}
18+
| ^^^^^^^^^^^^ required by this bound in `needs_const`
19+
20+
error[E0277]: the trait bound `(): Trait` is not satisfied
21+
--> $DIR/double-error-for-unimplemented-trait.rs:18:15
22+
|
23+
LL | needs_const(&());
24+
| ----------- ^^^ the trait `Trait` is not implemented for `()`
25+
| |
26+
| required by a bound introduced by this call
27+
|
28+
help: this trait has no implementations, consider adding one
29+
--> $DIR/double-error-for-unimplemented-trait.rs:6:1
30+
|
31+
LL | trait Trait {
32+
| ^^^^^^^^^^^
33+
note: required by a bound in `needs_const`
34+
--> $DIR/double-error-for-unimplemented-trait.rs:10:25
35+
|
36+
LL | const fn needs_const<T: ~const Trait>(_: &T) {}
37+
| ^^^^^^^^^^^^ required by this bound in `needs_const`
38+
39+
error: aborting due to 2 previous errors
40+
41+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)