about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_ast/src/visit.rs46
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs71
-rw-r--r--compiler/rustc_ast_passes/src/node_count.rs2
-rw-r--r--compiler/rustc_passes/src/hir_stats.rs3
-rw-r--r--compiler/rustc_resolve/src/late.rs12
5 files changed, 78 insertions, 56 deletions
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index d925c6dd354..e08ba73e0ae 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -33,6 +33,25 @@ pub enum FnCtxt {
 }
 
 #[derive(Copy, Clone, Debug)]
+pub enum BoundKind {
+    /// Trait bounds in generics bounds and type/trait alias.
+    /// E.g., `<T: Bound>`, `type A: Bound`, or `where T: Bound`.
+    Bound,
+
+    /// Trait bounds in `impl` type.
+    /// E.g., `type Foo = impl Bound1 + Bound2 + Bound3`.
+    Impl,
+
+    /// Trait bounds in trait object type.
+    /// E.g., `dyn Bound1 + Bound2 + Bound3`.
+    TraitObject,
+
+    /// Super traits of a trait.
+    /// E.g., `trait A: B`
+    SuperTraits,
+}
+
+#[derive(Copy, Clone, Debug)]
 pub enum FnKind<'a> {
     /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`.
     Fn(FnCtxt, Ident, &'a FnSig, &'a Visibility, &'a Generics, Option<&'a Block>),
@@ -139,7 +158,7 @@ pub trait Visitor<'ast>: Sized {
     fn visit_trait_ref(&mut self, t: &'ast TraitRef) {
         walk_trait_ref(self, t)
     }
-    fn visit_param_bound(&mut self, bounds: &'ast GenericBound) {
+    fn visit_param_bound(&mut self, bounds: &'ast GenericBound, _ctxt: BoundKind) {
         walk_param_bound(self, bounds)
     }
     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) {
         ItemKind::GlobalAsm(ref asm) => walk_inline_asm(visitor, asm),
         ItemKind::TyAlias(box TyAlias { ref generics, ref bounds, ref ty, .. }) => {
             visitor.visit_generics(generics);
-            walk_list!(visitor, visit_param_bound, bounds);
+            walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
             walk_list!(visitor, visit_ty, ty);
         }
         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) {
             ref items,
         }) => {
             visitor.visit_generics(generics);
-            walk_list!(visitor, visit_param_bound, bounds);
+            walk_list!(visitor, visit_param_bound, bounds, BoundKind::SuperTraits);
             walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Trait);
         }
         ItemKind::TraitAlias(ref generics, ref bounds) => {
             visitor.visit_generics(generics);
-            walk_list!(visitor, visit_param_bound, bounds);
+            walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
         }
         ItemKind::MacCall(ref mac) => visitor.visit_mac_call(mac),
         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) {
             visitor.visit_ty(ty);
             visitor.visit_anon_const(length)
         }
-        TyKind::TraitObject(ref bounds, ..) | TyKind::ImplTrait(_, ref bounds) => {
-            walk_list!(visitor, visit_param_bound, bounds);
+        TyKind::TraitObject(ref bounds, ..) => {
+            walk_list!(visitor, visit_param_bound, bounds, BoundKind::TraitObject);
+        }
+        TyKind::ImplTrait(_, ref bounds) => {
+            walk_list!(visitor, visit_param_bound, bounds, BoundKind::Impl);
         }
         TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression),
         TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err => {}
@@ -503,7 +525,7 @@ pub fn walk_assoc_constraint<'a, V: Visitor<'a>>(visitor: &mut V, constraint: &'
             Term::Const(c) => visitor.visit_anon_const(c),
         },
         AssocConstraintKind::Bound { ref bounds } => {
-            walk_list!(visitor, visit_param_bound, bounds);
+            walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
         }
     }
 }
@@ -566,7 +588,7 @@ pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignI
         }
         ForeignItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => {
             visitor.visit_generics(generics);
-            walk_list!(visitor, visit_param_bound, bounds);
+            walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
             walk_list!(visitor, visit_ty, ty);
         }
         ForeignItemKind::MacCall(mac) => {
@@ -585,7 +607,7 @@ pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericB
 pub fn walk_generic_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a GenericParam) {
     visitor.visit_ident(param.ident);
     walk_list!(visitor, visit_attribute, param.attrs.iter());
-    walk_list!(visitor, visit_param_bound, &param.bounds);
+    walk_list!(visitor, visit_param_bound, &param.bounds, BoundKind::Bound);
     match param.kind {
         GenericParamKind::Lifetime => (),
         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
             ..
         }) => {
             visitor.visit_ty(bounded_ty);
-            walk_list!(visitor, visit_param_bound, bounds);
+            walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
             walk_list!(visitor, visit_generic_param, bound_generic_params);
         }
         WherePredicate::RegionPredicate(WhereRegionPredicate {
             ref lifetime, ref bounds, ..
         }) => {
             visitor.visit_lifetime(lifetime);
-            walk_list!(visitor, visit_param_bound, bounds);
+            walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
         }
         WherePredicate::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty, .. }) => {
             visitor.visit_ty(lhs_ty);
@@ -672,7 +694,7 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem,
         }
         AssocItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => {
             visitor.visit_generics(generics);
-            walk_list!(visitor, visit_param_bound, bounds);
+            walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
             walk_list!(visitor, visit_ty, ty);
         }
         AssocItemKind::MacCall(mac) => {
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 8d815e95528..058a0f975a7 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -8,7 +8,7 @@
 
 use itertools::{Either, Itertools};
 use rustc_ast::ptr::P;
-use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
+use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor};
 use rustc_ast::walk_list;
 use rustc_ast::*;
 use rustc_ast_pretty::pprust::{self, State};
@@ -345,23 +345,6 @@ impl<'a> AstValidator<'a> {
         }
     }
 
-    // FIXME(ecstaticmorse): Instead, use `bound_context` to check this in `visit_param_bound`.
-    fn no_questions_in_bounds(&self, bounds: &GenericBounds, where_: &str, is_trait: bool) {
-        for bound in bounds {
-            if let GenericBound::Trait(ref poly, TraitBoundModifier::Maybe) = *bound {
-                let mut err = self.err_handler().struct_span_err(
-                    poly.span,
-                    &format!("`?Trait` is not permitted in {}", where_),
-                );
-                if is_trait {
-                    let path_str = pprust::path_to_string(&poly.trait_ref.path);
-                    err.note(&format!("traits are `?{}` by default", path_str));
-                }
-                err.emit();
-            }
-        }
-    }
-
     fn check_late_bound_lifetime_defs(&self, params: &[GenericParam]) {
         // Check only lifetime parameters are present and that the lifetime
         // parameters that are present have no bounds.
@@ -873,7 +856,6 @@ impl<'a> AstValidator<'a> {
                         any_lifetime_bounds = true;
                     }
                 }
-                self.no_questions_in_bounds(bounds, "trait object types", false);
             }
             TyKind::ImplTrait(_, ref bounds) => {
                 if self.is_impl_trait_banned {
@@ -1242,14 +1224,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                     self.deny_where_clause(&generics.where_clause, item.ident.span);
                     self.deny_items(items, item.ident.span);
                 }
-                self.no_questions_in_bounds(bounds, "supertraits", true);
 
                 // Equivalent of `visit::walk_item` for `ItemKind::Trait` that inserts a bound
                 // context for the supertraits.
                 self.visit_vis(&item.vis);
                 self.visit_ident(item.ident);
                 self.visit_generics(generics);
-                self.with_banned_tilde_const(|this| walk_list!(this, visit_param_bound, bounds));
+                self.with_banned_tilde_const(|this| {
+                    walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits)
+                });
                 walk_list!(self, visit_assoc_item, items, AssocCtxt::Trait);
                 walk_list!(self, visit_attribute, &item.attrs);
                 return;
@@ -1476,23 +1459,39 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
         visit::walk_generic_param(self, param);
     }
 
-    fn visit_param_bound(&mut self, bound: &'a GenericBound) {
-        match bound {
-            GenericBound::Trait(_, TraitBoundModifier::MaybeConst) => {
-                if !self.is_tilde_const_allowed {
+    fn visit_param_bound(&mut self, bound: &'a GenericBound, ctxt: BoundKind) {
+        if let GenericBound::Trait(ref poly, modify) = *bound {
+            match (ctxt, modify) {
+                (BoundKind::SuperTraits, TraitBoundModifier::Maybe) => {
+                    let mut err = self.err_handler().struct_span_err(
+                        poly.span,
+                        &format!("`?Trait` is not permitted in supertraits"),
+                    );
+                    let path_str = pprust::path_to_string(&poly.trait_ref.path);
+                    err.note(&format!("traits are `?{}` by default", path_str));
+                    err.emit();
+                }
+                (BoundKind::TraitObject, TraitBoundModifier::Maybe) => {
+                    let mut err = self.err_handler().struct_span_err(
+                        poly.span,
+                        &format!("`?Trait` is not permitted in trait object types"),
+                    );
+                    err.emit();
+                }
+                (_, TraitBoundModifier::MaybeConst) => {
+                    if !self.is_tilde_const_allowed {
+                        self.err_handler()
+                            .struct_span_err(bound.span(), "`~const` is not allowed here")
+                            .note("only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions")
+                            .emit();
+                    }
+                }
+                (_, TraitBoundModifier::MaybeConstMaybe) => {
                     self.err_handler()
-                        .struct_span_err(bound.span(), "`~const` is not allowed here")
-                        .note("only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions")
-                        .emit();
+                        .span_err(bound.span(), "`~const` and `?` are mutually exclusive");
                 }
+                _ => {}
             }
-
-            GenericBound::Trait(_, TraitBoundModifier::MaybeConstMaybe) => {
-                self.err_handler()
-                    .span_err(bound.span(), "`~const` and `?` are mutually exclusive");
-            }
-
-            _ => {}
         }
 
         visit::walk_param_bound(self, bound)
@@ -1662,7 +1661,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 walk_list!(self, visit_attribute, &item.attrs);
                 self.with_tilde_const_allowed(|this| {
                     this.visit_generics(generics);
-                    walk_list!(this, visit_param_bound, bounds);
+                    walk_list!(this, visit_param_bound, bounds, BoundKind::Bound);
                 });
                 walk_list!(self, visit_ty, ty);
             }
diff --git a/compiler/rustc_ast_passes/src/node_count.rs b/compiler/rustc_ast_passes/src/node_count.rs
index a4a48cc8e8a..48b79809c1b 100644
--- a/compiler/rustc_ast_passes/src/node_count.rs
+++ b/compiler/rustc_ast_passes/src/node_count.rs
@@ -76,7 +76,7 @@ impl<'ast> Visitor<'ast> for NodeCounter {
         self.count += 1;
         walk_trait_ref(self, t)
     }
-    fn visit_param_bound(&mut self, bounds: &GenericBound) {
+    fn visit_param_bound(&mut self, bounds: &GenericBound, _ctxt: BoundKind) {
         self.count += 1;
         walk_param_bound(self, bounds)
     }
diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs
index 6cf1aa480d2..237a8abfabe 100644
--- a/compiler/rustc_passes/src/hir_stats.rs
+++ b/compiler/rustc_passes/src/hir_stats.rs
@@ -3,6 +3,7 @@
 // completely accurate (some things might be counted twice, others missed).
 
 use rustc_ast::visit as ast_visit;
+use rustc_ast::visit::BoundKind;
 use rustc_ast::{self as ast, AttrId, NodeId};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir as hir;
@@ -302,7 +303,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
         ast_visit::walk_assoc_item(self, item, ctxt);
     }
 
-    fn visit_param_bound(&mut self, bounds: &'v ast::GenericBound) {
+    fn visit_param_bound(&mut self, bounds: &'v ast::GenericBound, _ctxt: BoundKind) {
         self.record("GenericBound", Id::None, bounds);
         ast_visit::walk_param_bound(self, bounds)
     }
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 7635ad9bd87..50055f8030c 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -12,7 +12,7 @@ use crate::{Module, ModuleOrUniformRoot, NameBinding, ParentScope, PathResult};
 use crate::{ResolutionError, Resolver, Segment, UseError};
 
 use rustc_ast::ptr::P;
-use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
+use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor};
 use rustc_ast::*;
 use rustc_ast_lowering::ResolverAstLowering;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -835,7 +835,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
                         this.visit_generic_param_vec(&bound_generic_params, false);
                         this.visit_ty(bounded_ty);
                         for bound in bounds {
-                            this.visit_param_bound(bound)
+                            this.visit_param_bound(bound, BoundKind::Bound)
                         }
                     },
                 );
@@ -1026,12 +1026,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                 match param.kind {
                     GenericParamKind::Lifetime => {
                         for bound in &param.bounds {
-                            this.visit_param_bound(bound);
+                            this.visit_param_bound(bound, BoundKind::Bound);
                         }
                     }
                     GenericParamKind::Type { ref default } => {
                         for bound in &param.bounds {
-                            this.visit_param_bound(bound);
+                            this.visit_param_bound(bound, BoundKind::Bound);
                         }
 
                         if let Some(ref ty) = default {
@@ -1496,7 +1496,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                             Res::SelfTy { trait_: Some(local_def_id), alias_to: None },
                             |this| {
                                 this.visit_generics(generics);
-                                walk_list!(this, visit_param_bound, bounds);
+                                walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits);
 
                                 let walk_assoc_item =
                                     |this: &mut Self,
@@ -1580,7 +1580,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                             Res::SelfTy { trait_: Some(local_def_id), alias_to: None },
                             |this| {
                                 this.visit_generics(generics);
-                                walk_list!(this, visit_param_bound, bounds);
+                                walk_list!(this, visit_param_bound, bounds, BoundKind::Bound);
                             },
                         );
                     },