about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_attr_data_structures/src/attributes.rs3
-rw-r--r--compiler/rustc_attr_data_structures/src/encode_cross_crate.rs1
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/traits.rs7
-rw-r--r--compiler/rustc_attr_parsing/src/context.rs5
-rw-r--r--compiler/rustc_builtin_macros/messages.ftl6
-rw-r--r--compiler/rustc_builtin_macros/src/cfg_select.rs16
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs68
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs2
-rw-r--r--compiler/rustc_parse/src/parser/cfg_select.rs10
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs59
-rw-r--r--compiler/rustc_parse/src/validate_attr.rs1
-rw-r--r--compiler/rustc_passes/src/check_attr.rs2
-rw-r--r--compiler/rustc_type_ir/src/walk.rs12
13 files changed, 134 insertions, 58 deletions
diff --git a/compiler/rustc_attr_data_structures/src/attributes.rs b/compiler/rustc_attr_data_structures/src/attributes.rs
index 995ac514d8d..3dedeb1b372 100644
--- a/compiler/rustc_attr_data_structures/src/attributes.rs
+++ b/compiler/rustc_attr_data_structures/src/attributes.rs
@@ -374,6 +374,9 @@ pub enum AttributeKind {
     /// Represents `#[path]`
     Path(Symbol, Span),
 
+    /// Represents `#[pointee]`
+    Pointee(Span),
+
     /// Represents `#[rustc_pub_transparent]` (used by the `repr_transparent_external_private_fields` lint).
     PubTransparent(Span),
 
diff --git a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs
index 494b570c86c..3e2dc0a15b2 100644
--- a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs
+++ b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs
@@ -57,6 +57,7 @@ impl AttributeKind {
             ParenSugar(..) => No,
             PassByValue(..) => Yes,
             Path(..) => No,
+            Pointee(..) => No,
             PubTransparent(..) => Yes,
             Repr { .. } => No,
             RustcLayoutScalarValidRangeEnd(..) => Yes,
diff --git a/compiler/rustc_attr_parsing/src/attributes/traits.rs b/compiler/rustc_attr_parsing/src/attributes/traits.rs
index ee8a33ae9c4..d5e088effd5 100644
--- a/compiler/rustc_attr_parsing/src/attributes/traits.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/traits.rs
@@ -145,3 +145,10 @@ impl<S: Stage> NoArgsAttributeParser<S> for FundamentalParser {
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
     const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::Fundamental;
 }
+
+pub(crate) struct PointeeParser;
+impl<S: Stage> NoArgsAttributeParser<S> for PointeeParser {
+    const PATH: &[Symbol] = &[sym::pointee];
+    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const CREATE: fn(Span) -> AttributeKind = AttributeKind::Pointee;
+}
diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs
index 1f6675b4c5a..567341d1517 100644
--- a/compiler/rustc_attr_parsing/src/context.rs
+++ b/compiler/rustc_attr_parsing/src/context.rs
@@ -47,8 +47,8 @@ use crate::attributes::test_attrs::IgnoreParser;
 use crate::attributes::traits::{
     AllowIncoherentImplParser, CoherenceIsCoreParser, CoinductiveParser, ConstTraitParser,
     DenyExplicitImplParser, DoNotImplementViaObjectParser, FundamentalParser, MarkerParser,
-    ParenSugarParser, SkipDuringMethodDispatchParser, SpecializationTraitParser, TypeConstParser,
-    UnsafeSpecializationMarkerParser,
+    ParenSugarParser, PointeeParser, SkipDuringMethodDispatchParser, SpecializationTraitParser,
+    TypeConstParser, UnsafeSpecializationMarkerParser,
 };
 use crate::attributes::transparency::TransparencyParser;
 use crate::attributes::{AttributeParser as _, Combine, Single, WithoutArgs};
@@ -177,6 +177,7 @@ attribute_parsers!(
         Single<WithoutArgs<OmitGdbPrettyPrinterSectionParser>>,
         Single<WithoutArgs<ParenSugarParser>>,
         Single<WithoutArgs<PassByValueParser>>,
+        Single<WithoutArgs<PointeeParser>>,
         Single<WithoutArgs<PubTransparentParser>>,
         Single<WithoutArgs<SpecializationTraitParser>>,
         Single<WithoutArgs<StdInternalSymbolParser>>,
diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl
index 183927edb02..ae186d744c4 100644
--- a/compiler/rustc_builtin_macros/messages.ftl
+++ b/compiler/rustc_builtin_macros/messages.ftl
@@ -81,11 +81,11 @@ builtin_macros_cfg_accessible_literal_path = `cfg_accessible` path cannot be a l
 builtin_macros_cfg_accessible_multiple_paths = multiple `cfg_accessible` paths are specified
 builtin_macros_cfg_accessible_unspecified_path = `cfg_accessible` path is not specified
 
-builtin_macros_cfg_select_no_matches = none of the rules in this `cfg_select` evaluated to true
+builtin_macros_cfg_select_no_matches = none of the predicates in this `cfg_select` evaluated to true
 
-builtin_macros_cfg_select_unreachable = unreachable rule
+builtin_macros_cfg_select_unreachable = unreachable predicate
     .label = always matches
-    .label2 = this rules is never reached
+    .label2 = this predicate is never reached
 
 builtin_macros_coerce_pointee_requires_maybe_sized = `derive(CoercePointee)` requires `{$name}` to be marked `?Sized`
 
diff --git a/compiler/rustc_builtin_macros/src/cfg_select.rs b/compiler/rustc_builtin_macros/src/cfg_select.rs
index 2dc387d5866..f22d5f255c2 100644
--- a/compiler/rustc_builtin_macros/src/cfg_select.rs
+++ b/compiler/rustc_builtin_macros/src/cfg_select.rs
@@ -1,12 +1,12 @@
 use rustc_ast::tokenstream::TokenStream;
 use rustc_attr_parsing as attr;
 use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult};
-use rustc_parse::parser::cfg_select::{CfgSelectBranches, CfgSelectRule, parse_cfg_select};
+use rustc_parse::parser::cfg_select::{CfgSelectBranches, CfgSelectPredicate, parse_cfg_select};
 use rustc_span::{Ident, Span, sym};
 
 use crate::errors::{CfgSelectNoMatches, CfgSelectUnreachable};
 
-/// Selects the first arm whose rule evaluates to true.
+/// Selects the first arm whose predicate evaluates to true.
 fn select_arm(ecx: &ExtCtxt<'_>, branches: CfgSelectBranches) -> Option<(TokenStream, Span)> {
     for (cfg, tt, arm_span) in branches.reachable {
         if attr::cfg_matches(
@@ -30,11 +30,11 @@ pub(super) fn expand_cfg_select<'cx>(
     ExpandResult::Ready(match parse_cfg_select(&mut ecx.new_parser_from_tts(tts)) {
         Ok(branches) => {
             if let Some((underscore, _, _)) = branches.wildcard {
-                // Warn for every unreachable rule. We store the fully parsed branch for rustfmt.
-                for (rule, _, _) in &branches.unreachable {
-                    let span = match rule {
-                        CfgSelectRule::Wildcard(underscore) => underscore.span,
-                        CfgSelectRule::Cfg(cfg) => cfg.span(),
+                // Warn for every unreachable predicate. We store the fully parsed branch for rustfmt.
+                for (predicate, _, _) in &branches.unreachable {
+                    let span = match predicate {
+                        CfgSelectPredicate::Wildcard(underscore) => underscore.span,
+                        CfgSelectPredicate::Cfg(cfg) => cfg.span(),
                     };
                     let err = CfgSelectUnreachable { span, wildcard_span: underscore.span };
                     ecx.dcx().emit_warn(err);
@@ -50,7 +50,7 @@ pub(super) fn expand_cfg_select<'cx>(
                     Ident::with_dummy_span(sym::cfg_select),
                 );
             } else {
-                // Emit a compiler error when none of the rules matched.
+                // Emit a compiler error when none of the predicates matched.
                 let guar = ecx.dcx().emit_err(CfgSelectNoMatches { span: sp });
                 DummyResult::any(sp, guar)
             }
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index 1eba1f2f03c..22d29eda913 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -44,17 +44,21 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         )?;
         self.copy_op_allow_transmute(&op, dest)?;
 
-        // Give the first pointer-size bytes provenance that knows about the type id.
+        // Give the each pointer-sized chunk provenance that knows about the type id.
         // Here we rely on `TypeId` being a newtype around an array of pointers, so we
-        // first project to its only field and then the first array element.
+        // first project to its only field and then the array elements.
         let alloc_id = tcx.reserve_and_set_type_id_alloc(ty);
         let first = self.project_field(dest, FieldIdx::ZERO)?;
-        let first = self.project_index(&first, 0)?;
-        let offset = self.read_scalar(&first)?.to_target_usize(&tcx)?;
-        let ptr = Pointer::new(alloc_id.into(), Size::from_bytes(offset));
-        let ptr = self.global_root_pointer(ptr)?;
-        let val = Scalar::from_pointer(ptr, &tcx);
-        self.write_scalar(val, &first)
+        let mut elem_iter = self.project_array_fields(&first)?;
+        while let Some((_, elem)) = elem_iter.next(self)? {
+            // Decorate this part of the hash with provenance; leave the integer part unchanged.
+            let hash_fragment = self.read_scalar(&elem)?.to_target_usize(&tcx)?;
+            let ptr = Pointer::new(alloc_id.into(), Size::from_bytes(hash_fragment));
+            let ptr = self.global_root_pointer(ptr)?;
+            let val = Scalar::from_pointer(ptr, &tcx);
+            self.write_scalar(val, &elem)?;
+        }
+        interp_ok(())
     }
 
     /// Returns `true` if emulation happened.
@@ -101,34 +105,36 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 let mut a_fields = self.project_array_fields(&a_fields)?;
                 let mut b_fields = self.project_array_fields(&b_fields)?;
 
-                let (_idx, a) = a_fields
-                    .next(self)?
-                    .expect("we know the layout of TypeId has at least 2 array elements");
-                let a = self.deref_pointer(&a)?;
-                let (a, offset_a) = self.get_ptr_type_id(a.ptr())?;
-
-                let (_idx, b) = b_fields
-                    .next(self)?
-                    .expect("we know the layout of TypeId has at least 2 array elements");
-                let b = self.deref_pointer(&b)?;
-                let (b, offset_b) = self.get_ptr_type_id(b.ptr())?;
+                let mut provenance_a = None;
+                let mut provenance_b = None;
+                let mut provenance_matches = true;
 
-                let provenance_matches = a == b;
+                while let Some((i, a)) = a_fields.next(self)? {
+                    let (_, b) = b_fields.next(self)?.unwrap();
 
-                let mut eq_id = offset_a == offset_b;
+                    let a = self.deref_pointer(&a)?;
+                    let (a, offset_a) = self.get_ptr_type_id(a.ptr())?;
 
-                while let Some((_, a)) = a_fields.next(self)? {
-                    let (_, b) = b_fields.next(self)?.unwrap();
+                    let b = self.deref_pointer(&b)?;
+                    let (b, offset_b) = self.get_ptr_type_id(b.ptr())?;
 
-                    let a = self.read_target_usize(&a)?;
-                    let b = self.read_target_usize(&b)?;
-                    eq_id &= a == b;
-                }
+                    if *provenance_a.get_or_insert(a) != a {
+                        throw_ub_format!(
+                            "type_id_eq: the first TypeId argument is invalid, the provenance of chunk {i} does not match the first chunk's"
+                        )
+                    }
+                    if *provenance_b.get_or_insert(b) != b {
+                        throw_ub_format!(
+                            "type_id_eq: the second TypeId argument is invalid, the provenance of chunk {i} does not match the first chunk's"
+                        )
+                    }
+                    provenance_matches &= a == b;
 
-                if !eq_id && provenance_matches {
-                    throw_ub_format!(
-                        "type_id_eq: one of the TypeId arguments is invalid, the hash does not match the type it represents"
-                    )
+                    if offset_a != offset_b && provenance_matches {
+                        throw_ub_format!(
+                            "type_id_eq: one of the TypeId arguments is invalid, chunk {i} of the hash does not match the type it represents"
+                        )
+                    }
                 }
 
                 self.write_scalar(Scalar::from_bool(provenance_matches), dest)?;
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
index cb106962be1..364ad38556b 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
@@ -49,7 +49,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             } = self.lower_poly_trait_ref(
                 &trait_bound.trait_ref,
                 trait_bound.span,
-                hir::BoundConstness::Never,
+                trait_bound.modifiers.constness,
                 hir::BoundPolarity::Positive,
                 dummy_self,
                 &mut user_written_bounds,
diff --git a/compiler/rustc_parse/src/parser/cfg_select.rs b/compiler/rustc_parse/src/parser/cfg_select.rs
index 24a05afff4a..2c6fb224d70 100644
--- a/compiler/rustc_parse/src/parser/cfg_select.rs
+++ b/compiler/rustc_parse/src/parser/cfg_select.rs
@@ -7,7 +7,7 @@ use rustc_span::Span;
 use crate::exp;
 use crate::parser::Parser;
 
-pub enum CfgSelectRule {
+pub enum CfgSelectPredicate {
     Cfg(MetaItemInner),
     Wildcard(Token),
 }
@@ -20,7 +20,7 @@ pub struct CfgSelectBranches {
     pub wildcard: Option<(Token, TokenStream, Span)>,
     /// All branches after the first wildcard, including further wildcards.
     /// These branches are kept for formatting.
-    pub unreachable: Vec<(CfgSelectRule, TokenStream, Span)>,
+    pub unreachable: Vec<(CfgSelectPredicate, TokenStream, Span)>,
 }
 
 /// Parses a `TokenTree` that must be of the form `{ /* ... */ }`, and returns a `TokenStream` where
@@ -52,7 +52,7 @@ pub fn parse_cfg_select<'a>(p: &mut Parser<'a>) -> PResult<'a, CfgSelectBranches
             match branches.wildcard {
                 None => branches.wildcard = Some((underscore, tts, span)),
                 Some(_) => {
-                    branches.unreachable.push((CfgSelectRule::Wildcard(underscore), tts, span))
+                    branches.unreachable.push((CfgSelectPredicate::Wildcard(underscore), tts, span))
                 }
             }
         } else {
@@ -64,7 +64,9 @@ pub fn parse_cfg_select<'a>(p: &mut Parser<'a>) -> PResult<'a, CfgSelectBranches
 
             match branches.wildcard {
                 None => branches.reachable.push((meta_item, tts, span)),
-                Some(_) => branches.unreachable.push((CfgSelectRule::Cfg(meta_item), tts, span)),
+                Some(_) => {
+                    branches.unreachable.push((CfgSelectPredicate::Cfg(meta_item), tts, span))
+                }
             }
         }
     }
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index a997be3405d..740dd10ea8b 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -575,14 +575,69 @@ impl<'a> Parser<'a> {
                 self.expect(exp!(CloseBracket))?;
             }
             TyKind::Array(elt_ty, length)
-        } else {
-            self.expect(exp!(CloseBracket))?;
+        } else if self.eat(exp!(CloseBracket)) {
             TyKind::Slice(elt_ty)
+        } else {
+            self.maybe_recover_array_ty_without_semi(elt_ty)?
         };
 
         Ok(ty)
     }
 
+    /// Recover from malformed array type syntax.
+    ///
+    /// This method attempts to recover from cases like:
+    /// - `[u8, 5]` → suggests using `;`, return a Array type
+    /// - `[u8 5]` → suggests using `;`, return a Array type
+    /// Consider to add more cases in the future.
+    fn maybe_recover_array_ty_without_semi(&mut self, elt_ty: P<Ty>) -> PResult<'a, TyKind> {
+        let span = self.token.span;
+        let token_descr = super::token_descr(&self.token);
+        let mut err =
+            self.dcx().struct_span_err(span, format!("expected `;` or `]`, found {}", token_descr));
+        err.span_label(span, "expected `;` or `]`");
+        err.note("you might have meant to write a slice or array type");
+
+        // If we cannot recover, return the error immediately.
+        if !self.may_recover() {
+            return Err(err);
+        }
+
+        let snapshot = self.create_snapshot_for_diagnostic();
+
+        let suggestion_span = if self.eat(exp!(Comma)) || self.eat(exp!(Star)) {
+            // Consume common erroneous separators.
+            self.prev_token.span
+        } else {
+            self.token.span.shrink_to_lo()
+        };
+
+        // we first try to parse pattern like `[u8 5]`
+        let length = match self.parse_expr_anon_const() {
+            Ok(length) => length,
+            Err(e) => {
+                e.cancel();
+                self.restore_snapshot(snapshot);
+                return Err(err);
+            }
+        };
+
+        if let Err(e) = self.expect(exp!(CloseBracket)) {
+            e.cancel();
+            self.restore_snapshot(snapshot);
+            return Err(err);
+        }
+
+        err.span_suggestion_verbose(
+            suggestion_span,
+            "you might have meant to use `;` as the separator",
+            ";",
+            Applicability::MaybeIncorrect,
+        );
+        err.emit();
+        Ok(TyKind::Array(elt_ty, length))
+    }
+
     fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
         let and_span = self.prev_token.span;
         let mut opt_lifetime = self.check_lifetime().then(|| self.expect_lifetime());
diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs
index e000d61083d..783d79d978a 100644
--- a/compiler/rustc_parse/src/validate_attr.rs
+++ b/compiler/rustc_parse/src/validate_attr.rs
@@ -297,6 +297,7 @@ pub fn check_builtin_meta_item(
                 | sym::align
                 | sym::deprecated
                 | sym::optimize
+                | sym::pointee
                 | sym::cold
                 | sym::target_feature
                 | sym::rustc_allow_const_fn_unstable
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 820255afe27..2009ddc1e2d 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -251,6 +251,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                     AttributeKind::BodyStability { .. }
                     | AttributeKind::ConstStabilityIndirect
                     | AttributeKind::MacroTransparency(_)
+                    | AttributeKind::Pointee(..)
                     | AttributeKind::Dummy
                     | AttributeKind::OmitGdbPrettyPrinterSection,
                 ) => { /* do nothing  */ }
@@ -381,7 +382,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                             | sym::cfg_attr_trace
                             // need to be fixed
                             | sym::cfi_encoding // FIXME(cfi_encoding)
-                            | sym::pointee // FIXME(derive_coerce_pointee)
                             | sym::instruction_set // broken on stable!!!
                             | sym::windows_subsystem // broken on stable!!!
                             | sym::patchable_function_entry // FIXME(patchable_function_entry)
diff --git a/compiler/rustc_type_ir/src/walk.rs b/compiler/rustc_type_ir/src/walk.rs
index 737550eb73e..9912fad1756 100644
--- a/compiler/rustc_type_ir/src/walk.rs
+++ b/compiler/rustc_type_ir/src/walk.rs
@@ -12,12 +12,6 @@ use crate::{self as ty, Interner};
 // avoid heap allocations.
 type TypeWalkerStack<I> = SmallVec<[<I as Interner>::GenericArg; 8]>;
 
-pub struct TypeWalker<I: Interner> {
-    stack: TypeWalkerStack<I>,
-    last_subtree: usize,
-    pub visited: SsoHashSet<I::GenericArg>,
-}
-
 /// An iterator for walking the type tree.
 ///
 /// It's very easy to produce a deeply
@@ -26,6 +20,12 @@ pub struct TypeWalker<I: Interner> {
 /// in this situation walker only visits each type once.
 /// It maintains a set of visited types and
 /// skips any types that are already there.
+pub struct TypeWalker<I: Interner> {
+    stack: TypeWalkerStack<I>,
+    last_subtree: usize,
+    pub visited: SsoHashSet<I::GenericArg>,
+}
+
 impl<I: Interner> TypeWalker<I> {
     pub fn new(root: I::GenericArg) -> Self {
         Self { stack: smallvec![root], last_subtree: 1, visited: SsoHashSet::new() }