Review comments
This commit is contained in:
parent
4568e7d62e
commit
b78c0d8a4d
2 changed files with 33 additions and 36 deletions
|
@ -81,13 +81,6 @@ struct AstValidator<'a> {
|
||||||
is_assoc_ty_bound_banned: bool,
|
is_assoc_ty_bound_banned: bool,
|
||||||
|
|
||||||
lint_buffer: &'a mut LintBuffer,
|
lint_buffer: &'a mut LintBuffer,
|
||||||
|
|
||||||
/// This is slightly complicated. Our representation for poly-trait-refs contains a single
|
|
||||||
/// binder and thus we only allow a single level of quantification. However,
|
|
||||||
/// the syntax of Rust permits quantification in two places in where clauses,
|
|
||||||
/// e.g., `T: for <'a> Foo<'a>` and `for <'a, 'b> &'b T: Foo<'a>`. If both are
|
|
||||||
/// defined, then error.
|
|
||||||
trait_ref_hack: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> AstValidator<'a> {
|
impl<'a> AstValidator<'a> {
|
||||||
|
@ -1227,17 +1220,33 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||||
// A type binding, eg `for<'c> Foo: Send+Clone+'c`
|
// A type binding, eg `for<'c> Foo: Send+Clone+'c`
|
||||||
self.check_late_bound_lifetime_defs(&bound_pred.bound_generic_params);
|
self.check_late_bound_lifetime_defs(&bound_pred.bound_generic_params);
|
||||||
|
|
||||||
self.visit_ty(&bound_pred.bounded_ty);
|
// This is slightly complicated. Our representation for poly-trait-refs contains a single
|
||||||
|
// binder and thus we only allow a single level of quantification. However,
|
||||||
self.trait_ref_hack = !bound_pred.bound_generic_params.is_empty();
|
// the syntax of Rust permits quantification in two places in where clauses,
|
||||||
walk_list!(self, visit_param_bound, &bound_pred.bounds);
|
// e.g., `T: for <'a> Foo<'a>` and `for <'a, 'b> &'b T: Foo<'a>`. If both are
|
||||||
walk_list!(self, visit_generic_param, &bound_pred.bound_generic_params);
|
// defined, then error.
|
||||||
self.trait_ref_hack = false;
|
if !bound_pred.bound_generic_params.is_empty() {
|
||||||
}
|
for bound in &bound_pred.bounds {
|
||||||
_ => {
|
match bound {
|
||||||
self.visit_where_predicate(predicate);
|
GenericBound::Trait(t, _) => {
|
||||||
|
if !t.bound_generic_params.is_empty() {
|
||||||
|
struct_span_err!(
|
||||||
|
self.err_handler(),
|
||||||
|
t.span,
|
||||||
|
E0316,
|
||||||
|
"nested quantification of lifetimes"
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GenericBound::Outlives(_) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
|
self.visit_where_predicate(predicate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1289,19 +1298,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||||
|
|
||||||
fn visit_poly_trait_ref(&mut self, t: &'a PolyTraitRef, m: &'a TraitBoundModifier) {
|
fn visit_poly_trait_ref(&mut self, t: &'a PolyTraitRef, m: &'a TraitBoundModifier) {
|
||||||
self.check_late_bound_lifetime_defs(&t.bound_generic_params);
|
self.check_late_bound_lifetime_defs(&t.bound_generic_params);
|
||||||
if self.trait_ref_hack && !t.bound_generic_params.is_empty() {
|
|
||||||
struct_span_err!(
|
|
||||||
self.err_handler(),
|
|
||||||
t.span,
|
|
||||||
E0316,
|
|
||||||
"nested quantification of lifetimes"
|
|
||||||
)
|
|
||||||
.emit();
|
|
||||||
}
|
|
||||||
let trait_ref_hack = self.trait_ref_hack;
|
|
||||||
self.trait_ref_hack = false;
|
|
||||||
visit::walk_poly_trait_ref(self, t, m);
|
visit::walk_poly_trait_ref(self, t, m);
|
||||||
self.trait_ref_hack = trait_ref_hack;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_variant_data(&mut self, s: &'a VariantData) {
|
fn visit_variant_data(&mut self, s: &'a VariantData) {
|
||||||
|
@ -1520,7 +1517,6 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) ->
|
||||||
is_impl_trait_banned: false,
|
is_impl_trait_banned: false,
|
||||||
is_assoc_ty_bound_banned: false,
|
is_assoc_ty_bound_banned: false,
|
||||||
lint_buffer: lints,
|
lint_buffer: lints,
|
||||||
trait_ref_hack: false,
|
|
||||||
};
|
};
|
||||||
visit::walk_crate(&mut validator, krate);
|
visit::walk_crate(&mut validator, krate);
|
||||||
|
|
||||||
|
|
|
@ -1323,14 +1323,15 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
// of "if there isn't a Binder scope above us, add one", but I
|
// of "if there isn't a Binder scope above us, add one", but I
|
||||||
// imagine there's a better way to go about this.
|
// imagine there's a better way to go about this.
|
||||||
let mut scope = self.scope;
|
let mut scope = self.scope;
|
||||||
let trait_ref_hack = loop {
|
let (binders, scope_type) = loop {
|
||||||
match scope {
|
match scope {
|
||||||
Scope::TraitRefBoundary { .. } | Scope::Body { .. } | Scope::Root => {
|
Scope::TraitRefBoundary { .. } | Scope::Body { .. } | Scope::Root => {
|
||||||
break false;
|
break (vec![], BinderScopeType::PolyTraitRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
Scope::Binder { .. } => {
|
Scope::Binder { hir_id, .. } => {
|
||||||
break true;
|
let binders = self.map.late_bound_vars.entry(*hir_id).or_default().clone();
|
||||||
|
break (binders, BinderScopeType::Concatenating);
|
||||||
}
|
}
|
||||||
|
|
||||||
Scope::Elision { s, .. }
|
Scope::Elision { s, .. }
|
||||||
|
@ -1341,8 +1342,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
match bound {
|
match bound {
|
||||||
hir::GenericBound::LangItemTrait(_, _, hir_id, _) if !trait_ref_hack => {
|
hir::GenericBound::LangItemTrait(_, _, hir_id, _) => {
|
||||||
self.map.late_bound_vars.insert(*hir_id, vec![]);
|
self.map.late_bound_vars.insert(*hir_id, binders);
|
||||||
let scope = Scope::Binder {
|
let scope = Scope::Binder {
|
||||||
hir_id: *hir_id,
|
hir_id: *hir_id,
|
||||||
lifetimes: FxHashMap::default(),
|
lifetimes: FxHashMap::default(),
|
||||||
|
@ -1350,7 +1351,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||||
next_early_index: self.next_early_index(),
|
next_early_index: self.next_early_index(),
|
||||||
track_lifetime_uses: true,
|
track_lifetime_uses: true,
|
||||||
opaque_type_parent: false,
|
opaque_type_parent: false,
|
||||||
scope_type: BinderScopeType::Other,
|
scope_type,
|
||||||
};
|
};
|
||||||
self.with(scope, |_, this| {
|
self.with(scope, |_, this| {
|
||||||
intravisit::walk_param_bound(this, bound);
|
intravisit::walk_param_bound(this, bound);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue