Skip to content

Commit 121a90d

Browse files
committed
Auto merge of #140313 - lcnr:wf-normalize-first, r=<try>
change false trivial bounds detection fixes #140309 TODO r? `@compiler-errors`
2 parents e3e432d + 37f147e commit 121a90d

22 files changed

+232
-38
lines changed

compiler/rustc_hir_analysis/src/check/wfcheck.rs

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,8 @@ use rustc_middle::query::Providers;
1919
use rustc_middle::traits::solve::NoSolution;
2020
use rustc_middle::ty::trait_def::TraitSpecializationKind;
2121
use rustc_middle::ty::{
22-
self, AdtKind, GenericArgKind, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFlags,
23-
TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode,
24-
Upcast,
22+
self, AdtKind, GenericArgKind, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFoldable,
23+
TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Upcast,
2524
};
2625
use rustc_middle::{bug, span_bug};
2726
use rustc_session::parse::feature_err;
@@ -111,16 +110,17 @@ where
111110

112111
let mut wfcx = WfCheckingCtxt { ocx, span, body_def_id, param_env };
113112

114-
if !tcx.features().trivial_bounds() {
115-
wfcx.check_false_global_bounds()
116-
}
117113
f(&mut wfcx)?;
118114

119115
let errors = wfcx.select_all_or_error();
120116
if !errors.is_empty() {
121117
return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
122118
}
123119

120+
if !tcx.features().trivial_bounds() {
121+
wfcx.check_false_global_bounds()?;
122+
}
123+
124124
let assumed_wf_types = wfcx.ocx.assumed_wf_types_and_report_errors(param_env, body_def_id)?;
125125
debug!(?assumed_wf_types);
126126

@@ -2274,7 +2274,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
22742274
/// Feature gates RFC 2056 -- trivial bounds, checking for global bounds that
22752275
/// aren't true.
22762276
#[instrument(level = "debug", skip(self))]
2277-
fn check_false_global_bounds(&mut self) {
2277+
fn check_false_global_bounds(&mut self) -> Result<(), ErrorGuaranteed> {
22782278
let tcx = self.ocx.infcx.tcx;
22792279
let mut span = self.span;
22802280
let empty_env = ty::ParamEnv::empty();
@@ -2283,17 +2283,22 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
22832283
// Check elaborated bounds.
22842284
let implied_obligations = traits::elaborate(tcx, predicates_with_span);
22852285

2286+
let mut global_obligations = vec![];
22862287
for (pred, obligation_span) in implied_obligations {
22872288
// We lower empty bounds like `Vec<dyn Copy>:` as
22882289
// `WellFormed(Vec<dyn Copy>)`, which will later get checked by
22892290
// regular WF checking
22902291
if let ty::ClauseKind::WellFormed(..) = pred.kind().skip_binder() {
22912292
continue;
22922293
}
2293-
// Match the existing behavior.
2294-
if pred.is_global() && !pred.has_type_flags(TypeFlags::HAS_BINDER_VARS) {
2295-
let pred = self.normalize(span, None, pred);
2296-
2294+
// Match the existing behavior. We normalize first to handle where-bounds
2295+
// like `u32: Trait<Assoc = T>`.
2296+
let clause = ObligationCause::misc(span, self.body_def_id);
2297+
let Ok(pred) = self.deeply_normalize(&clause, self.param_env, pred) else {
2298+
tcx.dcx().delayed_bug("encountered errors when normalizing where-clauses");
2299+
continue;
2300+
};
2301+
if pred.is_global() && pred.kind().bound_vars().is_empty() {
22972302
// only use the span of the predicate clause (#90869)
22982303
let hir_node = tcx.hir_node_by_def_id(self.body_def_id);
22992304
if let Some(hir::Generics { predicates, .. }) = hir_node.generics() {
@@ -2315,9 +2320,17 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
23152320
empty_env,
23162321
pred,
23172322
);
2318-
self.ocx.register_obligation(obligation);
2323+
global_obligations.push(obligation);
23192324
}
23202325
}
2326+
2327+
self.register_obligations(global_obligations);
2328+
let errors = self.select_all_or_error();
2329+
if !errors.is_empty() {
2330+
Err(self.infcx.err_ctxt().report_fulfillment_errors(errors))
2331+
} else {
2332+
Ok(())
2333+
}
23212334
}
23222335
}
23232336

tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty-not-wf.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@ fn take(
1212
K = { () }
1313
>,
1414
) {}
15-
//~^^^^^^ ERROR implementation of `Project` is not general enough
16-
//~^^^^ ERROR higher-ranked subtype error
15+
//~^^^ ERROR higher-ranked subtype error
1716
//~| ERROR higher-ranked subtype error
1817

1918
trait Project { type Out; }

tests/ui/associated-consts/assoc-const-eq-bound-var-in-ty-not-wf.stderr

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,5 @@ LL | K = { () }
1212
|
1313
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
1414

15-
error: implementation of `Project` is not general enough
16-
--> $DIR/assoc-const-eq-bound-var-in-ty-not-wf.rs:9:4
17-
|
18-
LL | fn take(
19-
| ^^^^ implementation of `Project` is not general enough
20-
|
21-
= note: `Project` would have to be implemented for the type `for<'a> fn(&'a str) -> &'a str`
22-
= note: ...but `Project` is actually implemented for the type `fn(&'0 str) -> &'0 str`, for some specific lifetime `'0`
23-
24-
error: aborting due to 3 previous errors
15+
error: aborting due to 2 previous errors
2516

tests/ui/associated-types/issue-69398.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//@ check-pass
2+
#![feature(trivial_bounds)]
23

34
pub trait Foo {
45
type Bar;

tests/ui/consts/issue-67696-const-prop-ice.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//@ compile-flags: --emit=mir,link -Zmir-opt-level=4
33
// Checks that we don't ICE due to attempting to run const prop
44
// on a function with unsatisifable 'where' clauses
5-
5+
#![feature(trivial_bounds)]
66
#![allow(unused)]
77

88
trait A {

tests/ui/feature-gates/feature-gate-trivial_bounds.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,7 @@ fn return_str() -> str where str: Sized { //~ ERROR
6060
*"Sized".to_string().into_boxed_str()
6161
}
6262

63-
// This is currently accepted because the function pointer isn't
64-
// considered global.
65-
fn global_hr(x: fn(&())) where fn(&()): Foo { // OK
63+
fn global_hr(x: fn(&())) where fn(&()): Foo { //~ ERROR
6664
x.test();
6765
}
6866

tests/ui/feature-gates/feature-gate-trivial_bounds.stderr

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,19 @@ help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
145145
LL + #![feature(trivial_bounds)]
146146
|
147147

148-
error: aborting due to 11 previous errors
148+
error[E0277]: the trait bound `for<'a> fn(&'a ()): Foo` is not satisfied
149+
--> $DIR/feature-gate-trivial_bounds.rs:63:32
150+
|
151+
LL | fn global_hr(x: fn(&())) where fn(&()): Foo {
152+
| ^^^^^^^^^^^^ the trait `Foo` is not implemented for `for<'a> fn(&'a ())`
153+
|
154+
= help: the trait `Foo` is implemented for `()`
155+
= help: see issue #48214
156+
help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
157+
|
158+
LL + #![feature(trivial_bounds)]
159+
|
160+
161+
error: aborting due to 12 previous errors
149162

150163
For more information about this error, try `rustc --explain E0277`.

tests/ui/issues/issue-36839.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//@ check-pass
2+
#![feature(trivial_bounds)]
23

34
pub trait Foo {
45
type Bar;

tests/ui/issues/issue-42796.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#![feature(trivial_bounds)]
12
pub trait Mirror<Smoke> {
23
type Image;
34
}

tests/ui/issues/issue-42796.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0382]: borrow of moved value: `s`
2-
--> $DIR/issue-42796.rs:18:20
2+
--> $DIR/issue-42796.rs:19:20
33
|
44
LL | let s = "Hello!".to_owned();
55
| - move occurs because `s` has type `String`, which does not implement the `Copy` trait

0 commit comments

Comments
 (0)