diff options
| author | bors <bors@rust-lang.org> | 2022-08-19 18:45:41 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-08-19 18:45:41 +0000 |
| commit | e1b28cd2f16bd5b832183d7968cae3bb9213e78d (patch) | |
| tree | c1c0b134e95cb9c2f80a95501c842318a6f7bb6f /compiler | |
| parent | 468887ef91e46847dff57b6b234cff0fad17cb71 (diff) | |
| parent | ecd2885eedd62dba3744b5e5a7051c7bb6e1eca9 (diff) | |
| download | rust-e1b28cd2f16bd5b832183d7968cae3bb9213e78d.tar.gz rust-e1b28cd2f16bd5b832183d7968cae3bb9213e78d.zip | |
Auto merge of #100740 - Dylan-DPC:rollup-0td6yq4, r=Dylan-DPC
Rollup of 9 pull requests Successful merges: - #99576 (Do not allow `Drop` impl on foreign fundamental types) - #100081 (never consider unsafe blocks unused if they would be required with deny(unsafe_op_in_unsafe_fn)) - #100208 (make NOP dyn casts not require anything about the vtable) - #100494 (Cleanup rustdoc themes) - #100522 (Only check the `DefId` for the recursion check in MIR inliner.) - #100592 (Manually implement Debug for ImportKind.) - #100598 (Don't fix builtin index when Where clause is found) - #100721 (Add diagnostics lints to `rustc_type_ir` module) - #100731 (rustdoc: count deref and non-deref as same set of used methods) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_codegen_cranelift/src/unsize.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/base.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_const_eval/src/interpret/cast.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_error_messages/locales/en-US/typeck.ftl | 4 | ||||
| -rw-r--r-- | compiler/rustc_errors/src/diagnostic_builder.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/query.rs | 22 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/check_unsafety.rs | 9 | ||||
| -rw-r--r-- | compiler/rustc_mir_transform/src/check_unsafety.rs | 88 | ||||
| -rw-r--r-- | compiler/rustc_mir_transform/src/inline.rs | 13 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/imports.rs | 40 | ||||
| -rw-r--r-- | compiler/rustc_type_ir/src/lib.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/check/writeback.rs | 26 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/coherence/builtin.rs | 8 |
13 files changed, 114 insertions, 109 deletions
diff --git a/compiler/rustc_codegen_cranelift/src/unsize.rs b/compiler/rustc_codegen_cranelift/src/unsize.rs index 052ca0a082b..dd9d891ddbd 100644 --- a/compiler/rustc_codegen_cranelift/src/unsize.rs +++ b/compiler/rustc_codegen_cranelift/src/unsize.rs @@ -29,6 +29,7 @@ pub(crate) fn unsized_info<'tcx>( let old_info = old_info.expect("unsized_info: missing old info for trait upcasting coercion"); if data_a.principal_def_id() == data_b.principal_def_id() { + // A NOP cast that doesn't actually change anything, should be allowed even with invalid vtables. return old_info; } diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index a840b270974..4c6be3f9108 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -151,6 +151,7 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let old_info = old_info.expect("unsized_info: missing old info for trait upcasting coercion"); if data_a.principal_def_id() == data_b.principal_def_id() { + // A NOP cast that doesn't actually change anything, should be allowed even with invalid vtables. return old_info; } diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index c97c31eb9da..14eb2a1537b 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -298,7 +298,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.write_immediate(val, dest) } (&ty::Dynamic(ref data_a, ..), &ty::Dynamic(ref data_b, ..)) => { - let (old_data, old_vptr) = self.read_immediate(src)?.to_scalar_pair()?; + let val = self.read_immediate(src)?; + if data_a.principal() == data_b.principal() { + // A NOP cast that doesn't actually change anything, should be allowed even with mismatching vtables. + return self.write_immediate(*val, dest); + } + let (old_data, old_vptr) = val.to_scalar_pair()?; let old_vptr = old_vptr.to_pointer(self)?; let (ty, old_trait) = self.get_ptr_vtable(old_vptr)?; if old_trait != data_a.principal() { diff --git a/compiler/rustc_error_messages/locales/en-US/typeck.ftl b/compiler/rustc_error_messages/locales/en-US/typeck.ftl index 0014da17c88..22b32ff838e 100644 --- a/compiler/rustc_error_messages/locales/en-US/typeck.ftl +++ b/compiler/rustc_error_messages/locales/en-US/typeck.ftl @@ -24,8 +24,8 @@ typeck_lifetimes_or_bounds_mismatch_on_trait = .generics_label = lifetimes in impl do not match this {$item_kind} in trait typeck_drop_impl_on_wrong_item = - the `Drop` trait may only be implemented for structs, enums, and unions - .label = must be a struct, enum, or union + the `Drop` trait may only be implemented for local structs, enums, and unions + .label = must be a struct, enum, or union in the current crate typeck_field_already_declared = field `{$field_name}` is already declared diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index 9e68ee282e6..04159bff4ff 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -566,7 +566,7 @@ impl Drop for DiagnosticBuilderInner<'_> { ), )); handler.emit_diagnostic(&mut self.diagnostic); - panic!(); + panic!("error was constructed but not emitted"); } } // `.emit()` was previously called, or maybe we're during `.cancel()`. diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index dd9f8795f94..594c14a642d 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -2,7 +2,7 @@ use crate::mir::{Body, ConstantKind, Promoted}; use crate::ty::{self, OpaqueHiddenType, Ty, TyCtxt}; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::vec_map::VecMap; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; @@ -115,21 +115,6 @@ pub enum UnusedUnsafe { /// `unsafe` block nested under another (used) `unsafe` block /// > ``… because it's nested under this `unsafe` block`` InUnsafeBlock(hir::HirId), - /// `unsafe` block nested under `unsafe fn` - /// > ``… because it's nested under this `unsafe fn` `` - /// - /// the second HirId here indicates the first usage of the `unsafe` block, - /// which allows retrieval of the LintLevelSource for why that operation would - /// have been permitted without the block - InUnsafeFn(hir::HirId, hir::HirId), -} - -#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)] -pub enum UsedUnsafeBlockData { - SomeDisallowedInUnsafeFn, - // the HirId here indicates the first usage of the `unsafe` block - // (i.e. the one that's first encountered in the MIR traversal of the unsafety check) - AllAllowedInUnsafeFn(hir::HirId), } #[derive(TyEncodable, TyDecodable, HashStable, Debug)] @@ -138,10 +123,7 @@ pub struct UnsafetyCheckResult { pub violations: Vec<UnsafetyViolation>, /// Used `unsafe` blocks in this function. This is used for the "unused_unsafe" lint. - /// - /// The keys are the used `unsafe` blocks, the UnusedUnsafeKind indicates whether - /// or not any of the usages happen at a place that doesn't allow `unsafe_op_in_unsafe_fn`. - pub used_unsafe_blocks: FxHashMap<hir::HirId, UsedUnsafeBlockData>, + pub used_unsafe_blocks: FxHashSet<hir::HirId>, /// This is `Some` iff the item is not a closure. pub unused_unsafes: Option<Vec<(hir::HirId, UnusedUnsafe)>>, diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 864caf0ba31..f0b0456c4b9 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -75,10 +75,11 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { match self.safety_context { SafetyContext::BuiltinUnsafeBlock => {} SafetyContext::UnsafeBlock { ref mut used, .. } => { - if !self.body_unsafety.is_unsafe() || !unsafe_op_in_unsafe_fn_allowed { - // Mark this block as useful - *used = true; - } + // Mark this block as useful (even inside `unsafe fn`, where it is technically + // redundant -- but we want to eventually enable `unsafe_op_in_unsafe_fn` by + // default which will require those blocks: + // https://github.com/rust-lang/rust/issues/71668#issuecomment-1203075594). + *used = true; } SafetyContext::UnsafeFn if unsafe_op_in_unsafe_fn_allowed => {} SafetyContext::UnsafeFn => { diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index d564f480166..0f5fd77f7ab 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -1,17 +1,16 @@ -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::FxHashSet; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::hir_id::HirId; use rustc_hir::intravisit; use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor}; +use rustc_middle::mir::*; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt}; -use rustc_middle::{lint, mir::*}; use rustc_session::lint::builtin::{UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE}; use rustc_session::lint::Level; -use std::collections::hash_map; use std::ops::Bound; pub struct UnsafetyChecker<'a, 'tcx> { @@ -23,10 +22,7 @@ pub struct UnsafetyChecker<'a, 'tcx> { param_env: ty::ParamEnv<'tcx>, /// Used `unsafe` blocks in this function. This is used for the "unused_unsafe" lint. - /// - /// The keys are the used `unsafe` blocks, the UnusedUnsafeKind indicates whether - /// or not any of the usages happen at a place that doesn't allow `unsafe_op_in_unsafe_fn`. - used_unsafe_blocks: FxHashMap<HirId, UsedUnsafeBlockData>, + used_unsafe_blocks: FxHashSet<HirId>, } impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { @@ -130,10 +126,7 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> { &AggregateKind::Closure(def_id, _) | &AggregateKind::Generator(def_id, _, _) => { let UnsafetyCheckResult { violations, used_unsafe_blocks, .. } = self.tcx.unsafety_check_result(def_id); - self.register_violations( - violations, - used_unsafe_blocks.iter().map(|(&h, &d)| (h, d)), - ); + self.register_violations(violations, used_unsafe_blocks.iter().copied()); } }, _ => {} @@ -257,22 +250,8 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> { fn register_violations<'a>( &mut self, violations: impl IntoIterator<Item = &'a UnsafetyViolation>, - new_used_unsafe_blocks: impl IntoIterator<Item = (HirId, UsedUnsafeBlockData)>, + new_used_unsafe_blocks: impl IntoIterator<Item = HirId>, ) { - use UsedUnsafeBlockData::{AllAllowedInUnsafeFn, SomeDisallowedInUnsafeFn}; - - let update_entry = |this: &mut Self, hir_id, new_usage| { - match this.used_unsafe_blocks.entry(hir_id) { - hash_map::Entry::Occupied(mut entry) => { - if new_usage == SomeDisallowedInUnsafeFn { - *entry.get_mut() = SomeDisallowedInUnsafeFn; - } - } - hash_map::Entry::Vacant(entry) => { - entry.insert(new_usage); - } - }; - }; let safety = self.body.source_scopes[self.source_info.scope] .local_data .as_ref() @@ -299,22 +278,14 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> { } }), Safety::BuiltinUnsafe => {} - Safety::ExplicitUnsafe(hir_id) => violations.into_iter().for_each(|violation| { - update_entry( - self, - hir_id, - match self.tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, violation.lint_root).0 - { - Level::Allow => AllAllowedInUnsafeFn(violation.lint_root), - _ => SomeDisallowedInUnsafeFn, - }, - ) + Safety::ExplicitUnsafe(hir_id) => violations.into_iter().for_each(|_violation| { + self.used_unsafe_blocks.insert(hir_id); }), }; - new_used_unsafe_blocks - .into_iter() - .for_each(|(hir_id, usage_data)| update_entry(self, hir_id, usage_data)); + new_used_unsafe_blocks.into_iter().for_each(|hir_id| { + self.used_unsafe_blocks.insert(hir_id); + }); } fn check_mut_borrowing_layout_constrained_field( &mut self, @@ -411,34 +382,28 @@ enum Context { struct UnusedUnsafeVisitor<'a, 'tcx> { tcx: TyCtxt<'tcx>, - used_unsafe_blocks: &'a FxHashMap<HirId, UsedUnsafeBlockData>, + used_unsafe_blocks: &'a FxHashSet<HirId>, context: Context, unused_unsafes: &'a mut Vec<(HirId, UnusedUnsafe)>, } impl<'tcx> intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'_, 'tcx> { fn visit_block(&mut self, block: &'tcx hir::Block<'tcx>) { - use UsedUnsafeBlockData::{AllAllowedInUnsafeFn, SomeDisallowedInUnsafeFn}; - if let hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::UserProvided) = block.rules { let used = match self.tcx.lint_level_at_node(UNUSED_UNSAFE, block.hir_id) { - (Level::Allow, _) => Some(SomeDisallowedInUnsafeFn), - _ => self.used_unsafe_blocks.get(&block.hir_id).copied(), + (Level::Allow, _) => true, + _ => self.used_unsafe_blocks.contains(&block.hir_id), }; let unused_unsafe = match (self.context, used) { - (_, None) => UnusedUnsafe::Unused, - (Context::Safe, Some(_)) - | (Context::UnsafeFn(_), Some(SomeDisallowedInUnsafeFn)) => { + (_, false) => UnusedUnsafe::Unused, + (Context::Safe, true) | (Context::UnsafeFn(_), true) => { let previous_context = self.context; self.context = Context::UnsafeBlock(block.hir_id); intravisit::walk_block(self, block); self.context = previous_context; return; } - (Context::UnsafeFn(hir_id), Some(AllAllowedInUnsafeFn(lint_root))) => { - UnusedUnsafe::InUnsafeFn(hir_id, lint_root) - } - (Context::UnsafeBlock(hir_id), Some(_)) => UnusedUnsafe::InUnsafeBlock(hir_id), + (Context::UnsafeBlock(hir_id), true) => UnusedUnsafe::InUnsafeBlock(hir_id), }; self.unused_unsafes.push((block.hir_id, unused_unsafe)); } @@ -462,7 +427,7 @@ impl<'tcx> intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'_, 'tcx> { fn check_unused_unsafe( tcx: TyCtxt<'_>, def_id: LocalDefId, - used_unsafe_blocks: &FxHashMap<HirId, UsedUnsafeBlockData>, + used_unsafe_blocks: &FxHashSet<HirId>, ) -> Vec<(HirId, UnusedUnsafe)> { let body_id = tcx.hir().maybe_body_owned_by(def_id); @@ -535,25 +500,6 @@ fn report_unused_unsafe(tcx: TyCtxt<'_>, kind: UnusedUnsafe, id: HirId) { "because it's nested under this `unsafe` block", ); } - UnusedUnsafe::InUnsafeFn(id, usage_lint_root) => { - db.span_label( - tcx.sess.source_map().guess_head_span(tcx.hir().span(id)), - "because it's nested under this `unsafe` fn", - ) - .note( - "this `unsafe` block does contain unsafe operations, \ - but those are already allowed in an `unsafe fn`", - ); - let (level, source) = - tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, usage_lint_root); - assert_eq!(level, Level::Allow); - lint::explain_lint_level_source( - UNSAFE_OP_IN_UNSAFE_FN, - Level::Allow, - source, - &mut db, - ); - } } db.emit(); diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 1e46b0a0e81..6704d3462f4 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -10,6 +10,7 @@ use rustc_middle::mir::*; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{self, ConstKind, Instance, InstanceDef, ParamEnv, Ty, TyCtxt}; use rustc_session::config::OptLevel; +use rustc_span::def_id::DefId; use rustc_span::{hygiene::ExpnKind, ExpnData, LocalExpnId, Span}; use rustc_target::spec::abi::Abi; @@ -103,8 +104,12 @@ struct Inliner<'tcx> { param_env: ParamEnv<'tcx>, /// Caller codegen attributes. codegen_fn_attrs: &'tcx CodegenFnAttrs, - /// Stack of inlined Instances. - history: Vec<ty::Instance<'tcx>>, + /// Stack of inlined instances. + /// We only check the `DefId` and not the substs because we want to + /// avoid inlining cases of polymorphic recursion. + /// The number of `DefId`s is finite, so checking history is enough + /// to ensure that we do not loop endlessly while inlining. + history: Vec<DefId>, /// Indicates that the caller body has been modified. changed: bool, } @@ -132,7 +137,7 @@ impl<'tcx> Inliner<'tcx> { Ok(new_blocks) => { debug!("inlined {}", callsite.callee); self.changed = true; - self.history.push(callsite.callee); + self.history.push(callsite.callee.def_id()); self.process_blocks(caller_body, new_blocks); self.history.pop(); } @@ -308,7 +313,7 @@ impl<'tcx> Inliner<'tcx> { return None; } - if self.history.contains(&callee) { + if self.history.contains(&callee.def_id()) { return None; } diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index b89273990d8..e0d57ded5bf 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -31,7 +31,7 @@ use std::{mem, ptr}; type Res = def::Res<NodeId>; /// Contains data for specific kinds of imports. -#[derive(Clone, Debug)] +#[derive(Clone)] pub enum ImportKind<'a> { Single { /// `source` in `use prefix::source as target`. @@ -62,6 +62,44 @@ pub enum ImportKind<'a> { MacroUse, } +/// Manually implement `Debug` for `ImportKind` because the `source/target_bindings` +/// contain `Cell`s which can introduce infinite loops while printing. +impl<'a> std::fmt::Debug for ImportKind<'a> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + use ImportKind::*; + match self { + Single { + ref source, + ref target, + ref type_ns_only, + ref nested, + ref additional_ids, + // Ignore the following to avoid an infinite loop while printing. + source_bindings: _, + target_bindings: _, + } => f + .debug_struct("Single") + .field("source", source) + .field("target", target) + .field("type_ns_only", type_ns_only) + .field("nested", nested) + .field("additional_ids", additional_ids) + .finish_non_exhaustive(), + Glob { ref is_prelude, ref max_vis } => f + .debug_struct("Glob") + .field("is_prelude", is_prelude) + .field("max_vis", max_vis) + .finish(), + ExternCrate { ref source, ref target } => f + .debug_struct("ExternCrate") + .field("source", source) + .field("target", target) + .finish(), + MacroUse => f.debug_struct("MacroUse").finish(), + } + } +} + /// One import. #[derive(Debug, Clone)] pub(crate) struct Import<'a> { diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 791e9e0f5a3..5488bca8f47 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -1,6 +1,8 @@ #![feature(fmt_helpers_for_derive)] #![feature(min_specialization)] #![feature(rustc_attrs)] +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate bitflags; diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index ebf1f506183..ba687bc4da4 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -3,7 +3,6 @@ // substitutions. use crate::check::FnCtxt; - use hir::def_id::LocalDefId; use rustc_data_structures::fx::FxHashMap; use rustc_errors::ErrorGuaranteed; @@ -16,6 +15,7 @@ use rustc_middle::mir::FakeReadCause; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast}; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable}; +use rustc_middle::ty::TypeckResults; use rustc_middle::ty::{self, ClosureSizeProfileData, Ty, TyCtxt}; use rustc_span::symbol::sym; use rustc_span::Span; @@ -192,6 +192,27 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } } + // (ouz-a 1005988): Normally `[T] : std::ops::Index<usize>` should be normalized + // into [T] but currently `Where` clause stops the normalization process for it, + // here we compare types of expr and base in a code without `Where` clause they would be equal + // if they are not we don't modify the expr, hence we bypass the ICE + fn is_builtin_index( + &mut self, + typeck_results: &TypeckResults<'tcx>, + e: &hir::Expr<'_>, + base_ty: Ty<'tcx>, + index_ty: Ty<'tcx>, + ) -> bool { + if let Some(elem_ty) = base_ty.builtin_index() { + let Some(exp_ty) = typeck_results.expr_ty_opt(e) else {return false;}; + let resolved_exp_ty = self.resolve(exp_ty, &e.span); + + elem_ty == resolved_exp_ty && index_ty == self.fcx.tcx.types.usize + } else { + false + } + } + // Similar to operators, indexing is always assumed to be overloaded // Here, correct cases where an indexing expression can be simplified // to use builtin indexing because the index type is known to be @@ -222,8 +243,9 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { ) }); let index_ty = self.fcx.resolve_vars_if_possible(index_ty); + let resolved_base_ty = self.resolve(*base_ty, &base.span); - if base_ty.builtin_index().is_some() && index_ty == self.fcx.tcx.types.usize { + if self.is_builtin_index(&typeck_results, e, resolved_base_ty, index_ty) { // Remove the method call record typeck_results.type_dependent_defs_mut().remove(e.hir_id); typeck_results.node_substs_mut().remove(e.hir_id); diff --git a/compiler/rustc_typeck/src/coherence/builtin.rs b/compiler/rustc_typeck/src/coherence/builtin.rs index 043e21fc1e3..2467a81638f 100644 --- a/compiler/rustc_typeck/src/coherence/builtin.rs +++ b/compiler/rustc_typeck/src/coherence/builtin.rs @@ -47,9 +47,11 @@ impl<'tcx> Checker<'tcx> { } fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: LocalDefId) { - // Destructors only work on nominal types. - if let ty::Adt(..) | ty::Error(_) = tcx.type_of(impl_did).kind() { - return; + // Destructors only work on local ADT types. + match tcx.type_of(impl_did).kind() { + ty::Adt(def, _) if def.did().is_local() => return, + ty::Error(_) => return, + _ => {} } let sp = match tcx.hir().expect_item(impl_did).kind { |
