Skip to content

Commit 20a081a

Browse files
Auto merge of #148823 - lcnr:generalize-no-subtyping, r=<try>
TypeRelating emit WellFormed, not generalize
2 parents 9312cd6 + aafb23b commit 20a081a

File tree

16 files changed

+227
-110
lines changed

16 files changed

+227
-110
lines changed

‎compiler/rustc_borrowck/src/polonius/liveness_constraints.rs‎

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ use std::collections::BTreeMap;
22

33
use rustc_index::bit_set::SparseBitMatrix;
44
use rustc_middle::mir::{Body, Location};
5-
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
5+
use rustc_middle::ty::relate::{
6+
self, Relate, RelateResult, TypeRelation, relate_args_with_variances,
7+
};
68
use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeVisitable};
79
use rustc_mir_dataflow::points::PointIndex;
810

@@ -256,6 +258,18 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for VarianceExtractor<'_, 'tcx> {
256258
self.tcx
257259
}
258260

261+
fn relate_item_args(
262+
&mut self,
263+
item_def_id: rustc_hir::def_id::DefId,
264+
a_arg: ty::GenericArgsRef<'tcx>,
265+
b_arg: ty::GenericArgsRef<'tcx>,
266+
f: impl FnOnce(ty::GenericArgsRef<'tcx>) -> Ty<'tcx>,
267+
) -> RelateResult<'tcx, Ty<'tcx>> {
268+
let variances = self.cx().variances_of(item_def_id);
269+
let args = relate_args_with_variances(self, item_def_id, variances, a_arg, b_arg, false)?;
270+
Ok(f(args))
271+
}
272+
259273
fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
260274
&mut self,
261275
variance: ty::Variance,

‎compiler/rustc_borrowck/src/type_check/relate_tys.rs‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use rustc_middle::mir::ConstraintCategory;
1010
use rustc_middle::traits::ObligationCause;
1111
use rustc_middle::traits::query::NoSolution;
1212
use rustc_middle::ty::relate::combine::{super_combine_consts, super_combine_tys};
13+
use rustc_middle::ty::relate::relate_args_with_variances;
1314
use rustc_middle::ty::{self, FnMutDelegate, Ty, TyCtxt, TypeVisitableExt};
1415
use rustc_middle::{bug, span_bug};
1516
use rustc_span::{Span, Symbol, sym};
@@ -303,6 +304,23 @@ impl<'b, 'tcx> TypeRelation<TyCtxt<'tcx>> for NllTypeRelating<'_, 'b, 'tcx> {
303304
self.type_checker.infcx.tcx
304305
}
305306

307+
fn relate_item_args(
308+
&mut self,
309+
item_def_id: rustc_hir::def_id::DefId,
310+
a_arg: ty::GenericArgsRef<'tcx>,
311+
b_arg: ty::GenericArgsRef<'tcx>,
312+
f: impl FnOnce(ty::GenericArgsRef<'tcx>) -> Ty<'tcx>,
313+
) -> RelateResult<'tcx, Ty<'tcx>> {
314+
let tcx = self.cx();
315+
let variances = tcx.variances_of(item_def_id);
316+
let args = relate_args_with_variances(self, item_def_id, variances, a_arg, b_arg, true)?;
317+
let ty = f(args);
318+
if variances.iter().any(|&v| v == ty::Bivariant) {
319+
self.register_predicates([ty::ClauseKind::WellFormed(ty.into())]);
320+
}
321+
Ok(ty)
322+
}
323+
306324
#[instrument(skip(self, info), level = "trace", ret)]
307325
fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
308326
&mut self,

‎compiler/rustc_infer/src/infer/outlives/test_type_match.rs‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::collections::hash_map::Entry;
33
use rustc_data_structures::fx::FxHashMap;
44
use rustc_middle::ty::error::TypeError;
55
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
6+
use rustc_type_ir::relate::relate_args_with_variances;
67
use tracing::instrument;
78

89
use crate::infer::region_constraints::VerifyIfEq;
@@ -137,6 +138,22 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for MatchAgainstHigherRankedOutlives<'tcx>
137138
self.tcx
138139
}
139140

141+
fn relate_item_args(
142+
&mut self,
143+
item_def_id: rustc_hir::def_id::DefId,
144+
a_arg: ty::GenericArgsRef<'tcx>,
145+
b_arg: ty::GenericArgsRef<'tcx>,
146+
f: impl FnOnce(ty::GenericArgsRef<'tcx>) -> Ty<'tcx>,
147+
) -> RelateResult<'tcx, Ty<'tcx>> {
148+
// FIXME(@lcnr): This is weird. We are ignoring variance
149+
// here, effectively treating everything as either covariant
150+
// or contravariant, as we only ever check whether the context is
151+
// bivariant.
152+
let variances = self.cx().variances_of(item_def_id);
153+
let args = relate_args_with_variances(self, item_def_id, variances, a_arg, b_arg, false)?;
154+
Ok(f(args))
155+
}
156+
140157
#[instrument(level = "trace", skip(self))]
141158
fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
142159
&mut self,

‎compiler/rustc_infer/src/infer/relate/generalize.rs‎

Lines changed: 26 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,13 @@ impl<'tcx> InferCtxt<'tcx> {
7070
//
7171
// We then relate `generalized_ty <: source_ty`, adding constraints like `'x: '?2` and
7272
// `?1 <: ?3`.
73-
let Generalization { value_may_be_infer: generalized_ty, has_unconstrained_ty_var } = self
74-
.generalize(
75-
relation.span(),
76-
relation.structurally_relate_aliases(),
77-
target_vid,
78-
instantiation_variance,
79-
source_ty,
80-
)?;
73+
let Generalization { value_may_be_infer: generalized_ty } = self.generalize(
74+
relation.span(),
75+
relation.structurally_relate_aliases(),
76+
target_vid,
77+
instantiation_variance,
78+
source_ty,
79+
)?;
8180

8281
// Constrain `b_vid` to the generalized type `generalized_ty`.
8382
if let &ty::Infer(ty::TyVar(generalized_vid)) = generalized_ty.kind() {
@@ -86,11 +85,6 @@ impl<'tcx> InferCtxt<'tcx> {
8685
self.inner.borrow_mut().type_variables().instantiate(target_vid, generalized_ty);
8786
}
8887

89-
// See the comment on `Generalization::has_unconstrained_ty_var`.
90-
if has_unconstrained_ty_var {
91-
relation.register_predicates([ty::ClauseKind::WellFormed(generalized_ty.into())]);
92-
}
93-
9488
// Finally, relate `generalized_ty` to `source_ty`, as described in previous comment.
9589
//
9690
// FIXME(#16847): This code is non-ideal because all these subtype
@@ -210,19 +204,15 @@ impl<'tcx> InferCtxt<'tcx> {
210204
) -> RelateResult<'tcx, ()> {
211205
// FIXME(generic_const_exprs): Occurs check failures for unevaluated
212206
// constants and generic expressions are not yet handled correctly.
213-
let Generalization { value_may_be_infer: generalized_ct, has_unconstrained_ty_var } = self
214-
.generalize(
215-
relation.span(),
216-
relation.structurally_relate_aliases(),
217-
target_vid,
218-
ty::Invariant,
219-
source_ct,
220-
)?;
207+
let Generalization { value_may_be_infer: generalized_ct } = self.generalize(
208+
relation.span(),
209+
relation.structurally_relate_aliases(),
210+
target_vid,
211+
ty::Invariant,
212+
source_ct,
213+
)?;
221214

222215
debug_assert!(!generalized_ct.is_ct_infer());
223-
if has_unconstrained_ty_var {
224-
bug!("unconstrained ty var when generalizing `{source_ct:?}`");
225-
}
226216

227217
self.inner
228218
.borrow_mut()
@@ -281,12 +271,10 @@ impl<'tcx> InferCtxt<'tcx> {
281271
ambient_variance,
282272
in_alias: false,
283273
cache: Default::default(),
284-
has_unconstrained_ty_var: false,
285274
};
286275

287276
let value_may_be_infer = generalizer.relate(source_term, source_term)?;
288-
let has_unconstrained_ty_var = generalizer.has_unconstrained_ty_var;
289-
Ok(Generalization { value_may_be_infer, has_unconstrained_ty_var })
277+
Ok(Generalization { value_may_be_infer })
290278
}
291279
}
292280

@@ -376,9 +364,6 @@ struct Generalizer<'me, 'tcx> {
376364
in_alias: bool,
377365

378366
cache: SsoHashMap<(Ty<'tcx>, ty::Variance, bool), Ty<'tcx>>,
379-
380-
/// See the field `has_unconstrained_ty_var` in `Generalization`.
381-
has_unconstrained_ty_var: bool,
382367
}
383368

384369
impl<'tcx> Generalizer<'_, 'tcx> {
@@ -391,10 +376,8 @@ impl<'tcx> Generalizer<'_, 'tcx> {
391376
}
392377

393378
/// Create a new type variable in the universe of the target when
394-
/// generalizing an alias. This has to set `has_unconstrained_ty_var`
395-
/// if we're currently in a bivariant context.
379+
/// generalizing an alias.
396380
fn next_ty_var_for_alias(&mut self) -> Ty<'tcx> {
397-
self.has_unconstrained_ty_var |= self.ambient_variance == ty::Bivariant;
398381
self.infcx.next_ty_var_in_universe(self.span, self.for_universe)
399382
}
400383

@@ -466,24 +449,19 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
466449
item_def_id: DefId,
467450
a_arg: ty::GenericArgsRef<'tcx>,
468451
b_arg: ty::GenericArgsRef<'tcx>,
469-
) -> RelateResult<'tcx, ty::GenericArgsRef<'tcx>> {
470-
if self.ambient_variance == ty::Invariant {
452+
f: impl FnOnce(ty::GenericArgsRef<'tcx>) -> Ty<'tcx>,
453+
) -> RelateResult<'tcx, Ty<'tcx>> {
454+
let args = if self.ambient_variance == ty::Invariant {
471455
// Avoid fetching the variance if we are in an invariant
472456
// context; no need, and it can induce dependency cycles
473457
// (e.g., #41849).
474458
relate::relate_args_invariantly(self, a_arg, b_arg)
475459
} else {
476460
let tcx = self.cx();
477-
let opt_variances = tcx.variances_of(item_def_id);
478-
relate::relate_args_with_variances(
479-
self,
480-
item_def_id,
481-
opt_variances,
482-
a_arg,
483-
b_arg,
484-
false,
485-
)
486-
}
461+
let variances = tcx.variances_of(item_def_id);
462+
relate::relate_args_with_variances(self, item_def_id, variances, a_arg, b_arg, false)
463+
}?;
464+
Ok(f(args))
487465
}
488466

489467
#[instrument(level = "debug", skip(self, variance, b), ret)]
@@ -545,14 +523,8 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
545523
}
546524
}
547525

548-
// Bivariant: make a fresh var, but remember that
549-
// it is unconstrained. See the comment in
550-
// `Generalization`.
551-
ty::Bivariant => self.has_unconstrained_ty_var = true,
552-
553-
// Co/contravariant: this will be
554-
// sufficiently constrained later on.
555-
ty::Covariant | ty::Contravariant => (),
526+
// We do need a fresh type variable otherwise.
527+
ty::Bivariant | ty::Covariant | ty::Contravariant => (),
556528
}
557529

558530
let origin = inner.type_variables().var_origin(vid);
@@ -771,32 +743,8 @@ struct Generalization<T> {
771743
/// for `?0` generalization returns an inference
772744
/// variable.
773745
///
774-
/// This has to be handled wotj care as it can
746+
/// This has to be handled with care as it can
775747
/// otherwise very easily result in infinite
776748
/// recursion.
777749
pub value_may_be_infer: T,
778-
779-
/// In general, we do not check whether all types which occur during
780-
/// type checking are well-formed. We only check wf of user-provided types
781-
/// and when actually using a type, e.g. for method calls.
782-
///
783-
/// This means that when subtyping, we may end up with unconstrained
784-
/// inference variables if a generalized type has bivariant parameters.
785-
/// A parameter may only be bivariant if it is constrained by a projection
786-
/// bound in a where-clause. As an example, imagine a type:
787-
///
788-
/// struct Foo<A, B> where A: Iterator<Item = B> {
789-
/// data: A
790-
/// }
791-
///
792-
/// here, `A` will be covariant, but `B` is unconstrained.
793-
///
794-
/// However, whatever it is, for `Foo` to be WF, it must be equal to `A::Item`.
795-
/// If we have an input `Foo<?A, ?B>`, then after generalization we will wind
796-
/// up with a type like `Foo<?C, ?D>`. When we enforce `Foo<?A, ?B> <: Foo<?C, ?D>`,
797-
/// we will wind up with the requirement that `?A <: ?C`, but no particular
798-
/// relationship between `?B` and `?D` (after all, these types may be completely
799-
/// different). If we do nothing else, this may mean that `?D` goes unconstrained
800-
/// (as in #41677). To avoid this we emit a `WellFormed` obligation in these cases.
801-
pub has_unconstrained_ty_var: bool,
802750
}

‎compiler/rustc_infer/src/infer/relate/lattice.rs‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use rustc_middle::ty::relate::combine::{super_combine_consts, super_combine_tys}
2222
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
2323
use rustc_middle::ty::{self, Ty, TyCtxt, TyVar, TypeVisitableExt};
2424
use rustc_span::Span;
25+
use rustc_type_ir::relate::relate_args_with_variances;
2526
use tracing::{debug, instrument};
2627

2728
use super::StructurallyRelateAliases;
@@ -75,6 +76,22 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for LatticeOp<'_, 'tcx> {
7576
self.infcx.tcx
7677
}
7778

79+
fn relate_item_args(
80+
&mut self,
81+
item_def_id: rustc_hir::def_id::DefId,
82+
a_arg: ty::GenericArgsRef<'tcx>,
83+
b_arg: ty::GenericArgsRef<'tcx>,
84+
f: impl FnOnce(ty::GenericArgsRef<'tcx>) -> Ty<'tcx>,
85+
) -> RelateResult<'tcx, Ty<'tcx>> {
86+
let variances = self.cx().variances_of(item_def_id);
87+
let args = relate_args_with_variances(self, item_def_id, variances, a_arg, b_arg, false)?;
88+
let ty = f(args);
89+
if variances.iter().any(|&v| v == ty::Bivariant) {
90+
self.register_predicates([ty::ClauseKind::WellFormed(ty.into())]);
91+
}
92+
Ok(ty)
93+
}
94+
7895
fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
7996
&mut self,
8097
variance: ty::Variance,

‎compiler/rustc_infer/src/infer/relate/type_relating.rs‎

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,17 +84,24 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, 'tcx> {
8484
item_def_id: rustc_hir::def_id::DefId,
8585
a_arg: ty::GenericArgsRef<'tcx>,
8686
b_arg: ty::GenericArgsRef<'tcx>,
87-
) -> RelateResult<'tcx, ty::GenericArgsRef<'tcx>> {
87+
f: impl FnOnce(ty::GenericArgsRef<'tcx>) -> Ty<'tcx>,
88+
) -> RelateResult<'tcx, Ty<'tcx>> {
8889
if self.ambient_variance == ty::Invariant {
8990
// Avoid fetching the variance if we are in an invariant
9091
// context; no need, and it can induce dependency cycles
9192
// (e.g., #41849).
92-
relate_args_invariantly(self, a_arg, b_arg)
93-
} else {
94-
let tcx = self.cx();
95-
let opt_variances = tcx.variances_of(item_def_id);
96-
relate_args_with_variances(self, item_def_id, opt_variances, a_arg, b_arg, false)
93+
let args = relate_args_invariantly(self, a_arg, b_arg)?;
94+
return Ok(f(args));
95+
}
96+
97+
let tcx = self.cx();
98+
let variances = tcx.variances_of(item_def_id);
99+
let args = relate_args_with_variances(self, item_def_id, variances, a_arg, b_arg, false)?;
100+
let ty = f(args);
101+
if variances.iter().any(|&v| v == ty::Bivariant) {
102+
self.register_predicates([ty::ClauseKind::WellFormed(ty.into())]);
97103
}
104+
Ok(ty)
98105
}
99106

100107
fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(

‎compiler/rustc_lint/src/impl_trait_overcaptures.rs‎

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ use rustc_infer::infer::outlives::env::OutlivesEnvironment;
1212
use rustc_macros::LintDiagnostic;
1313
use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
1414
use rustc_middle::ty::relate::{
15-
Relate, RelateResult, TypeRelation, structurally_relate_consts, structurally_relate_tys,
15+
Relate, RelateResult, TypeRelation, relate_args_with_variances, structurally_relate_consts,
16+
structurally_relate_tys,
1617
};
1718
use rustc_middle::ty::{
1819
self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
@@ -502,6 +503,18 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for FunctionalVariances<'tcx> {
502503
self.tcx
503504
}
504505

506+
fn relate_item_args(
507+
&mut self,
508+
item_def_id: rustc_hir::def_id::DefId,
509+
a_arg: ty::GenericArgsRef<'tcx>,
510+
b_arg: ty::GenericArgsRef<'tcx>,
511+
f: impl FnOnce(ty::GenericArgsRef<'tcx>) -> Ty<'tcx>,
512+
) -> RelateResult<'tcx, Ty<'tcx>> {
513+
let variances = self.cx().variances_of(item_def_id);
514+
let args = relate_args_with_variances(self, item_def_id, variances, a_arg, b_arg, false)?;
515+
Ok(f(args))
516+
}
517+
505518
fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
506519
&mut self,
507520
variance: ty::Variance,

‎compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,9 @@ where
235235
// See <https://github.com/rust-lang/trait-system-refactor-initiative/issues/185>.
236236
ecx.try_evaluate_added_goals()?;
237237

238-
// Add GAT where clauses from the trait's definition.
239-
// FIXME: We don't need these, since these are the type's own WF obligations.
238+
// Add GAT where clauses from the trait's definition. This is necessary
239+
// for soundness until we properly handle implied bounds on binders,
240+
// see tests/ui/generic-associated-types/must-prove-where-clauses-on-norm.rs.
240241
ecx.add_goals(
241242
GoalSource::AliasWellFormed,
242243
cx.own_predicates_of(goal.predicate.def_id())

‎compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2258,6 +2258,17 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for SameTypeModuloInfer<'_, 'tcx> {
22582258
self.0.tcx
22592259
}
22602260

2261+
fn relate_item_args(
2262+
&mut self,
2263+
_: rustc_hir::def_id::DefId,
2264+
a_arg: ty::GenericArgsRef<'tcx>,
2265+
b_arg: ty::GenericArgsRef<'tcx>,
2266+
f: impl FnOnce(ty::GenericArgsRef<'tcx>) -> Ty<'tcx>,
2267+
) -> RelateResult<'tcx, Ty<'tcx>> {
2268+
let args = relate::relate_args_invariantly(self, a_arg, b_arg)?;
2269+
Ok(f(args))
2270+
}
2271+
22612272
fn relate_with_variance<T: relate::Relate<TyCtxt<'tcx>>>(
22622273
&mut self,
22632274
_variance: ty::Variance,

0 commit comments

Comments
 (0)