Skip to content

Commit a0ef4bf

Browse files
committed
Add the generic_associated_types_extended feature
1 parent 335ffbf commit a0ef4bf

File tree

14 files changed

+251
-42
lines changed

14 files changed

+251
-42
lines changed

Cargo.lock

+10-10
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ dependencies = [
320320
"cargo-test-macro",
321321
"cargo-test-support",
322322
"cargo-util",
323-
"clap 3.1.1",
323+
"clap 3.1.6",
324324
"crates-io",
325325
"crossbeam-utils",
326326
"curl",
@@ -598,17 +598,17 @@ dependencies = [
598598

599599
[[package]]
600600
name = "clap"
601-
version = "3.1.1"
601+
version = "3.1.6"
602602
source = "registry+https://github.com/rust-lang/crates.io-index"
603-
checksum = "6d76c22c9b9b215eeb8d016ad3a90417bd13cb24cf8142756e6472445876cab7"
603+
checksum = "d8c93436c21e4698bacadf42917db28b23017027a4deccb35dbe47a7e7840123"
604604
dependencies = [
605605
"atty",
606606
"bitflags",
607607
"indexmap",
608608
"os_str_bytes",
609609
"strsim 0.10.0",
610610
"termcolor",
611-
"textwrap 0.14.2",
611+
"textwrap 0.15.0",
612612
]
613613

614614
[[package]]
@@ -1502,9 +1502,9 @@ dependencies = [
15021502

15031503
[[package]]
15041504
name = "git2"
1505-
version = "0.14.1"
1505+
version = "0.14.2"
15061506
source = "registry+https://github.com/rust-lang/crates.io-index"
1507-
checksum = "6e7d3b96ec1fcaa8431cf04a4f1ef5caafe58d5cf7bcc31f09c1626adddb0ffe"
1507+
checksum = "3826a6e0e2215d7a41c2bfc7c9244123969273f3476b939a226aac0ab56e9e3c"
15081508
dependencies = [
15091509
"bitflags",
15101510
"libc",
@@ -1974,9 +1974,9 @@ dependencies = [
19741974

19751975
[[package]]
19761976
name = "libgit2-sys"
1977-
version = "0.13.1+1.4.2"
1977+
version = "0.13.2+1.4.2"
19781978
source = "registry+https://github.com/rust-lang/crates.io-index"
1979-
checksum = "43e598aa7a4faedf1ea1b4608f582b06f0f40211eec551b7ef36019ae3f62def"
1979+
checksum = "3a42de9a51a5c12e00fc0e4ca6bc2ea43582fc6418488e8f615e905d886f258b"
19801980
dependencies = [
19811981
"cc",
19821982
"libc",
@@ -5024,9 +5024,9 @@ dependencies = [
50245024

50255025
[[package]]
50265026
name = "textwrap"
5027-
version = "0.14.2"
5027+
version = "0.15.0"
50285028
source = "registry+https://github.com/rust-lang/crates.io-index"
5029-
checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80"
5029+
checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
50305030

50315031
[[package]]
50325032
name = "thiserror"

compiler/rustc_feature/src/active.rs

+2
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,8 @@ declare_features! (
398398
(active, generic_arg_infer, "1.55.0", Some(85077), None),
399399
/// Allows associated types to be generic, e.g., `type Foo<T>;` (RFC 1598).
400400
(active, generic_associated_types, "1.23.0", Some(44265), None),
401+
/// An extension to the `generic_associated_types` feature, allowing incomplete features.
402+
(incomplete, generic_associated_types_extended, "1.61.0", Some(44265), None),
401403
/// Allows non-trivial generic constants which have to have wfness manually propagated to callers
402404
(incomplete, generic_const_exprs, "1.56.0", Some(76560), None),
403405
/// Allows using `..X`, `..=X`, `...X`, and `X..` as a pattern.

compiler/rustc_middle/src/ty/fold.rs

+47
Original file line numberDiff line numberDiff line change
@@ -1375,3 +1375,50 @@ impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector {
13751375
ControlFlow::CONTINUE
13761376
}
13771377
}
1378+
1379+
/// Finds the max universe present
1380+
pub struct MaxUniverse {
1381+
max_universe: ty::UniverseIndex,
1382+
}
1383+
1384+
impl MaxUniverse {
1385+
pub fn new() -> Self {
1386+
MaxUniverse { max_universe: ty::UniverseIndex::ROOT }
1387+
}
1388+
1389+
pub fn max_universe(self) -> ty::UniverseIndex {
1390+
self.max_universe
1391+
}
1392+
}
1393+
1394+
impl<'tcx> TypeVisitor<'tcx> for MaxUniverse {
1395+
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
1396+
if let ty::Placeholder(placeholder) = t.kind() {
1397+
self.max_universe = ty::UniverseIndex::from_u32(
1398+
self.max_universe.as_u32().max(placeholder.universe.as_u32()),
1399+
);
1400+
}
1401+
1402+
t.super_visit_with(self)
1403+
}
1404+
1405+
fn visit_const(&mut self, c: ty::consts::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
1406+
if let ty::ConstKind::Placeholder(placeholder) = c.val() {
1407+
self.max_universe = ty::UniverseIndex::from_u32(
1408+
self.max_universe.as_u32().max(placeholder.universe.as_u32()),
1409+
);
1410+
}
1411+
1412+
c.super_visit_with(self)
1413+
}
1414+
1415+
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
1416+
if let ty::RePlaceholder(placeholder) = *r {
1417+
self.max_universe = ty::UniverseIndex::from_u32(
1418+
self.max_universe.as_u32().max(placeholder.universe.as_u32()),
1419+
);
1420+
}
1421+
1422+
ControlFlow::CONTINUE
1423+
}
1424+
}

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,7 @@ symbols! {
723723
generators,
724724
generic_arg_infer,
725725
generic_associated_types,
726+
generic_associated_types_extended,
726727
generic_const_exprs,
727728
generic_param_attrs,
728729
get_context,

compiler/rustc_trait_selection/src/traits/auto_trait.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use super::*;
55

66
use crate::infer::region_constraints::{Constraint, RegionConstraintData};
77
use crate::infer::InferCtxt;
8+
use crate::traits::project::ProjectAndUnifyResult;
89
use rustc_middle::ty::fold::TypeFolder;
910
use rustc_middle::ty::{Region, RegionVid, Term};
1011

@@ -733,19 +734,19 @@ impl<'tcx> AutoTraitFinder<'tcx> {
733734
debug!("Projecting and unifying projection predicate {:?}", predicate);
734735

735736
match project::poly_project_and_unify_type(select, &obligation.with(p)) {
736-
Err(e) => {
737+
ProjectAndUnifyResult::MismatchedProjectionTypes(e) => {
737738
debug!(
738739
"evaluate_nested_obligations: Unable to unify predicate \
739740
'{:?}' '{:?}', bailing out",
740741
ty, e
741742
);
742743
return false;
743744
}
744-
Ok(Err(project::InProgress)) => {
745+
ProjectAndUnifyResult::Recursive => {
745746
debug!("evaluate_nested_obligations: recursive projection predicate");
746747
return false;
747748
}
748-
Ok(Ok(Some(v))) => {
749+
ProjectAndUnifyResult::Holds(v) => {
749750
// We only care about sub-obligations
750751
// when we started out trying to unify
751752
// some inference variables. See the comment above
@@ -764,7 +765,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
764765
}
765766
}
766767
}
767-
Ok(Ok(None)) => {
768+
ProjectAndUnifyResult::FailedNormalization => {
768769
// It's ok not to make progress when have no inference variables -
769770
// in that case, we were only performing unifcation to check if an
770771
// error occurred (which would indicate that it's impossible for our

compiler/rustc_trait_selection/src/traits/fulfill.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use rustc_middle::ty::{self, Binder, Const, Ty, TypeFoldable};
1515
use std::marker::PhantomData;
1616

1717
use super::const_evaluatable;
18-
use super::project;
18+
use super::project::{self, ProjectAndUnifyResult};
1919
use super::select::SelectionContext;
2020
use super::wf;
2121
use super::CodeAmbiguity;
@@ -752,8 +752,8 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
752752
}
753753

754754
match project::poly_project_and_unify_type(self.selcx, &project_obligation) {
755-
Ok(Ok(Some(os))) => ProcessResult::Changed(mk_pending(os)),
756-
Ok(Ok(None)) => {
755+
ProjectAndUnifyResult::Holds(os) => ProcessResult::Changed(mk_pending(os)),
756+
ProjectAndUnifyResult::FailedNormalization => {
757757
stalled_on.clear();
758758
stalled_on.extend(substs_infer_vars(
759759
self.selcx,
@@ -762,10 +762,12 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
762762
ProcessResult::Unchanged
763763
}
764764
// Let the caller handle the recursion
765-
Ok(Err(project::InProgress)) => ProcessResult::Changed(mk_pending(vec![
765+
ProjectAndUnifyResult::Recursive => ProcessResult::Changed(mk_pending(vec![
766766
project_obligation.with(project_obligation.predicate.to_predicate(tcx)),
767767
])),
768-
Err(e) => ProcessResult::Error(CodeProjectionError(e)),
768+
ProjectAndUnifyResult::MismatchedProjectionTypes(e) => {
769+
ProcessResult::Error(CodeProjectionError(e))
770+
}
769771
}
770772
}
771773
}

compiler/rustc_trait_selection/src/traits/project.rs

+48-19
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use rustc_hir::def::DefKind;
2727
use rustc_hir::def_id::DefId;
2828
use rustc_hir::lang_items::LangItem;
2929
use rustc_infer::infer::resolve::OpportunisticRegionResolver;
30+
use rustc_middle::ty::fold::MaxUniverse;
3031
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
3132
use rustc_middle::ty::subst::Subst;
3233
use rustc_middle::ty::{self, Term, ToPredicate, Ty, TyCtxt};
@@ -143,6 +144,18 @@ impl<'tcx> ProjectionCandidateSet<'tcx> {
143144
}
144145
}
145146

147+
/// Takes the place of a
148+
/// Result<
149+
/// Result<Option<Vec<PredicateObligation<'tcx>>>, InProgress>,
150+
/// MismatchedProjectionTypes<'tcx>,
151+
/// >
152+
pub(super) enum ProjectAndUnifyResult<'tcx> {
153+
Holds(Vec<PredicateObligation<'tcx>>),
154+
FailedNormalization,
155+
Recursive,
156+
MismatchedProjectionTypes(MismatchedProjectionTypes<'tcx>),
157+
}
158+
146159
/// Evaluates constraints of the form:
147160
///
148161
/// for<...> <T as Trait>::U == V
@@ -166,19 +179,39 @@ impl<'tcx> ProjectionCandidateSet<'tcx> {
166179
pub(super) fn poly_project_and_unify_type<'cx, 'tcx>(
167180
selcx: &mut SelectionContext<'cx, 'tcx>,
168181
obligation: &PolyProjectionObligation<'tcx>,
169-
) -> Result<
170-
Result<Option<Vec<PredicateObligation<'tcx>>>, InProgress>,
171-
MismatchedProjectionTypes<'tcx>,
172-
> {
182+
) -> ProjectAndUnifyResult<'tcx> {
173183
let infcx = selcx.infcx();
174-
infcx.commit_if_ok(|_snapshot| {
184+
let r = infcx.commit_if_ok(|_snapshot| {
185+
let old_universe = infcx.universe();
175186
let placeholder_predicate =
176187
infcx.replace_bound_vars_with_placeholders(obligation.predicate);
188+
let new_universe = infcx.universe();
177189

178190
let placeholder_obligation = obligation.with(placeholder_predicate);
179-
let result = project_and_unify_type(selcx, &placeholder_obligation)?;
180-
Ok(result)
181-
})
191+
match project_and_unify_type(selcx, &placeholder_obligation) {
192+
ProjectAndUnifyResult::MismatchedProjectionTypes(e) => Err(e),
193+
ProjectAndUnifyResult::Holds(obligations)
194+
if old_universe != new_universe
195+
&& selcx.tcx().features().generic_associated_types_extended =>
196+
{
197+
let new_obligations = obligations
198+
.into_iter()
199+
.filter(|obligation| {
200+
let mut visitor = MaxUniverse::new();
201+
obligation.predicate.visit_with(&mut visitor);
202+
visitor.max_universe() < new_universe
203+
})
204+
.collect();
205+
Ok(ProjectAndUnifyResult::Holds(new_obligations))
206+
}
207+
other => Ok(other),
208+
}
209+
});
210+
211+
match r {
212+
Ok(inner) => inner,
213+
Err(err) => ProjectAndUnifyResult::MismatchedProjectionTypes(err),
214+
}
182215
}
183216

184217
/// Evaluates constraints of the form:
@@ -188,15 +221,11 @@ pub(super) fn poly_project_and_unify_type<'cx, 'tcx>(
188221
/// If successful, this may result in additional obligations.
189222
///
190223
/// See [poly_project_and_unify_type] for an explanation of the return value.
224+
#[tracing::instrument(level = "debug", skip(selcx))]
191225
fn project_and_unify_type<'cx, 'tcx>(
192226
selcx: &mut SelectionContext<'cx, 'tcx>,
193227
obligation: &ProjectionObligation<'tcx>,
194-
) -> Result<
195-
Result<Option<Vec<PredicateObligation<'tcx>>>, InProgress>,
196-
MismatchedProjectionTypes<'tcx>,
197-
> {
198-
debug!(?obligation, "project_and_unify_type");
199-
228+
) -> ProjectAndUnifyResult<'tcx> {
200229
let mut obligations = vec![];
201230

202231
let infcx = selcx.infcx();
@@ -209,8 +238,8 @@ fn project_and_unify_type<'cx, 'tcx>(
209238
&mut obligations,
210239
) {
211240
Ok(Some(n)) => n,
212-
Ok(None) => return Ok(Ok(None)),
213-
Err(InProgress) => return Ok(Err(InProgress)),
241+
Ok(None) => return ProjectAndUnifyResult::FailedNormalization,
242+
Err(InProgress) => return ProjectAndUnifyResult::Recursive,
214243
};
215244
debug!(?normalized, ?obligations, "project_and_unify_type result");
216245
match infcx
@@ -219,11 +248,11 @@ fn project_and_unify_type<'cx, 'tcx>(
219248
{
220249
Ok(InferOk { obligations: inferred_obligations, value: () }) => {
221250
obligations.extend(inferred_obligations);
222-
Ok(Ok(Some(obligations)))
251+
ProjectAndUnifyResult::Holds(obligations)
223252
}
224253
Err(err) => {
225-
debug!("project_and_unify_type: equating types encountered error {:?}", err);
226-
Err(MismatchedProjectionTypes { err })
254+
debug!("equating types encountered error {:?}", err);
255+
ProjectAndUnifyResult::MismatchedProjectionTypes(MismatchedProjectionTypes { err })
227256
}
228257
}
229258
}

compiler/rustc_trait_selection/src/traits/select/mod.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use super::{ObligationCause, PredicateObligation, TraitObligation};
2525

2626
use crate::infer::{InferCtxt, InferOk, TypeFreshener};
2727
use crate::traits::error_reporting::InferCtxtExt;
28+
use crate::traits::project::ProjectAndUnifyResult;
2829
use crate::traits::project::ProjectionCacheKeyExt;
2930
use crate::traits::ProjectionCacheKey;
3031
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -551,7 +552,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
551552
let data = bound_predicate.rebind(data);
552553
let project_obligation = obligation.with(data);
553554
match project::poly_project_and_unify_type(self, &project_obligation) {
554-
Ok(Ok(Some(mut subobligations))) => {
555+
ProjectAndUnifyResult::Holds(mut subobligations) => {
555556
'compute_res: {
556557
// If we've previously marked this projection as 'complete', thne
557558
// use the final cached result (either `EvaluatedToOk` or
@@ -599,9 +600,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
599600
res
600601
}
601602
}
602-
Ok(Ok(None)) => Ok(EvaluatedToAmbig),
603-
Ok(Err(project::InProgress)) => Ok(EvaluatedToRecur),
604-
Err(_) => Ok(EvaluatedToErr),
603+
ProjectAndUnifyResult::FailedNormalization => Ok(EvaluatedToAmbig),
604+
ProjectAndUnifyResult::Recursive => Ok(EvaluatedToRecur),
605+
ProjectAndUnifyResult::MismatchedProjectionTypes(_) => Ok(EvaluatedToErr),
605606
}
606607
}
607608

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#![feature(generic_associated_types)]
2+
3+
// This feature doesn't *currently* fire on any specific code; it's just a
4+
// behavior change. Future changes might.
5+
#[rustc_error] //~ the
6+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0658]: the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable
2+
--> $DIR/feature-gate-generic_associated_types_extended.rs:5:1
3+
|
4+
LL | #[rustc_error]
5+
| ^^^^^^^^^^^^^^
6+
|
7+
= help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0658`.

0 commit comments

Comments
 (0)