Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 3 pull requests #132229

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions compiler/rustc_ast_lowering/src/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
modifiers: Option<ast::TraitBoundModifiers>,
) -> hir::QPath<'hir> {
let qself_position = qself.as_ref().map(|q| q.position);
let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx));
let qself = qself
.as_ref()
// Reject cases like `<impl Trait>::Assoc` and `<impl Trait as Trait>::Assoc`.
.map(|q| self.lower_ty(&q.ty, ImplTraitContext::Disallowed(ImplTraitPosition::Path)));

let partial_res =
self.resolver.get_partial_res(id).unwrap_or_else(|| PartialRes::new(Res::Err));
Expand Down Expand Up @@ -75,6 +78,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
None
};

// Only permit `impl Trait` in the final segment. E.g., we permit `Option<impl Trait>`,
// `option::Option<T>::Xyz<impl Trait>` and reject `option::Option<impl Trait>::Xyz`.
let itctx = |i| {
if i + 1 == p.segments.len() {
itctx
} else {
ImplTraitContext::Disallowed(ImplTraitPosition::Path)
}
};

let path_span_lo = p.span.shrink_to_lo();
let proj_start = p.segments.len() - unresolved_segments;
let path = self.arena.alloc(hir::Path {
Expand Down Expand Up @@ -121,7 +134,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
segment,
param_mode,
generic_args_mode,
itctx,
itctx(i),
bound_modifier_allowed_features.clone(),
)
},
Expand Down Expand Up @@ -185,7 +198,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
segment,
param_mode,
generic_args_mode,
itctx,
itctx(i),
None,
));
let qpath = hir::QPath::TypeRelative(ty, hir_segment);
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_ast_passes/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,6 @@ ast_passes_generic_before_constraints = generic arguments must come before the f

ast_passes_generic_default_trailing = generic parameters with a default must be trailing

ast_passes_impl_trait_path = `impl Trait` is not allowed in path parameters

ast_passes_incompatible_features = `{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed
.help = remove one of these features

Expand Down
46 changes: 0 additions & 46 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,6 @@ struct AstValidator<'a> {

disallow_tilde_const: Option<TildeConstReason>,

/// Used to ban `impl Trait` in path projections like `<impl Iterator>::Item`
/// or `Foo::Bar<impl Trait>`
is_impl_trait_banned: bool,

/// Used to ban explicit safety on foreign items when the extern block is not marked as unsafe.
extern_mod_safety: Option<Safety>,

Expand Down Expand Up @@ -123,12 +119,6 @@ impl<'a> AstValidator<'a> {
self.extern_mod_safety = old;
}

fn with_banned_impl_trait(&mut self, f: impl FnOnce(&mut Self)) {
let old = mem::replace(&mut self.is_impl_trait_banned, true);
f(self);
self.is_impl_trait_banned = old;
}

fn with_tilde_const(
&mut self,
disallowed: Option<TildeConstReason>,
Expand Down Expand Up @@ -213,37 +203,6 @@ impl<'a> AstValidator<'a> {
.with_tilde_const(Some(TildeConstReason::TraitObject), |this| {
visit::walk_ty(this, t)
}),
TyKind::Path(qself, path) => {
// 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.
if let Some(qself) = qself {
// `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 {
self.visit_path_segment(segment);
} else {
self.with_banned_impl_trait(|this| this.visit_path_segment(segment));
}
}
}
_ => visit::walk_ty(self, t),
}
}
Expand Down Expand Up @@ -737,10 +696,6 @@ impl<'a> AstValidator<'a> {
}
}
TyKind::ImplTrait(_, bounds) => {
if self.is_impl_trait_banned {
self.dcx().emit_err(errors::ImplTraitPath { span: ty.span });
}

if let Some(outer_impl_trait_sp) = self.outer_impl_trait {
self.dcx().emit_err(errors::NestedImplTrait {
span: ty.span,
Expand Down Expand Up @@ -1729,7 +1684,6 @@ pub fn check_crate(
has_proc_macro_decls: false,
outer_impl_trait: None,
disallow_tilde_const: Some(TildeConstReason::Item),
is_impl_trait_banned: false,
extern_mod_safety: None,
lint_buffer: lints,
};
Expand Down
7 changes: 0 additions & 7 deletions compiler/rustc_ast_passes/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -418,13 +418,6 @@ pub(crate) struct TraitObjectBound {
pub span: Span,
}

#[derive(Diagnostic)]
#[diag(ast_passes_impl_trait_path, code = E0667)]
pub(crate) struct ImplTraitPath {
#[primary_span]
pub span: Span,
}

#[derive(Diagnostic)]
#[diag(ast_passes_nested_impl_trait, code = E0666)]
pub(crate) struct NestedImplTrait {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ macro_rules! path {
($span:expr, $($part:ident)::*) => { vec![$(Ident::new(sym::$part, $span),)*] }
}

pub(crate) fn expand_deriving_smart_ptr(
pub(crate) fn expand_deriving_coerce_pointee(
cx: &ExtCtxt<'_>,
span: Span,
_mitem: &MetaItem,
Expand All @@ -41,7 +41,7 @@ pub(crate) fn expand_deriving_smart_ptr(
cx.dcx()
.struct_span_err(
span,
"`SmartPointer` can only be derived on `struct`s with `#[repr(transparent)]`",
"`CoercePointee` can only be derived on `struct`s with `#[repr(transparent)]`",
)
.emit();
return;
Expand All @@ -54,7 +54,7 @@ pub(crate) fn expand_deriving_smart_ptr(
cx.dcx()
.struct_span_err(
span,
"`SmartPointer` can only be derived on `struct`s with at least one field",
"`CoercePointee` can only be derived on `struct`s with at least one field",
)
.emit();
return;
Expand All @@ -64,7 +64,7 @@ pub(crate) fn expand_deriving_smart_ptr(
cx.dcx()
.struct_span_err(
span,
"`SmartPointer` can only be derived on `struct`s with `#[repr(transparent)]`",
"`CoercePointee` can only be derived on `struct`s with `#[repr(transparent)]`",
)
.emit();
return;
Expand Down Expand Up @@ -94,10 +94,10 @@ pub(crate) fn expand_deriving_smart_ptr(
.collect();

let pointee_param_idx = if type_params.is_empty() {
// `#[derive(SmartPointer)]` requires at least one generic type on the target `struct`
// `#[derive(CoercePointee)]` requires at least one generic type on the target `struct`
cx.dcx().struct_span_err(
span,
"`SmartPointer` can only be derived on `struct`s that are generic over at least one type",
"`CoercePointee` can only be derived on `struct`s that are generic over at least one type",
).emit();
return;
} else if type_params.len() == 1 {
Expand All @@ -113,15 +113,15 @@ pub(crate) fn expand_deriving_smart_ptr(
(None, _) => {
cx.dcx().struct_span_err(
span,
"exactly one generic type parameter must be marked as #[pointee] to derive SmartPointer traits",
"exactly one generic type parameter must be marked as #[pointee] to derive CoercePointee traits",
).emit();
return;
}
(Some((_, one)), Some((_, another))) => {
cx.dcx()
.struct_span_err(
vec![one, another],
"only one type parameter can be marked as `#[pointee]` when deriving SmartPointer traits",
"only one type parameter can be marked as `#[pointee]` when deriving CoercePointee traits",
)
.emit();
return;
Expand Down Expand Up @@ -185,7 +185,7 @@ pub(crate) fn expand_deriving_smart_ptr(
.struct_span_err(
pointee_ty_ident.span,
format!(
"`derive(SmartPointer)` requires {} to be marked `?Sized`",
"`derive(CoercePointee)` requires {} to be marked `?Sized`",
pointee_ty_ident.name
),
)
Expand All @@ -195,7 +195,7 @@ pub(crate) fn expand_deriving_smart_ptr(
let arg = GenericArg::Type(s_ty.clone());
let unsize = cx.path_all(span, true, path!(span, core::marker::Unsize), vec![arg]);
pointee.bounds.push(cx.trait_bound(unsize, false));
// Drop `#[pointee]` attribute since it should not be recognized outside `derive(SmartPointer)`
// Drop `#[pointee]` attribute since it should not be recognized outside `derive(CoercePointee)`
pointee.attrs.retain(|attr| !attr.has_name(sym::pointee));
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_builtin_macros/src/deriving/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ macro path_std($($x:tt)*) {

pub(crate) mod bounds;
pub(crate) mod clone;
pub(crate) mod coerce_pointee;
pub(crate) mod debug;
pub(crate) mod decodable;
pub(crate) mod default;
pub(crate) mod encodable;
pub(crate) mod hash;
pub(crate) mod smart_ptr;

#[path = "cmp/eq.rs"]
pub(crate) mod eq;
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_builtin_macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
PartialOrd: partial_ord::expand_deriving_partial_ord,
RustcDecodable: decodable::expand_deriving_rustc_decodable,
RustcEncodable: encodable::expand_deriving_rustc_encodable,
SmartPointer: smart_ptr::expand_deriving_smart_ptr,
CoercePointee: coerce_pointee::expand_deriving_coerce_pointee,
}

let client = proc_macro::bridge::client::Client::expand1(proc_macro::quote);
Expand Down
6 changes: 4 additions & 2 deletions compiler/rustc_error_codes/src/error_codes/E0667.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#### Note: this error code is no longer emitted by the compiler.

`impl Trait` is not allowed in path parameters.

Erroneous code example:

```compile_fail,E0667
```ignore (removed error code)
fn some_fn(mut x: impl Iterator) -> <impl Iterator>::Item { // error!
x.next().unwrap()
}
Expand All @@ -11,7 +13,7 @@ fn some_fn(mut x: impl Iterator) -> <impl Iterator>::Item { // error!
You cannot use `impl Trait` in path parameters. If you want something
equivalent, you can do this instead:

```
```ignore (removed error code)
fn some_fn<T: Iterator>(mut x: T) -> T::Item { // ok!
x.next().unwrap()
}
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/removed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ declare_features! (
/// Allows default type parameters to influence type inference.
(removed, default_type_parameter_fallback, "1.82.0", Some(27336),
Some("never properly implemented; requires significant design work")),
/// Allows deriving traits as per `SmartPointer` specification
(removed, derive_smart_pointer, "1.79.0", Some(123430), Some("replaced by `CoercePointee`")),
/// Allows using `#[doc(keyword = "...")]`.
(removed, doc_keyword, "1.28.0", Some(51315),
Some("merged into `#![feature(rustdoc_internals)]`")),
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,8 +450,6 @@ declare_features! (
(unstable, deprecated_suggestion, "1.61.0", Some(94785)),
/// Allows deref patterns.
(incomplete, deref_patterns, "1.79.0", Some(87121)),
/// Allows deriving `SmartPointer` traits
(unstable, derive_smart_pointer, "1.79.0", Some(123430)),
/// Controls errors in trait implementations.
(unstable, do_not_recommend, "1.67.0", Some(51992)),
/// Tells rustdoc to automatically generate `#[doc(cfg(...))]`.
Expand Down
9 changes: 0 additions & 9 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1203,15 +1203,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
err.emit()
} else if let Err(reported) = qself_ty.error_reported() {
reported
} else if let ty::Alias(ty::Opaque, alias_ty) = qself_ty.kind() {
// `<impl Trait as OtherTrait>::Assoc` makes no sense.
struct_span_code_err!(
self.dcx(),
tcx.def_span(alias_ty.def_id),
E0667,
"`impl Trait` is not allowed in path parameters"
)
.emit() // Already reported in an earlier stage.
} else {
self.maybe_report_similar_assoc_fn(span, qself_ty, qself)?;

Expand Down
17 changes: 5 additions & 12 deletions compiler/rustc_lint/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,14 @@
//! AST visitor. Also see `rustc_session::lint::builtin`, which contains the
//! definitions of lints that are emitted directly inside the main compiler.
//!
//! To add a new lint to rustc, declare it here using `declare_lint!()`.
//! To add a new lint to rustc, declare it here using [`declare_lint!`].
//! Then add code to emit the new lint in the appropriate circumstances.
//! You can do that in an existing `LintPass` if it makes sense, or in a
//! new `LintPass`, or using `Session::add_lint` elsewhere in the
//! compiler. Only do the latter if the check can't be written cleanly as a
//! `LintPass` (also, note that such lints will need to be defined in
//! `rustc_session::lint::builtin`, not here).
//!
//! If you define a new `EarlyLintPass`, you will also need to add it to the
//! `add_early_builtin!` or `add_early_builtin_with_new!` invocation in
//! `lib.rs`. Use the former for unit-like structs and the latter for structs
//! with a `pub fn new()`.
//! If you define a new [`EarlyLintPass`], you will also need to add it to the
//! [`crate::early_lint_methods!`] invocation in `lib.rs`.
//!
//! If you define a new `LateLintPass`, you will also need to add it to the
//! `late_lint_methods!` invocation in `lib.rs`.
//! If you define a new [`LateLintPass`], you will also need to add it to the
//! [`crate::late_lint_methods!`] invocation in `lib.rs`.

use std::fmt::Write;

Expand Down
20 changes: 3 additions & 17 deletions compiler/rustc_lint/src/context.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,7 @@
//! Implementation of lint checking.
//! Basic types for managing and implementing lints.
//!
//! The lint checking is mostly consolidated into one pass which runs
//! after all other analyses. Throughout compilation, lint warnings
//! can be added via the `add_lint` method on the Session structure. This
//! requires a span and an ID of the node that the lint is being added to. The
//! lint isn't actually emitted at that time because it is unknown what the
//! actual lint level at that location is.
//!
//! To actually emit lint warnings/errors, a separate pass is used.
//! A context keeps track of the current state of all lint levels.
//! Upon entering a node of the ast which can modify the lint settings, the
//! previous lint state is pushed onto a stack and the ast is then recursed
//! upon. As the ast is traversed, this keeps track of the current lint level
//! for all lint attributes.
//! See <https://rustc-dev-guide.rust-lang.org/diagnostics.html> for an
//! overview of how lints are implemented.

use std::cell::Cell;
use std::{iter, slice};
Expand Down Expand Up @@ -52,9 +41,6 @@ type LateLintPassFactory =
dyn for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx> + sync::DynSend + sync::DynSync;

/// Information about the registered lints.
///
/// This is basically the subset of `Context` that we can
/// build early in the compile pipeline.
pub struct LintStore {
/// Registered lints.
lints: Vec<&'static Lint>,
Expand Down
18 changes: 4 additions & 14 deletions compiler/rustc_lint/src/early.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,8 @@
//! Implementation of lint checking.
//! Implementation of the early lint pass.
//!
//! The lint checking is mostly consolidated into one pass which runs
//! after all other analyses. Throughout compilation, lint warnings
//! can be added via the `add_lint` method on the Session structure. This
//! requires a span and an ID of the node that the lint is being added to. The
//! lint isn't actually emitted at that time because it is unknown what the
//! actual lint level at that location is.
//!
//! To actually emit lint warnings/errors, a separate pass is used.
//! A context keeps track of the current state of all lint levels.
//! Upon entering a node of the ast which can modify the lint settings, the
//! previous lint state is pushed onto a stack and the ast is then recursed
//! upon. As the ast is traversed, this keeps track of the current lint level
//! for all lint attributes.
//! The early lint pass works on AST nodes after macro expansion and name
//! resolution, just before AST lowering. These lints are for purely
//! syntactical lints.

use rustc_ast::ptr::P;
use rustc_ast::visit::{self as ast_visit, Visitor, walk_list};
Expand Down
Loading
Loading