From 2655bc93ac83fc27873c05513af27cf8ff3da28a Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 24 Feb 2021 12:28:39 +0100 Subject: [PATCH 1/2] Add #[rustc_per_edition] for edition-dependent type aliases. --- compiler/rustc_feature/src/builtin_attrs.rs | 7 ++++ compiler/rustc_span/src/symbol.rs | 1 + compiler/rustc_typeck/src/astconv/mod.rs | 36 +++++++++++++++++---- 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index ac50703b5444e..00c594211085d 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -394,6 +394,13 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ may_dangle, Normal, template!(Word), dropck_eyepatch, "`may_dangle` has unstable semantics and may be removed in the future", ), + rustc_attr!( + rustc_per_edition, AssumedUsed, template!(Word), + "#[rustc_per_edition] can be applied to a type alias to make the resolution + dependent on the edition of the crate using this type alias. + It must be applied on an alias for a tuple, of which the fields correspond + to the Rust editions.", + ), // ========================================================================== // Internal attributes: Runtime related: diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index b112402ffe371..321f9678881af 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -996,6 +996,7 @@ symbols! { rustc_peek_liveness, rustc_peek_maybe_init, rustc_peek_maybe_uninit, + rustc_per_edition, rustc_polymorphize_error, rustc_private, rustc_proc_macro_decls, diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 947363fc3ed08..44748dcbff489 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -26,8 +26,8 @@ use rustc_middle::ty::GenericParamDefKind; use rustc_middle::ty::{self, Const, DefIdTree, Ty, TyCtxt, TypeFoldable}; use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; use rustc_span::lev_distance::find_best_match_for_name; -use rustc_span::symbol::{Ident, Symbol}; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::symbol::{sym, Ident, Symbol}; +use rustc_span::{edition, Span, DUMMY_SP}; use rustc_target::spec::abi; use rustc_trait_selection::traits; use rustc_trait_selection::traits::astconv_object_safety_violations; @@ -2053,12 +2053,34 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let substs = self.ast_path_substs_for_ty(span, did, item_segment.0); self.normalize_ty(span, tcx.mk_opaque(did, substs)) } + Res::Def(DefKind::TyAlias, did) => { + assert_eq!(opt_self_ty, None); + self.prohibit_generics(path.segments.split_last().unwrap().1); + let ty = self.ast_path_to_ty(span, did, path.segments.last().unwrap()); + if self.tcx().has_attr(did, sym::rustc_per_edition) { + let ty = if let ty::Tuple(..) = ty.kind() { + let mut fields = ty.tuple_fields(); + let edition = span.edition(); + edition::ALL_EDITIONS + .iter() + .take_while(|&&e| e != edition) + .fold(fields.next(), |ty, _| fields.next().or(ty)) + } else { + None + }; + ty.unwrap_or_else(|| { + self.tcx().sess.span_err( + self.tcx().def_span(did), + "#[rustc_per_edition] type alias needs to be a tuple of at least one field", + ); + tcx.ty_error() + }) + } else { + ty + } + } Res::Def( - DefKind::Enum - | DefKind::TyAlias - | DefKind::Struct - | DefKind::Union - | DefKind::ForeignTy, + DefKind::Enum | DefKind::Struct | DefKind::Union | DefKind::ForeignTy, did, ) => { assert_eq!(opt_self_ty, None); From a7c7fe690182185fb6502a6265aa14931e889a13 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 24 Feb 2021 19:30:25 +0100 Subject: [PATCH 2/2] Add test for #[rustc_per_edition]. --- src/test/ui/editions/auxiliary/per-edition.rs | 27 +++++++++++++++++++ src/test/ui/editions/rustc-per-edition.rs | 24 +++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 src/test/ui/editions/auxiliary/per-edition.rs create mode 100644 src/test/ui/editions/rustc-per-edition.rs diff --git a/src/test/ui/editions/auxiliary/per-edition.rs b/src/test/ui/editions/auxiliary/per-edition.rs new file mode 100644 index 0000000000000..b871f886ea6b3 --- /dev/null +++ b/src/test/ui/editions/auxiliary/per-edition.rs @@ -0,0 +1,27 @@ +// edition:2015 + +#![feature(rustc_attrs)] + +#[rustc_per_edition] +pub type I32OrStr = ( + i32, // 2015 + &'static str, // 2018+ +); + +pub type I32 = I32OrStr; + +pub use I32OrStr as Magic; + +#[macro_export] +macro_rules! int { + () => { + $crate::I32OrStr + } +} + +#[macro_export] +macro_rules! x { + () => { + X + } +} diff --git a/src/test/ui/editions/rustc-per-edition.rs b/src/test/ui/editions/rustc-per-edition.rs new file mode 100644 index 0000000000000..7a8ed0f9e041c --- /dev/null +++ b/src/test/ui/editions/rustc-per-edition.rs @@ -0,0 +1,24 @@ +// check-pass +// edition:2021 +// aux-build:per-edition.rs + +#![feature(rustc_attrs)] + +#[macro_use] +extern crate per_edition; + +#[rustc_per_edition] +type X = ( + u32, // 2015 + &'static str, // 2018, + f64, // 2021+ +); + +fn main() { + let _: X = 6.28; + let _: per_edition::I32 = 1i32; + let _: per_edition::I32OrStr = "hello"; + let _: per_edition::Magic = "world"; + let _: per_edition::int!() = 2i32; + let _: per_edition::x!() = 3u32; +}