-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Add the generic_associated_types_extended feature #94869
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,7 +28,7 @@ use rustc_hir::def_id::DefId; | |
use rustc_hir::lang_items::LangItem; | ||
use rustc_infer::infer::resolve::OpportunisticRegionResolver; | ||
use rustc_middle::traits::select::OverflowError; | ||
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; | ||
use rustc_middle::ty::fold::{MaxUniverse, TypeFoldable, TypeFolder}; | ||
use rustc_middle::ty::subst::Subst; | ||
use rustc_middle::ty::{self, Term, ToPredicate, Ty, TyCtxt}; | ||
use rustc_span::symbol::sym; | ||
|
@@ -144,6 +144,18 @@ impl<'tcx> ProjectionCandidateSet<'tcx> { | |
} | ||
} | ||
|
||
/// Takes the place of a | ||
/// Result< | ||
/// Result<Option<Vec<PredicateObligation<'tcx>>>, InProgress>, | ||
/// MismatchedProjectionTypes<'tcx>, | ||
/// > | ||
pub(super) enum ProjectAndUnifyResult<'tcx> { | ||
Holds(Vec<PredicateObligation<'tcx>>), | ||
FailedNormalization, | ||
Recursive, | ||
MismatchedProjectionTypes(MismatchedProjectionTypes<'tcx>), | ||
} | ||
|
||
/// Evaluates constraints of the form: | ||
/// | ||
/// for<...> <T as Trait>::U == V | ||
|
@@ -167,19 +179,47 @@ impl<'tcx> ProjectionCandidateSet<'tcx> { | |
pub(super) fn poly_project_and_unify_type<'cx, 'tcx>( | ||
selcx: &mut SelectionContext<'cx, 'tcx>, | ||
obligation: &PolyProjectionObligation<'tcx>, | ||
) -> Result< | ||
Result<Option<Vec<PredicateObligation<'tcx>>>, InProgress>, | ||
MismatchedProjectionTypes<'tcx>, | ||
> { | ||
) -> ProjectAndUnifyResult<'tcx> { | ||
let infcx = selcx.infcx(); | ||
infcx.commit_if_ok(|_snapshot| { | ||
let r = infcx.commit_if_ok(|_snapshot| { | ||
let old_universe = infcx.universe(); | ||
let placeholder_predicate = | ||
infcx.replace_bound_vars_with_placeholders(obligation.predicate); | ||
let new_universe = infcx.universe(); | ||
|
||
let placeholder_obligation = obligation.with(placeholder_predicate); | ||
let result = project_and_unify_type(selcx, &placeholder_obligation)?; | ||
Ok(result) | ||
}) | ||
match project_and_unify_type(selcx, &placeholder_obligation) { | ||
ProjectAndUnifyResult::MismatchedProjectionTypes(e) => Err(e), | ||
ProjectAndUnifyResult::Holds(obligations) | ||
if old_universe != new_universe | ||
&& selcx.tcx().features().generic_associated_types_extended => | ||
{ | ||
// If the `generic_associated_types_extended` feature is active, then we ignore any | ||
// obligations references lifetimes from any universe greater than or equal to the | ||
// universe just created. Otherwise, we can end up with something like `for<'a> I: 'a`, | ||
// which isn't quite what we want. Ideally, we want either an implied | ||
// `for<'a where I: 'a> I: 'a` or we want to "lazily" check these hold when we | ||
// substitute concrete regions. There is design work to be done here; until then, | ||
// however, this allows experimenting potential GAT features without running into | ||
// well-formedness issues. | ||
let new_obligations = obligations | ||
.into_iter() | ||
.filter(|obligation| { | ||
let mut visitor = MaxUniverse::new(); | ||
obligation.predicate.visit_with(&mut visitor); | ||
visitor.max_universe() < new_universe | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you leave a comment:
Also, dumb question, what's the difference between There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So, the
|
||
}) | ||
.collect(); | ||
Ok(ProjectAndUnifyResult::Holds(new_obligations)) | ||
} | ||
other => Ok(other), | ||
} | ||
}); | ||
|
||
match r { | ||
Ok(inner) => inner, | ||
Err(err) => ProjectAndUnifyResult::MismatchedProjectionTypes(err), | ||
} | ||
} | ||
|
||
/// Evaluates constraints of the form: | ||
|
@@ -189,15 +229,11 @@ pub(super) fn poly_project_and_unify_type<'cx, 'tcx>( | |
/// If successful, this may result in additional obligations. | ||
/// | ||
/// See [poly_project_and_unify_type] for an explanation of the return value. | ||
#[tracing::instrument(level = "debug", skip(selcx))] | ||
fn project_and_unify_type<'cx, 'tcx>( | ||
selcx: &mut SelectionContext<'cx, 'tcx>, | ||
obligation: &ProjectionObligation<'tcx>, | ||
) -> Result< | ||
Result<Option<Vec<PredicateObligation<'tcx>>>, InProgress>, | ||
MismatchedProjectionTypes<'tcx>, | ||
> { | ||
debug!(?obligation, "project_and_unify_type"); | ||
|
||
) -> ProjectAndUnifyResult<'tcx> { | ||
let mut obligations = vec![]; | ||
|
||
let infcx = selcx.infcx(); | ||
|
@@ -210,8 +246,8 @@ fn project_and_unify_type<'cx, 'tcx>( | |
&mut obligations, | ||
) { | ||
Ok(Some(n)) => n, | ||
Ok(None) => return Ok(Ok(None)), | ||
Err(InProgress) => return Ok(Err(InProgress)), | ||
Ok(None) => return ProjectAndUnifyResult::FailedNormalization, | ||
Err(InProgress) => return ProjectAndUnifyResult::Recursive, | ||
}; | ||
debug!(?normalized, ?obligations, "project_and_unify_type result"); | ||
match infcx | ||
|
@@ -220,11 +256,11 @@ fn project_and_unify_type<'cx, 'tcx>( | |
{ | ||
Ok(InferOk { obligations: inferred_obligations, value: () }) => { | ||
obligations.extend(inferred_obligations); | ||
Ok(Ok(Some(obligations))) | ||
ProjectAndUnifyResult::Holds(obligations) | ||
} | ||
Err(err) => { | ||
debug!("project_and_unify_type: equating types encountered error {:?}", err); | ||
Err(MismatchedProjectionTypes { err }) | ||
debug!("equating types encountered error {:?}", err); | ||
ProjectAndUnifyResult::MismatchedProjectionTypes(MismatchedProjectionTypes { err }) | ||
} | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#![feature(generic_associated_types)] | ||
|
||
// This feature doesn't *currently* fire on any specific code; it's just a | ||
// behavior change. Future changes might. | ||
#[rustc_error] //~ the | ||
fn main() {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
error[E0658]: the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable | ||
--> $DIR/feature-gate-generic_associated_types_extended.rs:5:1 | ||
| | ||
LL | #[rustc_error] | ||
| ^^^^^^^^^^^^^^ | ||
| | ||
= help: add `#![feature(rustc_attrs)]` to the crate attributes to enable | ||
|
||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0658`. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
error[E0276]: impl has stricter requirements than trait | ||
--> $DIR/lending_iterator.rs:14:45 | ||
| | ||
LL | fn from_iter<T: for<'x> LendingIterator<Item<'x> = A>>(iter: T) -> Self; | ||
| ------------------------------------------------------------------------ definition of `from_iter` from trait | ||
... | ||
LL | fn from_iter<I: for<'x> LendingIterator<Item<'x> = A>>(mut iter: I) -> Self { | ||
| ^^^^^^^^^^^^ impl has extra requirement `I: 'x` | ||
|
||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0276`. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
error[E0276]: impl has stricter requirements than trait | ||
--> $DIR/lending_iterator.rs:14:45 | ||
| | ||
LL | fn from_iter<T: for<'x> LendingIterator<Item<'x> = A>>(iter: T) -> Self; | ||
| ------------------------------------------------------------------------ definition of `from_iter` from trait | ||
... | ||
LL | fn from_iter<I: for<'x> LendingIterator<Item<'x> = A>>(mut iter: I) -> Self { | ||
| ^^^^^^^^^^^^ impl has extra requirement `I: 'x` | ||
|
||
error[E0311]: the parameter type `Self` may not live long enough | ||
--> $DIR/lending_iterator.rs:35:9 | ||
| | ||
LL | <B as FromLendingIterator<A>>::from_iter(self) | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
| | ||
= help: consider adding an explicit lifetime bound `Self: 'a`... | ||
= note: ...so that the type `Self` will meet its required lifetime bounds... | ||
note: ...that is required by this bound | ||
--> $DIR/lending_iterator.rs:10:45 | ||
| | ||
LL | fn from_iter<T: for<'x> LendingIterator<Item<'x> = A>>(iter: T) -> Self; | ||
| ^^^^^^^^^^^^ | ||
|
||
error: aborting due to 2 previous errors | ||
|
||
For more information about this error, try `rustc --explain E0276`. |
Uh oh!
There was an error while loading. Please reload this page.