2019-02-28 22:43:53 +00:00
// Validate AST before lowering it to HIR.
2016-05-22 14:51:22 +00:00
//
// This pass is supposed to catch things that fit into AST data structures,
// but not permitted by the language. It runs after expansion when AST is frozen,
// so it can check for erroneous constructions produced by syntax extensions.
// This pass is supposed to perform only simple checks not requiring name resolution
// or type checking or some other kind of complex analysis.
2020-04-05 23:34:16 +00:00
use itertools ::{ Either , Itertools } ;
2020-03-11 16:17:55 +00:00
use rustc_ast ::ptr ::P ;
2022-04-21 02:09:32 +00:00
use rustc_ast ::visit ::{ self , AssocCtxt , BoundKind , FnCtxt , FnKind , Visitor } ;
2020-02-29 17:37:32 +00:00
use rustc_ast ::walk_list ;
2020-04-27 17:56:11 +00:00
use rustc_ast ::* ;
2021-10-19 22:45:48 +00:00
use rustc_ast_pretty ::pprust ::{ self , State } ;
2019-02-05 15:52:17 +00:00
use rustc_data_structures ::fx ::FxHashMap ;
2022-08-18 17:43:01 +00:00
use rustc_errors ::{ error_code , fluent , pluralize , struct_span_err , Applicability } ;
2022-10-14 12:11:21 +00:00
use rustc_macros ::Subdiagnostic ;
2019-10-15 20:48:13 +00:00
use rustc_parse ::validate_attr ;
2022-02-07 06:23:37 +00:00
use rustc_session ::lint ::builtin ::{
DEPRECATED_WHERE_CLAUSE_LOCATION , MISSING_ABI , PATTERNS_IN_FNS_WITHOUT_BODY ,
} ;
2020-11-30 14:24:08 +00:00
use rustc_session ::lint ::{ BuiltinLintDiagnostics , LintBuffer } ;
2021-08-25 13:38:14 +00:00
use rustc_session ::Session ;
2021-08-08 14:49:13 +00:00
use rustc_span ::source_map ::Spanned ;
2020-04-19 11:00:18 +00:00
use rustc_span ::symbol ::{ kw , sym , Ident } ;
2019-12-31 17:15:40 +00:00
use rustc_span ::Span ;
2021-07-08 19:58:05 +00:00
use rustc_target ::spec ::abi ;
2019-12-24 22:38:22 +00:00
use std ::mem ;
2021-11-25 01:38:05 +00:00
use std ::ops ::{ Deref , DerefMut } ;
2016-05-22 14:51:22 +00:00
2022-08-17 19:36:57 +00:00
use crate ::errors ::* ;
2022-08-17 14:51:01 +00:00
2020-02-14 11:55:42 +00:00
const MORE_EXTERN : & str =
" for more information, visit https://doc.rust-lang.org/std/keyword.extern.html " ;
2020-01-29 00:30:01 +00:00
/// Is `self` allowed semantically as the first parameter in an `FnDecl`?
enum SelfSemantic {
Yes ,
No ,
}
2022-10-20 19:32:16 +00:00
/// What is the context that prevents using `~const`?
enum DisallowTildeConstContext < ' a > {
TraitObject ,
ImplTrait ,
Fn ( FnKind < ' a > ) ,
}
2016-03-06 12:54:44 +00:00
struct AstValidator < ' a > {
2016-05-22 14:51:22 +00:00
session : & ' a Session ,
2020-01-29 23:18:54 +00:00
/// The span of the `extern` in an `extern { ... }` block, if any.
extern_mod : Option < & ' a Item > ,
/// Are we inside a trait impl?
in_trait_impl : bool ,
2021-08-25 11:53:16 +00:00
in_const_trait_impl : bool ,
2019-01-17 06:28:39 +00:00
has_proc_macro_decls : bool ,
2019-01-18 11:35:14 +00:00
2019-05-05 12:06:04 +00:00
/// Used to ban nested `impl Trait`, e.g., `impl Into<impl Debug>`.
/// Nested `impl Trait` _is_ allowed in associated type position,
2019-02-28 22:43:53 +00:00
/// e.g., `impl Iterator<Item = impl Debug>`.
2019-08-03 19:59:22 +00:00
outer_impl_trait : Option < Span > ,
2019-01-18 11:35:14 +00:00
2022-10-20 19:32:16 +00:00
disallow_tilde_const : Option < DisallowTildeConstContext < ' a > > ,
2020-01-05 00:29:45 +00:00
2019-05-05 12:06:04 +00:00
/// Used to ban `impl Trait` in path projections like `<impl Iterator>::Item`
/// or `Foo::Bar<impl Trait>`
2019-01-18 11:35:14 +00:00
is_impl_trait_banned : bool ,
2019-02-20 21:24:32 +00:00
2019-03-21 17:55:09 +00:00
/// Used to ban associated type bounds (i.e., `Type<AssocType: Bounds>`) in
/// certain positions.
is_assoc_ty_bound_banned : bool ,
2022-03-09 18:04:09 +00:00
/// See [ForbiddenLetReason]
forbidden_let_reason : Option < ForbiddenLetReason > ,
2021-08-08 14:49:13 +00:00
2020-01-05 08:40:16 +00:00
lint_buffer : & ' a mut LintBuffer ,
2019-05-15 14:02:51 +00:00
}
2016-03-06 12:54:44 +00:00
impl < ' a > AstValidator < ' a > {
2021-08-25 11:53:16 +00:00
fn with_in_trait_impl (
& mut self ,
is_in : bool ,
constness : Option < Const > ,
f : impl FnOnce ( & mut Self ) ,
) {
2020-02-05 11:27:45 +00:00
let old = mem ::replace ( & mut self . in_trait_impl , is_in ) ;
2021-08-25 11:53:16 +00:00
let old_const =
mem ::replace ( & mut self . in_const_trait_impl , matches! ( constness , Some ( Const ::Yes ( _ ) ) ) ) ;
2020-02-05 11:27:45 +00:00
f ( self ) ;
self . in_trait_impl = old ;
2021-08-25 11:53:16 +00:00
self . in_const_trait_impl = old_const ;
2020-02-05 11:27:45 +00:00
}
2019-01-19 03:29:26 +00:00
fn with_banned_impl_trait ( & mut self , f : impl FnOnce ( & mut Self ) ) {
2019-06-22 23:39:13 +00:00
let old = mem ::replace ( & mut self . is_impl_trait_banned , true ) ;
f ( self ) ;
self . is_impl_trait_banned = old ;
2019-01-18 11:35:14 +00:00
}
2022-10-20 19:32:16 +00:00
fn with_tilde_const (
& mut self ,
disallowed : Option < DisallowTildeConstContext < ' a > > ,
f : impl FnOnce ( & mut Self ) ,
) {
let old = mem ::replace ( & mut self . disallow_tilde_const , disallowed ) ;
2021-08-25 11:53:16 +00:00
f ( self ) ;
2022-10-20 19:32:16 +00:00
self . disallow_tilde_const = old ;
2021-08-25 11:53:16 +00:00
}
2021-11-19 21:03:43 +00:00
fn with_tilde_const_allowed ( & mut self , f : impl FnOnce ( & mut Self ) ) {
2022-10-20 19:32:16 +00:00
self . with_tilde_const ( None , f )
2021-11-19 21:03:43 +00:00
}
2022-10-20 19:32:16 +00:00
fn with_banned_tilde_const (
& mut self ,
ctx : DisallowTildeConstContext < ' a > ,
f : impl FnOnce ( & mut Self ) ,
) {
self . with_tilde_const ( Some ( ctx ) , f )
2021-08-25 11:53:16 +00:00
}
2022-03-09 18:04:09 +00:00
fn with_let_management (
& mut self ,
forbidden_let_reason : Option < ForbiddenLetReason > ,
f : impl FnOnce ( & mut Self , Option < ForbiddenLetReason > ) ,
) {
let old = mem ::replace ( & mut self . forbidden_let_reason , forbidden_let_reason ) ;
2021-08-08 14:49:13 +00:00
f ( self , old ) ;
2022-03-09 18:04:09 +00:00
self . forbidden_let_reason = old ;
2021-08-08 14:49:13 +00:00
}
/// Emits an error banning the `let` expression provided in the given location.
2022-03-09 18:04:09 +00:00
fn ban_let_expr ( & self , expr : & ' a Expr , forbidden_let_reason : ForbiddenLetReason ) {
2022-08-20 18:40:08 +00:00
let sess = & self . session ;
if sess . opts . unstable_features . is_nightly_build ( ) {
2022-08-29 17:49:30 +00:00
sess . emit_err ( ForbiddenLet { span : expr . span , reason : forbidden_let_reason } ) ;
2022-08-20 18:40:08 +00:00
} else {
2022-08-29 17:49:30 +00:00
sess . emit_err ( ForbiddenLetStable { span : expr . span } ) ;
2022-08-20 18:40:08 +00:00
}
2021-08-08 14:49:13 +00:00
}
2021-10-19 22:45:48 +00:00
fn check_gat_where (
2022-02-07 06:23:37 +00:00
& mut self ,
id : NodeId ,
2021-10-19 22:45:48 +00:00
before_predicates : & [ WherePredicate ] ,
where_clauses : ( ast ::TyAliasWhereClause , ast ::TyAliasWhereClause ) ,
) {
if ! before_predicates . is_empty ( ) {
let mut state = State ::new ( ) ;
if ! where_clauses . 1.0 {
state . space ( ) ;
state . word_space ( " where " ) ;
} else {
state . word_space ( " , " ) ;
}
let mut first = true ;
for p in before_predicates . iter ( ) {
if ! first {
state . word_space ( " , " ) ;
}
first = false ;
state . print_where_predicate ( p ) ;
}
let suggestion = state . s . eof ( ) ;
2022-02-07 06:23:37 +00:00
self . lint_buffer . buffer_lint_with_diagnostic (
DEPRECATED_WHERE_CLAUSE_LOCATION ,
id ,
where_clauses . 0.1 ,
2022-10-22 09:07:54 +00:00
fluent ::ast_passes_deprecated_where_clause_location ,
2022-02-07 06:23:37 +00:00
BuiltinLintDiagnostics ::DeprecatedWhereclauseLocation (
2021-10-19 22:45:48 +00:00
where_clauses . 1. 1. shrink_to_hi ( ) ,
suggestion ,
2022-02-07 06:23:37 +00:00
) ,
) ;
2021-10-19 22:45:48 +00:00
}
}
2019-03-21 17:55:09 +00:00
fn with_banned_assoc_ty_bound ( & mut self , f : impl FnOnce ( & mut Self ) ) {
let old = mem ::replace ( & mut self . is_assoc_ty_bound_banned , true ) ;
f ( self ) ;
self . is_assoc_ty_bound_banned = old ;
}
2019-08-03 19:59:22 +00:00
fn with_impl_trait ( & mut self , outer : Option < Span > , f : impl FnOnce ( & mut Self ) ) {
2019-06-22 23:39:13 +00:00
let old = mem ::replace ( & mut self . outer_impl_trait , outer ) ;
2020-01-06 00:33:26 +00:00
if outer . is_some ( ) {
2022-10-20 19:32:16 +00:00
self . with_banned_tilde_const ( DisallowTildeConstContext ::ImplTrait , f ) ;
2020-01-06 00:33:26 +00:00
} else {
2021-08-25 11:53:16 +00:00
f ( self ) ;
2020-01-06 00:33:26 +00:00
}
2019-06-22 23:39:13 +00:00
self . outer_impl_trait = old ;
2020-01-05 00:29:45 +00:00
}
2021-07-30 08:56:45 +00:00
fn visit_assoc_constraint_from_generic_args ( & mut self , constraint : & ' a AssocConstraint ) {
2019-03-21 17:55:09 +00:00
match constraint . kind {
2021-07-30 08:56:45 +00:00
AssocConstraintKind ::Equality { .. } = > { }
AssocConstraintKind ::Bound { .. } = > {
2019-03-21 17:55:09 +00:00
if self . is_assoc_ty_bound_banned {
2022-08-17 19:36:57 +00:00
self . session . emit_err ( ForbiddenAssocConstraint { span : constraint . span } ) ;
2019-03-21 17:55:09 +00:00
}
2019-02-28 22:43:53 +00:00
}
2019-03-11 14:14:24 +00:00
}
2021-07-30 08:56:45 +00:00
self . visit_assoc_constraint ( constraint ) ;
2019-03-11 14:14:24 +00:00
}
2019-02-28 22:43:53 +00:00
// Mirrors `visit::walk_ty`, but tracks relevant state.
2019-01-18 11:35:14 +00:00
fn walk_ty ( & mut self , t : & ' a Ty ) {
2022-11-28 19:16:44 +00:00
match & t . kind {
2019-01-18 11:35:14 +00:00
TyKind ::ImplTrait ( .. ) = > {
2019-08-03 19:59:22 +00:00
self . with_impl_trait ( Some ( t . span ) , | this | visit ::walk_ty ( this , t ) )
2019-01-18 11:35:14 +00:00
}
2022-10-20 19:32:16 +00:00
TyKind ::TraitObject ( .. ) = > self
. with_banned_tilde_const ( DisallowTildeConstContext ::TraitObject , | this | {
visit ::walk_ty ( this , t )
} ) ,
2022-11-28 19:16:44 +00:00
TyKind ::Path ( qself , path ) = > {
2019-01-18 11:35:14 +00:00
// We allow these:
// - `Option<impl Trait>`
// - `option::Option<impl Trait>`
// - `option::Option<T>::Foo<impl Trait>
//
// But not these:
// - `<impl Trait>::Foo`
// - `option::Option<impl Trait>::Foo`.
//
// To implement this, we disallow `impl Trait` from `qself`
// (for cases like `<impl Trait>::Foo>`)
// but we allow `impl Trait` in `GenericArgs`
// iff there are no more PathSegments.
2022-11-28 19:16:44 +00:00
if let Some ( qself ) = qself {
2019-01-18 11:35:14 +00:00
// `impl Trait` in `qself` is always illegal
self . with_banned_impl_trait ( | this | this . visit_ty ( & qself . ty ) ) ;
}
// Note that there should be a call to visit_path here,
// so if any logic is added to process `Path`s a call to it should be
// added both in visit_path and here. This code mirrors visit::walk_path.
for ( i , segment ) in path . segments . iter ( ) . enumerate ( ) {
// Allow `impl Trait` iff we're on the final path segment
if i = = path . segments . len ( ) - 1 {
2022-09-12 00:43:34 +00:00
self . visit_path_segment ( segment ) ;
2019-01-18 11:35:14 +00:00
} else {
2022-09-12 00:43:34 +00:00
self . with_banned_impl_trait ( | this | this . visit_path_segment ( segment ) ) ;
2019-01-18 11:35:14 +00:00
}
}
}
_ = > visit ::walk_ty ( self , t ) ,
}
}
2020-01-09 10:18:47 +00:00
fn err_handler ( & self ) -> & rustc_errors ::Handler {
2018-07-26 22:18:06 +00:00
& self . session . diagnostic ( )
2016-05-22 14:51:22 +00:00
}
2018-03-19 00:54:56 +00:00
fn check_lifetime ( & self , ident : Ident ) {
2020-12-30 01:28:08 +00:00
let valid_names = [ kw ::UnderscoreLifetime , kw ::StaticLifetime , kw ::Empty ] ;
2018-05-13 13:14:43 +00:00
if ! valid_names . contains ( & ident . name ) & & ident . without_first_quote ( ) . is_reserved ( ) {
2022-08-17 19:36:57 +00:00
self . session . emit_err ( KeywordLifetime { span : ident . span } ) ;
2017-12-06 09:28:01 +00:00
}
}
2018-03-19 00:54:56 +00:00
fn check_label ( & self , ident : Ident ) {
2018-05-13 13:14:43 +00:00
if ident . without_first_quote ( ) . is_reserved ( ) {
2022-08-17 19:36:57 +00:00
self . session . emit_err ( InvalidLabel { span : ident . span , name : ident . name } ) ;
2016-05-22 14:51:22 +00:00
}
}
2016-05-22 15:07:28 +00:00
2022-08-17 19:36:57 +00:00
fn invalid_visibility ( & self , vis : & Visibility , note : Option < InvalidVisibilityNote > ) {
2020-08-21 23:11:00 +00:00
if let VisibilityKind ::Inherited = vis . kind {
2019-12-24 22:38:22 +00:00
return ;
2018-03-20 22:58:25 +00:00
}
2022-08-17 19:36:57 +00:00
self . session . emit_err ( InvalidVisibility {
span : vis . span ,
implied : if vis . kind . is_pub ( ) { Some ( vis . span ) } else { None } ,
note ,
} ) ;
2016-05-22 15:07:28 +00:00
}
2016-07-16 21:15:15 +00:00
2020-11-30 14:24:08 +00:00
fn check_decl_no_pat ( decl : & FnDecl , mut report_err : impl FnMut ( Span , Option < Ident > , bool ) ) {
2019-12-01 11:43:39 +00:00
for Param { pat , .. } in & decl . inputs {
match pat . kind {
2022-08-30 22:34:35 +00:00
PatKind ::Ident ( BindingAnnotation ::NONE , _ , None ) | PatKind ::Wild = > { }
PatKind ::Ident ( BindingAnnotation ::MUT , ident , None ) = > {
2020-11-30 14:24:08 +00:00
report_err ( pat . span , Some ( ident ) , true )
2019-12-24 22:38:22 +00:00
}
2020-11-30 14:24:08 +00:00
_ = > report_err ( pat . span , None , false ) ,
2016-07-16 21:15:15 +00:00
}
}
}
2016-08-07 21:33:35 +00:00
2020-01-30 01:42:33 +00:00
fn check_trait_fn_not_const ( & self , constness : Const ) {
if let Const ::Yes ( span ) = constness {
2022-08-18 08:38:11 +00:00
self . session . emit_err ( TraitFnConst { span } ) ;
2016-08-07 21:33:35 +00:00
}
}
2016-10-22 00:33:36 +00:00
2018-07-27 14:50:28 +00:00
fn check_late_bound_lifetime_defs ( & self , params : & [ GenericParam ] ) {
2018-05-26 18:16:21 +00:00
// Check only lifetime parameters are present and that the lifetime
// parameters that are present have no bounds.
2019-12-24 22:38:22 +00:00
let non_lt_param_spans : Vec < _ > = params
. iter ( )
. filter_map ( | param | match param . kind {
GenericParamKind ::Lifetime { .. } = > {
if ! param . bounds . is_empty ( ) {
let spans : Vec < _ > = param . bounds . iter ( ) . map ( | b | b . span ( ) ) . collect ( ) ;
2022-08-18 08:38:11 +00:00
self . session . emit_err ( ForbiddenLifetimeBound { spans } ) ;
2019-12-24 22:38:22 +00:00
}
None
2018-03-06 10:22:24 +00:00
}
2019-12-24 22:38:22 +00:00
_ = > Some ( param . ident . span ) ,
} )
. collect ( ) ;
2018-05-27 15:56:01 +00:00
if ! non_lt_param_spans . is_empty ( ) {
2022-08-18 08:38:11 +00:00
self . session . emit_err ( ForbiddenNonLifetimeParam { spans : non_lt_param_spans } ) ;
2018-03-06 10:22:24 +00:00
}
}
2018-08-31 18:35:03 +00:00
2020-01-29 00:30:01 +00:00
fn check_fn_decl ( & self , fn_decl : & FnDecl , self_semantic : SelfSemantic ) {
2021-09-07 21:48:03 +00:00
self . check_decl_num_args ( fn_decl ) ;
2020-01-29 00:30:01 +00:00
self . check_decl_cvaradic_pos ( fn_decl ) ;
self . check_decl_attrs ( fn_decl ) ;
self . check_decl_self_param ( fn_decl , self_semantic ) ;
}
2021-09-07 21:48:03 +00:00
/// Emits fatal error if function declaration has more than `u16::MAX` arguments
/// Error is fatal to prevent errors during typechecking
fn check_decl_num_args ( & self , fn_decl : & FnDecl ) {
let max_num_args : usize = u16 ::MAX . into ( ) ;
if fn_decl . inputs . len ( ) > max_num_args {
let Param { span , .. } = fn_decl . inputs [ 0 ] ;
2022-08-18 12:20:50 +00:00
self . session . emit_fatal ( FnParamTooMany { span , max_num_args } ) ;
2021-09-07 21:48:03 +00:00
}
}
2020-01-29 00:30:01 +00:00
fn check_decl_cvaradic_pos ( & self , fn_decl : & FnDecl ) {
2019-12-02 02:16:12 +00:00
match & * fn_decl . inputs {
2019-12-24 22:38:22 +00:00
[ Param { ty , span , .. } ] = > {
if let TyKind ::CVarArgs = ty . kind {
2022-08-18 09:20:14 +00:00
self . session . emit_err ( FnParamCVarArgsOnly { span : * span } ) ;
2019-12-24 22:38:22 +00:00
}
}
[ ps @ .. , _ ] = > {
for Param { ty , span , .. } in ps {
if let TyKind ::CVarArgs = ty . kind {
2022-08-18 09:20:14 +00:00
self . session . emit_err ( FnParamCVarArgsNotLast { span : * span } ) ;
2019-12-24 22:38:22 +00:00
}
2019-12-02 02:16:12 +00:00
}
}
_ = > { }
}
2020-01-29 00:30:01 +00:00
}
2019-12-02 02:16:12 +00:00
2020-01-29 00:30:01 +00:00
fn check_decl_attrs ( & self , fn_decl : & FnDecl ) {
2019-06-09 10:58:40 +00:00
fn_decl
. inputs
. iter ( )
. flat_map ( | i | i . attrs . as_ref ( ) )
. filter ( | attr | {
2022-06-03 22:04:19 +00:00
let arr = [
sym ::allow ,
sym ::cfg ,
sym ::cfg_attr ,
sym ::deny ,
sym ::expect ,
sym ::forbid ,
sym ::warn ,
] ;
2020-01-11 12:15:20 +00:00
! arr . contains ( & attr . name_or_empty ( ) ) & & rustc_attr ::is_builtin_attr ( attr )
2019-06-09 10:58:40 +00:00
} )
2019-12-24 22:38:22 +00:00
. for_each ( | attr | {
if attr . is_doc_comment ( ) {
2022-08-18 09:20:14 +00:00
self . session . emit_err ( FnParamDocComment { span : attr . span } ) ;
2019-12-24 22:38:22 +00:00
} else {
2022-08-18 09:20:14 +00:00
self . session . emit_err ( FnParamForbiddenAttr { span : attr . span } ) ;
2019-12-24 22:38:22 +00:00
}
2019-06-09 10:58:40 +00:00
} ) ;
}
2019-11-30 17:25:44 +00:00
2020-01-29 00:30:01 +00:00
fn check_decl_self_param ( & self , fn_decl : & FnDecl , self_semantic : SelfSemantic ) {
if let ( SelfSemantic ::No , [ param , .. ] ) = ( self_semantic , & * fn_decl . inputs ) {
if param . is_self ( ) {
2022-08-18 09:20:14 +00:00
self . session . emit_err ( FnParamForbiddenSelf { span : param . span } ) ;
2020-01-29 00:30:01 +00:00
}
}
}
2019-11-30 17:25:44 +00:00
fn check_defaultness ( & self , span : Span , defaultness : Defaultness ) {
2020-02-22 01:01:53 +00:00
if let Defaultness ::Default ( def_span ) = defaultness {
2020-03-09 18:42:37 +00:00
let span = self . session . source_map ( ) . guess_head_span ( span ) ;
2022-08-18 17:43:01 +00:00
self . session . emit_err ( ForbiddenDefault { span , def_span } ) ;
2019-11-30 17:25:44 +00:00
}
}
2019-12-01 06:24:07 +00:00
2022-08-18 17:43:01 +00:00
/// If `sp` ends with a semicolon, returns it as a `Span`
/// Otherwise, returns `sp.shrink_to_hi()`
fn ending_semi_or_hi ( & self , sp : Span ) -> Span {
2022-03-22 22:29:07 +00:00
let source_map = self . session . source_map ( ) ;
let end = source_map . end_point ( sp ) ;
2022-08-18 17:43:01 +00:00
if source_map . span_to_snippet ( end ) . map ( | s | s = = " ; " ) . unwrap_or ( false ) {
2022-03-22 22:29:07 +00:00
end
} else {
sp . shrink_to_hi ( )
2020-01-29 23:18:54 +00:00
}
}
2020-02-14 11:55:42 +00:00
fn check_type_no_bounds ( & self , bounds : & [ GenericBound ] , ctx : & str ) {
2019-12-01 09:25:45 +00:00
let span = match bounds {
[ ] = > return ,
[ b0 ] = > b0 . span ( ) ,
[ b0 , .. , bl ] = > b0 . span ( ) . to ( bl . span ( ) ) ,
} ;
self . err_handler ( )
2020-02-14 11:55:42 +00:00
. struct_span_err ( span , & format! ( " bounds on `type`s in {} have no effect " , ctx ) )
. emit ( ) ;
}
2021-10-19 22:45:48 +00:00
fn check_foreign_ty_genericless ( & self , generics : & Generics , where_span : Span ) {
2020-02-14 11:55:42 +00:00
let cannot_have = | span , descr , remove_descr | {
self . err_handler ( )
. struct_span_err (
span ,
& format! ( " `type`s inside `extern` blocks cannot have {} " , descr ) ,
)
. span_suggestion (
span ,
& format! ( " remove the {} " , remove_descr ) ,
2022-06-13 06:48:40 +00:00
" " ,
2020-02-14 11:55:42 +00:00
Applicability ::MaybeIncorrect ,
)
. span_label ( self . current_extern_span ( ) , " `extern` block begins here " )
. note ( MORE_EXTERN )
. emit ( ) ;
} ;
if ! generics . params . is_empty ( ) {
cannot_have ( generics . span , " generic parameters " , " generic parameters " ) ;
}
if ! generics . where_clause . predicates . is_empty ( ) {
2021-10-19 22:45:48 +00:00
cannot_have ( where_span , " `where` clauses " , " `where` clause " ) ;
2020-02-14 11:55:42 +00:00
}
}
2020-02-14 14:56:05 +00:00
fn check_foreign_kind_bodyless ( & self , ident : Ident , kind : & str , body : Option < Span > ) {
2022-02-18 23:48:49 +00:00
let Some ( body ) = body else {
return ;
2020-02-14 11:55:42 +00:00
} ;
self . err_handler ( )
2020-02-14 14:56:05 +00:00
. struct_span_err ( ident . span , & format! ( " incorrect ` {} ` inside `extern` block " , kind ) )
2020-02-14 11:55:42 +00:00
. span_label ( ident . span , " cannot have a body " )
2020-02-14 14:56:05 +00:00
. span_label ( body , " the invalid body " )
2020-02-14 11:55:42 +00:00
. span_label (
self . current_extern_span ( ) ,
2020-02-14 14:56:05 +00:00
format! (
" `extern` blocks define existing foreign {0}s and {0}s \
inside of them cannot have a body " ,
kind
) ,
2020-02-14 11:55:42 +00:00
)
. note ( MORE_EXTERN )
2019-12-01 09:25:45 +00:00
. emit ( ) ;
}
2019-12-02 01:38:33 +00:00
2020-01-29 23:18:54 +00:00
/// An `fn` in `extern { ... }` cannot have a body `{ ... }`.
fn check_foreign_fn_bodyless ( & self , ident : Ident , body : Option < & Block > ) {
2022-02-18 23:48:49 +00:00
let Some ( body ) = body else {
return ;
2020-01-29 23:18:54 +00:00
} ;
self . err_handler ( )
. struct_span_err ( ident . span , " incorrect function inside `extern` block " )
. span_label ( ident . span , " cannot have a body " )
. span_suggestion (
body . span ,
" remove the invalid body " ,
2022-06-13 06:48:40 +00:00
" ; " ,
2020-01-29 23:18:54 +00:00
Applicability ::MaybeIncorrect ,
)
. help (
" you might have meant to write a function accessible through FFI, \
which can be done by writing ` extern fn ` outside of the ` extern ` block " ,
)
. span_label (
self . current_extern_span ( ) ,
" `extern` blocks define existing foreign functions and functions \
inside of them cannot have a body " ,
)
2020-02-14 11:55:42 +00:00
. note ( MORE_EXTERN )
2020-01-29 23:18:54 +00:00
. emit ( ) ;
}
fn current_extern_span ( & self ) -> Span {
2020-03-09 18:42:37 +00:00
self . session . source_map ( ) . guess_head_span ( self . extern_mod . unwrap ( ) . span )
2020-01-29 23:18:54 +00:00
}
2020-10-29 15:51:46 +00:00
/// An `fn` in `extern { ... }` cannot have qualifiers, e.g. `async fn`.
2020-01-29 23:18:54 +00:00
fn check_foreign_fn_headerless ( & self , ident : Ident , span : Span , header : FnHeader ) {
if header . has_qualifiers ( ) {
self . err_handler ( )
. struct_span_err ( ident . span , " functions in `extern` blocks cannot have qualifiers " )
. span_label ( self . current_extern_span ( ) , " in this `extern` block " )
2020-11-15 20:36:07 +00:00
. span_suggestion_verbose (
2020-01-29 23:18:54 +00:00
span . until ( ident . span . shrink_to_lo ( ) ) ,
" remove the qualifiers " ,
2022-06-13 06:48:40 +00:00
" fn " ,
2020-01-29 23:18:54 +00:00
Applicability ::MaybeIncorrect ,
)
. emit ( ) ;
}
}
2021-04-06 15:49:59 +00:00
/// An item in `extern { ... }` cannot use non-ascii identifier.
fn check_foreign_item_ascii_only ( & self , ident : Ident ) {
2021-12-15 05:13:11 +00:00
if ! ident . as_str ( ) . is_ascii ( ) {
2021-04-06 15:49:59 +00:00
let n = 83942 ;
self . err_handler ( )
. struct_span_err (
ident . span ,
" items in `extern` blocks cannot use non-ascii identifiers " ,
)
. span_label ( self . current_extern_span ( ) , " in this `extern` block " )
. note ( & format! (
2021-10-03 06:53:02 +00:00
" this limitation may be lifted in the future; see issue #{} <https://github.com/rust-lang/rust/issues/{}> for more information " ,
2021-04-06 15:49:59 +00:00
n , n ,
) )
. emit ( ) ;
}
}
2022-03-30 05:39:38 +00:00
/// Reject C-variadic type unless the function is foreign,
2020-01-29 23:18:54 +00:00
/// or free and `unsafe extern "C"` semantically.
2022-03-30 05:42:10 +00:00
fn check_c_variadic_type ( & self , fk : FnKind < ' a > ) {
2020-01-29 23:18:54 +00:00
match ( fk . ctxt ( ) , fk . header ( ) ) {
( Some ( FnCtxt ::Foreign ) , _ ) = > return ,
( Some ( FnCtxt ::Free ) , Some ( header ) ) = > match header . ext {
2022-07-02 17:25:55 +00:00
Extern ::Explicit ( StrLit { symbol_unescaped : sym ::C , .. } , _ )
| Extern ::Implicit ( _ )
2020-01-30 01:42:33 +00:00
if matches! ( header . unsafety , Unsafe ::Yes ( _ ) ) = >
2020-01-29 23:18:54 +00:00
{
return ;
}
_ = > { }
} ,
_ = > { }
} ;
for Param { ty , span , .. } in & fk . decl ( ) . inputs {
2019-12-02 01:38:33 +00:00
if let TyKind ::CVarArgs = ty . kind {
self . err_handler ( )
. struct_span_err (
* span ,
2021-06-09 10:41:03 +00:00
" only foreign or `unsafe extern \" C \" ` functions may be C-variadic " ,
2019-12-02 01:38:33 +00:00
)
. emit ( ) ;
}
}
}
2020-01-29 23:18:54 +00:00
2020-02-14 14:56:05 +00:00
fn check_item_named ( & self , ident : Ident , kind : & str ) {
if ident . name ! = kw ::Underscore {
return ;
}
self . err_handler ( )
. struct_span_err ( ident . span , & format! ( " ` {} ` items in this context need a name " , kind ) )
. span_label ( ident . span , format! ( " `_` is not a valid name for this ` {} ` item " , kind ) )
. emit ( ) ;
}
2020-03-11 16:17:55 +00:00
2020-05-16 06:09:01 +00:00
fn check_nomangle_item_asciionly ( & self , ident : Ident , item_span : Span ) {
if ident . name . as_str ( ) . is_ascii ( ) {
return ;
}
let head_span = self . session . source_map ( ) . guess_head_span ( item_span ) ;
struct_span_err! (
self . session ,
head_span ,
E0754 ,
" `#[no_mangle]` requires ASCII identifier "
)
. emit ( ) ;
}
fn check_mod_file_item_asciionly ( & self , ident : Ident ) {
if ident . name . as_str ( ) . is_ascii ( ) {
return ;
}
struct_span_err! (
self . session ,
ident . span ,
E0754 ,
2021-04-06 15:49:59 +00:00
" trying to load file for module `{}` with non-ascii identifier name " ,
2020-05-16 06:09:01 +00:00
ident . name
)
. help ( " consider using `#[path]` attribute to specify filesystem path " )
. emit ( ) ;
}
2020-03-11 16:17:55 +00:00
fn deny_generic_params ( & self , generics : & Generics , ident_span : Span ) {
if ! generics . params . is_empty ( ) {
struct_span_err! (
self . session ,
generics . span ,
E0567 ,
" auto traits cannot have generic parameters "
)
. span_label ( ident_span , " auto trait cannot have generic parameters " )
. span_suggestion (
generics . span ,
" remove the parameters " ,
2022-06-13 06:48:40 +00:00
" " ,
2020-03-11 16:17:55 +00:00
Applicability ::MachineApplicable ,
)
. emit ( ) ;
}
}
2021-10-03 15:58:10 +00:00
fn emit_e0568 ( & self , span : Span , ident_span : Span ) {
struct_span_err! (
self . session ,
span ,
E0568 ,
" auto traits cannot have super traits or lifetime bounds "
)
. span_label ( ident_span , " auto trait cannot have super traits or lifetime bounds " )
. span_suggestion (
span ,
" remove the super traits or lifetime bounds " ,
2022-06-13 06:48:40 +00:00
" " ,
2021-10-03 15:58:10 +00:00
Applicability ::MachineApplicable ,
)
. emit ( ) ;
}
2020-03-11 16:17:55 +00:00
fn deny_super_traits ( & self , bounds : & GenericBounds , ident_span : Span ) {
2021-10-03 15:58:10 +00:00
if let [ .. , last ] = & bounds [ .. ] {
let span = ident_span . shrink_to_hi ( ) . to ( last . span ( ) ) ;
self . emit_e0568 ( span , ident_span ) ;
}
}
fn deny_where_clause ( & self , where_clause : & WhereClause , ident_span : Span ) {
if ! where_clause . predicates . is_empty ( ) {
self . emit_e0568 ( where_clause . span , ident_span ) ;
2020-03-11 16:17:55 +00:00
}
}
fn deny_items ( & self , trait_items : & [ P < AssocItem > ] , ident_span : Span ) {
if ! trait_items . is_empty ( ) {
let spans : Vec < _ > = trait_items . iter ( ) . map ( | i | i . ident . span ) . collect ( ) ;
2021-10-03 15:58:10 +00:00
let total_span = trait_items . first ( ) . unwrap ( ) . span . to ( trait_items . last ( ) . unwrap ( ) . span ) ;
2020-03-11 16:17:55 +00:00
struct_span_err! (
self . session ,
spans ,
E0380 ,
2021-10-03 15:58:10 +00:00
" auto traits cannot have associated items "
)
. span_suggestion (
total_span ,
" remove these associated items " ,
2022-06-13 06:48:40 +00:00
" " ,
2021-10-03 15:58:10 +00:00
Applicability ::MachineApplicable ,
2020-03-11 16:17:55 +00:00
)
2021-10-03 15:58:10 +00:00
. span_label ( ident_span , " auto trait cannot have associated items " )
2020-03-11 16:17:55 +00:00
. emit ( ) ;
}
}
2020-03-22 03:40:05 +00:00
2020-04-05 23:34:16 +00:00
fn correct_generic_order_suggestion ( & self , data : & AngleBracketedArgs ) -> String {
2020-03-29 18:31:58 +00:00
// Lifetimes always come first.
let lt_sugg = data . args . iter ( ) . filter_map ( | arg | match arg {
AngleBracketedArg ::Arg ( lt @ GenericArg ::Lifetime ( _ ) ) = > {
Some ( pprust ::to_string ( | s | s . print_generic_arg ( lt ) ) )
}
_ = > None ,
} ) ;
let args_sugg = data . args . iter ( ) . filter_map ( | a | match a {
2020-04-05 23:34:16 +00:00
AngleBracketedArg ::Arg ( GenericArg ::Lifetime ( _ ) ) | AngleBracketedArg ::Constraint ( _ ) = > {
None
}
2020-03-29 18:31:58 +00:00
AngleBracketedArg ::Arg ( arg ) = > Some ( pprust ::to_string ( | s | s . print_generic_arg ( arg ) ) ) ,
} ) ;
2020-04-05 23:34:16 +00:00
// Constraints always come last.
2020-03-29 18:31:58 +00:00
let constraint_sugg = data . args . iter ( ) . filter_map ( | a | match a {
AngleBracketedArg ::Arg ( _ ) = > None ,
AngleBracketedArg ::Constraint ( c ) = > {
Some ( pprust ::to_string ( | s | s . print_assoc_constraint ( c ) ) )
}
} ) ;
format! (
" <{}> " ,
lt_sugg . chain ( args_sugg ) . chain ( constraint_sugg ) . collect ::< Vec < String > > ( ) . join ( " , " )
)
}
2020-03-22 03:40:05 +00:00
/// Enforce generic args coming before constraints in `<...>` of a path segment.
fn check_generic_args_before_constraints ( & self , data : & AngleBracketedArgs ) {
// Early exit in case it's partitioned as it should be.
if data . args . iter ( ) . is_partitioned ( | arg | matches! ( arg , AngleBracketedArg ::Arg ( _ ) ) ) {
return ;
}
// Find all generic argument coming after the first constraint...
2020-04-05 23:34:16 +00:00
let ( constraint_spans , arg_spans ) : ( Vec < Span > , Vec < Span > ) =
data . args . iter ( ) . partition_map ( | arg | match arg {
AngleBracketedArg ::Constraint ( c ) = > Either ::Left ( c . span ) ,
AngleBracketedArg ::Arg ( a ) = > Either ::Right ( a . span ( ) ) ,
} ) ;
2020-03-29 18:31:58 +00:00
let args_len = arg_spans . len ( ) ;
2020-03-28 20:48:04 +00:00
let constraint_len = constraint_spans . len ( ) ;
2020-03-22 03:40:05 +00:00
// ...and then error:
self . err_handler ( )
. struct_span_err (
2020-03-28 20:48:04 +00:00
arg_spans . clone ( ) ,
2020-03-27 06:39:10 +00:00
" generic arguments must come before the first constraint " ,
2020-03-22 03:40:05 +00:00
)
2020-04-06 00:02:44 +00:00
. span_label ( constraint_spans [ 0 ] , & format! ( " constraint {} " , pluralize! ( constraint_len ) ) )
. span_label (
* arg_spans . iter ( ) . last ( ) . unwrap ( ) ,
& format! ( " generic argument {} " , pluralize! ( args_len ) ) ,
)
. span_labels ( constraint_spans , " " )
. span_labels ( arg_spans , " " )
2020-03-29 18:31:58 +00:00
. span_suggestion_verbose (
data . span ,
& format! (
" move the constraint{} after the generic argument{} " ,
pluralize! ( constraint_len ) ,
pluralize! ( args_len )
) ,
2020-04-05 23:34:16 +00:00
self . correct_generic_order_suggestion ( & data ) ,
2020-03-29 00:45:36 +00:00
Applicability ::MachineApplicable ,
)
2020-03-22 03:40:05 +00:00
. emit ( ) ;
}
2021-05-16 14:51:00 +00:00
fn visit_ty_common ( & mut self , ty : & ' a Ty ) {
2022-11-28 19:16:44 +00:00
match & ty . kind {
TyKind ::BareFn ( bfty ) = > {
2021-05-16 14:51:00 +00:00
self . check_fn_decl ( & bfty . decl , SelfSemantic ::No ) ;
Self ::check_decl_no_pat ( & bfty . decl , | span , _ , _ | {
struct_span_err! (
self . session ,
span ,
E0561 ,
" patterns aren't allowed in function pointer types "
)
. emit ( ) ;
} ) ;
self . check_late_bound_lifetime_defs ( & bfty . generic_params ) ;
2022-07-02 17:25:55 +00:00
if let Extern ::Implicit ( _ ) = bfty . ext {
2021-07-08 19:58:05 +00:00
let sig_span = self . session . source_map ( ) . next_point ( ty . span . shrink_to_lo ( ) ) ;
self . maybe_lint_missing_abi ( sig_span , ty . id ) ;
}
2021-05-16 14:51:00 +00:00
}
2022-11-28 19:16:44 +00:00
TyKind ::TraitObject ( bounds , .. ) = > {
2021-05-16 14:51:00 +00:00
let mut any_lifetime_bounds = false ;
for bound in bounds {
2022-11-28 19:16:44 +00:00
if let GenericBound ::Outlives ( lifetime ) = bound {
2021-05-16 14:51:00 +00:00
if any_lifetime_bounds {
struct_span_err! (
self . session ,
lifetime . ident . span ,
E0226 ,
" only a single explicit lifetime bound is permitted "
)
. emit ( ) ;
break ;
}
any_lifetime_bounds = true ;
}
}
}
2022-11-28 19:16:44 +00:00
TyKind ::ImplTrait ( _ , bounds ) = > {
2021-05-16 14:51:00 +00:00
if self . is_impl_trait_banned {
struct_span_err! (
self . session ,
ty . span ,
E0667 ,
" `impl Trait` is not allowed in path parameters "
)
. emit ( ) ;
}
if let Some ( outer_impl_trait_sp ) = self . outer_impl_trait {
struct_span_err! (
self . session ,
ty . span ,
E0666 ,
" nested `impl Trait` is not allowed "
)
. span_label ( outer_impl_trait_sp , " outer `impl Trait` " )
. span_label ( ty . span , " nested `impl Trait` here " )
. emit ( ) ;
}
if ! bounds . iter ( ) . any ( | b | matches! ( b , GenericBound ::Trait ( .. ) ) ) {
self . err_handler ( ) . span_err ( ty . span , " at least one trait must be specified " ) ;
}
}
_ = > { }
}
}
2021-07-08 19:58:05 +00:00
fn maybe_lint_missing_abi ( & mut self , span : Span , id : NodeId ) {
// FIXME(davidtwco): This is a hack to detect macros which produce spans of the
// call site which do not have a macro backtrace. See #61963.
let is_macro_callsite = self
. session
. source_map ( )
. span_to_snippet ( span )
. map ( | snippet | snippet . starts_with ( " #[ " ) )
. unwrap_or ( true ) ;
if ! is_macro_callsite {
self . lint_buffer . buffer_lint_with_diagnostic (
MISSING_ABI ,
id ,
span ,
" extern declarations without an explicit ABI are deprecated " ,
BuiltinLintDiagnostics ::MissingAbi ( span , abi ::Abi ::FALLBACK ) ,
)
}
}
2019-02-05 15:52:17 +00:00
}
2020-03-19 19:20:09 +00:00
/// Checks that generic parameters are in the correct order,
/// which is lifetimes, then types and then consts. (`<'a, T, const N: usize>`)
2020-12-30 16:43:30 +00:00
fn validate_generic_param_order (
2020-01-09 10:18:47 +00:00
handler : & rustc_errors ::Handler ,
2020-12-30 16:43:30 +00:00
generics : & [ GenericParam ] ,
2019-02-05 15:52:17 +00:00
span : Span ,
) {
let mut max_param : Option < ParamKindOrd > = None ;
let mut out_of_order = FxHashMap ::default ( ) ;
2021-06-09 21:09:12 +00:00
let mut param_idents = Vec ::with_capacity ( generics . len ( ) ) ;
2019-02-05 15:52:17 +00:00
2021-06-09 21:09:12 +00:00
for ( idx , param ) in generics . iter ( ) . enumerate ( ) {
let ident = param . ident ;
let ( kind , bounds , span ) = ( & param . kind , & param . bounds , ident . span ) ;
2020-12-30 16:43:30 +00:00
let ( ord_kind , ident ) = match & param . kind {
2021-06-09 21:09:12 +00:00
GenericParamKind ::Lifetime = > ( ParamKindOrd ::Lifetime , ident . to_string ( ) ) ,
2022-11-28 19:16:44 +00:00
GenericParamKind ::Type { .. } = > ( ParamKindOrd ::TypeOrConst , ident . to_string ( ) ) ,
GenericParamKind ::Const { ty , .. } = > {
2020-12-30 16:43:30 +00:00
let ty = pprust ::ty_to_string ( ty ) ;
2022-09-08 13:10:49 +00:00
( ParamKindOrd ::TypeOrConst , format! ( " const {} : {} " , ident , ty ) )
2020-12-30 16:43:30 +00:00
}
} ;
2021-06-09 21:09:12 +00:00
param_idents . push ( ( kind , ord_kind , bounds , idx , ident ) ) ;
2019-02-05 15:52:17 +00:00
match max_param {
2021-06-09 21:09:12 +00:00
Some ( max_param ) if max_param > ord_kind = > {
let entry = out_of_order . entry ( ord_kind ) . or_insert ( ( max_param , vec! [ ] ) ) ;
2019-02-05 15:52:17 +00:00
entry . 1. push ( span ) ;
}
2021-06-09 21:09:12 +00:00
Some ( _ ) | None = > max_param = Some ( ord_kind ) ,
2019-02-05 15:52:17 +00:00
} ;
}
if ! out_of_order . is_empty ( ) {
2021-06-09 21:09:12 +00:00
let mut ordered_params = " < " . to_string ( ) ;
2020-12-30 16:43:30 +00:00
param_idents . sort_by_key ( | & ( _ , po , _ , i , _ ) | ( po , i ) ) ;
2019-02-05 15:52:17 +00:00
let mut first = true ;
2020-12-30 16:43:30 +00:00
for ( kind , _ , bounds , _ , ident ) in param_idents {
2019-02-05 15:52:17 +00:00
if ! first {
ordered_params + = " , " ;
}
2019-02-05 18:00:07 +00:00
ordered_params + = & ident ;
2021-06-09 21:09:12 +00:00
if ! bounds . is_empty ( ) {
ordered_params + = " : " ;
ordered_params + = & pprust ::bounds_to_string ( & bounds ) ;
2019-03-30 19:30:36 +00:00
}
2021-06-09 21:09:12 +00:00
2020-12-30 16:43:30 +00:00
match kind {
GenericParamKind ::Type { default : Some ( default ) } = > {
ordered_params + = " = " ;
ordered_params + = & pprust ::ty_to_string ( default ) ;
}
GenericParamKind ::Type { default : None } = > ( ) ,
GenericParamKind ::Lifetime = > ( ) ,
2021-05-29 02:54:32 +00:00
GenericParamKind ::Const { ty : _ , kw_span : _ , default : Some ( default ) } = > {
ordered_params + = " = " ;
ordered_params + = & pprust ::expr_to_string ( & * default . value ) ;
}
GenericParamKind ::Const { ty : _ , kw_span : _ , default : None } = > ( ) ,
2020-12-30 16:43:30 +00:00
}
2019-02-05 15:52:17 +00:00
first = false ;
}
2021-06-09 21:09:12 +00:00
ordered_params + = " > " ;
for ( param_ord , ( max_param , spans ) ) in & out_of_order {
let mut err = handler . struct_span_err (
2020-01-21 23:07:07 +00:00
spans . clone ( ) ,
2019-03-30 19:57:04 +00:00
& format! (
2020-01-21 23:07:07 +00:00
" {} parameters must be declared prior to {} parameters " ,
param_ord , max_param ,
2019-03-30 19:57:04 +00:00
) ,
2019-02-05 15:52:17 +00:00
) ;
2021-06-09 21:09:12 +00:00
err . span_suggestion (
span ,
2021-10-23 15:57:13 +00:00
" reorder the parameters: lifetimes, then consts and types " ,
2022-06-13 06:48:40 +00:00
& ordered_params ,
2021-06-09 21:09:12 +00:00
Applicability ::MachineApplicable ,
) ;
err . emit ( ) ;
}
2019-02-05 15:52:17 +00:00
}
2016-05-22 14:51:22 +00:00
}
2016-12-06 10:26:52 +00:00
impl < ' a > Visitor < ' a > for AstValidator < ' a > {
2019-10-11 19:00:09 +00:00
fn visit_attribute ( & mut self , attr : & Attribute ) {
2022-11-24 05:00:57 +00:00
validate_attr ::check_attr ( & self . session . parse_sess , attr ) ;
2019-10-11 19:00:09 +00:00
}
2016-12-06 10:26:52 +00:00
fn visit_expr ( & mut self , expr : & ' a Expr ) {
2022-03-09 18:04:09 +00:00
self . with_let_management ( Some ( ForbiddenLetReason ::GenericForbidden ) , | this , forbidden_let_reason | {
match & expr . kind {
ExprKind ::Binary ( Spanned { node : BinOpKind ::Or , span } , lhs , rhs ) = > {
2022-03-31 21:33:05 +00:00
let local_reason = Some ( ForbiddenLetReason ::NotSupportedOr ( * span ) ) ;
this . with_let_management ( local_reason , | this , _ | this . visit_expr ( lhs ) ) ;
this . with_let_management ( local_reason , | this , _ | this . visit_expr ( rhs ) ) ;
2022-03-09 18:04:09 +00:00
}
ExprKind ::If ( cond , then , opt_else ) = > {
this . visit_block ( then ) ;
walk_list! ( this , visit_expr , opt_else ) ;
this . with_let_management ( None , | this , _ | this . visit_expr ( cond ) ) ;
return ;
}
ExprKind ::Let ( .. ) if let Some ( elem ) = forbidden_let_reason = > {
this . ban_let_expr ( expr , elem ) ;
} ,
ExprKind ::Match ( scrutinee , arms ) = > {
this . visit_expr ( scrutinee ) ;
for arm in arms {
this . visit_expr ( & arm . body ) ;
this . visit_pat ( & arm . pat ) ;
walk_list! ( this , visit_attribute , & arm . attrs ) ;
if let Some ( guard ) = & arm . guard & & let ExprKind ::Let ( _ , guard_expr , _ ) = & guard . kind {
this . with_let_management ( None , | this , _ | {
this . visit_expr ( guard_expr )
} ) ;
2021-08-08 14:49:13 +00:00
return ;
}
}
}
2022-03-31 21:33:05 +00:00
ExprKind ::Paren ( local_expr ) = > {
fn has_let_expr ( expr : & Expr ) -> bool {
2022-11-28 19:16:44 +00:00
match & expr . kind {
ExprKind ::Binary ( _ , lhs , rhs ) = > has_let_expr ( lhs ) | | has_let_expr ( rhs ) ,
2022-03-31 21:33:05 +00:00
ExprKind ::Let ( .. ) = > true ,
_ = > false ,
}
}
let local_reason = if has_let_expr ( local_expr ) {
Some ( ForbiddenLetReason ::NotSupportedParentheses ( local_expr . span ) )
}
else {
forbidden_let_reason
} ;
this . with_let_management ( local_reason , | this , _ | this . visit_expr ( local_expr ) ) ;
}
ExprKind ::Binary ( Spanned { node : BinOpKind ::And , .. } , .. ) = > {
2022-03-09 18:04:09 +00:00
this . with_let_management ( forbidden_let_reason , | this , _ | visit ::walk_expr ( this , expr ) ) ;
return ;
}
ExprKind ::While ( cond , then , opt_label ) = > {
walk_list! ( this , visit_label , opt_label ) ;
this . visit_block ( then ) ;
this . with_let_management ( None , | this , _ | this . visit_expr ( cond ) ) ;
return ;
}
_ = > visit ::walk_expr ( this , expr ) ,
2021-08-08 14:49:13 +00:00
}
} ) ;
2016-05-22 14:51:22 +00:00
}
2016-05-22 15:07:28 +00:00
2016-12-06 10:26:52 +00:00
fn visit_ty ( & mut self , ty : & ' a Ty ) {
2021-05-16 14:51:00 +00:00
self . visit_ty_common ( ty ) ;
2019-01-18 11:35:14 +00:00
self . walk_ty ( ty )
2016-07-16 21:15:15 +00:00
}
2018-01-15 22:44:32 +00:00
fn visit_label ( & mut self , label : & ' a Label ) {
2018-03-19 00:54:56 +00:00
self . check_label ( label . ident ) ;
2018-01-15 22:44:32 +00:00
visit ::walk_label ( self , label ) ;
}
2022-05-10 17:56:46 +00:00
fn visit_lifetime ( & mut self , lifetime : & ' a Lifetime , _ : visit ::LifetimeCtxt ) {
2018-03-19 00:54:56 +00:00
self . check_lifetime ( lifetime . ident ) ;
2017-12-07 08:52:25 +00:00
visit ::walk_lifetime ( self , lifetime ) ;
}
2022-10-21 08:27:39 +00:00
fn visit_field_def ( & mut self , field : & ' a FieldDef ) {
visit ::walk_field_def ( self , field )
2021-05-16 14:51:00 +00:00
}
2016-12-06 10:26:52 +00:00
fn visit_item ( & mut self , item : & ' a Item ) {
2020-07-30 01:27:50 +00:00
if item . attrs . iter ( ) . any ( | attr | self . session . is_proc_macro_attr ( attr ) ) {
2019-01-17 06:28:39 +00:00
self . has_proc_macro_decls = true ;
}
2020-07-30 01:27:50 +00:00
if self . session . contains_name ( & item . attrs , sym ::no_mangle ) {
2020-05-16 06:09:01 +00:00
self . check_nomangle_item_asciionly ( item . ident , item . span ) ;
}
2022-11-28 19:16:44 +00:00
match & item . kind {
2021-11-07 08:43:49 +00:00
ItemKind ::Impl ( box Impl {
2020-01-14 04:30:20 +00:00
unsafety ,
polarity ,
defaultness : _ ,
2021-08-25 11:53:16 +00:00
constness ,
2022-11-28 19:16:44 +00:00
generics ,
of_trait : Some ( t ) ,
self_ty ,
items ,
2021-01-29 07:31:08 +00:00
} ) = > {
2022-11-28 19:16:44 +00:00
self . with_in_trait_impl ( true , Some ( * constness ) , | this | {
2020-02-05 11:27:45 +00:00
this . invalid_visibility ( & item . vis , None ) ;
if let TyKind ::Err = self_ty . kind {
this . err_handler ( )
. struct_span_err (
item . span ,
" `impl Trait for .. {}` is an obsolete syntax " ,
)
. help ( " use `auto trait Trait {}` instead " )
. emit ( ) ;
}
2022-11-28 19:16:44 +00:00
if let ( & Unsafe ::Yes ( span ) , & ImplPolarity ::Negative ( sp ) ) = ( unsafety , polarity )
{
2020-02-05 11:27:45 +00:00
struct_span_err! (
this . session ,
2020-03-05 00:15:23 +00:00
sp . to ( t . path . span ) ,
2020-02-05 11:27:45 +00:00
E0198 ,
" negative impls cannot be unsafe "
)
2020-03-05 23:39:35 +00:00
. span_label ( sp , " negative because of this " )
2020-01-30 01:42:33 +00:00
. span_label ( span , " unsafe because of this " )
2019-12-24 22:38:22 +00:00
. emit ( ) ;
2020-02-05 11:27:45 +00:00
}
2020-01-29 23:18:54 +00:00
2021-08-25 11:53:16 +00:00
this . visit_vis ( & item . vis ) ;
this . visit_ident ( item . ident ) ;
if let Const ::Yes ( _ ) = constness {
this . with_tilde_const_allowed ( | this | this . visit_generics ( generics ) ) ;
} else {
this . visit_generics ( generics ) ;
}
this . visit_trait_ref ( t ) ;
this . visit_ty ( self_ty ) ;
walk_list! ( this , visit_assoc_item , items , AssocCtxt ::Impl ) ;
2020-02-05 11:27:45 +00:00
} ) ;
2022-11-08 12:43:03 +00:00
walk_list! ( self , visit_attribute , & item . attrs ) ;
2020-01-29 23:18:54 +00:00
return ; // Avoid visiting again.
2016-05-22 15:07:28 +00:00
}
2021-11-07 08:43:49 +00:00
ItemKind ::Impl ( box Impl {
2020-01-14 04:30:20 +00:00
unsafety ,
polarity ,
defaultness ,
2020-01-14 04:30:25 +00:00
constness ,
2020-01-14 04:30:20 +00:00
generics : _ ,
of_trait : None ,
2022-11-28 19:16:44 +00:00
self_ty ,
2020-01-14 04:30:20 +00:00
items : _ ,
2021-01-29 07:31:08 +00:00
} ) = > {
2020-03-06 19:58:52 +00:00
let error = | annotation_span , annotation | {
2020-03-05 23:39:35 +00:00
let mut err = self . err_handler ( ) . struct_span_err (
self_ty . span ,
& format! ( " inherent impls cannot be {} " , annotation ) ,
) ;
err . span_label ( annotation_span , & format! ( " {} because of this " , annotation ) ) ;
err . span_label ( self_ty . span , " inherent impl for this type " ) ;
2020-03-06 19:58:52 +00:00
err
2020-03-05 23:39:35 +00:00
} ;
2019-12-24 22:38:22 +00:00
self . invalid_visibility (
& item . vis ,
2022-08-17 19:36:57 +00:00
Some ( InvalidVisibilityNote ::IndividualImplItems ) ,
2019-12-24 22:38:22 +00:00
) ;
2022-11-28 19:16:44 +00:00
if let & Unsafe ::Yes ( span ) = unsafety {
2020-03-06 19:58:52 +00:00
error ( span , " unsafe " ) . code ( error_code! ( E0197 ) ) . emit ( ) ;
2017-12-02 19:15:03 +00:00
}
2022-11-28 19:16:44 +00:00
if let & ImplPolarity ::Negative ( span ) = polarity {
2020-03-06 19:58:52 +00:00
error ( span , " negative " ) . emit ( ) ;
2017-12-02 19:15:03 +00:00
}
2022-11-28 19:16:44 +00:00
if let & Defaultness ::Default ( def_span ) = defaultness {
2020-03-06 19:58:52 +00:00
error ( def_span , " `default` " )
2020-02-22 01:01:53 +00:00
. note ( " only trait implementations may be annotated with `default` " )
2019-12-24 22:38:22 +00:00
. emit ( ) ;
2017-12-02 19:15:03 +00:00
}
2022-11-28 19:16:44 +00:00
if let & Const ::Yes ( span ) = constness {
2020-03-06 19:58:52 +00:00
error ( span , " `const` " )
2020-01-14 04:30:25 +00:00
. note ( " only trait implementations may be annotated with `const` " )
. emit ( ) ;
}
2016-05-22 15:07:28 +00:00
}
2022-11-28 19:16:44 +00:00
ItemKind ::Fn ( box Fn { defaultness , sig , generics , body } ) = > {
self . check_defaultness ( item . span , * defaultness ) ;
2020-01-29 23:18:54 +00:00
if body . is_none ( ) {
2022-08-18 17:43:01 +00:00
self . session . emit_err ( FnWithoutBody {
span : item . span ,
replace_span : self . ending_semi_or_hi ( item . span ) ,
extern_block_suggestion : match sig . header . ext {
Extern ::None = > None ,
Extern ::Implicit ( start_span ) = > Some ( ExternBlockSuggestion {
start_span ,
end_span : item . span . shrink_to_hi ( ) ,
abi : None ,
} ) ,
Extern ::Explicit ( abi , start_span ) = > Some ( ExternBlockSuggestion {
start_span ,
end_span : item . span . shrink_to_hi ( ) ,
abi : Some ( abi . symbol_unescaped ) ,
} ) ,
} ,
} ) ;
2019-12-02 01:38:33 +00:00
}
2022-07-02 17:53:16 +00:00
2021-08-25 11:53:16 +00:00
self . visit_vis ( & item . vis ) ;
self . visit_ident ( item . ident ) ;
2021-11-19 21:03:43 +00:00
let kind =
FnKind ::Fn ( FnCtxt ::Free , item . ident , sig , & item . vis , generics , body . as_deref ( ) ) ;
2021-08-25 11:53:16 +00:00
self . visit_fn ( kind , item . span , item . id ) ;
walk_list! ( self , visit_attribute , & item . attrs ) ;
2021-08-25 13:38:14 +00:00
return ; // Avoid visiting again.
2019-02-05 15:52:17 +00:00
}
2021-07-08 19:58:05 +00:00
ItemKind ::ForeignMod ( ForeignMod { abi , unsafety , .. } ) = > {
2020-01-29 23:18:54 +00:00
let old_item = mem ::replace ( & mut self . extern_mod , Some ( item ) ) ;
2018-01-29 05:12:09 +00:00
self . invalid_visibility (
& item . vis ,
2022-08-17 19:36:57 +00:00
Some ( InvalidVisibilityNote ::IndividualForeignItems ) ,
2018-01-29 05:12:09 +00:00
) ;
2022-11-28 19:16:44 +00:00
if let & Unsafe ::Yes ( span ) = unsafety {
2020-08-23 10:42:19 +00:00
self . err_handler ( ) . span_err ( span , " extern block cannot be declared unsafe " ) ;
}
2021-07-08 19:58:05 +00:00
if abi . is_none ( ) {
self . maybe_lint_missing_abi ( item . span , item . id ) ;
}
2020-01-29 23:18:54 +00:00
visit ::walk_item ( self , item ) ;
self . extern_mod = old_item ;
return ; // Avoid visiting again.
2016-05-22 15:07:28 +00:00
}
2022-11-28 19:16:44 +00:00
ItemKind ::Enum ( def , _ ) = > {
2016-05-22 15:07:28 +00:00
for variant in & def . variants {
2019-11-07 10:26:36 +00:00
self . invalid_visibility ( & variant . vis , None ) ;
2019-08-14 00:40:21 +00:00
for field in variant . data . fields ( ) {
2018-01-29 05:12:09 +00:00
self . invalid_visibility ( & field . vis , None ) ;
2016-05-22 15:07:28 +00:00
}
}
}
2022-11-28 19:16:44 +00:00
ItemKind ::Trait ( box Trait { is_auto , generics , bounds , items , .. } ) = > {
if * is_auto = = IsAuto ::Yes {
2017-10-15 18:03:03 +00:00
// Auto traits cannot have generics, super traits nor contain items.
2020-03-11 16:17:55 +00:00
self . deny_generic_params ( generics , item . ident . span ) ;
self . deny_super_traits ( bounds , item . ident . span ) ;
2021-10-03 15:58:10 +00:00
self . deny_where_clause ( & generics . where_clause , item . ident . span ) ;
2021-11-07 08:43:49 +00:00
self . deny_items ( items , item . ident . span ) ;
2017-10-15 18:03:03 +00:00
}
2020-01-05 00:29:45 +00:00
// Equivalent of `visit::walk_item` for `ItemKind::Trait` that inserts a bound
// context for the supertraits.
2020-01-05 02:34:10 +00:00
self . visit_vis ( & item . vis ) ;
self . visit_ident ( item . ident ) ;
2020-01-05 00:29:45 +00:00
self . visit_generics ( generics ) ;
2022-01-28 14:47:20 +00:00
self . with_tilde_const_allowed ( | this | {
2022-04-21 02:09:32 +00:00
walk_list! ( this , visit_param_bound , bounds , BoundKind ::SuperTraits )
2022-04-20 11:06:32 +00:00
} ) ;
2021-11-07 08:43:49 +00:00
walk_list! ( self , visit_assoc_item , items , AssocCtxt ::Trait ) ;
2020-01-05 02:34:10 +00:00
walk_list! ( self , visit_attribute , & item . attrs ) ;
2022-11-08 12:43:03 +00:00
return ; // Avoid visiting again
2016-08-07 21:33:35 +00:00
}
2022-11-28 19:16:44 +00:00
ItemKind ::Mod ( unsafety , mod_kind ) = > {
if let & Unsafe ::Yes ( span ) = unsafety {
2020-08-23 10:42:19 +00:00
self . err_handler ( ) . span_err ( span , " module cannot be declared unsafe " ) ;
}
2018-11-27 02:59:49 +00:00
// Ensure that `path` attributes on modules are recorded as used (cf. issue #35584).
2021-02-16 21:56:07 +00:00
if ! matches! ( mod_kind , ModKind ::Loaded ( _ , Inline ::Yes , _ ) )
& & ! self . session . contains_name ( & item . attrs , sym ::path )
{
2020-05-16 06:09:01 +00:00
self . check_mod_file_item_asciionly ( item . ident ) ;
}
2016-08-12 08:15:40 +00:00
}
2022-11-28 19:16:44 +00:00
ItemKind ::Union ( vdata , .. ) = > {
2018-09-07 13:10:16 +00:00
if vdata . fields ( ) . is_empty ( ) {
2019-12-24 22:38:22 +00:00
self . err_handler ( ) . span_err ( item . span , " unions cannot have zero fields " ) ;
2016-07-16 21:15:15 +00:00
}
}
2020-02-23 09:24:30 +00:00
ItemKind ::Const ( def , .. , None ) = > {
2022-11-28 19:16:44 +00:00
self . check_defaultness ( item . span , * def ) ;
2022-08-18 17:43:01 +00:00
self . session . emit_err ( ConstWithoutBody {
span : item . span ,
replace_span : self . ending_semi_or_hi ( item . span ) ,
} ) ;
2020-02-14 13:21:02 +00:00
}
ItemKind ::Static ( .. , None ) = > {
2022-08-18 17:43:01 +00:00
self . session . emit_err ( StaticWithoutBody {
span : item . span ,
replace_span : self . ending_semi_or_hi ( item . span ) ,
} ) ;
2020-02-14 13:21:02 +00:00
}
2022-11-28 19:16:44 +00:00
ItemKind ::TyAlias ( box TyAlias { defaultness , where_clauses , bounds , ty , .. } ) = > {
self . check_defaultness ( item . span , * defaultness ) ;
2021-11-07 08:43:49 +00:00
if ty . is_none ( ) {
2022-08-18 17:43:01 +00:00
self . session . emit_err ( TyAliasWithoutBody {
span : item . span ,
replace_span : self . ending_semi_or_hi ( item . span ) ,
} ) ;
2020-02-21 22:00:27 +00:00
}
self . check_type_no_bounds ( bounds , " this context " ) ;
2021-10-19 22:45:48 +00:00
if where_clauses . 1.0 {
2022-02-14 18:00:10 +00:00
let mut err = self . err_handler ( ) . struct_span_err (
2021-10-19 22:45:48 +00:00
where_clauses . 1.1 ,
" where clauses are not allowed after the type for type aliases " ,
2022-02-14 18:00:10 +00:00
) ;
err . note (
" see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information " ,
) ;
err . emit ( ) ;
2021-10-19 22:45:48 +00:00
}
2020-02-21 22:00:27 +00:00
}
2016-05-22 15:07:28 +00:00
_ = > { }
}
2021-08-25 11:53:16 +00:00
visit ::walk_item ( self , item ) ;
2016-05-22 15:07:28 +00:00
}
2016-12-06 10:26:52 +00:00
fn visit_foreign_item ( & mut self , fi : & ' a ForeignItem ) {
2020-01-29 23:18:54 +00:00
match & fi . kind {
2021-11-07 08:43:49 +00:00
ForeignItemKind ::Fn ( box Fn { defaultness , sig , body , .. } ) = > {
self . check_defaultness ( fi . span , * defaultness ) ;
2020-01-29 23:18:54 +00:00
self . check_foreign_fn_bodyless ( fi . ident , body . as_deref ( ) ) ;
self . check_foreign_fn_headerless ( fi . ident , fi . span , sig . header ) ;
2021-04-06 15:49:59 +00:00
self . check_foreign_item_ascii_only ( fi . ident ) ;
2016-07-16 21:15:15 +00:00
}
2021-10-19 22:45:48 +00:00
ForeignItemKind ::TyAlias ( box TyAlias {
defaultness ,
generics ,
where_clauses ,
bounds ,
ty ,
..
} ) = > {
2021-11-07 08:43:49 +00:00
self . check_defaultness ( fi . span , * defaultness ) ;
self . check_foreign_kind_bodyless ( fi . ident , " type " , ty . as_ref ( ) . map ( | b | b . span ) ) ;
2020-02-14 11:55:42 +00:00
self . check_type_no_bounds ( bounds , " `extern` blocks " ) ;
2021-10-19 22:45:48 +00:00
self . check_foreign_ty_genericless ( generics , where_clauses . 0.1 ) ;
2021-04-06 15:49:59 +00:00
self . check_foreign_item_ascii_only ( fi . ident ) ;
2020-02-14 11:55:42 +00:00
}
2020-02-14 14:56:05 +00:00
ForeignItemKind ::Static ( _ , _ , body ) = > {
self . check_foreign_kind_bodyless ( fi . ident , " static " , body . as_ref ( ) . map ( | b | b . span ) ) ;
2021-04-06 15:49:59 +00:00
self . check_foreign_item_ascii_only ( fi . ident ) ;
2020-02-14 14:56:05 +00:00
}
2020-02-29 16:32:20 +00:00
ForeignItemKind ::MacCall ( .. ) = > { }
2016-07-16 21:15:15 +00:00
}
visit ::walk_foreign_item ( self , fi )
}
2019-02-28 22:43:53 +00:00
// Mirrors `visit::walk_generic_args`, but tracks relevant state.
2022-09-12 00:43:34 +00:00
fn visit_generic_args ( & mut self , generic_args : & ' a GenericArgs ) {
2022-11-28 19:16:44 +00:00
match generic_args {
GenericArgs ::AngleBracketed ( data ) = > {
2020-03-22 03:40:05 +00:00
self . check_generic_args_before_constraints ( data ) ;
for arg in & data . args {
match arg {
AngleBracketedArg ::Arg ( arg ) = > self . visit_generic_arg ( arg ) ,
// Type bindings such as `Item = impl Debug` in `Iterator<Item = Debug>`
// are allowed to contain nested `impl Trait`.
AngleBracketedArg ::Constraint ( constraint ) = > {
self . with_impl_trait ( None , | this | {
2021-07-30 08:56:45 +00:00
this . visit_assoc_constraint_from_generic_args ( constraint ) ;
2020-03-22 03:40:05 +00:00
} ) ;
}
}
}
2019-01-18 11:35:14 +00:00
}
2022-11-28 19:16:44 +00:00
GenericArgs ::Parenthesized ( data ) = > {
2019-01-18 11:35:14 +00:00
walk_list! ( self , visit_ty , & data . inputs ) ;
2020-02-15 03:10:59 +00:00
if let FnRetTy ::Ty ( ty ) = & data . output {
2019-03-11 14:14:24 +00:00
// `-> Foo` syntax is essentially an associated type binding,
// so it is also allowed to contain nested `impl Trait`.
2019-12-01 15:00:08 +00:00
self . with_impl_trait ( None , | this | this . visit_ty ( ty ) ) ;
2019-01-18 11:35:14 +00:00
}
}
}
}
2018-05-27 15:56:01 +00:00
fn visit_generics ( & mut self , generics : & ' a Generics ) {
2021-03-01 11:50:09 +00:00
let mut prev_param_default = None ;
2018-05-27 15:56:01 +00:00
for param in & generics . params {
2020-07-22 20:58:54 +00:00
match param . kind {
GenericParamKind ::Lifetime = > ( ) ,
2021-03-01 11:50:09 +00:00
GenericParamKind ::Type { default : Some ( _ ) , .. }
| GenericParamKind ::Const { default : Some ( _ ) , .. } = > {
prev_param_default = Some ( param . ident . span ) ;
2020-07-22 20:58:54 +00:00
}
GenericParamKind ::Type { .. } | GenericParamKind ::Const { .. } = > {
2021-03-01 11:50:09 +00:00
if let Some ( span ) = prev_param_default {
2020-07-22 20:58:54 +00:00
let mut err = self . err_handler ( ) . struct_span_err (
span ,
2021-03-01 11:50:09 +00:00
" generic parameters with a default must be trailing " ,
2020-07-22 20:58:54 +00:00
) ;
err . emit ( ) ;
break ;
}
2017-10-16 19:07:26 +00:00
}
}
2017-01-17 18:18:29 +00:00
}
2019-02-05 15:52:17 +00:00
2021-10-23 15:57:13 +00:00
validate_generic_param_order ( self . err_handler ( ) , & generics . params , generics . span ) ;
2019-02-05 15:52:17 +00:00
2018-05-27 15:56:01 +00:00
for predicate in & generics . where_clause . predicates {
2022-11-28 19:16:44 +00:00
if let WherePredicate ::EqPredicate ( predicate ) = predicate {
2020-04-08 18:10:16 +00:00
deny_equality_constraints ( self , predicate , generics ) ;
2017-01-17 18:18:29 +00:00
}
}
2021-04-21 07:12:04 +00:00
walk_list! ( self , visit_generic_param , & generics . params ) ;
for predicate in & generics . where_clause . predicates {
match predicate {
WherePredicate ::BoundPredicate ( bound_pred ) = > {
// A type binding, eg `for<'c> Foo: Send+Clone+'c`
self . check_late_bound_lifetime_defs ( & bound_pred . bound_generic_params ) ;
2019-02-05 15:52:17 +00:00
2021-04-21 15:49:59 +00:00
// This is slightly complicated. Our representation for poly-trait-refs contains a single
// binder and thus we only allow a single level of quantification. However,
// the syntax of Rust permits quantification in two places in where clauses,
// e.g., `T: for <'a> Foo<'a>` and `for <'a, 'b> &'b T: Foo<'a>`. If both are
// defined, then error.
if ! bound_pred . bound_generic_params . is_empty ( ) {
for bound in & bound_pred . bounds {
match bound {
GenericBound ::Trait ( t , _ ) = > {
if ! t . bound_generic_params . is_empty ( ) {
struct_span_err! (
self . err_handler ( ) ,
t . span ,
E0316 ,
" nested quantification of lifetimes "
)
. emit ( ) ;
}
}
GenericBound ::Outlives ( _ ) = > { }
}
}
}
2021-04-21 07:12:04 +00:00
}
2021-04-21 15:49:59 +00:00
_ = > { }
2021-04-21 07:12:04 +00:00
}
2021-04-21 15:49:59 +00:00
self . visit_where_predicate ( predicate ) ;
2021-04-21 07:12:04 +00:00
}
2017-01-17 18:18:29 +00:00
}
2017-06-24 18:26:04 +00:00
2018-05-30 11:36:53 +00:00
fn visit_generic_param ( & mut self , param : & ' a GenericParam ) {
2018-05-31 14:52:17 +00:00
if let GenericParamKind ::Lifetime { .. } = param . kind {
self . check_lifetime ( param . ident ) ;
2018-05-30 11:36:53 +00:00
}
visit ::walk_generic_param ( self , param ) ;
}
2022-04-21 02:09:32 +00:00
fn visit_param_bound ( & mut self , bound : & ' a GenericBound , ctxt : BoundKind ) {
2022-11-28 19:16:44 +00:00
if let GenericBound ::Trait ( poly , modify ) = bound {
2022-04-20 11:06:32 +00:00
match ( ctxt , modify ) {
2022-04-21 02:09:32 +00:00
( BoundKind ::SuperTraits , TraitBoundModifier ::Maybe ) = > {
2022-05-26 11:14:24 +00:00
let mut err = self
. err_handler ( )
. struct_span_err ( poly . span , " `?Trait` is not permitted in supertraits " ) ;
2022-04-20 11:06:32 +00:00
let path_str = pprust ::path_to_string ( & poly . trait_ref . path ) ;
err . note ( & format! ( " traits are `? {} ` by default " , path_str ) ) ;
err . emit ( ) ;
}
2022-04-21 02:09:32 +00:00
( BoundKind ::TraitObject , TraitBoundModifier ::Maybe ) = > {
2022-04-20 11:06:32 +00:00
let mut err = self . err_handler ( ) . struct_span_err (
poly . span ,
2022-05-26 11:14:24 +00:00
" `?Trait` is not permitted in trait object types " ,
2022-04-20 11:06:32 +00:00
) ;
err . emit ( ) ;
}
2022-10-20 19:32:16 +00:00
( _ , TraitBoundModifier ::MaybeConst ) if let Some ( reason ) = & self . disallow_tilde_const = > {
let mut err = self . err_handler ( ) . struct_span_err ( bound . span ( ) , " `~const` is not allowed here " ) ;
match reason {
DisallowTildeConstContext ::TraitObject = > err . note ( " trait objects cannot have `~const` trait bounds " ) ,
DisallowTildeConstContext ::ImplTrait = > err . note ( " `impl Trait`s cannot have `~const` trait bounds " ) ,
DisallowTildeConstContext ::Fn ( FnKind ::Closure ( .. ) ) = > err . note ( " closures cannot have `~const` trait bounds " ) ,
DisallowTildeConstContext ::Fn ( FnKind ::Fn ( _ , ident , .. ) ) = > err . span_note ( ident . span , " this function is not `const`, so it cannot have `~const` trait bounds " ) ,
} ;
err . emit ( ) ;
2022-04-20 11:06:32 +00:00
}
( _ , TraitBoundModifier ::MaybeConstMaybe ) = > {
2021-08-25 13:38:14 +00:00
self . err_handler ( )
2022-04-20 11:06:32 +00:00
. span_err ( bound . span ( ) , " `~const` and `?` are mutually exclusive " ) ;
2020-01-05 00:29:45 +00:00
}
2022-04-20 11:06:32 +00:00
_ = > { }
2020-01-20 09:20:45 +00:00
}
2020-01-05 00:29:45 +00:00
}
visit ::walk_param_bound ( self , bound )
}
2022-08-11 01:05:26 +00:00
fn visit_poly_trait_ref ( & mut self , t : & ' a PolyTraitRef ) {
2018-03-06 10:22:24 +00:00
self . check_late_bound_lifetime_defs ( & t . bound_generic_params ) ;
2022-08-11 01:05:26 +00:00
visit ::walk_poly_trait_ref ( self , t ) ;
2018-03-06 10:22:24 +00:00
}
2018-03-11 02:16:26 +00:00
2019-08-24 16:54:40 +00:00
fn visit_variant_data ( & mut self , s : & ' a VariantData ) {
2019-03-21 17:55:09 +00:00
self . with_banned_assoc_ty_bound ( | this | visit ::walk_struct_def ( this , s ) )
}
2022-08-10 02:02:48 +00:00
fn visit_enum_def ( & mut self , enum_definition : & ' a EnumDef ) {
self . with_banned_assoc_ty_bound ( | this | visit ::walk_enum_def ( this , enum_definition ) )
2019-03-21 17:55:09 +00:00
}
2020-01-29 23:18:54 +00:00
fn visit_fn ( & mut self , fk : FnKind < ' a > , span : Span , id : NodeId ) {
// Only associated `fn`s can have `self` parameters.
let self_semantic = match fk . ctxt ( ) {
Some ( FnCtxt ::Assoc ( _ ) ) = > SelfSemantic ::Yes ,
_ = > SelfSemantic ::No ,
} ;
self . check_fn_decl ( fk . decl ( ) , self_semantic ) ;
2022-03-30 05:42:10 +00:00
self . check_c_variadic_type ( fk ) ;
2020-01-29 23:18:54 +00:00
2020-01-30 12:02:06 +00:00
// Functions cannot both be `const async`
if let Some ( FnHeader {
constness : Const ::Yes ( cspan ) ,
asyncness : Async ::Yes { span : aspan , .. } ,
..
} ) = fk . header ( )
{
self . err_handler ( )
2020-03-06 18:55:21 +00:00
. struct_span_err (
vec! [ * cspan , * aspan ] ,
" functions cannot be both `const` and `async` " ,
)
2020-01-30 12:02:06 +00:00
. span_label ( * cspan , " `const` because of this " )
. span_label ( * aspan , " `async` because of this " )
2020-03-06 18:55:21 +00:00
. span_label ( span , " " ) // Point at the fn header.
2020-01-30 12:02:06 +00:00
. emit ( ) ;
}
2022-06-02 16:15:05 +00:00
if let FnKind ::Closure ( ClosureBinder ::For { generic_params , .. } , .. ) = fk {
self . check_late_bound_lifetime_defs ( generic_params ) ;
}
2021-07-08 19:58:05 +00:00
if let FnKind ::Fn (
_ ,
_ ,
2022-07-02 17:25:55 +00:00
FnSig { span : sig_span , header : FnHeader { ext : Extern ::Implicit ( _ ) , .. } , .. } ,
2021-07-08 19:58:05 +00:00
_ ,
_ ,
2021-11-19 21:03:43 +00:00
_ ,
2021-07-08 19:58:05 +00:00
) = fk
{
self . maybe_lint_missing_abi ( * sig_span , id ) ;
}
2020-01-29 23:18:54 +00:00
// Functions without bodies cannot have patterns.
2021-11-19 21:03:43 +00:00
if let FnKind ::Fn ( ctxt , _ , sig , _ , _ , None ) = fk {
2020-11-30 14:24:08 +00:00
Self ::check_decl_no_pat ( & sig . decl , | span , ident , mut_ident | {
2020-01-29 23:18:54 +00:00
let ( code , msg , label ) = match ctxt {
FnCtxt ::Foreign = > (
error_code! ( E0130 ) ,
" patterns aren't allowed in foreign function declarations " ,
" pattern not allowed in foreign function " ,
) ,
_ = > (
error_code! ( E0642 ) ,
" patterns aren't allowed in functions without bodies " ,
" pattern not allowed in function without body " ,
) ,
} ;
if mut_ident & & matches! ( ctxt , FnCtxt ::Assoc ( _ ) ) {
2020-11-30 14:24:08 +00:00
if let Some ( ident ) = ident {
let diag = BuiltinLintDiagnostics ::PatternsInFnsWithoutBody ( span , ident ) ;
self . lint_buffer . buffer_lint_with_diagnostic (
PATTERNS_IN_FNS_WITHOUT_BODY ,
id ,
span ,
msg ,
diag ,
)
}
2020-01-29 23:18:54 +00:00
} else {
self . err_handler ( )
. struct_span_err ( span , msg )
. span_label ( span , label )
. code ( code )
. emit ( ) ;
}
} ) ;
2019-06-09 10:58:40 +00:00
}
2020-01-29 23:18:54 +00:00
2022-10-20 19:32:16 +00:00
let tilde_const_allowed =
matches! ( fk . header ( ) , Some ( FnHeader { constness : ast ::Const ::Yes ( _ ) , .. } ) )
| | matches! ( fk . ctxt ( ) , Some ( FnCtxt ::Assoc ( _ ) ) ) ;
let disallowed = ( ! tilde_const_allowed ) . then ( | | DisallowTildeConstContext ::Fn ( fk ) ) ;
2021-11-19 21:03:43 +00:00
2022-10-20 19:32:16 +00:00
self . with_tilde_const ( disallowed , | this | visit ::walk_fn ( this , fk ) ) ;
2019-06-09 10:58:40 +00:00
}
2019-11-07 10:26:36 +00:00
2020-01-29 23:18:54 +00:00
fn visit_assoc_item ( & mut self , item : & ' a AssocItem , ctxt : AssocCtxt ) {
2021-08-07 18:10:57 +00:00
if self . session . contains_name ( & item . attrs , sym ::no_mangle ) {
self . check_nomangle_item_asciionly ( item . ident , item . span ) ;
}
2020-02-23 09:24:30 +00:00
if ctxt = = AssocCtxt ::Trait | | ! self . in_trait_impl {
self . check_defaultness ( item . span , item . kind . defaultness ( ) ) ;
2019-12-02 01:53:18 +00:00
}
2020-01-29 23:18:54 +00:00
if ctxt = = AssocCtxt ::Impl {
match & item . kind {
2020-02-23 09:24:30 +00:00
AssocItemKind ::Const ( _ , _ , body ) = > {
2022-08-18 17:43:01 +00:00
if body . is_none ( ) {
self . session . emit_err ( AssocConstWithoutBody {
span : item . span ,
replace_span : self . ending_semi_or_hi ( item . span ) ,
} ) ;
}
2020-01-29 23:18:54 +00:00
}
2021-11-07 08:43:49 +00:00
AssocItemKind ::Fn ( box Fn { body , .. } ) = > {
2022-08-18 17:43:01 +00:00
if body . is_none ( ) {
self . session . emit_err ( AssocFnWithoutBody {
span : item . span ,
replace_span : self . ending_semi_or_hi ( item . span ) ,
} ) ;
}
2020-01-29 23:18:54 +00:00
}
2022-10-10 02:05:24 +00:00
AssocItemKind ::Type ( box TyAlias {
2021-10-19 22:45:48 +00:00
generics ,
where_clauses ,
where_predicates_split ,
bounds ,
ty ,
..
} ) = > {
2022-08-18 17:43:01 +00:00
if ty . is_none ( ) {
self . session . emit_err ( AssocTypeWithoutBody {
span : item . span ,
replace_span : self . ending_semi_or_hi ( item . span ) ,
} ) ;
}
2020-02-14 11:55:42 +00:00
self . check_type_no_bounds ( bounds , " `impl`s " ) ;
2021-10-19 22:45:48 +00:00
if ty . is_some ( ) {
self . check_gat_where (
2022-02-07 06:23:37 +00:00
item . id ,
2021-10-19 22:45:48 +00:00
generics . where_clause . predicates . split_at ( * where_predicates_split ) . 0 ,
* where_clauses ,
) ;
}
2020-01-29 23:18:54 +00:00
}
_ = > { }
}
}
2019-12-02 01:38:33 +00:00
2020-01-29 23:18:54 +00:00
if ctxt = = AssocCtxt ::Trait | | self . in_trait_impl {
self . invalid_visibility ( & item . vis , None ) ;
2021-11-07 08:43:49 +00:00
if let AssocItemKind ::Fn ( box Fn { sig , .. } ) = & item . kind {
2020-01-29 23:18:54 +00:00
self . check_trait_fn_not_const ( sig . header . constness ) ;
}
2019-12-02 01:38:33 +00:00
}
2020-01-29 23:18:54 +00:00
2020-02-15 21:21:00 +00:00
if let AssocItemKind ::Const ( .. ) = item . kind {
self . check_item_named ( item . ident , " const " ) ;
2020-02-14 14:56:05 +00:00
}
2022-11-28 19:16:44 +00:00
match & item . kind {
AssocItemKind ::Type ( box TyAlias { generics , bounds , ty , .. } )
2021-08-25 11:53:16 +00:00
if ctxt = = AssocCtxt ::Trait = >
{
self . visit_vis ( & item . vis ) ;
self . visit_ident ( item . ident ) ;
walk_list! ( self , visit_attribute , & item . attrs ) ;
self . with_tilde_const_allowed ( | this | {
this . visit_generics ( generics ) ;
2022-04-21 02:09:32 +00:00
walk_list! ( this , visit_param_bound , bounds , BoundKind ::Bound ) ;
2021-08-25 11:53:16 +00:00
} ) ;
walk_list! ( self , visit_ty , ty ) ;
}
2022-11-28 19:16:44 +00:00
AssocItemKind ::Fn ( box Fn { sig , generics , body , .. } )
2021-09-03 10:37:57 +00:00
if self . in_const_trait_impl
| | ctxt = = AssocCtxt ::Trait
| | matches! ( sig . header . constness , Const ::Yes ( _ ) ) = >
2021-08-25 11:53:16 +00:00
{
self . visit_vis ( & item . vis ) ;
self . visit_ident ( item . ident ) ;
2021-11-19 21:03:43 +00:00
let kind = FnKind ::Fn (
FnCtxt ::Assoc ( ctxt ) ,
item . ident ,
sig ,
& item . vis ,
generics ,
body . as_deref ( ) ,
) ;
2021-08-25 11:53:16 +00:00
self . visit_fn ( kind , item . span , item . id ) ;
}
_ = > self
. with_in_trait_impl ( false , None , | this | visit ::walk_assoc_item ( this , item , ctxt ) ) ,
}
2019-12-02 01:38:33 +00:00
}
2016-05-22 14:51:22 +00:00
}
2020-05-04 18:09:10 +00:00
/// When encountering an equality constraint in a `where` clause, emit an error. If the code seems
/// like it's setting an associated type, provide an appropriate suggestion.
2020-04-08 18:10:16 +00:00
fn deny_equality_constraints (
this : & mut AstValidator < '_ > ,
predicate : & WhereEqPredicate ,
generics : & Generics ,
) {
let mut err = this . err_handler ( ) . struct_span_err (
predicate . span ,
" equality constraints are not yet supported in `where` clauses " ,
) ;
err . span_label ( predicate . span , " not supported " ) ;
// Given `<A as Foo>::Bar = RhsTy`, suggest `A: Foo<Bar = RhsTy>`.
if let TyKind ::Path ( Some ( qself ) , full_path ) = & predicate . lhs_ty . kind {
if let TyKind ::Path ( None , path ) = & qself . ty . kind {
match & path . segments [ .. ] {
[ PathSegment { ident , args : None , .. } ] = > {
for param in & generics . params {
if param . ident = = * ident {
let param = ident ;
match & full_path . segments [ qself . position .. ] {
2020-11-19 17:28:38 +00:00
[ PathSegment { ident , args , .. } ] = > {
2020-04-08 18:10:16 +00:00
// Make a new `Path` from `foo::Bar` to `Foo<Bar = RhsTy>`.
let mut assoc_path = full_path . clone ( ) ;
// Remove `Bar` from `Foo::Bar`.
assoc_path . segments . pop ( ) ;
let len = assoc_path . segments . len ( ) - 1 ;
2022-11-16 21:58:58 +00:00
let gen_args = args . as_deref ( ) . cloned ( ) ;
2020-04-08 18:10:16 +00:00
// Build `<Bar = RhsTy>`.
2021-07-30 08:56:45 +00:00
let arg = AngleBracketedArg ::Constraint ( AssocConstraint {
2020-04-08 18:10:16 +00:00
id : rustc_ast ::node_id ::DUMMY_NODE_ID ,
ident : * ident ,
2020-11-19 17:28:38 +00:00
gen_args ,
2021-07-30 08:56:45 +00:00
kind : AssocConstraintKind ::Equality {
2022-01-07 03:58:32 +00:00
term : predicate . rhs_ty . clone ( ) . into ( ) ,
2020-04-08 18:10:16 +00:00
} ,
span : ident . span ,
} ) ;
// Add `<Bar = RhsTy>` to `Foo`.
match & mut assoc_path . segments [ len ] . args {
Some ( args ) = > match args . deref_mut ( ) {
GenericArgs ::Parenthesized ( _ ) = > continue ,
GenericArgs ::AngleBracketed ( args ) = > {
args . args . push ( arg ) ;
}
} ,
empty_args = > {
* empty_args = AngleBracketedArgs {
span : ident . span ,
args : vec ! [ arg ] ,
}
. into ( ) ;
}
}
err . span_suggestion_verbose (
predicate . span ,
& format! (
" if `{}` is an associated type you're trying to set, \
use the associated type binding syntax " ,
ident
) ,
format! (
" {}: {} " ,
param ,
pprust ::path_to_string ( & assoc_path )
) ,
Applicability ::MaybeIncorrect ,
) ;
}
_ = > { }
} ;
}
}
}
_ = > { }
}
}
}
2021-11-25 01:38:05 +00:00
// Given `A: Foo, A::Bar = RhsTy`, suggest `A: Foo<Bar = RhsTy>`.
if let TyKind ::Path ( None , full_path ) = & predicate . lhs_ty . kind {
if let [ potential_param , potential_assoc ] = & full_path . segments [ .. ] {
for param in & generics . params {
if param . ident = = potential_param . ident {
for bound in & param . bounds {
if let ast ::GenericBound ::Trait ( trait_ref , TraitBoundModifier ::None ) = bound
{
if let [ trait_segment ] = & trait_ref . trait_ref . path . segments [ .. ] {
let assoc = pprust ::path_to_string ( & ast ::Path ::from_ident (
potential_assoc . ident ,
) ) ;
let ty = pprust ::ty_to_string ( & predicate . rhs_ty ) ;
let ( args , span ) = match & trait_segment . args {
Some ( args ) = > match args . deref ( ) {
ast ::GenericArgs ::AngleBracketed ( args ) = > {
let Some ( arg ) = args . args . last ( ) else {
continue ;
} ;
(
format! ( " , {} = {} " , assoc , ty ) ,
arg . span ( ) . shrink_to_hi ( ) ,
)
}
_ = > continue ,
} ,
None = > (
format! ( " < {} = {} > " , assoc , ty ) ,
trait_segment . span ( ) . shrink_to_hi ( ) ,
) ,
} ;
err . multipart_suggestion (
& format! (
" if `{}::{}` is an associated type you're trying to set, \
use the associated type binding syntax " ,
trait_segment . ident , potential_assoc . ident ,
) ,
vec! [ ( span , args ) , ( predicate . span , String ::new ( ) ) ] ,
Applicability ::MaybeIncorrect ,
) ;
}
}
}
}
}
}
}
2020-04-08 18:10:16 +00:00
err . note (
" see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information " ,
) ;
err . emit ( ) ;
}
2020-01-05 08:40:16 +00:00
pub fn check_crate ( session : & Session , krate : & Crate , lints : & mut LintBuffer ) -> bool {
2019-01-17 06:28:39 +00:00
let mut validator = AstValidator {
2019-01-18 11:35:14 +00:00
session ,
2020-01-29 23:18:54 +00:00
extern_mod : None ,
in_trait_impl : false ,
2021-08-25 11:53:16 +00:00
in_const_trait_impl : false ,
2019-01-17 06:28:39 +00:00
has_proc_macro_decls : false ,
2019-01-18 11:35:14 +00:00
outer_impl_trait : None ,
2022-10-20 19:32:16 +00:00
disallow_tilde_const : None ,
2019-01-18 11:35:14 +00:00
is_impl_trait_banned : false ,
2019-03-21 17:55:09 +00:00
is_assoc_ty_bound_banned : false ,
2022-03-09 18:04:09 +00:00
forbidden_let_reason : Some ( ForbiddenLetReason ::GenericForbidden ) ,
2019-10-25 13:15:33 +00:00
lint_buffer : lints ,
2019-01-17 06:28:39 +00:00
} ;
visit ::walk_crate ( & mut validator , krate ) ;
2019-07-18 21:24:58 +00:00
validator . has_proc_macro_decls
2016-05-22 14:51:22 +00:00
}
2022-03-09 18:04:09 +00:00
/// Used to forbid `let` expressions in certain syntactic locations.
2022-10-14 12:11:21 +00:00
#[ derive(Clone, Copy, Subdiagnostic) ]
2022-08-17 14:51:01 +00:00
pub ( crate ) enum ForbiddenLetReason {
2022-03-09 18:04:09 +00:00
/// `let` is not valid and the source environment is not important
GenericForbidden ,
2022-03-31 21:33:05 +00:00
/// A let chain with the `||` operator
2022-10-22 09:07:54 +00:00
#[ note(not_supported_or) ]
2022-10-14 12:11:21 +00:00
NotSupportedOr ( #[ primary_span ] Span ) ,
2022-03-31 21:33:05 +00:00
/// A let chain with invalid parentheses
///
2022-08-18 02:13:37 +00:00
/// For example, `let 1 = 1 && (expr && expr)` is allowed
2022-03-31 21:33:05 +00:00
/// but `(let 1 = 1 && (let 1 = 1 && (let 1 = 1))) && let a = 1` is not
2022-10-22 09:07:54 +00:00
#[ note(not_supported_parentheses) ]
2022-10-14 12:11:21 +00:00
NotSupportedParentheses ( #[ primary_span ] Span ) ,
2022-03-09 18:04:09 +00:00
}