Skip to content

Commit 7417110

Browse files
committed
Auto merge of rust-lang#96246 - SparrowLii:bound_contxet, r=compiler-errors
Add `BoundKind` in `visit_param_bounds` to check questions in bounds From the FIXME in the impl of `AstValidator`. Better bound checks by adding `BoundCtxt` type parameter to `visit_param_bound` cc `@ecstatic-morse`
2 parents 756ffb8 + 38bd4fb commit 7417110

File tree

5 files changed

+78
-56
lines changed

5 files changed

+78
-56
lines changed

compiler/rustc_ast/src/visit.rs

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

35+
#[derive(Copy, Clone, Debug)]
36+
pub enum BoundKind {
37+
/// Trait bounds in generics bounds and type/trait alias.
38+
/// E.g., `<T: Bound>`, `type A: Bound`, or `where T: Bound`.
39+
Bound,
40+
41+
/// Trait bounds in `impl` type.
42+
/// E.g., `type Foo = impl Bound1 + Bound2 + Bound3`.
43+
Impl,
44+
45+
/// Trait bounds in trait object type.
46+
/// E.g., `dyn Bound1 + Bound2 + Bound3`.
47+
TraitObject,
48+
49+
/// Super traits of a trait.
50+
/// E.g., `trait A: B`
51+
SuperTraits,
52+
}
53+
3554
#[derive(Copy, Clone, Debug)]
3655
pub enum FnKind<'a> {
3756
/// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`.
@@ -139,7 +158,7 @@ pub trait Visitor<'ast>: Sized {
139158
fn visit_trait_ref(&mut self, t: &'ast TraitRef) {
140159
walk_trait_ref(self, t)
141160
}
142-
fn visit_param_bound(&mut self, bounds: &'ast GenericBound) {
161+
fn visit_param_bound(&mut self, bounds: &'ast GenericBound, _ctxt: BoundKind) {
143162
walk_param_bound(self, bounds)
144163
}
145164
fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef, m: &'ast TraitBoundModifier) {
@@ -311,7 +330,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
311330
ItemKind::GlobalAsm(ref asm) => walk_inline_asm(visitor, asm),
312331
ItemKind::TyAlias(box TyAlias { ref generics, ref bounds, ref ty, .. }) => {
313332
visitor.visit_generics(generics);
314-
walk_list!(visitor, visit_param_bound, bounds);
333+
walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
315334
walk_list!(visitor, visit_ty, ty);
316335
}
317336
ItemKind::Enum(ref enum_definition, ref generics) => {
@@ -346,12 +365,12 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
346365
ref items,
347366
}) => {
348367
visitor.visit_generics(generics);
349-
walk_list!(visitor, visit_param_bound, bounds);
368+
walk_list!(visitor, visit_param_bound, bounds, BoundKind::SuperTraits);
350369
walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Trait);
351370
}
352371
ItemKind::TraitAlias(ref generics, ref bounds) => {
353372
visitor.visit_generics(generics);
354-
walk_list!(visitor, visit_param_bound, bounds);
373+
walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
355374
}
356375
ItemKind::MacCall(ref mac) => visitor.visit_mac_call(mac),
357376
ItemKind::MacroDef(ref ts) => visitor.visit_mac_def(ts, item.id),
@@ -416,8 +435,11 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) {
416435
visitor.visit_ty(ty);
417436
visitor.visit_anon_const(length)
418437
}
419-
TyKind::TraitObject(ref bounds, ..) | TyKind::ImplTrait(_, ref bounds) => {
420-
walk_list!(visitor, visit_param_bound, bounds);
438+
TyKind::TraitObject(ref bounds, ..) => {
439+
walk_list!(visitor, visit_param_bound, bounds, BoundKind::TraitObject);
440+
}
441+
TyKind::ImplTrait(_, ref bounds) => {
442+
walk_list!(visitor, visit_param_bound, bounds, BoundKind::Impl);
421443
}
422444
TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression),
423445
TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err => {}
@@ -503,7 +525,7 @@ pub fn walk_assoc_constraint<'a, V: Visitor<'a>>(visitor: &mut V, constraint: &'
503525
Term::Const(c) => visitor.visit_anon_const(c),
504526
},
505527
AssocConstraintKind::Bound { ref bounds } => {
506-
walk_list!(visitor, visit_param_bound, bounds);
528+
walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
507529
}
508530
}
509531
}
@@ -566,7 +588,7 @@ pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignI
566588
}
567589
ForeignItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => {
568590
visitor.visit_generics(generics);
569-
walk_list!(visitor, visit_param_bound, bounds);
591+
walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
570592
walk_list!(visitor, visit_ty, ty);
571593
}
572594
ForeignItemKind::MacCall(mac) => {
@@ -585,7 +607,7 @@ pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericB
585607
pub fn walk_generic_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a GenericParam) {
586608
visitor.visit_ident(param.ident);
587609
walk_list!(visitor, visit_attribute, param.attrs.iter());
588-
walk_list!(visitor, visit_param_bound, &param.bounds);
610+
walk_list!(visitor, visit_param_bound, &param.bounds, BoundKind::Bound);
589611
match param.kind {
590612
GenericParamKind::Lifetime => (),
591613
GenericParamKind::Type { ref default } => walk_list!(visitor, visit_ty, default),
@@ -612,14 +634,14 @@ pub fn walk_where_predicate<'a, V: Visitor<'a>>(visitor: &mut V, predicate: &'a
612634
..
613635
}) => {
614636
visitor.visit_ty(bounded_ty);
615-
walk_list!(visitor, visit_param_bound, bounds);
637+
walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
616638
walk_list!(visitor, visit_generic_param, bound_generic_params);
617639
}
618640
WherePredicate::RegionPredicate(WhereRegionPredicate {
619641
ref lifetime, ref bounds, ..
620642
}) => {
621643
visitor.visit_lifetime(lifetime);
622-
walk_list!(visitor, visit_param_bound, bounds);
644+
walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
623645
}
624646
WherePredicate::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty, .. }) => {
625647
visitor.visit_ty(lhs_ty);
@@ -672,7 +694,7 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem,
672694
}
673695
AssocItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => {
674696
visitor.visit_generics(generics);
675-
walk_list!(visitor, visit_param_bound, bounds);
697+
walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
676698
walk_list!(visitor, visit_ty, ty);
677699
}
678700
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, BoundKind, 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, BoundKind::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: BoundKind) {
1463+
if let GenericBound::Trait(ref poly, modify) = *bound {
1464+
match (ctxt, modify) {
1465+
(BoundKind::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+
(BoundKind::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, BoundKind::Bound);
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: BoundKind) {
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::BoundKind;
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: BoundKind) {
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, BoundKind, 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, BoundKind::Bound)
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, BoundKind::Bound);
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, BoundKind::Bound);
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, BoundKind::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, BoundKind::Bound);
15841584
},
15851585
);
15861586
},

0 commit comments

Comments
 (0)