diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 8e4f4c8e71a2..4e688d66e38f 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -422,7 +422,27 @@ impl Default for WhereClause { /// A single predicate in a where-clause. #[derive(Clone, Encodable, Decodable, Debug)] -pub enum WherePredicate { +pub struct WherePredicate { + pub attrs: AttrVec, + pub kind: WherePredicateKind, + pub id: NodeId, +} + +impl WherePredicate { + pub fn with_kind(&self, kind: WherePredicateKind) -> WherePredicate { + self.map_kind(|_| kind) + } + pub fn map_kind( + &self, + f: impl FnOnce(&WherePredicateKind) -> WherePredicateKind, + ) -> WherePredicate { + WherePredicate { attrs: self.attrs.clone(), kind: f(&self.kind), id: DUMMY_NODE_ID } + } +} + +/// Predicate kind in where-clause. +#[derive(Clone, Encodable, Decodable, Debug)] +pub enum WherePredicateKind { /// A type bound (e.g., `for<'c> Foo: Send + Clone + 'c`). BoundPredicate(WhereBoundPredicate), /// A lifetime predicate (e.g., `'a: 'b + 'c`). @@ -431,12 +451,12 @@ pub enum WherePredicate { EqPredicate(WhereEqPredicate), } -impl WherePredicate { +impl WherePredicateKind { pub fn span(&self) -> Span { match self { - WherePredicate::BoundPredicate(p) => p.span, - WherePredicate::RegionPredicate(p) => p.span, - WherePredicate::EqPredicate(p) => p.span, + WherePredicateKind::BoundPredicate(p) => p.span, + WherePredicateKind::RegionPredicate(p) => p.span, + WherePredicateKind::EqPredicate(p) => p.span, } } } diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs index 60f8c6e10481..c4d16e80cad2 100644 --- a/compiler/rustc_ast/src/ast_traits.rs +++ b/compiler/rustc_ast/src/ast_traits.rs @@ -11,7 +11,7 @@ use crate::tokenstream::LazyAttrTokenStream; use crate::{ Arm, AssocItem, AttrItem, AttrKind, AttrVec, Attribute, Block, Crate, Expr, ExprField, FieldDef, ForeignItem, GenericParam, Item, NodeId, Param, Pat, PatField, Path, Stmt, StmtKind, - Ty, Variant, Visibility, + Ty, Variant, Visibility, WherePredicate, }; /// A utility trait to reduce boilerplate. @@ -79,6 +79,7 @@ impl_has_node_id!( Stmt, Ty, Variant, + WherePredicate, ); impl> HasNodeId for T { @@ -127,7 +128,16 @@ macro_rules! impl_has_tokens_none { } impl_has_tokens!(AssocItem, AttrItem, Block, Expr, ForeignItem, Item, Pat, Path, Ty, Visibility); -impl_has_tokens_none!(Arm, ExprField, FieldDef, GenericParam, Param, PatField, Variant); +impl_has_tokens_none!( + Arm, + ExprField, + FieldDef, + GenericParam, + Param, + PatField, + Variant, + WherePredicate +); impl> HasTokens for T { fn tokens(&self) -> Option<&LazyAttrTokenStream> { @@ -289,6 +299,7 @@ impl_has_attrs!( Param, PatField, Variant, + WherePredicate, ); impl_has_attrs_none!(Attribute, AttrItem, Block, Pat, Path, Ty, Visibility); diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 2afbd979c302..e10a3e635d62 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -286,8 +286,11 @@ pub trait MutVisitor: Sized { walk_where_clause(self, where_clause); } - fn visit_where_predicate(&mut self, where_predicate: &mut WherePredicate) { - walk_where_predicate(self, where_predicate); + fn filter_map_where_predicate( + &mut self, + where_predicate: WherePredicate, + ) -> Option { + walk_filter_map_where_predicate(self, where_predicate) } fn visit_vis(&mut self, vis: &mut Visibility) { @@ -987,32 +990,39 @@ fn walk_ty_alias_where_clauses(vis: &mut T, tawcs: &mut TyAliasWh fn walk_where_clause(vis: &mut T, wc: &mut WhereClause) { let WhereClause { has_where_token: _, predicates, span } = wc; - visit_thin_vec(predicates, |predicate| vis.visit_where_predicate(predicate)); + predicates.flat_map_in_place(|predicate| vis.filter_map_where_predicate(predicate)); vis.visit_span(span); } -fn walk_where_predicate(vis: &mut T, pred: &mut WherePredicate) { - match pred { - WherePredicate::BoundPredicate(bp) => { +pub fn walk_filter_map_where_predicate( + vis: &mut T, + mut pred: WherePredicate, +) -> Option { + let WherePredicate { ref mut attrs, ref mut kind, ref mut id } = pred; + vis.visit_id(id); + visit_attrs(vis, attrs); + match kind { + WherePredicateKind::BoundPredicate(bp) => { let WhereBoundPredicate { span, bound_generic_params, bounded_ty, bounds } = bp; bound_generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param)); vis.visit_ty(bounded_ty); visit_vec(bounds, |bound| vis.visit_param_bound(bound, BoundKind::Bound)); vis.visit_span(span); } - WherePredicate::RegionPredicate(rp) => { + WherePredicateKind::RegionPredicate(rp) => { let WhereRegionPredicate { span, lifetime, bounds } = rp; vis.visit_lifetime(lifetime); visit_vec(bounds, |bound| vis.visit_param_bound(bound, BoundKind::Bound)); vis.visit_span(span); } - WherePredicate::EqPredicate(ep) => { + WherePredicateKind::EqPredicate(ep) => { let WhereEqPredicate { span, lhs_ty, rhs_ty } = ep; vis.visit_ty(lhs_ty); vis.visit_ty(rhs_ty); vis.visit_span(span); } } + Some(pred) } fn walk_variant_data(vis: &mut T, vdata: &mut VariantData) { diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index eb71ec5f4ec9..76b5151544ea 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -786,8 +786,10 @@ pub fn walk_where_predicate<'a, V: Visitor<'a>>( visitor: &mut V, predicate: &'a WherePredicate, ) -> V::Result { - match predicate { - WherePredicate::BoundPredicate(WhereBoundPredicate { + let WherePredicate { attrs, kind, id: _ } = predicate; + walk_list!(visitor, visit_attribute, attrs); + match kind { + WherePredicateKind::BoundPredicate(WhereBoundPredicate { bounded_ty, bounds, bound_generic_params, @@ -797,11 +799,11 @@ pub fn walk_where_predicate<'a, V: Visitor<'a>>( try_visit!(visitor.visit_ty(bounded_ty)); walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); } - WherePredicate::RegionPredicate(WhereRegionPredicate { lifetime, bounds, span: _ }) => { + WherePredicateKind::RegionPredicate(WhereRegionPredicate { lifetime, bounds, span: _ }) => { try_visit!(visitor.visit_lifetime(lifetime, LifetimeCtxt::Bound)); walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); } - WherePredicate::EqPredicate(WhereEqPredicate { lhs_ty, rhs_ty, span: _ }) => { + WherePredicateKind::EqPredicate(WhereEqPredicate { lhs_ty, rhs_ty, span: _ }) => { try_visit!(visitor.visit_ty(lhs_ty)); try_visit!(visitor.visit_ty(rhs_ty)); } diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index 6289966561f5..7525a352201e 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -381,8 +381,9 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_where_predicate(&mut self, predicate: &'hir WherePredicate<'hir>) { - match predicate { - WherePredicate::BoundPredicate(pred) => { + self.insert(predicate.span(), predicate.hir_id, Node::WherePredicate(predicate)); + match predicate.kind { + WherePredicateKind::BoundPredicate(pred) => { self.insert(pred.span, pred.hir_id, Node::WhereBoundPredicate(pred)); self.with_parent(pred.hir_id, |this| { intravisit::walk_where_predicate(this, predicate) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index d72456075011..64f3e73cc4b8 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1400,7 +1400,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // keep track of the Span info. Now, `::add_implicit_sized_bound` // checks both param bounds and where clauses for `?Sized`. for pred in &generics.where_clause.predicates { - let WherePredicate::BoundPredicate(bound_pred) = pred else { + let WherePredicateKind::BoundPredicate(ref bound_pred) = pred.kind else { continue; }; let compute_is_param = || { @@ -1538,8 +1538,8 @@ impl<'hir> LoweringContext<'_, 'hir> { }); let span = self.lower_span(span); - match kind { - GenericParamKind::Const { .. } => None, + let kind = match kind { + GenericParamKind::Const { .. } => return None, GenericParamKind::Type { .. } => { let def_id = self.local_def_id(id).to_def_id(); let hir_id = self.next_id(); @@ -1554,37 +1554,40 @@ impl<'hir> LoweringContext<'_, 'hir> { let ty_id = self.next_id(); let bounded_ty = self.ty_path(ty_id, param_span, hir::QPath::Resolved(None, ty_path)); - Some(hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { + hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate { hir_id: self.next_id(), bounded_ty: self.arena.alloc(bounded_ty), bounds, span, bound_generic_params: &[], origin, - })) + }) } GenericParamKind::Lifetime => { let ident = self.lower_ident(ident); let lt_id = self.next_node_id(); let lifetime = self.new_named_lifetime(id, lt_id, ident); - Some(hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate { + hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate { lifetime, span, bounds, in_where_clause: false, - })) + }) } - } + }; + Some(hir::WherePredicate { hir_id: self.next_id(), kind: self.arena.alloc(kind) }) } fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicate<'hir> { - match pred { - WherePredicate::BoundPredicate(WhereBoundPredicate { + let hir_id = self.lower_node_id(pred.id); + self.lower_attrs(hir_id, &pred.attrs); + let kind = match &pred.kind { + WherePredicateKind::BoundPredicate(WhereBoundPredicate { bound_generic_params, bounded_ty, bounds, span, - }) => hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { + }) => hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate { hir_id: self.next_id(), bound_generic_params: self .lower_generic_params(bound_generic_params, hir::GenericParamSource::Binder), @@ -1597,19 +1600,21 @@ impl<'hir> LoweringContext<'_, 'hir> { span: self.lower_span(*span), origin: PredicateOrigin::WhereClause, }), - WherePredicate::RegionPredicate(WhereRegionPredicate { lifetime, bounds, span }) => { - hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate { - span: self.lower_span(*span), - lifetime: self.lower_lifetime(lifetime), - bounds: self.lower_param_bounds( - bounds, - ImplTraitContext::Disallowed(ImplTraitPosition::Bound), - ), - in_where_clause: true, - }) - } - WherePredicate::EqPredicate(WhereEqPredicate { lhs_ty, rhs_ty, span }) => { - hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { + WherePredicateKind::RegionPredicate(WhereRegionPredicate { + lifetime, + bounds, + span, + }) => hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate { + span: self.lower_span(*span), + lifetime: self.lower_lifetime(lifetime), + bounds: self.lower_param_bounds( + bounds, + ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + ), + in_where_clause: true, + }), + WherePredicateKind::EqPredicate(WhereEqPredicate { lhs_ty, rhs_ty, span }) => { + hir::WherePredicateKind::EqPredicate(hir::WhereEqPredicate { lhs_ty: self .lower_ty(lhs_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Bound)), rhs_ty: self @@ -1617,6 +1622,8 @@ impl<'hir> LoweringContext<'_, 'hir> { span: self.lower_span(*span), }) } - } + }; + let kind = self.arena.alloc(kind); + hir::WherePredicate { hir_id, kind } } } diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 0a4f86d4822f..8b7e832d9e3e 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1202,14 +1202,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> { validate_generic_param_order(self.dcx(), &generics.params, generics.span); for predicate in &generics.where_clause.predicates { - if let WherePredicate::EqPredicate(predicate) = predicate { + if let WherePredicateKind::EqPredicate(ref predicate) = predicate.kind { deny_equality_constraints(self, predicate, generics); } } walk_list!(self, visit_generic_param, &generics.params); for predicate in &generics.where_clause.predicates { - match predicate { - WherePredicate::BoundPredicate(bound_pred) => { + match predicate.kind { + WherePredicateKind::BoundPredicate(ref bound_pred) => { // 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, @@ -1593,18 +1593,18 @@ fn deny_equality_constraints( let mut preds = generics.where_clause.predicates.iter().peekable(); // Find the predicate that shouldn't have been in the where bound list. while let Some(pred) = preds.next() { - if let WherePredicate::EqPredicate(pred) = pred + if let WherePredicateKind::EqPredicate(ref pred) = pred.kind && pred.span == predicate.span { if let Some(next) = preds.peek() { // This is the first predicate, remove the trailing comma as well. - span = span.with_hi(next.span().lo()); + span = span.with_hi(next.kind.span().lo()); } else if let Some(prev) = prev { // Remove the previous comma as well. span = span.with_lo(prev.hi()); } } - prev = Some(pred.span()); + prev = Some(pred.kind.span()); } span }; @@ -1621,8 +1621,8 @@ fn deny_equality_constraints( if let TyKind::Path(None, full_path) = &predicate.lhs_ty.kind { // Given `A: Foo, Foo::Bar = RhsTy`, suggest `A: Foo`. for bounds in generics.params.iter().map(|p| &p.bounds).chain( - generics.where_clause.predicates.iter().filter_map(|pred| match pred { - WherePredicate::BoundPredicate(p) => Some(&p.bounds), + generics.where_clause.predicates.iter().filter_map(|pred| match pred.kind { + WherePredicateKind::BoundPredicate(ref p) => Some(&p.bounds), _ => None, }), ) { @@ -1645,8 +1645,8 @@ fn deny_equality_constraints( // Given `A: Foo, A::Bar = RhsTy`, suggest `A: Foo`. if let [potential_param, potential_assoc] = &full_path.segments[..] { for (ident, bounds) in generics.params.iter().map(|p| (p.ident, &p.bounds)).chain( - generics.where_clause.predicates.iter().filter_map(|pred| match pred { - WherePredicate::BoundPredicate(p) + generics.where_clause.predicates.iter().filter_map(|pred| match pred.kind { + WherePredicateKind::BoundPredicate(ref p) if let ast::TyKind::Path(None, path) = &p.bounded_ty.kind && let [segment] = &path.segments[..] => { diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index d646150a620c..089eaae4ad00 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -344,8 +344,9 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { fn visit_generics(&mut self, g: &'a ast::Generics) { for predicate in &g.where_clause.predicates { - match predicate { - ast::WherePredicate::BoundPredicate(bound_pred) => { + visit::walk_list!(self, visit_attribute, &predicate.attrs); + match predicate.kind { + ast::WherePredicateKind::BoundPredicate(ref bound_pred) => { // A type bound (e.g., `for<'c> Foo: Send + Clone + 'c`). self.check_late_bound_lifetime_defs(&bound_pred.bound_generic_params); } diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 8279c66836c0..81e1e1a27828 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -726,11 +726,14 @@ impl<'a> State<'a> { } pub fn print_where_predicate(&mut self, predicate: &ast::WherePredicate) { - match predicate { - ast::WherePredicate::BoundPredicate(where_bound_predicate) => { + let &ast::WherePredicate { ref attrs, ref kind, id } = predicate; + self.ann.pre(self, AnnNode::SubItem(id)); + self.print_outer_attributes(attrs); + match kind { + ast::WherePredicateKind::BoundPredicate(where_bound_predicate) => { self.print_where_bound_predicate(where_bound_predicate); } - ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { + ast::WherePredicateKind::RegionPredicate(ast::WhereRegionPredicate { lifetime, bounds, .. @@ -742,13 +745,16 @@ impl<'a> State<'a> { self.print_lifetime_bounds(bounds); } } - ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { lhs_ty, rhs_ty, .. }) => { + ast::WherePredicateKind::EqPredicate(ast::WhereEqPredicate { + lhs_ty, rhs_ty, .. + }) => { self.print_type(lhs_ty); self.space(); self.word_space("="); self.print_type(rhs_ty); } } + self.ann.post(self, AnnNode::SubItem(id)); } pub(crate) fn print_where_bound_predicate( diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 801c7af2de70..76bb89640256 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -1061,8 +1061,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { && let spans = hir_generics .predicates .iter() - .filter_map(|pred| match pred { - hir::WherePredicate::BoundPredicate(pred) => Some(pred), + .filter_map(|pred| match pred.kind { + hir::WherePredicateKind::BoundPredicate(pred) => Some(pred), _ => None, }) .filter(|pred| { diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 6333d59a1bc8..634eedd3d62a 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -5,7 +5,7 @@ use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::GenericBound::Trait; use rustc_hir::QPath::Resolved; -use rustc_hir::WherePredicate::BoundPredicate; +use rustc_hir::WherePredicateKind::BoundPredicate; use rustc_hir::def::Res::Def; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; @@ -236,7 +236,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let mut hrtb_bounds = vec![]; gat_id_and_generics.iter().flatten().for_each(|(gat_hir_id, generics)| { for pred in generics.predicates { - let BoundPredicate(WhereBoundPredicate { bound_generic_params, bounds, .. }) = pred + let BoundPredicate(WhereBoundPredicate { bound_generic_params, bounds, .. }) = + pred.kind else { continue; }; @@ -272,7 +273,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { bounded_ty, bounds, .. - }) = predicate + }) = predicate.kind else { return; }; diff --git a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs index 53e938ee216b..9a37d0409884 100644 --- a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs +++ b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs @@ -288,21 +288,25 @@ pub(crate) fn expand_deriving_coerce_pointee( // // We should also write a few new `where` bounds from `#[pointee] T` to `__S` // as well as any bound that indirectly involves the `#[pointee] T` type. - for bound in &generics.where_clause.predicates { - if let ast::WherePredicate::BoundPredicate(bound) = bound { + for predicate in &generics.where_clause.predicates { + if let ast::WherePredicateKind::BoundPredicate(ref bound) = predicate.kind { let mut substitution = TypeSubstitution { from_name: pointee_ty_ident.name, to_ty: &s_ty, rewritten: false, }; - let mut predicate = ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { - span: bound.span, - bound_generic_params: bound.bound_generic_params.clone(), - bounded_ty: bound.bounded_ty.clone(), - bounds: bound.bounds.clone(), - }); - substitution.visit_where_predicate(&mut predicate); - if substitution.rewritten { + let predicate = predicate.with_kind(ast::WherePredicateKind::BoundPredicate( + ast::WhereBoundPredicate { + span: bound.span, + bound_generic_params: bound.bound_generic_params.clone(), + bounded_ty: bound.bounded_ty.clone(), + bounds: bound.bounds.clone(), + }, + )); + let predicate = substitution.filter_map_where_predicate(predicate); + if substitution.rewritten + && let Some(predicate) = predicate + { impl_generics.where_clause.predicates.push(predicate); } } @@ -319,7 +323,7 @@ pub(crate) fn expand_deriving_coerce_pointee( fn contains_maybe_sized_bound_on_pointee(predicates: &[WherePredicate], pointee: Symbol) -> bool { for bound in predicates { - if let ast::WherePredicate::BoundPredicate(bound) = bound + if let ast::WherePredicateKind::BoundPredicate(ref bound) = bound.kind && bound.bounded_ty.kind.is_simple_path().is_some_and(|name| name == pointee) { for bound in &bound.bounds { @@ -384,9 +388,12 @@ impl<'a> ast::mut_visit::MutVisitor for TypeSubstitution<'a> { } } - fn visit_where_predicate(&mut self, where_predicate: &mut ast::WherePredicate) { - match where_predicate { - rustc_ast::WherePredicate::BoundPredicate(bound) => { + fn filter_map_where_predicate( + &mut self, + mut where_predicate: ast::WherePredicate, + ) -> Option { + match where_predicate.kind { + rustc_ast::WherePredicateKind::BoundPredicate(ref mut bound) => { bound .bound_generic_params .flat_map_in_place(|param| self.flat_map_generic_param(param)); @@ -395,9 +402,10 @@ impl<'a> ast::mut_visit::MutVisitor for TypeSubstitution<'a> { self.visit_param_bound(bound, BoundKind::Bound) } } - rustc_ast::WherePredicate::RegionPredicate(_) - | rustc_ast::WherePredicate::EqPredicate(_) => {} + rustc_ast::WherePredicateKind::RegionPredicate(_) + | rustc_ast::WherePredicateKind::EqPredicate(_) => {} } + Some(where_predicate) } } diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 82baaca9a464..ccc5ef8094fc 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -684,26 +684,29 @@ impl<'a> TraitDef<'a> { // and similarly for where clauses where_clause.predicates.extend(generics.where_clause.predicates.iter().map(|clause| { - match clause { - ast::WherePredicate::BoundPredicate(wb) => { + clause.map_kind(|clause| match clause { + ast::WherePredicateKind::BoundPredicate(wb) => { let span = wb.span.with_ctxt(ctxt); - ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { + ast::WherePredicateKind::BoundPredicate(ast::WhereBoundPredicate { span, ..wb.clone() }) } - ast::WherePredicate::RegionPredicate(wr) => { + ast::WherePredicateKind::RegionPredicate(wr) => { let span = wr.span.with_ctxt(ctxt); - ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { + ast::WherePredicateKind::RegionPredicate(ast::WhereRegionPredicate { span, ..wr.clone() }) } - ast::WherePredicate::EqPredicate(we) => { + ast::WherePredicateKind::EqPredicate(we) => { let span = we.span.with_ctxt(ctxt); - ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { span, ..we.clone() }) + ast::WherePredicateKind::EqPredicate(ast::WhereEqPredicate { + span, + ..we.clone() + }) } - } + }) })); let ty_param_names: Vec = params @@ -757,7 +760,12 @@ impl<'a> TraitDef<'a> { bounds, }; - let predicate = ast::WherePredicate::BoundPredicate(predicate); + let kind = ast::WherePredicateKind::BoundPredicate(predicate); + let predicate = ast::WherePredicate { + attrs: ThinVec::new(), + kind, + id: ast::DUMMY_NODE_ID, + }; where_clause.predicates.push(predicate); } } diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl index f26c7c1ba0bc..5dd22ed42f96 100644 --- a/compiler/rustc_expand/messages.ftl +++ b/compiler/rustc_expand/messages.ftl @@ -21,6 +21,9 @@ expand_attributes_wrong_form = expand_cannot_be_name_of_macro = `{$trait_ident}` cannot be a name of {$macro_type} macro +expand_cfg_attribute_in_where_is_unstable = + `#[cfg]` attribute in `where` clause is unstable + expand_collapse_debuginfo_illegal = illegal value for attribute #[collapse_debuginfo(no|external|yes)] @@ -173,6 +176,10 @@ expand_resolve_relative_path = expand_trace_macro = trace_macro +expand_unsupported_attributes_in_where = + attributes in `where` clauses are not supported + .help = only `#[cfg]` is supported in where clauses + expand_unsupported_key_value = key-value macro attributes are not supported diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index 7bd7c3055391..1e425eb11bc3 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -1,6 +1,7 @@ use std::borrow::Cow; use rustc_ast::ast; +use rustc_errors::MultiSpan; use rustc_errors::codes::*; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_session::Limit; @@ -497,3 +498,11 @@ pub(crate) struct ProcMacroBackCompat { pub crate_name: String, pub fixed_version: String, } + +#[derive(Diagnostic)] +#[diag(expand_unsupported_attributes_in_where)] +#[help] +pub(crate) struct UnsupportedAttributesInWhere { + #[primary_span] + pub span: MultiSpan, +} diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 04ac7891023f..c84a4f3acfea 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -37,8 +37,8 @@ use crate::base::*; use crate::config::StripUnconfigured; use crate::errors::{ EmptyDelegationMac, GlobDelegationOutsideImpls, GlobDelegationTraitlessQpath, IncompleteParse, - RecursionLimitReached, RemoveExprNotSupported, RemoveNodeNotSupported, UnsupportedKeyValue, - WrongFragmentKind, + RecursionLimitReached, RemoveExprNotSupported, RemoveNodeNotSupported, + UnsupportedAttributesInWhere, UnsupportedKeyValue, WrongFragmentKind, }; use crate::fluent_generated; use crate::mbe::diagnostics::annotate_err_with_kind; @@ -2179,6 +2179,42 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { self.visit_node(node) } + fn filter_map_where_predicate( + &mut self, + mut pred: ast::WherePredicate, + ) -> Option { + if self.cx.ecfg.features.cfg_attribute_in_where() { + while let Some((attr, pos, _derives)) = self.take_first_attr(&mut pred) { + match attr.name_or_empty() { + sym::cfg => { + if !self.expand_cfg_true(&mut pred, attr, pos).0 { + return None; + } + } + _ => continue, + } + } + let spans = pred + .attrs + .iter() + .filter(|attr| attr.name_or_empty() != sym::cfg) + .map(|attr| attr.span) + .collect::>(); + if !spans.is_empty() { + self.cx.dcx().emit_err(UnsupportedAttributesInWhere { span: spans.into() }); + } + } else if !pred.attrs.is_empty() { + feature_err( + self.cx.sess, + sym::cfg_attribute_in_where, + pred.attrs.iter().map(|attr| attr.span).collect::>(), + fluent_generated::expand_cfg_attribute_in_where_is_unstable, + ) + .emit(); + } + assign_id!(self, &mut pred.id, || walk_filter_map_where_predicate(self, pred)) + } + fn visit_expr(&mut self, node: &mut P) { // FIXME: Feature gating is performed inconsistently between `Expr` and `OptExpr`. if let Some(attr) = node.attrs.first() { diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index a99d90488861..f877d361d2be 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -389,6 +389,8 @@ declare_features! ( (unstable, async_for_loop, "1.77.0", Some(118898)), /// Allows using C-variadics. (unstable, c_variadic, "1.34.0", Some(44930)), + /// Allows the use of `#[cfg]` in `where` clauses. + (unstable, cfg_attribute_in_where, "CURRENT_RUSTC_VERSION", Some(115590)), /// Allows the use of `#[cfg()]`. (unstable, cfg_boolean_literals, "1.83.0", Some(131204)), /// Allows the use of `#[cfg(overflow_checks)` to check if integer overflow behaviour. diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 12b01266a931..84ee423cbb96 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -714,8 +714,10 @@ impl<'hir> Generics<'hir> { &self, param_def_id: LocalDefId, ) -> impl Iterator> { - self.predicates.iter().filter_map(move |pred| match pred { - WherePredicate::BoundPredicate(bp) if bp.is_param_bound(param_def_id.to_def_id()) => { + self.predicates.iter().filter_map(move |pred| match pred.kind { + WherePredicateKind::BoundPredicate(bp) + if bp.is_param_bound(param_def_id.to_def_id()) => + { Some(bp) } _ => None, @@ -726,8 +728,8 @@ impl<'hir> Generics<'hir> { &self, param_def_id: LocalDefId, ) -> impl Iterator> { - self.predicates.iter().filter_map(move |pred| match pred { - WherePredicate::RegionPredicate(rp) if rp.is_param_bound(param_def_id) => Some(rp), + self.predicates.iter().filter_map(move |pred| match pred.kind { + WherePredicateKind::RegionPredicate(rp) if rp.is_param_bound(param_def_id) => Some(rp), _ => None, }) } @@ -841,7 +843,28 @@ impl<'hir> Generics<'hir> { /// A single predicate in a where-clause. #[derive(Debug, Clone, Copy, HashStable_Generic)] -pub enum WherePredicate<'hir> { +pub struct WherePredicate<'hir> { + pub hir_id: HirId, + pub kind: &'hir WherePredicateKind<'hir>, +} + +impl<'hir> WherePredicate<'hir> { + pub fn span(&self) -> Span { + self.kind.span() + } + + pub fn in_where_clause(&self) -> bool { + self.kind.in_where_clause() + } + + pub fn bounds(&self) -> GenericBounds<'hir> { + self.kind.bounds() + } +} + +/// The kind of a single predicate in a where-clause. +#[derive(Debug, Clone, Copy, HashStable_Generic)] +pub enum WherePredicateKind<'hir> { /// A type bound (e.g., `for<'c> Foo: Send + Clone + 'c`). BoundPredicate(WhereBoundPredicate<'hir>), /// A lifetime predicate (e.g., `'a: 'b + 'c`). @@ -850,28 +873,28 @@ pub enum WherePredicate<'hir> { EqPredicate(WhereEqPredicate<'hir>), } -impl<'hir> WherePredicate<'hir> { +impl<'hir> WherePredicateKind<'hir> { pub fn span(&self) -> Span { match self { - WherePredicate::BoundPredicate(p) => p.span, - WherePredicate::RegionPredicate(p) => p.span, - WherePredicate::EqPredicate(p) => p.span, + WherePredicateKind::BoundPredicate(p) => p.span, + WherePredicateKind::RegionPredicate(p) => p.span, + WherePredicateKind::EqPredicate(p) => p.span, } } pub fn in_where_clause(&self) -> bool { match self { - WherePredicate::BoundPredicate(p) => p.origin == PredicateOrigin::WhereClause, - WherePredicate::RegionPredicate(p) => p.in_where_clause, - WherePredicate::EqPredicate(_) => false, + WherePredicateKind::BoundPredicate(p) => p.origin == PredicateOrigin::WhereClause, + WherePredicateKind::RegionPredicate(p) => p.in_where_clause, + WherePredicateKind::EqPredicate(_) => false, } } pub fn bounds(&self) -> GenericBounds<'hir> { match self { - WherePredicate::BoundPredicate(p) => p.bounds, - WherePredicate::RegionPredicate(p) => p.bounds, - WherePredicate::EqPredicate(_) => &[], + WherePredicateKind::BoundPredicate(p) => p.bounds, + WherePredicateKind::RegionPredicate(p) => p.bounds, + WherePredicateKind::EqPredicate(_) => &[], } } } @@ -3795,6 +3818,7 @@ pub enum Node<'hir> { GenericParam(&'hir GenericParam<'hir>), Crate(&'hir Mod<'hir>), Infer(&'hir InferArg), + WherePredicate(&'hir WherePredicate<'hir>), WhereBoundPredicate(&'hir WhereBoundPredicate<'hir>), // FIXME: Merge into `Node::Infer`. ArrayLenInfer(&'hir InferArg), @@ -3850,6 +3874,7 @@ impl<'hir> Node<'hir> { | Node::TraitRef(..) | Node::OpaqueTy(..) | Node::Infer(..) + | Node::WherePredicate(..) | Node::WhereBoundPredicate(..) | Node::ArrayLenInfer(..) | Node::Synthetic diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index a453af3f7fd3..bbd0022e750a 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -961,8 +961,9 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>( visitor: &mut V, predicate: &'v WherePredicate<'v>, ) -> V::Result { - match *predicate { - WherePredicate::BoundPredicate(WhereBoundPredicate { + try_visit!(visitor.visit_id(predicate.hir_id)); + match *predicate.kind { + WherePredicateKind::BoundPredicate(WhereBoundPredicate { hir_id, ref bounded_ty, bounds, @@ -975,7 +976,7 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>( walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_generic_param, bound_generic_params); } - WherePredicate::RegionPredicate(WhereRegionPredicate { + WherePredicateKind::RegionPredicate(WhereRegionPredicate { ref lifetime, bounds, span: _, @@ -984,7 +985,7 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>( try_visit!(visitor.visit_lifetime(lifetime)); walk_list!(visitor, visit_param_bound, bounds); } - WherePredicate::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty, span: _ }) => { + WherePredicateKind::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty, span: _ }) => { try_visit!(visitor.visit_ty(lhs_ty)); try_visit!(visitor.visit_ty(rhs_ty)); } diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 0b7d3f8b0850..34fdef83c7f9 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -1101,7 +1101,7 @@ fn check_region_bounds_on_impl_item<'tcx>( // FIXME: we could potentially look at the impl's bounds to not point at bounds that // *are* present in the impl. for p in trait_generics.predicates { - if let hir::WherePredicate::BoundPredicate(pred) = p { + if let hir::WherePredicateKind::BoundPredicate(pred) = p.kind { for b in pred.bounds { if let hir::GenericBound::Outlives(lt) = b { bounds_span.push(lt.ident.span); @@ -1114,7 +1114,7 @@ fn check_region_bounds_on_impl_item<'tcx>( { let mut impl_bounds = 0; for p in impl_generics.predicates { - if let hir::WherePredicate::BoundPredicate(pred) = p { + if let hir::WherePredicateKind::BoundPredicate(pred) = p.kind { for b in pred.bounds { if let hir::GenericBound::Outlives(_) = b { impl_bounds += 1; diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index d01c3784adec..c820da077dbd 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1970,8 +1970,8 @@ fn check_variances_for_type_defn<'tcx>( hir_generics .predicates .iter() - .filter_map(|predicate| match predicate { - hir::WherePredicate::BoundPredicate(predicate) => { + .filter_map(|predicate| match predicate.kind { + hir::WherePredicateKind::BoundPredicate(predicate) => { match icx.lower_ty(predicate.bounded_ty).kind() { ty::Param(data) => Some(Parameter(data.index)), _ => None, diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index efe84e0006fd..6d001432ccc7 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -237,8 +237,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen trace!(?predicates); // Add inline `` bounds and bounds in the where clause. for predicate in hir_generics.predicates { - match predicate { - hir::WherePredicate::BoundPredicate(bound_pred) => { + match predicate.kind { + hir::WherePredicateKind::BoundPredicate(bound_pred) => { let ty = icx.lowerer().lower_ty_maybe_return_type_notation(bound_pred.bounded_ty); let bound_vars = tcx.late_bound_vars(bound_pred.hir_id); @@ -274,7 +274,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen predicates.extend(bounds.clauses()); } - hir::WherePredicate::RegionPredicate(region_pred) => { + hir::WherePredicateKind::RegionPredicate(region_pred) => { let r1 = icx .lowerer() .lower_lifetime(region_pred.lifetime, RegionInferReason::RegionPredicate); @@ -297,7 +297,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen })) } - hir::WherePredicate::EqPredicate(..) => { + hir::WherePredicateKind::EqPredicate(..) => { // FIXME(#20041) } } @@ -847,7 +847,7 @@ impl<'tcx> ItemCtxt<'tcx> { let mut bounds = Bounds::default(); for predicate in hir_generics.predicates { - let hir::WherePredicate::BoundPredicate(predicate) = predicate else { + let hir::WherePredicateKind::BoundPredicate(predicate) = predicate.kind else { continue; }; diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 9483439ae4e8..d763724694c4 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -917,8 +917,8 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { } fn visit_where_predicate(&mut self, predicate: &'tcx hir::WherePredicate<'tcx>) { - match predicate { - &hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { + match predicate.kind { + &hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate { hir_id, bounded_ty, bounds, @@ -960,7 +960,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { walk_list!(this, visit_param_bound, bounds); }) } - &hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate { + &hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate { lifetime, bounds, .. @@ -968,7 +968,9 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { self.visit_lifetime(lifetime); walk_list!(self, visit_param_bound, bounds); } - &hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { lhs_ty, rhs_ty, .. }) => { + &hir::WherePredicateKind::EqPredicate(hir::WhereEqPredicate { + lhs_ty, rhs_ty, .. + }) => { self.visit_ty(lhs_ty); self.visit_ty(rhs_ty); } @@ -2049,7 +2051,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { // bounds since we'll be emitting a hard error in HIR lowering, so this // is purely speculative. let one_bound = generics.predicates.iter().find_map(|predicate| { - let hir::WherePredicate::BoundPredicate(predicate) = predicate else { + let hir::WherePredicateKind::BoundPredicate(predicate) = predicate.kind + else { return None; }; let hir::TyKind::Path(hir::QPath::Resolved(None, bounded_path)) = diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index a5709089db68..76847e1f747c 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -67,7 +67,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { search_bounds(hir_bounds); if let Some((self_ty, where_clause)) = self_ty_where_predicates { for clause in where_clause { - if let hir::WherePredicate::BoundPredicate(pred) = clause + if let hir::WherePredicateKind::BoundPredicate(pred) = clause.kind && pred.is_param_bound(self_ty.to_def_id()) { search_bounds(pred.bounds); diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 2073f2868b4f..f1f3d7c0c474 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -117,6 +117,7 @@ impl<'a> State<'a> { Node::Ctor(..) => panic!("cannot print isolated Ctor"), Node::LetStmt(a) => self.print_local_decl(a), Node::Crate(..) => panic!("cannot print Crate"), + Node::WherePredicate(pred) => self.print_where_predicate(pred), Node::WhereBoundPredicate(pred) => { self.print_formal_generic_params(pred.bound_generic_params); self.print_type(pred.bounded_ty); @@ -2160,47 +2161,51 @@ impl<'a> State<'a> { if i != 0 { self.word_space(","); } + self.print_where_predicate(predicate); + } + } - match *predicate { - hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { - bound_generic_params, - bounded_ty, - bounds, - .. - }) => { - self.print_formal_generic_params(bound_generic_params); - self.print_type(bounded_ty); - self.print_bounds(":", bounds); - } - hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate { - lifetime, - bounds, - .. - }) => { - self.print_lifetime(lifetime); - self.word(":"); - - for (i, bound) in bounds.iter().enumerate() { - match bound { - GenericBound::Outlives(lt) => { - self.print_lifetime(lt); - } - _ => panic!("unexpected bound on lifetime param: {bound:?}"), - } + fn print_where_predicate(&mut self, predicate: &hir::WherePredicate<'_>) { + self.print_outer_attributes(self.attrs(predicate.hir_id)); + match *predicate.kind { + hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate { + bound_generic_params, + bounded_ty, + bounds, + .. + }) => { + self.print_formal_generic_params(bound_generic_params); + self.print_type(bounded_ty); + self.print_bounds(":", bounds); + } + hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate { + lifetime, + bounds, + .. + }) => { + self.print_lifetime(lifetime); + self.word(":"); - if i != 0 { - self.word(":"); + for (i, bound) in bounds.iter().enumerate() { + match bound { + GenericBound::Outlives(lt) => { + self.print_lifetime(lt); } + _ => panic!("unexpected bound on lifetime param: {bound:?}"), + } + + if i != 0 { + self.word(":"); } } - hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { - lhs_ty, rhs_ty, .. - }) => { - self.print_type(lhs_ty); - self.space(); - self.word_space("="); - self.print_type(rhs_ty); - } + } + hir::WherePredicateKind::EqPredicate(hir::WhereEqPredicate { + lhs_ty, rhs_ty, .. + }) => { + self.print_type(lhs_ty); + self.space(); + self.word_space("="); + self.print_type(rhs_ty); } } } diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index d6e5fab610ed..aa9be1e851d9 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -391,6 +391,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | hir::Node::GenericParam(_) | hir::Node::Crate(_) | hir::Node::Infer(_) + | hir::Node::WherePredicate(_) | hir::Node::WhereBoundPredicate(_) | hir::Node::ArrayLenInfer(_) | hir::Node::PreciseCapturingNonLifetimeArg(_) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 3f703c2fcf69..ac9cc2b9d89b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -10,7 +10,7 @@ use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::lang_items::LangItem; use rustc_hir::{ Arm, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, GenericBound, HirId, - Node, Path, QPath, Stmt, StmtKind, TyKind, WherePredicate, + Node, Path, QPath, Stmt, StmtKind, TyKind, WherePredicateKind, }; use rustc_hir_analysis::collect::suggest_impl_trait; use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer; @@ -1004,8 +1004,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // get all where BoundPredicates here, because they are used in two cases below let where_predicates = predicates .iter() - .filter_map(|p| match p { - WherePredicate::BoundPredicate(hir::WhereBoundPredicate { + .filter_map(|p| match p.kind { + WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate { bounds, bounded_ty, .. diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 02d22ee49bd6..cc832c42e327 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1391,7 +1391,7 @@ declare_lint_pass!(TypeAliasBounds => [TYPE_ALIAS_BOUNDS]); impl TypeAliasBounds { pub(crate) fn affects_object_lifetime_defaults(pred: &hir::WherePredicate<'_>) -> bool { // Bounds of the form `T: 'a` with `T` type param affect object lifetime defaults. - if let hir::WherePredicate::BoundPredicate(pred) = pred + if let hir::WherePredicateKind::BoundPredicate(pred) = pred.kind && pred.bounds.iter().any(|bound| matches!(bound, hir::GenericBound::Outlives(_))) && pred.bound_generic_params.is_empty() // indeed, even if absent from the RHS && pred.bounded_ty.as_generic_param().is_some() @@ -2064,8 +2064,8 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { let mut dropped_where_predicate_count = 0; for (i, where_predicate) in hir_generics.predicates.iter().enumerate() { let (relevant_lifetimes, bounds, predicate_span, in_where_clause) = - match where_predicate { - hir::WherePredicate::RegionPredicate(predicate) => { + match where_predicate.kind { + hir::WherePredicateKind::RegionPredicate(predicate) => { if let Some(ResolvedArg::EarlyBound(region_def_id)) = cx.tcx.named_bound_var(predicate.lifetime.hir_id) { @@ -2088,7 +2088,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { continue; } } - hir::WherePredicate::BoundPredicate(predicate) => { + hir::WherePredicateKind::BoundPredicate(predicate) => { // FIXME we can also infer bounds on associated types, // and should check for them here. match predicate.bounded_ty.kind { diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index bbb290c9459e..5fd426f62589 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -1295,12 +1295,12 @@ impl EarlyLintPass for UnusedParens { } fn enter_where_predicate(&mut self, _: &EarlyContext<'_>, pred: &ast::WherePredicate) { - use rustc_ast::{WhereBoundPredicate, WherePredicate}; - if let WherePredicate::BoundPredicate(WhereBoundPredicate { + use rustc_ast::{WhereBoundPredicate, WherePredicateKind}; + if let WherePredicateKind::BoundPredicate(WhereBoundPredicate { bounded_ty, bound_generic_params, .. - }) = pred + }) = &pred.kind && let ast::TyKind::Paren(_) = &bounded_ty.kind && bound_generic_params.is_empty() { diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 926691013dd8..9a61d573785f 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -947,6 +947,7 @@ impl<'hir> Map<'hir> { Node::Infer(i) => i.span, Node::LetStmt(local) => local.span, Node::Crate(item) => item.spans.inner_span, + Node::WherePredicate(pred) => pred.span(), Node::WhereBoundPredicate(pred) => pred.span, Node::ArrayLenInfer(inf) => inf.span, Node::PreciseCapturingNonLifetimeArg(param) => param.ident.span, @@ -1225,6 +1226,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { format!("{id} (generic_param {})", path_str(param.def_id)) } Node::Crate(..) => String::from("(root_crate)"), + Node::WherePredicate(_) => node_str("where predicate"), Node::WhereBoundPredicate(_) => node_str("where bound predicate"), Node::ArrayLenInfer(_) => node_str("array len infer"), Node::Synthetic => unreachable!(), diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 84f52bfe48f2..fd807882e0f7 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -8,7 +8,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Applicability, Diag, DiagArgValue, IntoDiagArg, into_diag_arg_using_display}; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir, LangItem, PredicateOrigin, WherePredicate}; +use rustc_hir::{self as hir, LangItem, PredicateOrigin, WherePredicateKind}; use rustc_span::{BytePos, Span}; use rustc_type_ir::TyKind::*; @@ -180,7 +180,7 @@ fn suggest_changing_unsized_bound( // First look at the `where` clause because we can have `where T: ?Sized`, // then look at params. for (where_pos, predicate) in generics.predicates.iter().enumerate() { - let WherePredicate::BoundPredicate(predicate) = predicate else { + let WherePredicateKind::BoundPredicate(predicate) = predicate.kind else { continue; }; if !predicate.is_param_bound(param.def_id.to_def_id()) { diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index 5aebe716b0a1..4cfbf68a68ae 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -1,6 +1,7 @@ use ast::token::Delimiter; use rustc_ast::{ - self as ast, AttrVec, GenericBounds, GenericParam, GenericParamKind, TyKind, WhereClause, token, + self as ast, AttrVec, DUMMY_NODE_ID, GenericBounds, GenericParam, GenericParamKind, TyKind, + WhereClause, token, }; use rustc_errors::{Applicability, PResult}; use rustc_span::Span; @@ -15,7 +16,7 @@ use crate::errors::{ }; enum PredicateOrStructBody { - Predicate(ast::WherePredicate), + Predicate(ast::WherePredicateKind), StructBody(ThinVec), } @@ -340,42 +341,62 @@ impl<'a> Parser<'a> { loop { let where_sp = where_lo.to(self.prev_token.span); let pred_lo = self.token.span; - if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) { - let lifetime = self.expect_lifetime(); - // Bounds starting with a colon are mandatory, but possibly empty. - self.expect(&token::Colon)?; - let bounds = self.parse_lt_param_bounds(); - where_clause.predicates.push(ast::WherePredicate::RegionPredicate( - ast::WhereRegionPredicate { - span: pred_lo.to(self.prev_token.span), - lifetime, - bounds, - }, - )); - } else if self.check_type() { - match self.parse_ty_where_predicate_or_recover_tuple_struct_body( - struct_, pred_lo, where_sp, - )? { - PredicateOrStructBody::Predicate(pred) => where_clause.predicates.push(pred), - PredicateOrStructBody::StructBody(body) => { - tuple_struct_body = Some(body); - break; + let attrs = self.parse_outer_attributes()?; + let mut should_break = false; + let predicate = + self.collect_tokens(None, attrs, ForceCollect::Yes, |this, attrs| { + let mut predicate = None; + let trailing = Trailing::No; + let use_pre_attr_pos = UsePreAttrPos::No; + if this.check_lifetime() && this.look_ahead(1, |t| !t.is_like_plus()) { + let lifetime = this.expect_lifetime(); + // Bounds starting with a colon are mandatory, but possibly empty. + this.expect(&token::Colon)?; + let bounds = this.parse_lt_param_bounds(); + let kind = + ast::WherePredicateKind::RegionPredicate(ast::WhereRegionPredicate { + span: pred_lo.to(this.prev_token.span), + lifetime, + bounds, + }); + predicate = Some(ast::WherePredicate { attrs, kind, id: DUMMY_NODE_ID }); + } else if this.check_type() { + match this.parse_ty_where_predicate_or_recover_tuple_struct_body( + struct_, pred_lo, where_sp, + )? { + PredicateOrStructBody::Predicate(kind) => { + predicate = + Some(ast::WherePredicate { attrs, kind, id: DUMMY_NODE_ID }); + } + PredicateOrStructBody::StructBody(body) => { + tuple_struct_body = Some(body); + should_break = true; + return Ok((predicate, trailing, use_pre_attr_pos)); + } + } + } else { + should_break = true; + return Ok((predicate, trailing, use_pre_attr_pos)); } - } - } else { - break; + let prev_token = this.prev_token.span; + let ate_comma = this.eat(&token::Comma); + + if this.eat_keyword_noexpect(kw::Where) { + this.dcx().emit_err(MultipleWhereClauses { + span: this.token.span, + previous: pred_lo, + between: prev_token.shrink_to_hi().to(this.prev_token.span), + }); + } else if !ate_comma { + should_break = true; + return Ok((predicate, trailing, use_pre_attr_pos)); + } + Ok((predicate, trailing, use_pre_attr_pos)) + })?; + if let Some(predicate) = predicate { + where_clause.predicates.push(predicate) } - - let prev_token = self.prev_token.span; - let ate_comma = self.eat(&token::Comma); - - if self.eat_keyword_noexpect(kw::Where) { - self.dcx().emit_err(MultipleWhereClauses { - span: self.token.span, - previous: pred_lo, - between: prev_token.shrink_to_hi().to(self.prev_token.span), - }); - } else if !ate_comma { + if should_break { break; } } @@ -448,7 +469,7 @@ impl<'a> Parser<'a> { } } - fn parse_ty_where_predicate(&mut self) -> PResult<'a, ast::WherePredicate> { + fn parse_ty_where_predicate(&mut self) -> PResult<'a, ast::WherePredicateKind> { let lo = self.token.span; // Parse optional `for<'a, 'b>`. // This `for` is parsed greedily and applies to the whole predicate, @@ -464,7 +485,7 @@ impl<'a> Parser<'a> { let ty = self.parse_ty_for_where_clause()?; if self.eat(&token::Colon) { let bounds = self.parse_generic_bounds()?; - Ok(ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { + Ok(ast::WherePredicateKind::BoundPredicate(ast::WhereBoundPredicate { span: lo.to(self.prev_token.span), bound_generic_params: lifetime_defs, bounded_ty: ty, @@ -474,7 +495,7 @@ impl<'a> Parser<'a> { // FIXME: We are just dropping the binders in lifetime_defs on the floor here. } else if self.eat(&token::Eq) || self.eat(&token::EqEq) { let rhs_ty = self.parse_ty()?; - Ok(ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { + Ok(ast::WherePredicateKind::EqPredicate(ast::WhereEqPredicate { span: lo.to(self.prev_token.span), lhs_ty: ty, rhs_ty, diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index 27714a0fdcca..7d47a025342a 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -355,7 +355,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { } fn visit_where_predicate(&mut self, p: &'v hir::WherePredicate<'v>) { - record_variants!((self, p, p, Id::None, hir, WherePredicate, WherePredicate), [ + record_variants!((self, p, p.kind, Id::None, hir, WherePredicate, WherePredicateKind), [ BoundPredicate, RegionPredicate, EqPredicate @@ -608,7 +608,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { } fn visit_where_predicate(&mut self, p: &'v ast::WherePredicate) { - record_variants!((self, p, p, Id::None, ast, WherePredicate, WherePredicate), [ + record_variants!((self, p, &p.kind, Id::None, ast, WherePredicate, WherePredicateKind), [ BoundPredicate, RegionPredicate, EqPredicate diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index f4a85c358e38..deec96a2717c 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -670,7 +670,7 @@ struct DiagMetadata<'ast> { current_trait_object: Option<&'ast [ast::GenericBound]>, /// Given `where ::Baz: String`, suggest `where T: Bar`. - current_where_predicate: Option<&'ast WherePredicate>, + current_where_predicate: Option<&'ast WherePredicateKind>, current_type_path: Option<&'ast Ty>, @@ -1266,15 +1266,16 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r fn visit_where_predicate(&mut self, p: &'ast WherePredicate) { debug!("visit_where_predicate {:?}", p); - let previous_value = replace(&mut self.diag_metadata.current_where_predicate, Some(p)); + let previous_value = + replace(&mut self.diag_metadata.current_where_predicate, Some(&p.kind)); self.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| { - if let WherePredicate::BoundPredicate(WhereBoundPredicate { + if let WherePredicateKind::BoundPredicate(WhereBoundPredicate { ref bounded_ty, ref bounds, ref bound_generic_params, span: predicate_span, .. - }) = p + }) = &p.kind { let span = predicate_span.shrink_to_lo().to(bounded_ty.span.shrink_to_lo()); this.with_generic_param_rib( diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index f0632a21091b..463095867a7a 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1289,7 +1289,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { fn restrict_assoc_type_in_where_clause(&mut self, span: Span, err: &mut Diag<'_>) -> bool { // Detect that we are actually in a `where` predicate. let (bounded_ty, bounds, where_span) = - if let Some(ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { + if let Some(ast::WherePredicateKind::BoundPredicate(ast::WhereBoundPredicate { bounded_ty, bound_generic_params, bounds, @@ -2811,7 +2811,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { // for<'a, 'b> T: Trait + 'b // ^^^^^^^^^^^ suggest outer binder `for<'a, 'b>` if let LifetimeBinderKind::WhereBound = kind - && let Some(ast::WherePredicate::BoundPredicate( + && let Some(ast::WherePredicateKind::BoundPredicate( ast::WhereBoundPredicate { bounded_ty, bounds, .. }, )) = self.diag_metadata.current_where_predicate && bounded_ty.id == binder diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 890c4fdafef8..05afd4beb49b 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -540,6 +540,7 @@ symbols! { cfg_accessible, cfg_attr, cfg_attr_multi, + cfg_attribute_in_where, cfg_autodiff_fallback, cfg_boolean_literals, cfg_doctest, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 553bb61ed043..d1f4a36be1f3 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -5226,7 +5226,7 @@ fn point_at_assoc_type_restriction( let mut predicates = generics.predicates.iter().peekable(); let mut prev: Option<&hir::WhereBoundPredicate<'_>> = None; while let Some(pred) = predicates.next() { - let hir::WherePredicate::BoundPredicate(pred) = pred else { + let hir::WherePredicateKind::BoundPredicate(pred) = pred.kind else { continue; }; let mut bounds = pred.bounds.iter(); @@ -5252,8 +5252,8 @@ fn point_at_assoc_type_restriction( .iter() .filter(|p| { matches!( - p, - hir::WherePredicate::BoundPredicate(p) + p.kind, + hir::WherePredicateKind::BoundPredicate(p) if hir::PredicateOrigin::WhereClause == p.origin ) }) @@ -5263,7 +5263,8 @@ fn point_at_assoc_type_restriction( // There's only one `where` bound, that needs to be removed. Remove the whole // `where` clause. generics.where_clause_span - } else if let Some(hir::WherePredicate::BoundPredicate(next)) = predicates.peek() + } else if let Some(next) = predicates.peek() + && let hir::WherePredicateKind::BoundPredicate(next) = next.kind && pred.origin == next.origin { // There's another bound, include the comma for the current one. diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index 0eaacbcfbea6..286e02f700b6 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -150,8 +150,8 @@ fn get_sized_bounds(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]> .predicates .iter() .filter_map(|pred| { - match pred { - hir::WherePredicate::BoundPredicate(pred) + match pred.kind { + hir::WherePredicateKind::BoundPredicate(pred) if pred.bounded_ty.hir_id.owner.to_def_id() == trait_def_id => { // Fetch spans for trait bounds that are Sized: diff --git a/tests/ui/feature-gates/feature-gate-cfg_attribute_in_where.a.stderr b/tests/ui/feature-gates/feature-gate-cfg_attribute_in_where.a.stderr new file mode 100644 index 000000000000..cefc3b995f4e --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-cfg_attribute_in_where.a.stderr @@ -0,0 +1,243 @@ +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:12:5 + | +LL | #[cfg(a)] T: TraitA, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:13:5 + | +LL | #[cfg(b)] T: TraitB, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:17:9 + | +LL | #[cfg(a)] U: TraitA, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:18:9 + | +LL | #[cfg(b)] U: TraitB; + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:22:9 + | +LL | #[cfg(a)] U: TraitA, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:23:9 + | +LL | #[cfg(b)] U: TraitB; + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:28:5 + | +LL | #[cfg(a)] T: TraitA, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:29:5 + | +LL | #[cfg(b)] T: TraitB, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:32:9 + | +LL | #[cfg(a)] U: TraitA, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:33:9 + | +LL | #[cfg(b)] U: TraitB; + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:37:9 + | +LL | #[cfg(a)] U: TraitA, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:38:9 + | +LL | #[cfg(b)] U: TraitB, {} + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:43:5 + | +LL | #[cfg(a)] T: TraitA, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:44:5 + | +LL | #[cfg(b)] T: TraitB, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:51:5 + | +LL | #[cfg(a)] T: TraitA, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:52:5 + | +LL | #[cfg(b)] T: TraitB, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:60:5 + | +LL | #[cfg(a)] T: TraitA, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:61:5 + | +LL | #[cfg(b)] T: TraitB, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:68:5 + | +LL | #[cfg(a)] T: TraitA, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:69:5 + | +LL | #[cfg(b)] T: TraitB = T; + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:72:5 + | +LL | #[cfg(a)] T: TraitA, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:73:5 + | +LL | #[cfg(b)] T: TraitB, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:76:9 + | +LL | #[cfg(a)] U: TraitA, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:77:9 + | +LL | #[cfg(b)] U: TraitB, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 24 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-cfg_attribute_in_where.b.stderr b/tests/ui/feature-gates/feature-gate-cfg_attribute_in_where.b.stderr new file mode 100644 index 000000000000..cefc3b995f4e --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-cfg_attribute_in_where.b.stderr @@ -0,0 +1,243 @@ +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:12:5 + | +LL | #[cfg(a)] T: TraitA, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:13:5 + | +LL | #[cfg(b)] T: TraitB, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:17:9 + | +LL | #[cfg(a)] U: TraitA, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:18:9 + | +LL | #[cfg(b)] U: TraitB; + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:22:9 + | +LL | #[cfg(a)] U: TraitA, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:23:9 + | +LL | #[cfg(b)] U: TraitB; + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:28:5 + | +LL | #[cfg(a)] T: TraitA, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:29:5 + | +LL | #[cfg(b)] T: TraitB, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:32:9 + | +LL | #[cfg(a)] U: TraitA, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:33:9 + | +LL | #[cfg(b)] U: TraitB; + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:37:9 + | +LL | #[cfg(a)] U: TraitA, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:38:9 + | +LL | #[cfg(b)] U: TraitB, {} + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:43:5 + | +LL | #[cfg(a)] T: TraitA, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:44:5 + | +LL | #[cfg(b)] T: TraitB, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:51:5 + | +LL | #[cfg(a)] T: TraitA, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:52:5 + | +LL | #[cfg(b)] T: TraitB, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:60:5 + | +LL | #[cfg(a)] T: TraitA, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:61:5 + | +LL | #[cfg(b)] T: TraitB, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:68:5 + | +LL | #[cfg(a)] T: TraitA, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:69:5 + | +LL | #[cfg(b)] T: TraitB = T; + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:72:5 + | +LL | #[cfg(a)] T: TraitA, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:73:5 + | +LL | #[cfg(b)] T: TraitB, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:76:9 + | +LL | #[cfg(a)] U: TraitA, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `#[cfg]` attribute in `where` clause is unstable + --> $DIR/feature-gate-cfg_attribute_in_where.rs:77:9 + | +LL | #[cfg(b)] U: TraitB, + | ^^^^^^^^^ + | + = note: see issue #115590 for more information + = help: add `#![feature(cfg_attribute_in_where)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 24 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-cfg_attribute_in_where.rs b/tests/ui/feature-gates/feature-gate-cfg_attribute_in_where.rs new file mode 100644 index 000000000000..f72367790a96 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-cfg_attribute_in_where.rs @@ -0,0 +1,79 @@ +//@ revisions: a b + +#![crate_type = "lib"] +use std::marker::PhantomData; + +trait TraitA {} + +trait TraitB {} + +trait A +where + #[cfg(a)] T: TraitA, //~ `#[cfg]` attribute in `where` clause is unstable + #[cfg(b)] T: TraitB, //~ `#[cfg]` attribute in `where` clause is unstable +{ + type B + where + #[cfg(a)] U: TraitA, //~ `#[cfg]` attribute in `where` clause is unstable + #[cfg(b)] U: TraitB; //~ `#[cfg]` attribute in `where` clause is unstable + + fn foo(&self) + where + #[cfg(a)] U: TraitA, //~ `#[cfg]` attribute in `where` clause is unstable + #[cfg(b)] U: TraitB; //~ `#[cfg]` attribute in `where` clause is unstable +} + +impl A for T +where + #[cfg(a)] T: TraitA, //~ `#[cfg]` attribute in `where` clause is unstable + #[cfg(b)] T: TraitB, //~ `#[cfg]` attribute in `where` clause is unstable +{ + type B = () where + #[cfg(a)] U: TraitA, //~ `#[cfg]` attribute in `where` clause is unstable + #[cfg(b)] U: TraitB; //~ `#[cfg]` attribute in `where` clause is unstable + + fn foo(&self) + where + #[cfg(a)] U: TraitA, //~ `#[cfg]` attribute in `where` clause is unstable + #[cfg(b)] U: TraitB, {} //~ `#[cfg]` attribute in `where` clause is unstable +} + +struct C +where + #[cfg(a)] T: TraitA, //~ `#[cfg]` attribute in `where` clause is unstable + #[cfg(b)] T: TraitB, //~ `#[cfg]` attribute in `where` clause is unstable +{ + _t: PhantomData, +} + +union D +where + #[cfg(a)] T: TraitA, //~ `#[cfg]` attribute in `where` clause is unstable + #[cfg(b)] T: TraitB, //~ `#[cfg]` attribute in `where` clause is unstable +{ + + _t: PhantomData, +} + +enum E +where + #[cfg(a)] T: TraitA, //~ `#[cfg]` attribute in `where` clause is unstable + #[cfg(b)] T: TraitB, //~ `#[cfg]` attribute in `where` clause is unstable +{ + E(PhantomData), +} + +type F +where + #[cfg(a)] T: TraitA, //~ `#[cfg]` attribute in `where` clause is unstable + #[cfg(b)] T: TraitB = T; //~ `#[cfg]` attribute in `where` clause is unstable + +impl C where + #[cfg(a)] T: TraitA, //~ `#[cfg]` attribute in `where` clause is unstable + #[cfg(b)] T: TraitB, //~ `#[cfg]` attribute in `where` clause is unstable +{ + fn new() where + #[cfg(a)] U: TraitA, //~ `#[cfg]` attribute in `where` clause is unstable + #[cfg(b)] U: TraitB, //~ `#[cfg]` attribute in `where` clause is unstable + {} +} diff --git a/tests/ui/parser/bounds-lifetime-where.rs b/tests/ui/parser/bounds-lifetime-where.rs index 7ff75233d3a8..730be7139bec 100644 --- a/tests/ui/parser/bounds-lifetime-where.rs +++ b/tests/ui/parser/bounds-lifetime-where.rs @@ -5,6 +5,6 @@ type A where 'a:, = u8; // OK type A where 'a: 'b + 'c = u8; // OK type A where = u8; // OK type A where 'a: 'b + = u8; // OK -type A where , = u8; //~ ERROR expected one of `;`, `=`, `where`, lifetime, or type, found `,` +type A where , = u8; //~ ERROR expected one of `#`, `;`, `=`, `where`, lifetime, or type, found `,` fn main() {} diff --git a/tests/ui/parser/bounds-lifetime-where.stderr b/tests/ui/parser/bounds-lifetime-where.stderr index 9dd963afc796..5aadb5fff320 100644 --- a/tests/ui/parser/bounds-lifetime-where.stderr +++ b/tests/ui/parser/bounds-lifetime-where.stderr @@ -1,8 +1,8 @@ -error: expected one of `;`, `=`, `where`, lifetime, or type, found `,` +error: expected one of `#`, `;`, `=`, `where`, lifetime, or type, found `,` --> $DIR/bounds-lifetime-where.rs:8:14 | LL | type A where , = u8; - | ^ expected one of `;`, `=`, `where`, lifetime, or type + | ^ expected one of `#`, `;`, `=`, `where`, lifetime, or type error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/misplaced-return-type-where-in-next-line-issue-126311.stderr b/tests/ui/parser/issues/misplaced-return-type-where-in-next-line-issue-126311.stderr index 196a46d7ea54..6245f81d533b 100644 --- a/tests/ui/parser/issues/misplaced-return-type-where-in-next-line-issue-126311.stderr +++ b/tests/ui/parser/issues/misplaced-return-type-where-in-next-line-issue-126311.stderr @@ -2,7 +2,7 @@ error: return type should be specified after the function parameters --> $DIR/misplaced-return-type-where-in-next-line-issue-126311.rs:5:15 | LL | K: Clone, -> Result - | ^^ expected one of `{`, lifetime, or type + | ^^ expected one of `#`, `{`, lifetime, or type | help: place the return type after the function parameters | diff --git a/tests/ui/stats/hir-stats.stderr b/tests/ui/stats/hir-stats.stderr index bd0c8cbc3b12..9e0b5fb89183 100644 --- a/tests/ui/stats/hir-stats.stderr +++ b/tests/ui/stats/hir-stats.stderr @@ -5,11 +5,11 @@ ast-stats-1 Crate 40 ( 0.6%) 1 40 ast-stats-1 GenericArgs 40 ( 0.6%) 1 40 ast-stats-1 - AngleBracketed 40 ( 0.6%) 1 ast-stats-1 ExprField 48 ( 0.7%) 1 48 -ast-stats-1 WherePredicate 56 ( 0.8%) 1 56 -ast-stats-1 - BoundPredicate 56 ( 0.8%) 1 ast-stats-1 Attribute 64 ( 1.0%) 2 32 ast-stats-1 - DocComment 32 ( 0.5%) 1 ast-stats-1 - Normal 32 ( 0.5%) 1 +ast-stats-1 WherePredicate 72 ( 1.1%) 1 72 +ast-stats-1 - BoundPredicate 72 ( 1.1%) 1 ast-stats-1 Local 80 ( 1.2%) 1 80 ast-stats-1 ForeignItem 88 ( 1.3%) 1 88 ast-stats-1 - Fn 88 ( 1.3%) 1 @@ -24,8 +24,8 @@ ast-stats-1 - Expr 96 ( 1.4%) 3 ast-stats-1 Block 192 ( 2.9%) 6 32 ast-stats-1 Variant 208 ( 3.1%) 2 104 ast-stats-1 AssocItem 352 ( 5.3%) 4 88 -ast-stats-1 - Type 176 ( 2.7%) 2 -ast-stats-1 - Fn 176 ( 2.7%) 2 +ast-stats-1 - Type 176 ( 2.6%) 2 +ast-stats-1 - Fn 176 ( 2.6%) 2 ast-stats-1 GenericBound 352 ( 5.3%) 4 88 ast-stats-1 - Trait 352 ( 5.3%) 4 ast-stats-1 GenericParam 480 ( 7.2%) 5 96 @@ -38,7 +38,7 @@ ast-stats-1 - Path 72 ( 1.1%) 1 ast-stats-1 - Match 72 ( 1.1%) 1 ast-stats-1 - Struct 72 ( 1.1%) 1 ast-stats-1 - Lit 144 ( 2.2%) 2 -ast-stats-1 - Block 216 ( 3.3%) 3 +ast-stats-1 - Block 216 ( 3.2%) 3 ast-stats-1 PathSegment 744 (11.2%) 31 24 ast-stats-1 Ty 896 (13.5%) 14 64 ast-stats-1 - Ref 64 ( 1.0%) 1 @@ -53,7 +53,7 @@ ast-stats-1 - Enum 136 ( 2.0%) 1 ast-stats-1 - Fn 272 ( 4.1%) 2 ast-stats-1 - Use 408 ( 6.1%) 3 ast-stats-1 ---------------------------------------------------------------- -ast-stats-1 Total 6_640 +ast-stats-1 Total 6_656 ast-stats-1 ast-stats-2 POST EXPANSION AST STATS ast-stats-2 Name Accumulated Size Count Item Size @@ -62,8 +62,8 @@ ast-stats-2 Crate 40 ( 0.5%) 1 40 ast-stats-2 GenericArgs 40 ( 0.5%) 1 40 ast-stats-2 - AngleBracketed 40 ( 0.5%) 1 ast-stats-2 ExprField 48 ( 0.7%) 1 48 -ast-stats-2 WherePredicate 56 ( 0.8%) 1 56 -ast-stats-2 - BoundPredicate 56 ( 0.8%) 1 +ast-stats-2 WherePredicate 72 ( 1.0%) 1 72 +ast-stats-2 - BoundPredicate 72 ( 1.0%) 1 ast-stats-2 Local 80 ( 1.1%) 1 80 ast-stats-2 ForeignItem 88 ( 1.2%) 1 88 ast-stats-2 - Fn 88 ( 1.2%) 1 @@ -80,7 +80,7 @@ ast-stats-2 - Let 32 ( 0.4%) 1 ast-stats-2 - Semi 32 ( 0.4%) 1 ast-stats-2 - Expr 96 ( 1.3%) 3 ast-stats-2 Block 192 ( 2.6%) 6 32 -ast-stats-2 Variant 208 ( 2.9%) 2 104 +ast-stats-2 Variant 208 ( 2.8%) 2 104 ast-stats-2 AssocItem 352 ( 4.8%) 4 88 ast-stats-2 - Type 176 ( 2.4%) 2 ast-stats-2 - Fn 176 ( 2.4%) 2 @@ -98,7 +98,7 @@ ast-stats-2 - Struct 72 ( 1.0%) 1 ast-stats-2 - InlineAsm 72 ( 1.0%) 1 ast-stats-2 - Lit 144 ( 2.0%) 2 ast-stats-2 - Block 216 ( 3.0%) 3 -ast-stats-2 PathSegment 864 (11.9%) 36 24 +ast-stats-2 PathSegment 864 (11.8%) 36 24 ast-stats-2 Ty 896 (12.3%) 14 64 ast-stats-2 - Ref 64 ( 0.9%) 1 ast-stats-2 - Ptr 64 ( 0.9%) 1 @@ -111,9 +111,9 @@ ast-stats-2 - Impl 136 ( 1.9%) 1 ast-stats-2 - ExternCrate 136 ( 1.9%) 1 ast-stats-2 - ForeignMod 136 ( 1.9%) 1 ast-stats-2 - Fn 272 ( 3.7%) 2 -ast-stats-2 - Use 544 ( 7.5%) 4 +ast-stats-2 - Use 544 ( 7.4%) 4 ast-stats-2 ---------------------------------------------------------------- -ast-stats-2 Total 7_288 +ast-stats-2 Total 7_304 ast-stats-2 hir-stats HIR STATS hir-stats Name Accumulated Size Count Item Size @@ -121,7 +121,9 @@ hir-stats ---------------------------------------------------------------- hir-stats ForeignItemRef 24 ( 0.3%) 1 24 hir-stats Lifetime 24 ( 0.3%) 1 24 hir-stats Mod 32 ( 0.4%) 1 32 -hir-stats ExprField 40 ( 0.4%) 1 40 +hir-stats ExprField 40 ( 0.5%) 1 40 +hir-stats WherePredicate 48 ( 0.5%) 3 16 +hir-stats - BoundPredicate 48 ( 0.5%) 3 hir-stats TraitItemRef 56 ( 0.6%) 2 28 hir-stats GenericArg 64 ( 0.7%) 4 16 hir-stats - Type 16 ( 0.2%) 1 @@ -137,42 +139,40 @@ hir-stats Stmt 96 ( 1.1%) 3 32 hir-stats - Let 32 ( 0.4%) 1 hir-stats - Semi 32 ( 0.4%) 1 hir-stats - Expr 32 ( 0.4%) 1 -hir-stats FnDecl 120 ( 1.3%) 3 40 +hir-stats FnDecl 120 ( 1.4%) 3 40 hir-stats Attribute 128 ( 1.4%) 4 32 hir-stats GenericArgs 144 ( 1.6%) 3 48 hir-stats Variant 144 ( 1.6%) 2 72 -hir-stats WherePredicate 192 ( 2.1%) 3 64 -hir-stats - BoundPredicate 192 ( 2.1%) 3 -hir-stats GenericBound 256 ( 2.8%) 4 64 -hir-stats - Trait 256 ( 2.8%) 4 +hir-stats GenericBound 256 ( 2.9%) 4 64 +hir-stats - Trait 256 ( 2.9%) 4 hir-stats Block 288 ( 3.2%) 6 48 -hir-stats GenericParam 360 ( 4.0%) 5 72 -hir-stats Pat 360 ( 4.0%) 5 72 +hir-stats GenericParam 360 ( 4.1%) 5 72 +hir-stats Pat 360 ( 4.1%) 5 72 hir-stats - Struct 72 ( 0.8%) 1 hir-stats - Wild 72 ( 0.8%) 1 hir-stats - Binding 216 ( 2.4%) 3 -hir-stats Generics 560 ( 6.2%) 10 56 -hir-stats Ty 720 ( 8.0%) 15 48 +hir-stats Generics 560 ( 6.3%) 10 56 +hir-stats Ty 720 ( 8.1%) 15 48 hir-stats - Ref 48 ( 0.5%) 1 hir-stats - Ptr 48 ( 0.5%) 1 -hir-stats - Path 624 ( 6.9%) 13 -hir-stats Expr 768 ( 8.5%) 12 64 +hir-stats - Path 624 ( 7.0%) 13 +hir-stats Expr 768 ( 8.6%) 12 64 hir-stats - Path 64 ( 0.7%) 1 hir-stats - Match 64 ( 0.7%) 1 hir-stats - Struct 64 ( 0.7%) 1 hir-stats - InlineAsm 64 ( 0.7%) 1 hir-stats - Lit 128 ( 1.4%) 2 hir-stats - Block 384 ( 4.3%) 6 -hir-stats Item 968 (10.7%) 11 88 +hir-stats Item 968 (10.9%) 11 88 hir-stats - Enum 88 ( 1.0%) 1 hir-stats - Trait 88 ( 1.0%) 1 hir-stats - Impl 88 ( 1.0%) 1 hir-stats - ExternCrate 88 ( 1.0%) 1 hir-stats - ForeignMod 88 ( 1.0%) 1 hir-stats - Fn 176 ( 2.0%) 2 -hir-stats - Use 352 ( 3.9%) 4 -hir-stats Path 1_240 (13.7%) 31 40 -hir-stats PathSegment 1_920 (21.3%) 40 48 +hir-stats - Use 352 ( 4.0%) 4 +hir-stats Path 1_240 (14.0%) 31 40 +hir-stats PathSegment 1_920 (21.6%) 40 48 hir-stats ---------------------------------------------------------------- -hir-stats Total 9_024 +hir-stats Total 8_880 hir-stats diff --git a/tests/ui/where-clauses/cfg_attribute.rs b/tests/ui/where-clauses/cfg_attribute.rs new file mode 100644 index 000000000000..8815edc36c5c --- /dev/null +++ b/tests/ui/where-clauses/cfg_attribute.rs @@ -0,0 +1,91 @@ +//@ revisions: a b +//@ check-pass + +#![crate_type = "lib"] +#![feature(cfg_attribute_in_where)] +use std::marker::PhantomData; + +#[cfg(a)] +trait TraitA {} + +#[cfg(b)] +trait TraitB {} + +trait A +where + #[cfg(a)] T: TraitA, + #[cfg(b)] T: TraitB, +{ + type B + where + #[cfg(a)] U: TraitA, + #[cfg(b)] U: TraitB; + + fn foo(&self) + where + #[cfg(a)] U: TraitA, + #[cfg(b)] U: TraitB; +} + +impl A for T +where + #[cfg(a)] T: TraitA, + #[cfg(b)] T: TraitB, +{ + type B = () where + #[cfg(a)] U: TraitA, + #[cfg(b)] U: TraitB; + + fn foo(&self) + where + #[cfg(a)] U: TraitA, + #[cfg(b)] U: TraitB, {} +} + +struct C +where + #[cfg(a)] T: TraitA, + #[cfg(b)] T: TraitB, +{ + _t: PhantomData, +} + +union D +where + #[cfg(a)] T: TraitA, + #[cfg(b)] T: TraitB, +{ + + _t: PhantomData, +} + +enum E +where + #[cfg(a)] T: TraitA, + #[cfg(b)] T: TraitB, +{ + E(PhantomData), +} + +#[allow(type_alias_bounds)] +type F +where + #[cfg(a)] T: TraitA, + #[cfg(b)] T: TraitB = T; + +impl C where + #[cfg(a)] T: TraitA, + #[cfg(b)] T: TraitB, +{ + fn new() where + #[cfg(a)] U: TraitA, + #[cfg(b)] U: TraitB, + {} +} + +fn foo() +where + #[cfg(a)] T: TraitA, + #[cfg(b)] T: TraitB, +{ +} diff --git a/tests/ui/where-clauses/unsupported_attribute.rs b/tests/ui/where-clauses/unsupported_attribute.rs new file mode 100644 index 000000000000..564fc5c73340 --- /dev/null +++ b/tests/ui/where-clauses/unsupported_attribute.rs @@ -0,0 +1,28 @@ +#![crate_type = "lib"] +#![feature(cfg_attribute_in_where)] + +trait Trait {} + +fn foo<'a, T>() +where + #[doc = "doc"] T: Trait, //~ ERROR attributes in `where` clauses are not supported + #[doc = "doc"] 'a: 'static, //~ ERROR attributes in `where` clauses are not supported + #[ignore] T: Trait, //~ ERROR attributes in `where` clauses are not supported + #[ignore] 'a: 'static, //~ ERROR attributes in `where` clauses are not supported + #[should_panic] T: Trait, //~ ERROR attributes in `where` clauses are not supported + #[should_panic] 'a: 'static, //~ ERROR attributes in `where` clauses are not supported + #[macro_use] T: Trait, //~ ERROR attributes in `where` clauses are not supported + #[macro_use] 'a: 'static, //~ ERROR attributes in `where` clauses are not supported + #[allow(unused)] T: Trait, //~ ERROR attributes in `where` clauses are not supported + #[allow(unused)] 'a: 'static, //~ ERROR attributes in `where` clauses are not supported + #[warn(unused)] T: Trait, //~ ERROR attributes in `where` clauses are not supported + #[warn(unused)] 'a: 'static, //~ ERROR attributes in `where` clauses are not supported + #[deny(unused)] T: Trait, //~ ERROR attributes in `where` clauses are not supported + #[deny(unused)] 'a: 'static, //~ ERROR attributes in `where` clauses are not supported + #[forbid(unused)] T: Trait, //~ ERROR attributes in `where` clauses are not supported + #[forbid(unused)] 'a: 'static, //~ ERROR attributes in `where` clauses are not supported + #[deprecated] T: Trait, //~ ERROR attributes in `where` clauses are not supported + #[deprecated] 'a: 'static, //~ ERROR attributes in `where` clauses are not supported + #[automatically_derived] T: Trait, //~ ERROR attributes in `where` clauses are not supported + #[automatically_derived] 'a: 'static, //~ ERROR attributes in `where` clauses are not supported +{} diff --git a/tests/ui/where-clauses/unsupported_attribute.stderr b/tests/ui/where-clauses/unsupported_attribute.stderr new file mode 100644 index 000000000000..23ee2337e675 --- /dev/null +++ b/tests/ui/where-clauses/unsupported_attribute.stderr @@ -0,0 +1,162 @@ +error: attributes in `where` clauses are not supported + --> $DIR/unsupported_attribute.rs:8:5 + | +LL | #[doc = "doc"] T: Trait, + | ^^^^^^^^^^^^^^ + | + = help: only `#[cfg]` is supported in where clauses + +error: attributes in `where` clauses are not supported + --> $DIR/unsupported_attribute.rs:9:5 + | +LL | #[doc = "doc"] 'a: 'static, + | ^^^^^^^^^^^^^^ + | + = help: only `#[cfg]` is supported in where clauses + +error: attributes in `where` clauses are not supported + --> $DIR/unsupported_attribute.rs:10:5 + | +LL | #[ignore] T: Trait, + | ^^^^^^^^^ + | + = help: only `#[cfg]` is supported in where clauses + +error: attributes in `where` clauses are not supported + --> $DIR/unsupported_attribute.rs:11:5 + | +LL | #[ignore] 'a: 'static, + | ^^^^^^^^^ + | + = help: only `#[cfg]` is supported in where clauses + +error: attributes in `where` clauses are not supported + --> $DIR/unsupported_attribute.rs:12:5 + | +LL | #[should_panic] T: Trait, + | ^^^^^^^^^^^^^^^ + | + = help: only `#[cfg]` is supported in where clauses + +error: attributes in `where` clauses are not supported + --> $DIR/unsupported_attribute.rs:13:5 + | +LL | #[should_panic] 'a: 'static, + | ^^^^^^^^^^^^^^^ + | + = help: only `#[cfg]` is supported in where clauses + +error: attributes in `where` clauses are not supported + --> $DIR/unsupported_attribute.rs:14:5 + | +LL | #[macro_use] T: Trait, + | ^^^^^^^^^^^^ + | + = help: only `#[cfg]` is supported in where clauses + +error: attributes in `where` clauses are not supported + --> $DIR/unsupported_attribute.rs:15:5 + | +LL | #[macro_use] 'a: 'static, + | ^^^^^^^^^^^^ + | + = help: only `#[cfg]` is supported in where clauses + +error: attributes in `where` clauses are not supported + --> $DIR/unsupported_attribute.rs:16:5 + | +LL | #[allow(unused)] T: Trait, + | ^^^^^^^^^^^^^^^^ + | + = help: only `#[cfg]` is supported in where clauses + +error: attributes in `where` clauses are not supported + --> $DIR/unsupported_attribute.rs:17:5 + | +LL | #[allow(unused)] 'a: 'static, + | ^^^^^^^^^^^^^^^^ + | + = help: only `#[cfg]` is supported in where clauses + +error: attributes in `where` clauses are not supported + --> $DIR/unsupported_attribute.rs:18:5 + | +LL | #[warn(unused)] T: Trait, + | ^^^^^^^^^^^^^^^ + | + = help: only `#[cfg]` is supported in where clauses + +error: attributes in `where` clauses are not supported + --> $DIR/unsupported_attribute.rs:19:5 + | +LL | #[warn(unused)] 'a: 'static, + | ^^^^^^^^^^^^^^^ + | + = help: only `#[cfg]` is supported in where clauses + +error: attributes in `where` clauses are not supported + --> $DIR/unsupported_attribute.rs:20:5 + | +LL | #[deny(unused)] T: Trait, + | ^^^^^^^^^^^^^^^ + | + = help: only `#[cfg]` is supported in where clauses + +error: attributes in `where` clauses are not supported + --> $DIR/unsupported_attribute.rs:21:5 + | +LL | #[deny(unused)] 'a: 'static, + | ^^^^^^^^^^^^^^^ + | + = help: only `#[cfg]` is supported in where clauses + +error: attributes in `where` clauses are not supported + --> $DIR/unsupported_attribute.rs:22:5 + | +LL | #[forbid(unused)] T: Trait, + | ^^^^^^^^^^^^^^^^^ + | + = help: only `#[cfg]` is supported in where clauses + +error: attributes in `where` clauses are not supported + --> $DIR/unsupported_attribute.rs:23:5 + | +LL | #[forbid(unused)] 'a: 'static, + | ^^^^^^^^^^^^^^^^^ + | + = help: only `#[cfg]` is supported in where clauses + +error: attributes in `where` clauses are not supported + --> $DIR/unsupported_attribute.rs:24:5 + | +LL | #[deprecated] T: Trait, + | ^^^^^^^^^^^^^ + | + = help: only `#[cfg]` is supported in where clauses + +error: attributes in `where` clauses are not supported + --> $DIR/unsupported_attribute.rs:25:5 + | +LL | #[deprecated] 'a: 'static, + | ^^^^^^^^^^^^^ + | + = help: only `#[cfg]` is supported in where clauses + +error: attributes in `where` clauses are not supported + --> $DIR/unsupported_attribute.rs:26:5 + | +LL | #[automatically_derived] T: Trait, + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: only `#[cfg]` is supported in where clauses + +error: attributes in `where` clauses are not supported + --> $DIR/unsupported_attribute.rs:27:5 + | +LL | #[automatically_derived] 'a: 'static, + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: only `#[cfg]` is supported in where clauses + +error: aborting due to 20 previous errors +