diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 9ea5d1ed5fa27..9b589a185c30c 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -36,6 +36,29 @@ enum SelfSemantic { No, } +struct Context<'a> { + outer_trait_or_trait_impl: Option>, + /// Used to ban nested `impl Trait`, e.g., `impl Into`. + /// Nested `impl Trait` _is_ allowed in associated type position, + /// e.g., `impl Iterator`. + outer_impl_trait: Option, + /// Used to ban `impl Trait` in path projections like `::Item` + /// or `Foo::Bar` + is_impl_trait_banned: bool, + disallow_tilde_const: Option>, +} + +impl Default for Context<'_> { + fn default() -> Self { + Self { + outer_trait_or_trait_impl: None, + outer_impl_trait: None, + is_impl_trait_banned: false, + disallow_tilde_const: Some(DisallowTildeConstContext::Item), + } + } +} + /// What is the context that prevents using `~const`? // FIXME(effects): Consider getting rid of this in favor of `errors::TildeConstReason`, they're // almost identical. This gets rid of an abstraction layer which might be considered bad. @@ -73,20 +96,9 @@ struct AstValidator<'a> { /// The span of the `extern` in an `extern { ... }` block, if any. extern_mod: Option<&'a Item>, - outer_trait_or_trait_impl: Option>, - has_proc_macro_decls: bool, - /// Used to ban nested `impl Trait`, e.g., `impl Into`. - /// Nested `impl Trait` _is_ allowed in associated type position, - /// e.g., `impl Iterator`. - outer_impl_trait: Option, - - disallow_tilde_const: Option>, - - /// Used to ban `impl Trait` in path projections like `::Item` - /// or `Foo::Bar` - is_impl_trait_banned: bool, + context: Context<'a>, lint_buffer: &'a mut LintBuffer, } @@ -134,6 +146,18 @@ impl<'a> AstValidator<'a> { self.disallow_tilde_const = old; } + fn with_impl_trait(&mut self, outer: Option, f: impl FnOnce(&mut Self)) { + let old = mem::replace(&mut self.outer_impl_trait, outer); + f(self); + self.outer_impl_trait = old; + } + + fn in_new_context(&mut self, f: impl FnOnce(&mut Self)) { + let context = mem::take(&mut self.context); + f(self); + self.context = context; + } + fn check_type_alias_where_clause_location( &mut self, ty_alias: &TyAlias, @@ -172,12 +196,6 @@ impl<'a> AstValidator<'a> { }) } - fn with_impl_trait(&mut self, outer: Option, f: impl FnOnce(&mut Self)) { - let old = mem::replace(&mut self.outer_impl_trait, outer); - f(self); - self.outer_impl_trait = old; - } - // Mirrors `visit::walk_ty`, but tracks relevant state. fn walk_ty(&mut self, t: &'a Ty) { match &t.kind { @@ -418,10 +436,10 @@ impl<'a> AstValidator<'a> { } 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() { - self.dcx().emit_err(errors::FnParamForbiddenSelf { span: param.span }); - } + if let (SelfSemantic::No, [param, ..]) = (self_semantic, &*fn_decl.inputs) + && param.is_self() + { + self.dcx().emit_err(errors::FnParamForbiddenSelf { span: param.span }); } } @@ -550,16 +568,16 @@ impl<'a> AstValidator<'a> { return; } - if let Some(header) = fk.header() { - if let Const::Yes(const_span) = header.constness { - let mut spans = variadic_spans.clone(); - spans.push(const_span); - self.dcx().emit_err(errors::ConstAndCVariadic { - spans, - const_span, - variadic_spans: variadic_spans.clone(), - }); - } + if let Some(header) = fk.header() + && let Const::Yes(const_span) = header.constness + { + let mut spans = variadic_spans.clone(); + spans.push(const_span); + self.dcx().emit_err(errors::ConstAndCVariadic { + spans, + const_span, + variadic_spans: variadic_spans.clone(), + }); } match (fk.ctxt(), fk.header()) { @@ -753,8 +771,24 @@ impl<'a> AstValidator<'a> { } } -/// Checks that generic parameters are in the correct order, -/// which is lifetimes, then types and then consts. (`<'a, T, const N: usize>`) +impl<'a> std::ops::Deref for AstValidator<'a> { + type Target = Context<'a>; + + fn deref(&self) -> &Self::Target { + &self.context + } +} + +impl<'a> std::ops::DerefMut for AstValidator<'a> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.context + } +} + +/// Checks that generic parameters are in the correct order. +/// +/// Namely lifetimes first, followed by types and consts. +/// E.g., `<'a, T, const N: usize>` and `<'a, const N: usize, T>`. fn validate_generic_param_order( dcx: &rustc_errors::DiagCtxt, generics: &[GenericParam], @@ -785,48 +819,49 @@ fn validate_generic_param_order( }; } - if !out_of_order.is_empty() { - let mut ordered_params = "<".to_string(); - param_idents.sort_by_key(|&(_, po, _, i, _)| (po, i)); - let mut first = true; - for (kind, _, bounds, _, ident) in param_idents { - if !first { - ordered_params += ", "; - } - ordered_params += &ident; - - if !bounds.is_empty() { - ordered_params += ": "; - ordered_params += &pprust::bounds_to_string(bounds); - } + if out_of_order.is_empty() { + return; + } - match kind { - GenericParamKind::Type { default: Some(default) } => { - ordered_params += " = "; - ordered_params += &pprust::ty_to_string(default); - } - GenericParamKind::Type { default: None } => (), - GenericParamKind::Lifetime => (), - 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 } => (), - } - first = false; + let mut ordered_params = "<".to_string(); + param_idents.sort_by_key(|&(_, po, _, i, _)| (po, i)); + let mut first = true; + for (kind, _, bounds, _, ident) in param_idents { + if !first { + ordered_params += ", "; } + ordered_params += &ident; - ordered_params += ">"; + if !bounds.is_empty() { + ordered_params += ": "; + ordered_params += &pprust::bounds_to_string(bounds); + } - for (param_ord, (max_param, spans)) in &out_of_order { - dcx.emit_err(errors::OutOfOrderParams { - spans: spans.clone(), - sugg_span: span, - param_ord, - max_param, - ordered_params: &ordered_params, - }); + match kind { + GenericParamKind::Type { default: Some(default) } => { + ordered_params += " = "; + ordered_params += &pprust::ty_to_string(default); + } + GenericParamKind::Type { default: None } => (), + GenericParamKind::Lifetime => (), + 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 } => (), } + first = false; + } + ordered_params += ">"; + + for (param_ord, (max_param, spans)) in &out_of_order { + dcx.emit_err(errors::OutOfOrderParams { + spans: spans.clone(), + sugg_span: span, + param_ord, + max_param, + ordered_params: &ordered_params, + }); } } @@ -925,35 +960,38 @@ impl<'a> Visitor<'a> for AstValidator<'a> { only_trait: only_trait.then_some(()), }; - self.visibility_not_permitted( - &item.vis, - errors::VisibilityNotPermittedNote::IndividualImplItems, - ); - if let &Unsafe::Yes(span) = unsafety { - self.dcx().emit_err(errors::InherentImplCannotUnsafe { - span: self_ty.span, - annotation_span: span, - annotation: "unsafe", - self_ty: self_ty.span, - }); - } - if let &ImplPolarity::Negative(span) = polarity { - self.dcx().emit_err(error(span, "negative", false)); - } - if let &Defaultness::Default(def_span) = defaultness { - self.dcx().emit_err(error(def_span, "`default`", true)); - } - if let &Const::Yes(span) = constness { - self.dcx().emit_err(error(span, "`const`", true)); - } + self.with_in_trait_impl(None, |this| { + this.visibility_not_permitted( + &item.vis, + errors::VisibilityNotPermittedNote::IndividualImplItems, + ); + if let &Unsafe::Yes(span) = unsafety { + this.dcx().emit_err(errors::InherentImplCannotUnsafe { + span: self_ty.span, + annotation_span: span, + annotation: "unsafe", + self_ty: self_ty.span, + }); + } + if let &ImplPolarity::Negative(span) = polarity { + this.dcx().emit_err(error(span, "negative", false)); + } + if let &Defaultness::Default(def_span) = defaultness { + this.dcx().emit_err(error(def_span, "`default`", true)); + } + if let &Const::Yes(span) = constness { + this.dcx().emit_err(error(span, "`const`", true)); + } - self.visit_vis(&item.vis); - self.visit_ident(item.ident); - self.with_tilde_const(Some(DisallowTildeConstContext::Impl(item.span)), |this| { - this.visit_generics(generics) + this.visit_vis(&item.vis); + this.visit_ident(item.ident); + this.with_tilde_const( + Some(DisallowTildeConstContext::Impl(item.span)), + |this| this.visit_generics(generics), + ); + this.visit_ty(self_ty); + walk_list!(this, visit_assoc_item, items, AssocCtxt::Impl); }); - self.visit_ty(self_ty); - walk_list!(self, visit_assoc_item, items, AssocCtxt::Impl); walk_list!(self, visit_attribute, &item.attrs); return; // Avoid visiting again. } @@ -1509,6 +1547,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { { self.visit_vis(&item.vis); self.visit_ident(item.ident); + walk_list!(self, visit_attribute, &item.attrs); let kind = FnKind::Fn( FnCtxt::Assoc(ctxt), item.ident, @@ -1529,13 +1568,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } None => DisallowTildeConstContext::InherentAssocTy(item.span), }); - self.with_tilde_const(disallowed, |this| { - this.with_in_trait_impl(None, |this| visit::walk_assoc_item(this, item, ctxt)) - }) + self.with_tilde_const(disallowed, |this| visit::walk_assoc_item(this, item, ctxt)) } - _ => self.with_in_trait_impl(None, |this| visit::walk_assoc_item(this, item, ctxt)), + _ => visit::walk_assoc_item(self, item, ctxt), } } + + fn visit_anon_const(&mut self, c: &'a AnonConst) { + self.in_new_context(|this| visit::walk_anon_const(this, c)) + } } /// When encountering an equality constraint in a `where` clause, emit an error. If the code seems @@ -1553,85 +1594,82 @@ fn deny_equality_constraints( && let [PathSegment { ident, args: None, .. }] = &path.segments[..] { for param in &generics.params { - if param.ident == *ident - && let [PathSegment { ident, args, .. }] = &full_path.segments[qself.position..] - { - // Make a new `Path` from `foo::Bar` to `Foo`. - let mut assoc_path = full_path.clone(); - // Remove `Bar` from `Foo::Bar`. - assoc_path.segments.pop(); - let len = assoc_path.segments.len() - 1; - let gen_args = args.as_deref().cloned(); - // Build ``. - let arg = AngleBracketedArg::Constraint(AssocConstraint { - id: rustc_ast::node_id::DUMMY_NODE_ID, - ident: *ident, - gen_args, - kind: AssocConstraintKind::Equality { term: predicate.rhs_ty.clone().into() }, - span: ident.span, - }); - // Add `` 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 = Some( - AngleBracketedArgs { span: ident.span, args: thin_vec![arg] }.into(), - ); + if param.ident != *ident { + continue; + } + let [PathSegment { ident, args, .. }] = &full_path.segments[qself.position..] else { + continue; + }; + + // Make a new `Path` from `foo::Bar` to `Foo`. + let mut assoc_path = full_path.clone(); + // Remove `Bar` from `Foo::Bar`. + assoc_path.segments.pop(); + let gen_args = args.as_deref().cloned(); + // Build ``. + let arg = AngleBracketedArg::Constraint(AssocConstraint { + id: rustc_ast::node_id::DUMMY_NODE_ID, + ident: *ident, + gen_args, + kind: AssocConstraintKind::Equality { term: predicate.rhs_ty.clone().into() }, + span: ident.span, + }); + // Add `` to `Foo`. + match &mut assoc_path.segments.last_mut().unwrap().args { + Some(args) => match args.deref_mut() { + GenericArgs::Parenthesized(_) => continue, + GenericArgs::AngleBracketed(args) => { + args.args.push(arg); } + }, + empty_args => { + *empty_args = + Some(AngleBracketedArgs { span: ident.span, args: thin_vec![arg] }.into()); } - err.assoc = Some(errors::AssociatedSuggestion { - span: predicate.span, - ident: *ident, - param: param.ident, - path: pprust::path_to_string(&assoc_path), - }) } + err.assoc = Some(errors::AssociatedSuggestion { + span: predicate.span, + ident: *ident, + param: param.ident, + path: pprust::path_to_string(&assoc_path), + }) } } // Given `A: Foo, A::Bar = RhsTy`, suggest `A: Foo`. - 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 ¶m.bounds { - if let ast::GenericBound::Trait(trait_ref, TraitBoundModifiers::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(), - ), + if let TyKind::Path(None, full_path) = &predicate.lhs_ty.kind + && let [potential_param, potential_assoc] = &full_path.segments[..] + { + for param in &generics.params { + if param.ident != potential_param.ident { + continue; + }; + + for bound in ¶m.bounds { + if let ast::GenericBound::Trait(trait_ref, TraitBoundModifiers::NONE) = bound + && 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; }; - err.assoc2 = Some(errors::AssociatedSuggestion2 { - span, - args, - predicate: predicate.span, - trait_segment: trait_segment.ident, - potential_assoc: potential_assoc.ident, - }); + (format!(", {assoc} = {ty}"), arg.span().shrink_to_hi()) } - } - } + _ => continue, + }, + None => (format!("<{assoc} = {ty}>"), trait_segment.span().shrink_to_hi()), + }; + err.assoc2 = Some(errors::AssociatedSuggestion2 { + span, + args, + predicate: predicate.span, + trait_segment: trait_segment.ident, + potential_assoc: potential_assoc.ident, + }); } } } @@ -1649,11 +1687,8 @@ pub fn check_crate( session, features, extern_mod: None, - outer_trait_or_trait_impl: None, has_proc_macro_decls: false, - outer_impl_trait: None, - disallow_tilde_const: Some(DisallowTildeConstContext::Item), - is_impl_trait_banned: false, + context: Context::default(), lint_buffer: lints, }; visit::walk_crate(&mut validator, krate); diff --git a/tests/ui/parser/defaultness-invalid-places-fail-semantic.rs b/tests/ui/parser/semantic/defaultness-invalid-places-fail-semantic.rs similarity index 100% rename from tests/ui/parser/defaultness-invalid-places-fail-semantic.rs rename to tests/ui/parser/semantic/defaultness-invalid-places-fail-semantic.rs diff --git a/tests/ui/parser/defaultness-invalid-places-fail-semantic.stderr b/tests/ui/parser/semantic/defaultness-invalid-places-fail-semantic.stderr similarity index 100% rename from tests/ui/parser/defaultness-invalid-places-fail-semantic.stderr rename to tests/ui/parser/semantic/defaultness-invalid-places-fail-semantic.stderr diff --git a/tests/ui/parser/fn-body-optional-semantic-fail.rs b/tests/ui/parser/semantic/fn-body-optional-semantic-fail.rs similarity index 100% rename from tests/ui/parser/fn-body-optional-semantic-fail.rs rename to tests/ui/parser/semantic/fn-body-optional-semantic-fail.rs diff --git a/tests/ui/parser/fn-body-optional-semantic-fail.stderr b/tests/ui/parser/semantic/fn-body-optional-semantic-fail.stderr similarity index 100% rename from tests/ui/parser/fn-body-optional-semantic-fail.stderr rename to tests/ui/parser/semantic/fn-body-optional-semantic-fail.stderr diff --git a/tests/ui/parser/fn-header-semantic-fail.rs b/tests/ui/parser/semantic/fn-header-semantic-fail.rs similarity index 100% rename from tests/ui/parser/fn-header-semantic-fail.rs rename to tests/ui/parser/semantic/fn-header-semantic-fail.rs diff --git a/tests/ui/parser/fn-header-semantic-fail.stderr b/tests/ui/parser/semantic/fn-header-semantic-fail.stderr similarity index 100% rename from tests/ui/parser/fn-header-semantic-fail.stderr rename to tests/ui/parser/semantic/fn-header-semantic-fail.stderr diff --git a/tests/ui/parser/foreign-const-semantic-fail.rs b/tests/ui/parser/semantic/foreign-const-semantic-fail.rs similarity index 100% rename from tests/ui/parser/foreign-const-semantic-fail.rs rename to tests/ui/parser/semantic/foreign-const-semantic-fail.rs diff --git a/tests/ui/parser/foreign-const-semantic-fail.stderr b/tests/ui/parser/semantic/foreign-const-semantic-fail.stderr similarity index 100% rename from tests/ui/parser/foreign-const-semantic-fail.stderr rename to tests/ui/parser/semantic/foreign-const-semantic-fail.stderr diff --git a/tests/ui/parser/foreign-static-semantic-fail.rs b/tests/ui/parser/semantic/foreign-static-semantic-fail.rs similarity index 100% rename from tests/ui/parser/foreign-static-semantic-fail.rs rename to tests/ui/parser/semantic/foreign-static-semantic-fail.rs diff --git a/tests/ui/parser/foreign-static-semantic-fail.stderr b/tests/ui/parser/semantic/foreign-static-semantic-fail.stderr similarity index 100% rename from tests/ui/parser/foreign-static-semantic-fail.stderr rename to tests/ui/parser/semantic/foreign-static-semantic-fail.stderr diff --git a/tests/ui/parser/foreign-ty-semantic-fail.rs b/tests/ui/parser/semantic/foreign-ty-semantic-fail.rs similarity index 100% rename from tests/ui/parser/foreign-ty-semantic-fail.rs rename to tests/ui/parser/semantic/foreign-ty-semantic-fail.rs diff --git a/tests/ui/parser/foreign-ty-semantic-fail.stderr b/tests/ui/parser/semantic/foreign-ty-semantic-fail.stderr similarity index 100% rename from tests/ui/parser/foreign-ty-semantic-fail.stderr rename to tests/ui/parser/semantic/foreign-ty-semantic-fail.stderr diff --git a/tests/ui/parser/impl-item-const-semantic-fail.rs b/tests/ui/parser/semantic/impl-item-const-semantic-fail.rs similarity index 100% rename from tests/ui/parser/impl-item-const-semantic-fail.rs rename to tests/ui/parser/semantic/impl-item-const-semantic-fail.rs diff --git a/tests/ui/parser/impl-item-const-semantic-fail.stderr b/tests/ui/parser/semantic/impl-item-const-semantic-fail.stderr similarity index 100% rename from tests/ui/parser/impl-item-const-semantic-fail.stderr rename to tests/ui/parser/semantic/impl-item-const-semantic-fail.stderr diff --git a/tests/ui/parser/impl-item-fn-no-body-semantic-fail.rs b/tests/ui/parser/semantic/impl-item-fn-no-body-semantic-fail.rs similarity index 100% rename from tests/ui/parser/impl-item-fn-no-body-semantic-fail.rs rename to tests/ui/parser/semantic/impl-item-fn-no-body-semantic-fail.rs diff --git a/tests/ui/parser/impl-item-fn-no-body-semantic-fail.stderr b/tests/ui/parser/semantic/impl-item-fn-no-body-semantic-fail.stderr similarity index 100% rename from tests/ui/parser/impl-item-fn-no-body-semantic-fail.stderr rename to tests/ui/parser/semantic/impl-item-fn-no-body-semantic-fail.stderr diff --git a/tests/ui/parser/impl-item-type-no-body-semantic-fail.rs b/tests/ui/parser/semantic/impl-item-type-no-body-semantic-fail.rs similarity index 100% rename from tests/ui/parser/impl-item-type-no-body-semantic-fail.rs rename to tests/ui/parser/semantic/impl-item-type-no-body-semantic-fail.rs diff --git a/tests/ui/parser/impl-item-type-no-body-semantic-fail.stderr b/tests/ui/parser/semantic/impl-item-type-no-body-semantic-fail.stderr similarity index 100% rename from tests/ui/parser/impl-item-type-no-body-semantic-fail.stderr rename to tests/ui/parser/semantic/impl-item-type-no-body-semantic-fail.stderr diff --git a/tests/ui/parser/semantic/impls-nested-within-fns-semantic-0.rs b/tests/ui/parser/semantic/impls-nested-within-fns-semantic-0.rs new file mode 100644 index 0000000000000..007329558bde5 --- /dev/null +++ b/tests/ui/parser/semantic/impls-nested-within-fns-semantic-0.rs @@ -0,0 +1,15 @@ +// Regression test for issue #119924. +// check-pass + +pub struct Type; + +trait Trait { + fn provided() { + impl Type { + // This visibility qualifier used to get rejected. + pub fn perform() {} + } + } +} + +fn main() {} diff --git a/tests/ui/parser/semantic/impls-nested-within-fns-semantic-1.rs b/tests/ui/parser/semantic/impls-nested-within-fns-semantic-1.rs new file mode 100644 index 0000000000000..61634c18bcfa9 --- /dev/null +++ b/tests/ui/parser/semantic/impls-nested-within-fns-semantic-1.rs @@ -0,0 +1,21 @@ +// Regression test for issue #119924. +// check-pass +#![feature(const_trait_impl, effects)] + +pub struct Type; + +#[const_trait] +trait Trait { + fn required(); +} + +impl const Trait for () { + fn required() { + impl Type { + // This visibility qualifier used to get rejected. + pub fn perform() {} + } + } +} + +fn main() {} diff --git a/tests/ui/parser/item-free-const-no-body-semantic-fail.rs b/tests/ui/parser/semantic/item-free-const-no-body-semantic-fail.rs similarity index 100% rename from tests/ui/parser/item-free-const-no-body-semantic-fail.rs rename to tests/ui/parser/semantic/item-free-const-no-body-semantic-fail.rs diff --git a/tests/ui/parser/item-free-const-no-body-semantic-fail.stderr b/tests/ui/parser/semantic/item-free-const-no-body-semantic-fail.stderr similarity index 100% rename from tests/ui/parser/item-free-const-no-body-semantic-fail.stderr rename to tests/ui/parser/semantic/item-free-const-no-body-semantic-fail.stderr diff --git a/tests/ui/parser/item-free-static-no-body-semantic-fail.rs b/tests/ui/parser/semantic/item-free-static-no-body-semantic-fail.rs similarity index 100% rename from tests/ui/parser/item-free-static-no-body-semantic-fail.rs rename to tests/ui/parser/semantic/item-free-static-no-body-semantic-fail.rs diff --git a/tests/ui/parser/item-free-static-no-body-semantic-fail.stderr b/tests/ui/parser/semantic/item-free-static-no-body-semantic-fail.stderr similarity index 100% rename from tests/ui/parser/item-free-static-no-body-semantic-fail.stderr rename to tests/ui/parser/semantic/item-free-static-no-body-semantic-fail.stderr diff --git a/tests/ui/parser/item-free-type-bounds-semantic-fail.rs b/tests/ui/parser/semantic/item-free-type-bounds-semantic-fail.rs similarity index 100% rename from tests/ui/parser/item-free-type-bounds-semantic-fail.rs rename to tests/ui/parser/semantic/item-free-type-bounds-semantic-fail.rs diff --git a/tests/ui/parser/item-free-type-bounds-semantic-fail.stderr b/tests/ui/parser/semantic/item-free-type-bounds-semantic-fail.stderr similarity index 100% rename from tests/ui/parser/item-free-type-bounds-semantic-fail.stderr rename to tests/ui/parser/semantic/item-free-type-bounds-semantic-fail.stderr diff --git a/tests/ui/parser/semantic/items-nested-within-anon-consts-semantic.rs b/tests/ui/parser/semantic/items-nested-within-anon-consts-semantic.rs new file mode 100644 index 0000000000000..da37df6560579 --- /dev/null +++ b/tests/ui/parser/semantic/items-nested-within-anon-consts-semantic.rs @@ -0,0 +1,51 @@ +// Regression test for issues #119924 and #89342. +// check-pass + +struct Type; +struct Expr; + +trait Trait0 { + fn required(_: Expr<{ + impl Type { + // This visibility qualifier used to get rejected. + pub fn perform() {} + } + 0 + }>); +} + +trait Trait1 {} + +impl Trait1 for () +where + [(); { + impl Type { + // This visibility qualifier used to get rejected. + pub const STORE: Self = Self; + } + 0 + }]: +{} + +trait Trait2 {} + +fn f(_: impl Trait2<{ + // This impl-Trait used to get rejected as "nested" impl-Trait. + fn g(_: impl Sized) {} + false +}>) {} + +fn scope() { + let _: as Trait3>::Projected; +} + +trait Trait3 { type Projected; } +struct Parametrized; + +impl Trait3 for Parametrized { type Projected = (); } + +fn main() {} diff --git a/tests/ui/parser/self-param-semantic-fail.rs b/tests/ui/parser/semantic/self-param-semantic-fail.rs similarity index 100% rename from tests/ui/parser/self-param-semantic-fail.rs rename to tests/ui/parser/semantic/self-param-semantic-fail.rs diff --git a/tests/ui/parser/self-param-semantic-fail.stderr b/tests/ui/parser/semantic/self-param-semantic-fail.stderr similarity index 100% rename from tests/ui/parser/self-param-semantic-fail.stderr rename to tests/ui/parser/semantic/self-param-semantic-fail.stderr diff --git a/tests/ui/parser/variadic-ffi-semantic-restrictions.rs b/tests/ui/parser/semantic/variadic-ffi-semantic-restrictions.rs similarity index 100% rename from tests/ui/parser/variadic-ffi-semantic-restrictions.rs rename to tests/ui/parser/semantic/variadic-ffi-semantic-restrictions.rs diff --git a/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr b/tests/ui/parser/semantic/variadic-ffi-semantic-restrictions.stderr similarity index 100% rename from tests/ui/parser/variadic-ffi-semantic-restrictions.stderr rename to tests/ui/parser/semantic/variadic-ffi-semantic-restrictions.stderr diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places-nested.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places-nested.rs new file mode 100644 index 0000000000000..3f3f4b8cddfb1 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places-nested.rs @@ -0,0 +1,39 @@ +// Regression test for issue #119924. +#![feature(const_trait_impl, effects)] +#![allow(incomplete_features)] + +pub struct Type; + +#[const_trait] +trait Trait0 { + fn provided() { + impl Type { + fn perform() {} + //~^ ERROR `~const` is not allowed here + } + } +} + +struct Expr; + +#[const_trait] +trait Trait1 { + fn required(_: Expr<{ + impl Type { + fn compute() {} + //~^ ERROR `~const` is not allowed here + } + 0 + }>); +} + +#[const_trait] +trait Trait2 {} + +const fn operate>(U); + //~^ ERROR `~const` is not allowed here + 0 +}>>() {} + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places-nested.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places-nested.stderr new file mode 100644 index 0000000000000..a51d9b872d5f4 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places-nested.stderr @@ -0,0 +1,34 @@ +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places-nested.rs:11:27 + | +LL | fn perform() {} + | ^^^^^^ + | +note: this function is not `const`, so it cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places-nested.rs:11:16 + | +LL | fn perform() {} + | ^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places-nested.rs:23:27 + | +LL | fn compute() {} + | ^^^^^^ + | +note: this function is not `const`, so it cannot have `~const` trait bounds + --> $DIR/tilde-const-invalid-places-nested.rs:23:16 + | +LL | fn compute() {} + | ^^^^^^^ + +error: `~const` is not allowed here + --> $DIR/tilde-const-invalid-places-nested.rs:34:17 + | +LL | struct I>(U); + | ^^^^^^ + | + = note: this item cannot have `~const` trait bounds + +error: aborting due to 3 previous errors +