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 6 pull requests #104805

Closed
wants to merge 15 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
17 changes: 17 additions & 0 deletions compiler/rustc_lint/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1245,6 +1245,23 @@ impl<'tcx> LateContext<'tcx> {

AbsolutePathPrinter { tcx: self.tcx }.print_def_path(def_id, &[]).unwrap()
}

/// Returns the associated type `name` for `self_ty` as an implementation of `trait_id`.
/// Do not invoke without first verifying that the type implements the trait.
pub fn get_associated_type(
&self,
self_ty: Ty<'tcx>,
trait_id: DefId,
name: &str,
) -> Option<Ty<'tcx>> {
let tcx = self.tcx;
tcx.associated_items(trait_id)
.find_by_name_and_kind(tcx, Ident::from_str(name), ty::AssocKind::Type, trait_id)
.and_then(|assoc| {
let proj = tcx.mk_projection(assoc.def_id, tcx.mk_substs_trait(self_ty, []));
tcx.try_normalize_erasing_regions(self.param_env, proj).ok()
})
}
}

impl<'tcx> abi::HasDataLayout for LateContext<'tcx> {
Expand Down
92 changes: 92 additions & 0 deletions compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
use crate::{LateContext, LateLintPass, LintContext};

use rustc_errors::DelayDm;
use rustc_hir as hir;
use rustc_middle::{traits::util::supertraits, ty};
use rustc_span::sym;

declare_lint! {
/// The `deref_into_dyn_supertrait` lint is output whenever there is a use of the
/// `Deref` implementation with a `dyn SuperTrait` type as `Output`.
///
/// These implementations will become shadowed when the `trait_upcasting` feature is stabilized.
/// The `deref` functions will no longer be called implicitly, so there might be behavior change.
///
/// ### Example
///
/// ```rust,compile_fail
/// #![deny(deref_into_dyn_supertrait)]
/// #![allow(dead_code)]
///
/// use core::ops::Deref;
///
/// trait A {}
/// trait B: A {}
/// impl<'a> Deref for dyn 'a + B {
/// type Target = dyn A;
/// fn deref(&self) -> &Self::Target {
/// todo!()
/// }
/// }
///
/// fn take_a(_: &dyn A) { }
///
/// fn take_b(b: &dyn B) {
/// take_a(b);
/// }
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// The dyn upcasting coercion feature adds new coercion rules, taking priority
/// over certain other coercion rules, which will cause some behavior change.
pub DEREF_INTO_DYN_SUPERTRAIT,
Warn,
"`Deref` implementation usage with a supertrait trait object for output might be shadowed in the future",
@future_incompatible = FutureIncompatibleInfo {
reference: "issue #89460 <https://github.com/rust-lang/rust/issues/89460>",
};
}

declare_lint_pass!(DerefIntoDynSupertrait => [DEREF_INTO_DYN_SUPERTRAIT]);

impl<'tcx> LateLintPass<'tcx> for DerefIntoDynSupertrait {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
// `Deref` is being implemented for `t`
if let hir::ItemKind::Impl(impl_) = item.kind
&& let Some(trait_) = &impl_.of_trait
&& let t = cx.tcx.type_of(item.owner_id)
&& let opt_did @ Some(did) = trait_.trait_def_id()
&& opt_did == cx.tcx.lang_items().deref_trait()
// `t` is `dyn t_principal`
&& let ty::Dynamic(data, _, ty::Dyn) = t.kind()
&& let Some(t_principal) = data.principal()
// `<T as Deref>::Target` is `dyn target_principal`
&& let Some(target) = cx.get_associated_type(t, did, "Target")
&& let ty::Dynamic(data, _, ty::Dyn) = target.kind()
&& let Some(target_principal) = data.principal()
// `target_principal` is a supertrait of `t_principal`
&& supertraits(cx.tcx, t_principal.with_self_ty(cx.tcx, cx.tcx.types.trait_object_dummy_self))
.any(|sup| sup.map_bound(|x| ty::ExistentialTraitRef::erase_self_ty(cx.tcx, x)) == target_principal)
{
cx.struct_span_lint(
DEREF_INTO_DYN_SUPERTRAIT,
cx.tcx.def_span(item.owner_id.def_id),
DelayDm(|| {
format!(
"`{t}` implements `Deref` with supertrait `{target_principal}` as target"
)
}),
|lint| {
if let Some(target_span) = impl_.items.iter().find_map(|i| (i.ident.name == sym::Target).then_some(i.span)) {
lint.span_label(target_span, "target type is set here");
}

lint
},
)
}
}
}
3 changes: 3 additions & 0 deletions compiler/rustc_lint/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ extern crate tracing;
mod array_into_iter;
pub mod builtin;
mod context;
mod deref_into_dyn_supertrait;
mod early;
mod enum_intrinsics_non_enums;
mod errors;
Expand Down Expand Up @@ -87,6 +88,7 @@ use rustc_span::Span;

use array_into_iter::ArrayIntoIter;
use builtin::*;
use deref_into_dyn_supertrait::*;
use enum_intrinsics_non_enums::EnumIntrinsicsNonEnums;
use for_loops_over_fallibles::*;
use hidden_unicode_codepoints::*;
Expand Down Expand Up @@ -192,6 +194,7 @@ macro_rules! late_lint_mod_passes {
$args,
[
ForLoopsOverFallibles: ForLoopsOverFallibles,
DerefIntoDynSupertrait: DerefIntoDynSupertrait,
HardwiredLints: HardwiredLints,
ImproperCTypesDeclarations: ImproperCTypesDeclarations,
ImproperCTypesDefinitions: ImproperCTypesDefinitions,
Expand Down
46 changes: 0 additions & 46 deletions compiler/rustc_lint_defs/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3262,7 +3262,6 @@ declare_lint_pass! {
UNUSED_TUPLE_STRUCT_FIELDS,
NON_EXHAUSTIVE_OMITTED_PATTERNS,
TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
DEREF_INTO_DYN_SUPERTRAIT,
DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
DUPLICATE_MACRO_ATTRIBUTES,
SUSPICIOUS_AUTO_TRAIT_IMPLS,
Expand Down Expand Up @@ -3764,51 +3763,6 @@ declare_lint! {
"invisible directionality-changing codepoints in comment"
}

declare_lint! {
/// The `deref_into_dyn_supertrait` lint is output whenever there is a use of the
/// `Deref` implementation with a `dyn SuperTrait` type as `Output`.
///
/// These implementations will become shadowed when the `trait_upcasting` feature is stabilized.
/// The `deref` functions will no longer be called implicitly, so there might be behavior change.
///
/// ### Example
///
/// ```rust,compile_fail
/// #![deny(deref_into_dyn_supertrait)]
/// #![allow(dead_code)]
///
/// use core::ops::Deref;
///
/// trait A {}
/// trait B: A {}
/// impl<'a> Deref for dyn 'a + B {
/// type Target = dyn A;
/// fn deref(&self) -> &Self::Target {
/// todo!()
/// }
/// }
///
/// fn take_a(_: &dyn A) { }
///
/// fn take_b(b: &dyn B) {
/// take_a(b);
/// }
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// The dyn upcasting coercion feature adds new coercion rules, taking priority
/// over certain other coercion rules, which will cause some behavior change.
pub DEREF_INTO_DYN_SUPERTRAIT,
Warn,
"`Deref` implementation usage with a supertrait trait object for output might be shadowed in the future",
@future_incompatible = FutureIncompatibleInfo {
reference: "issue #89460 <https://github.com/rust-lang/rust/issues/89460>",
};
}

declare_lint! {
/// The `duplicate_macro_attributes` lint detects when a `#[test]`-like built-in macro
/// attribute is duplicated on an item. This lint may trigger on `bench`, `cfg_eval`, `test`
Expand Down
23 changes: 0 additions & 23 deletions compiler/rustc_middle/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -651,12 +651,6 @@ pub enum ImplSource<'tcx, N> {
/// Same as above, but for a function pointer type with the given signature.
FnPointer(ImplSourceFnPointerData<'tcx, N>),

/// ImplSource for a builtin `DeterminantKind` trait implementation.
DiscriminantKind(ImplSourceDiscriminantKindData),

/// ImplSource for a builtin `Pointee` trait implementation.
Pointee(ImplSourcePointeeData),

/// ImplSource automatically generated for a generator.
Generator(ImplSourceGeneratorData<'tcx, N>),

Expand All @@ -678,8 +672,6 @@ impl<'tcx, N> ImplSource<'tcx, N> {
ImplSource::Generator(c) => c.nested,
ImplSource::Object(d) => d.nested,
ImplSource::FnPointer(d) => d.nested,
ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData)
| ImplSource::Pointee(ImplSourcePointeeData) => vec![],
ImplSource::TraitAlias(d) => d.nested,
ImplSource::TraitUpcasting(d) => d.nested,
ImplSource::ConstDestruct(i) => i.nested,
Expand All @@ -696,8 +688,6 @@ impl<'tcx, N> ImplSource<'tcx, N> {
ImplSource::Generator(c) => &c.nested,
ImplSource::Object(d) => &d.nested,
ImplSource::FnPointer(d) => &d.nested,
ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData)
| ImplSource::Pointee(ImplSourcePointeeData) => &[],
ImplSource::TraitAlias(d) => &d.nested,
ImplSource::TraitUpcasting(d) => &d.nested,
ImplSource::ConstDestruct(i) => &i.nested,
Expand Down Expand Up @@ -741,12 +731,6 @@ impl<'tcx, N> ImplSource<'tcx, N> {
fn_ty: p.fn_ty,
nested: p.nested.into_iter().map(f).collect(),
}),
ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData) => {
ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData)
}
ImplSource::Pointee(ImplSourcePointeeData) => {
ImplSource::Pointee(ImplSourcePointeeData)
}
ImplSource::TraitAlias(d) => ImplSource::TraitAlias(ImplSourceTraitAliasData {
alias_def_id: d.alias_def_id,
substs: d.substs,
Expand Down Expand Up @@ -856,13 +840,6 @@ pub struct ImplSourceFnPointerData<'tcx, N> {
pub nested: Vec<N>,
}

// FIXME(@lcnr): This should be refactored and merged with other builtin vtables.
#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
pub struct ImplSourceDiscriminantKindData;

#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
pub struct ImplSourcePointeeData;

#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct ImplSourceConstDestructData<N> {
Expand Down
12 changes: 6 additions & 6 deletions compiler/rustc_middle/src/traits/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,12 @@ pub type EvaluationCache<'tcx> = Cache<
/// parameter environment.
#[derive(PartialEq, Eq, Debug, Clone, TypeFoldable, TypeVisitable)]
pub enum SelectionCandidate<'tcx> {
/// A builtin implementation for some specific traits, used in cases
/// where we cannot rely an ordinary library implementations.
///
/// The most notable examples are `sized`, `Copy` and `Clone`. This is also
/// used for the `DiscriminantKind` and `Pointee` trait, both of which have
/// an associated type.
BuiltinCandidate {
/// `false` if there are no *further* obligations.
has_nested: bool,
Expand Down Expand Up @@ -137,12 +143,6 @@ pub enum SelectionCandidate<'tcx> {
is_const: bool,
},

/// Builtin implementation of `DiscriminantKind`.
DiscriminantKindCandidate,

/// Builtin implementation of `Pointee`.
PointeeCandidate,

TraitAliasCandidate,

/// Matching `dyn Trait` with a supertrait of `Trait`. The index is the
Expand Down
12 changes: 0 additions & 12 deletions compiler/rustc_middle/src/traits/structural_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSource<'tcx, N> {

super::ImplSource::FnPointer(ref d) => write!(f, "({:?})", d),

super::ImplSource::DiscriminantKind(ref d) => write!(f, "{:?}", d),

super::ImplSource::Pointee(ref d) => write!(f, "{:?}", d),

super::ImplSource::Object(ref d) => write!(f, "{:?}", d),

super::ImplSource::Param(ref n, ct) => {
Expand Down Expand Up @@ -125,11 +121,3 @@ impl<N: fmt::Debug> fmt::Debug for traits::ImplSourceConstDestructData<N> {
write!(f, "ImplSourceConstDestructData(nested={:?})", self.nested)
}
}

///////////////////////////////////////////////////////////////////////////
// Lift implementations

TrivialTypeTraversalAndLiftImpls! {
super::ImplSourceDiscriminantKindData,
super::ImplSourcePointeeData,
}
28 changes: 10 additions & 18 deletions compiler/rustc_resolve/src/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use rustc_middle::metadata::ModChild;
use rustc_middle::ty::{self, DefIdTree};
use rustc_session::cstore::CrateStore;
use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind};
use rustc_span::source_map::{respan, Spanned};
use rustc_span::source_map::respan;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span;

Expand Down Expand Up @@ -329,10 +329,12 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
.iter()
.map(|field| respan(field.span, field.ident.map_or(kw::Empty, |ident| ident.name)))
.collect();
self.insert_field_names(def_id, field_names);
self.r.field_names.insert(def_id, field_names);
}

fn insert_field_names(&mut self, def_id: DefId, field_names: Vec<Spanned<Symbol>>) {
fn insert_field_names_extern(&mut self, def_id: DefId) {
let field_names =
self.r.cstore().struct_field_names_untracked(def_id, self.r.session).collect();
self.r.field_names.insert(def_id, field_names);
}

Expand Down Expand Up @@ -995,8 +997,6 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
let cstore = self.r.cstore();
match res {
Res::Def(DefKind::Struct, def_id) => {
let field_names =
cstore.struct_field_names_untracked(def_id, self.r.session).collect();
if let Some((ctor_kind, ctor_def_id)) = cstore.ctor_untracked(def_id) {
let ctor_res = Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id);
let ctor_vis = cstore.visibility_untracked(ctor_def_id);
Expand All @@ -1006,13 +1006,9 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
.struct_constructors
.insert(def_id, (ctor_res, ctor_vis, field_visibilities));
}
self.insert_field_names(def_id, field_names);
}
Res::Def(DefKind::Union, def_id) => {
let field_names =
cstore.struct_field_names_untracked(def_id, self.r.session).collect();
self.insert_field_names(def_id, field_names);
self.insert_field_names_extern(def_id)
}
Res::Def(DefKind::Union, def_id) => self.insert_field_names_extern(def_id),
Res::Def(DefKind::AssocFn, def_id) => {
if cstore.fn_has_self_parameter_untracked(def_id, self.r.session) {
self.r.has_self.insert(def_id);
Expand Down Expand Up @@ -1514,20 +1510,16 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
};

// Define a constructor name in the value namespace.
let fields_id = if let Some((ctor_kind, ctor_node_id)) = CtorKind::from_ast(&variant.data) {
if let Some((ctor_kind, ctor_node_id)) = CtorKind::from_ast(&variant.data) {
let ctor_def_id = self.r.local_def_id(ctor_node_id);
let ctor_res =
Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id.to_def_id());
self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, variant.span, expn_id));
self.r.visibilities.insert(ctor_def_id, ctor_vis);
ctor_def_id
} else {
def_id
};
}

// Record field names for error reporting.
// FIXME: Always use non-ctor id as the key.
self.insert_field_names_local(fields_id.to_def_id(), &variant.data);
self.insert_field_names_local(def_id.to_def_id(), &variant.data);

visit::walk_variant(self, variant);
}
Expand Down
Loading