Skip to content

Commit 4375b36

Browse files
committed
Add BoundCtxt in visit_param_bounds to check questions in bounds
1 parent 27af517 commit 4375b36

File tree

5 files changed

+66
-56
lines changed

5 files changed

+66
-56
lines changed

compiler/rustc_ast/src/visit.rs

+22-12
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ pub enum FnCtxt {
3232
Assoc(AssocCtxt),
3333
}
3434

35+
#[derive(Copy, Clone, Debug)]
36+
pub enum BoundCtxt {
37+
Normal,
38+
TraitObject,
39+
SuperTraits,
40+
}
41+
3542
#[derive(Copy, Clone, Debug)]
3643
pub enum FnKind<'a> {
3744
/// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`.
@@ -139,7 +146,7 @@ pub trait Visitor<'ast>: Sized {
139146
fn visit_trait_ref(&mut self, t: &'ast TraitRef) {
140147
walk_trait_ref(self, t)
141148
}
142-
fn visit_param_bound(&mut self, bounds: &'ast GenericBound) {
149+
fn visit_param_bound(&mut self, bounds: &'ast GenericBound, _ctxt: BoundCtxt) {
143150
walk_param_bound(self, bounds)
144151
}
145152
fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef, m: &'ast TraitBoundModifier) {
@@ -311,7 +318,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
311318
ItemKind::GlobalAsm(ref asm) => walk_inline_asm(visitor, asm),
312319
ItemKind::TyAlias(box TyAlias { ref generics, ref bounds, ref ty, .. }) => {
313320
visitor.visit_generics(generics);
314-
walk_list!(visitor, visit_param_bound, bounds);
321+
walk_list!(visitor, visit_param_bound, bounds, BoundCtxt::Normal);
315322
walk_list!(visitor, visit_ty, ty);
316323
}
317324
ItemKind::Enum(ref enum_definition, ref generics) => {
@@ -346,12 +353,12 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
346353
ref items,
347354
}) => {
348355
visitor.visit_generics(generics);
349-
walk_list!(visitor, visit_param_bound, bounds);
356+
walk_list!(visitor, visit_param_bound, bounds, BoundCtxt::SuperTraits);
350357
walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Trait);
351358
}
352359
ItemKind::TraitAlias(ref generics, ref bounds) => {
353360
visitor.visit_generics(generics);
354-
walk_list!(visitor, visit_param_bound, bounds);
361+
walk_list!(visitor, visit_param_bound, bounds, BoundCtxt::Normal);
355362
}
356363
ItemKind::MacCall(ref mac) => visitor.visit_mac_call(mac),
357364
ItemKind::MacroDef(ref ts) => visitor.visit_mac_def(ts, item.id),
@@ -416,8 +423,11 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) {
416423
visitor.visit_ty(ty);
417424
visitor.visit_anon_const(length)
418425
}
419-
TyKind::TraitObject(ref bounds, ..) | TyKind::ImplTrait(_, ref bounds) => {
420-
walk_list!(visitor, visit_param_bound, bounds);
426+
TyKind::TraitObject(ref bounds, ..) => {
427+
walk_list!(visitor, visit_param_bound, bounds, BoundCtxt::TraitObject);
428+
}
429+
TyKind::ImplTrait(_, ref bounds) => {
430+
walk_list!(visitor, visit_param_bound, bounds, BoundCtxt::Normal);
421431
}
422432
TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression),
423433
TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err => {}
@@ -503,7 +513,7 @@ pub fn walk_assoc_constraint<'a, V: Visitor<'a>>(visitor: &mut V, constraint: &'
503513
Term::Const(c) => visitor.visit_anon_const(c),
504514
},
505515
AssocConstraintKind::Bound { ref bounds } => {
506-
walk_list!(visitor, visit_param_bound, bounds);
516+
walk_list!(visitor, visit_param_bound, bounds, BoundCtxt::Normal);
507517
}
508518
}
509519
}
@@ -566,7 +576,7 @@ pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignI
566576
}
567577
ForeignItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => {
568578
visitor.visit_generics(generics);
569-
walk_list!(visitor, visit_param_bound, bounds);
579+
walk_list!(visitor, visit_param_bound, bounds, BoundCtxt::Normal);
570580
walk_list!(visitor, visit_ty, ty);
571581
}
572582
ForeignItemKind::MacCall(mac) => {
@@ -585,7 +595,7 @@ pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericB
585595
pub fn walk_generic_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a GenericParam) {
586596
visitor.visit_ident(param.ident);
587597
walk_list!(visitor, visit_attribute, param.attrs.iter());
588-
walk_list!(visitor, visit_param_bound, &param.bounds);
598+
walk_list!(visitor, visit_param_bound, &param.bounds, BoundCtxt::Normal);
589599
match param.kind {
590600
GenericParamKind::Lifetime => (),
591601
GenericParamKind::Type { ref default } => walk_list!(visitor, visit_ty, default),
@@ -612,14 +622,14 @@ pub fn walk_where_predicate<'a, V: Visitor<'a>>(visitor: &mut V, predicate: &'a
612622
..
613623
}) => {
614624
visitor.visit_ty(bounded_ty);
615-
walk_list!(visitor, visit_param_bound, bounds);
625+
walk_list!(visitor, visit_param_bound, bounds, BoundCtxt::Normal);
616626
walk_list!(visitor, visit_generic_param, bound_generic_params);
617627
}
618628
WherePredicate::RegionPredicate(WhereRegionPredicate {
619629
ref lifetime, ref bounds, ..
620630
}) => {
621631
visitor.visit_lifetime(lifetime);
622-
walk_list!(visitor, visit_param_bound, bounds);
632+
walk_list!(visitor, visit_param_bound, bounds, BoundCtxt::Normal);
623633
}
624634
WherePredicate::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty, .. }) => {
625635
visitor.visit_ty(lhs_ty);
@@ -672,7 +682,7 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem,
672682
}
673683
AssocItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => {
674684
visitor.visit_generics(generics);
675-
walk_list!(visitor, visit_param_bound, bounds);
685+
walk_list!(visitor, visit_param_bound, bounds, BoundCtxt::Normal);
676686
walk_list!(visitor, visit_ty, ty);
677687
}
678688
AssocItemKind::MacCall(mac) => {

compiler/rustc_ast_passes/src/ast_validation.rs

+35-36
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
use itertools::{Either, Itertools};
1010
use rustc_ast::ptr::P;
11-
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
11+
use rustc_ast::visit::{self, AssocCtxt, BoundCtxt, FnCtxt, FnKind, Visitor};
1212
use rustc_ast::walk_list;
1313
use rustc_ast::*;
1414
use rustc_ast_pretty::pprust::{self, State};
@@ -345,23 +345,6 @@ impl<'a> AstValidator<'a> {
345345
}
346346
}
347347

348-
// FIXME(ecstaticmorse): Instead, use `bound_context` to check this in `visit_param_bound`.
349-
fn no_questions_in_bounds(&self, bounds: &GenericBounds, where_: &str, is_trait: bool) {
350-
for bound in bounds {
351-
if let GenericBound::Trait(ref poly, TraitBoundModifier::Maybe) = *bound {
352-
let mut err = self.err_handler().struct_span_err(
353-
poly.span,
354-
&format!("`?Trait` is not permitted in {}", where_),
355-
);
356-
if is_trait {
357-
let path_str = pprust::path_to_string(&poly.trait_ref.path);
358-
err.note(&format!("traits are `?{}` by default", path_str));
359-
}
360-
err.emit();
361-
}
362-
}
363-
}
364-
365348
fn check_late_bound_lifetime_defs(&self, params: &[GenericParam]) {
366349
// Check only lifetime parameters are present and that the lifetime
367350
// parameters that are present have no bounds.
@@ -873,7 +856,6 @@ impl<'a> AstValidator<'a> {
873856
any_lifetime_bounds = true;
874857
}
875858
}
876-
self.no_questions_in_bounds(bounds, "trait object types", false);
877859
}
878860
TyKind::ImplTrait(_, ref bounds) => {
879861
if self.is_impl_trait_banned {
@@ -1242,14 +1224,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
12421224
self.deny_where_clause(&generics.where_clause, item.ident.span);
12431225
self.deny_items(items, item.ident.span);
12441226
}
1245-
self.no_questions_in_bounds(bounds, "supertraits", true);
12461227

12471228
// Equivalent of `visit::walk_item` for `ItemKind::Trait` that inserts a bound
12481229
// context for the supertraits.
12491230
self.visit_vis(&item.vis);
12501231
self.visit_ident(item.ident);
12511232
self.visit_generics(generics);
1252-
self.with_banned_tilde_const(|this| walk_list!(this, visit_param_bound, bounds));
1233+
self.with_banned_tilde_const(|this| {
1234+
walk_list!(this, visit_param_bound, bounds, BoundCtxt::SuperTraits)
1235+
});
12531236
walk_list!(self, visit_assoc_item, items, AssocCtxt::Trait);
12541237
walk_list!(self, visit_attribute, &item.attrs);
12551238
return;
@@ -1476,23 +1459,39 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
14761459
visit::walk_generic_param(self, param);
14771460
}
14781461

1479-
fn visit_param_bound(&mut self, bound: &'a GenericBound) {
1480-
match bound {
1481-
GenericBound::Trait(_, TraitBoundModifier::MaybeConst) => {
1482-
if !self.is_tilde_const_allowed {
1462+
fn visit_param_bound(&mut self, bound: &'a GenericBound, ctxt: BoundCtxt) {
1463+
if let GenericBound::Trait(ref poly, modify) = *bound {
1464+
match (ctxt, modify) {
1465+
(BoundCtxt::SuperTraits, TraitBoundModifier::Maybe) => {
1466+
let mut err = self.err_handler().struct_span_err(
1467+
poly.span,
1468+
&format!("`?Trait` is not permitted in supertraits"),
1469+
);
1470+
let path_str = pprust::path_to_string(&poly.trait_ref.path);
1471+
err.note(&format!("traits are `?{}` by default", path_str));
1472+
err.emit();
1473+
}
1474+
(BoundCtxt::TraitObject, TraitBoundModifier::Maybe) => {
1475+
let mut err = self.err_handler().struct_span_err(
1476+
poly.span,
1477+
&format!("`?Trait` is not permitted in trait object types"),
1478+
);
1479+
err.emit();
1480+
}
1481+
(_, TraitBoundModifier::MaybeConst) => {
1482+
if !self.is_tilde_const_allowed {
1483+
self.err_handler()
1484+
.struct_span_err(bound.span(), "`~const` is not allowed here")
1485+
.note("only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions")
1486+
.emit();
1487+
}
1488+
}
1489+
(_, TraitBoundModifier::MaybeConstMaybe) => {
14831490
self.err_handler()
1484-
.struct_span_err(bound.span(), "`~const` is not allowed here")
1485-
.note("only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions")
1486-
.emit();
1491+
.span_err(bound.span(), "`~const` and `?` are mutually exclusive");
14871492
}
1493+
_ => {}
14881494
}
1489-
1490-
GenericBound::Trait(_, TraitBoundModifier::MaybeConstMaybe) => {
1491-
self.err_handler()
1492-
.span_err(bound.span(), "`~const` and `?` are mutually exclusive");
1493-
}
1494-
1495-
_ => {}
14961495
}
14971496

14981497
visit::walk_param_bound(self, bound)
@@ -1662,7 +1661,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
16621661
walk_list!(self, visit_attribute, &item.attrs);
16631662
self.with_tilde_const_allowed(|this| {
16641663
this.visit_generics(generics);
1665-
walk_list!(this, visit_param_bound, bounds);
1664+
walk_list!(this, visit_param_bound, bounds, BoundCtxt::Normal);
16661665
});
16671666
walk_list!(self, visit_ty, ty);
16681667
}

compiler/rustc_ast_passes/src/node_count.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ impl<'ast> Visitor<'ast> for NodeCounter {
7676
self.count += 1;
7777
walk_trait_ref(self, t)
7878
}
79-
fn visit_param_bound(&mut self, bounds: &GenericBound) {
79+
fn visit_param_bound(&mut self, bounds: &GenericBound, _ctxt: BoundCtxt) {
8080
self.count += 1;
8181
walk_param_bound(self, bounds)
8282
}

compiler/rustc_passes/src/hir_stats.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// completely accurate (some things might be counted twice, others missed).
44

55
use rustc_ast::visit as ast_visit;
6+
use rustc_ast::visit::BoundCtxt;
67
use rustc_ast::{self as ast, AttrId, NodeId};
78
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
89
use rustc_hir as hir;
@@ -302,7 +303,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
302303
ast_visit::walk_assoc_item(self, item, ctxt);
303304
}
304305

305-
fn visit_param_bound(&mut self, bounds: &'v ast::GenericBound) {
306+
fn visit_param_bound(&mut self, bounds: &'v ast::GenericBound, _ctxt: BoundCtxt) {
306307
self.record("GenericBound", Id::None, bounds);
307308
ast_visit::walk_param_bound(self, bounds)
308309
}

compiler/rustc_resolve/src/late.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::{Module, ModuleOrUniformRoot, NameBinding, ParentScope, PathResult};
1212
use crate::{ResolutionError, Resolver, Segment, UseError};
1313

1414
use rustc_ast::ptr::P;
15-
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
15+
use rustc_ast::visit::{self, AssocCtxt, BoundCtxt, FnCtxt, FnKind, Visitor};
1616
use rustc_ast::*;
1717
use rustc_ast_lowering::ResolverAstLowering;
1818
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -835,7 +835,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
835835
this.visit_generic_param_vec(&bound_generic_params, false);
836836
this.visit_ty(bounded_ty);
837837
for bound in bounds {
838-
this.visit_param_bound(bound)
838+
this.visit_param_bound(bound, BoundCtxt::Normal)
839839
}
840840
},
841841
);
@@ -1026,12 +1026,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
10261026
match param.kind {
10271027
GenericParamKind::Lifetime => {
10281028
for bound in &param.bounds {
1029-
this.visit_param_bound(bound);
1029+
this.visit_param_bound(bound, BoundCtxt::Normal);
10301030
}
10311031
}
10321032
GenericParamKind::Type { ref default } => {
10331033
for bound in &param.bounds {
1034-
this.visit_param_bound(bound);
1034+
this.visit_param_bound(bound, BoundCtxt::Normal);
10351035
}
10361036

10371037
if let Some(ref ty) = default {
@@ -1496,7 +1496,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
14961496
Res::SelfTy { trait_: Some(local_def_id), alias_to: None },
14971497
|this| {
14981498
this.visit_generics(generics);
1499-
walk_list!(this, visit_param_bound, bounds);
1499+
walk_list!(this, visit_param_bound, bounds, BoundCtxt::SuperTraits);
15001500

15011501
let walk_assoc_item =
15021502
|this: &mut Self,
@@ -1580,7 +1580,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
15801580
Res::SelfTy { trait_: Some(local_def_id), alias_to: None },
15811581
|this| {
15821582
this.visit_generics(generics);
1583-
walk_list!(this, visit_param_bound, bounds);
1583+
walk_list!(this, visit_param_bound, bounds, BoundCtxt::Normal);
15841584
},
15851585
);
15861586
},

0 commit comments

Comments
 (0)