From 46af9870727abe142963c9873e960242188dbaab Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Mon, 1 Jul 2024 08:36:28 +0000 Subject: [PATCH] Add `constness` to `TraitDef` --- compiler/rustc_ast_lowering/src/item.rs | 9 ++++--- compiler/rustc_feature/src/builtin_attrs.rs | 2 +- compiler/rustc_hir_analysis/src/bounds.rs | 4 ++-- compiler/rustc_hir_analysis/src/collect.rs | 8 ++++++- .../src/hir_ty_lowering/mod.rs | 12 +++------- compiler/rustc_hir_typeck/src/method/mod.rs | 4 ++-- compiler/rustc_middle/src/ty/mod.rs | 7 +++++- compiler/rustc_middle/src/ty/trait_def.rs | 3 +++ .../rustc_must_implement_one_of_misuse.stderr | 24 +++++++++---------- 9 files changed, 42 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index d59ac576629..0ad23b53566 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -625,9 +625,12 @@ impl<'hir> LoweringContext<'_, 'hir> { _ => Const::No, } } else { - self.tcx - .get_attr(def_id, sym::const_trait) - .map_or(Const::No, |attr| Const::Yes(attr.span)) + if self.tcx.is_const_trait(def_id) { + // FIXME(effects) span + Const::Yes(self.tcx.def_ident_span(def_id).unwrap()) + } else { + Const::No + } } } else { Const::No diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index a4245f0908e..0d990cbd664 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -556,7 +556,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), // RFC 2632 gated!( - const_trait, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes, const_trait_impl, + const_trait, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No, const_trait_impl, "`const_trait` is a temporary placeholder for marking a trait that is suitable for `const` \ `impls` and all default bodies as `const`, which may be removed or renamed in the \ future." diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs index c7ee89e73c2..c30a6f1eeb9 100644 --- a/compiler/rustc_hir_analysis/src/bounds.rs +++ b/compiler/rustc_hir_analysis/src/bounds.rs @@ -7,7 +7,7 @@ use rustc_hir::LangItem; use rustc_middle::ty::fold::FnMutDelegate; use rustc_middle::ty::{self, Ty, TyCtxt, Upcast}; use rustc_span::def_id::DefId; -use rustc_span::{sym, Span}; +use rustc_span::Span; /// Collects together a list of type bounds. These lists of bounds occur in many places /// in Rust's syntax: @@ -80,7 +80,7 @@ impl<'tcx> Bounds<'tcx> { } (_, ty::BoundConstness::NotConst) => { - if !tcx.has_attr(bound_trait_ref.def_id(), sym::const_trait) { + if !tcx.is_const_trait(bound_trait_ref.def_id()) { return; } tcx.consts.true_ diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 41fbef48940..01a1872f1cb 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1194,6 +1194,11 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef { _ => span_bug!(item.span, "trait_def_of_item invoked on non-trait"), }; + let constness = if tcx.has_attr(def_id, sym::const_trait) { + hir::Constness::Const + } else { + hir::Constness::NotConst + }; let paren_sugar = tcx.has_attr(def_id, sym::rustc_paren_sugar); if paren_sugar && !tcx.features().unboxed_closures { tcx.dcx().emit_err(errors::ParenSugarAttribute { span: item.span }); @@ -1348,6 +1353,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef { ty::TraitDef { def_id: def_id.to_def_id(), safety, + constness, paren_sugar, has_auto_impl: is_auto, is_marker, @@ -1680,7 +1686,7 @@ fn check_impl_constness( } let trait_def_id = hir_trait_ref.trait_def_id()?; - if tcx.has_attr(trait_def_id, sym::const_trait) { + if tcx.is_const_trait(trait_def_id) { return None; } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 2a68d3915bb..af7e49ce17d 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -47,7 +47,7 @@ use rustc_middle::{bug, span_bug}; use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::symbol::{kw, Ident, Symbol}; -use rustc_span::{sym, Span, DUMMY_SP}; +use rustc_span::{Span, DUMMY_SP}; use rustc_target::spec::abi; use rustc_trait_selection::traits::wf::object_region_bounds; use rustc_trait_selection::traits::{self, ObligationCtxt}; @@ -559,7 +559,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } if let ty::BoundConstness::Const | ty::BoundConstness::ConstIfConst = constness && generics.has_self - && !tcx.has_attr(def_id, sym::const_trait) + && !tcx.is_const_trait(def_id) { let reported = tcx.dcx().emit_err(crate::errors::ConstBoundForNonConstTrait { span, @@ -1847,19 +1847,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { path.segments[..path.segments.len() - 2].iter(), GenericsArgsErrExtend::None, ); - // HACK: until we support ``, assume all of them are. - let constness = if tcx.has_attr(tcx.parent(def_id), sym::const_trait) { - ty::BoundConstness::ConstIfConst - } else { - ty::BoundConstness::NotConst - }; self.lower_qpath( span, opt_self_ty, def_id, &path.segments[path.segments.len() - 2], path.segments.last().unwrap(), - constness, + ty::BoundConstness::NotConst, ) } Res::PrimTy(prim_ty) => { diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index ff8899ae036..dc1b888374c 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -21,7 +21,7 @@ use rustc_middle::ty::{self, GenericParamDefKind, Ty, TypeVisitableExt}; use rustc_middle::ty::{GenericArgs, GenericArgsRef}; use rustc_middle::{bug, span_bug}; use rustc_span::symbol::Ident; -use rustc_span::{sym, Span}; +use rustc_span::Span; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::{self, NormalizeExt}; @@ -359,7 +359,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // FIXME(effects) find a better way to do this // Operators don't have generic methods, but making them `#[const_trait]` gives them // `const host: bool`. - let args = if self.tcx.has_attr(trait_def_id, sym::const_trait) { + let args = if self.tcx.is_const_trait(trait_def_id) { self.tcx.mk_args_from_iter( args.iter() .chain([self.tcx.expected_host_effect_param_for_body(self.body_id).into()]), diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 7d57d88f40f..9f8b46f8ab0 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1966,9 +1966,14 @@ impl<'tcx> TyCtxt<'tcx> { ) && self.constness(def_id) == hir::Constness::Const } + #[inline] + pub fn is_const_trait(self, def_id: DefId) -> bool { + self.trait_def(def_id).constness == hir::Constness::Const + } + #[inline] pub fn is_const_default_method(self, def_id: DefId) -> bool { - matches!(self.trait_of_item(def_id), Some(trait_id) if self.has_attr(trait_id, sym::const_trait)) + matches!(self.trait_of_item(def_id), Some(trait_id) if self.is_const_trait(trait_id)) } pub fn impl_method_has_trait_impl_trait_tys(self, def_id: DefId) -> bool { diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index 4dba97c3b5b..25cd10979ee 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -18,6 +18,9 @@ pub struct TraitDef { pub safety: hir::Safety, + /// Whether this trait has been annotated with `#[const_trait]`. + pub constness: hir::Constness, + /// If `true`, then this trait had the `#[rustc_paren_sugar]` /// attribute, indicating that it should be used with `Foo()` /// sugar. This is a temporary thing -- eventually any trait will diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr b/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr index 38e692521ca..03a4017b3d7 100644 --- a/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr +++ b/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr @@ -22,18 +22,6 @@ LL | LL | struct Struct {} | ---------------- not a trait -error: function not found in this trait - --> $DIR/rustc_must_implement_one_of_misuse.rs:3:31 - | -LL | #[rustc_must_implement_one_of(a, b)] - | ^ - -error: function not found in this trait - --> $DIR/rustc_must_implement_one_of_misuse.rs:3:34 - | -LL | #[rustc_must_implement_one_of(a, b)] - | ^ - error: function not found in this trait --> $DIR/rustc_must_implement_one_of_misuse.rs:8:34 | @@ -46,6 +34,18 @@ error: the `#[rustc_must_implement_one_of]` attribute must be used with at least LL | #[rustc_must_implement_one_of(a)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: function not found in this trait + --> $DIR/rustc_must_implement_one_of_misuse.rs:3:31 + | +LL | #[rustc_must_implement_one_of(a, b)] + | ^ + +error: function not found in this trait + --> $DIR/rustc_must_implement_one_of_misuse.rs:3:34 + | +LL | #[rustc_must_implement_one_of(a, b)] + | ^ + error: not a function --> $DIR/rustc_must_implement_one_of_misuse.rs:26:5 |