, Self::AttrsTy, AddSemicolon) {
struct OptExprTag;
impl InvocationCollectorNode for AstNodeWrapper, OptExprTag> {
type OutputTy = Option
>;
- type AttrsTy = ast::AttrVec;
const KIND: AstFragmentKind = AstFragmentKind::OptExpr;
fn to_annotatable(self) -> Annotatable {
Annotatable::Expr(self.wrapped)
@@ -1772,7 +1767,7 @@ fn walk_flat_map(mut self, visitor: &mut V) -> Self::OutputTy {
fn is_mac_call(&self) -> bool {
matches!(self.wrapped.kind, ast::ExprKind::MacCall(..))
}
- fn take_mac_call(self) -> (P, Self::AttrsTy, AddSemicolon) {
+ fn take_mac_call(self) -> (P, ast::AttrVec, AddSemicolon) {
let node = self.wrapped.into_inner();
match node.kind {
ExprKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No),
@@ -1794,7 +1789,6 @@ fn dummy() -> MethodReceiverTag {
}
impl InvocationCollectorNode for AstNodeWrapper, MethodReceiverTag> {
type OutputTy = Self;
- type AttrsTy = ast::AttrVec;
const KIND: AstFragmentKind = AstFragmentKind::MethodReceiverExpr;
fn descr() -> &'static str {
"an expression"
@@ -1811,7 +1805,7 @@ fn walk(&mut self, visitor: &mut V) {
fn is_mac_call(&self) -> bool {
matches!(self.wrapped.kind, ast::ExprKind::MacCall(..))
}
- fn take_mac_call(self) -> (P, Self::AttrsTy, AddSemicolon) {
+ fn take_mac_call(self) -> (P, ast::AttrVec, AddSemicolon) {
let node = self.wrapped.into_inner();
match node.kind {
ExprKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No),
diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs
index 79f838e2e33f..cd744977bb32 100644
--- a/compiler/rustc_expand/src/lib.rs
+++ b/compiler/rustc_expand/src/lib.rs
@@ -1,7 +1,6 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![allow(rustc::diagnostic_outside_of_impl)]
-#![cfg_attr(bootstrap, feature(let_chains))]
#![doc(rust_logo)]
#![feature(array_windows)]
#![feature(associated_type_defaults)]
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index e3e4eefe5e10..809d1630ddec 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -96,7 +96,7 @@ macro_rules! declare_features {
/// Allows `#[cfg_attr(predicate, multiple, attributes, here)]`.
(accepted, cfg_attr_multi, "1.33.0", Some(54881)),
/// Allows the use of `#[cfg()]`.
- (accepted, cfg_boolean_literals, "CURRENT_RUSTC_VERSION", Some(131204)),
+ (accepted, cfg_boolean_literals, "1.88.0", Some(131204)),
/// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests.
(accepted, cfg_doctest, "1.40.0", Some(62210)),
/// Enables `#[cfg(panic = "...")]` config key.
@@ -301,7 +301,7 @@ macro_rules! declare_features {
/// For example, you can write `Foo(a, ref b)` where `a` is by-move and `b` is by-ref.
(accepted, move_ref_pattern, "1.49.0", Some(68354)),
/// Allows using `#[naked]` on functions.
- (accepted, naked_functions, "CURRENT_RUSTC_VERSION", Some(90957)),
+ (accepted, naked_functions, "1.88.0", Some(90957)),
/// Allows specifying modifiers in the link attribute: `#[link(modifiers = "...")]`
(accepted, native_link_modifiers, "1.61.0", Some(81490)),
/// Allows specifying the bundle link modifier
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
index 402e18c5d148..687d859df535 100644
--- a/compiler/rustc_feature/src/removed.rs
+++ b/compiler/rustc_feature/src/removed.rs
@@ -143,7 +143,7 @@ macro_rules! declare_features {
(removed, infer_static_outlives_requirements, "1.63.0", Some(54185),
Some("removed as it caused some confusion and discussion was inactive for years")),
/// Allow anonymous constants from an inline `const` block in pattern position
- (removed, inline_const_pat, "CURRENT_RUSTC_VERSION", Some(76001),
+ (removed, inline_const_pat, "1.88.0", Some(76001),
Some("removed due to implementation concerns as it requires significant refactorings")),
/// Lazily evaluate constants. This allows constants to depend on type parameters.
(removed, lazy_normalization_consts, "1.46.0", Some(72219), Some("superseded by `generic_const_exprs`")),
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index a5f89b7a076a..8fb10736539a 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -206,7 +206,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
/// Allows access to the emscripten_wasm_eh config, used by panic_unwind and unwind
(internal, cfg_emscripten_wasm_eh, "1.86.0", None),
/// Allows checking whether or not the backend correctly supports unstable float types.
- (internal, cfg_target_has_reliable_f16_f128, "CURRENT_RUSTC_VERSION", None),
+ (internal, cfg_target_has_reliable_f16_f128, "1.88.0", None),
/// Allows identifying the `compiler_builtins` crate.
(internal, compiler_builtins, "1.13.0", None),
/// Allows writing custom MIR
@@ -316,7 +316,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
// Unstable `#[target_feature]` directives.
(unstable, aarch64_unstable_target_feature, "1.82.0", Some(44839)),
(unstable, aarch64_ver_target_feature, "1.27.0", Some(44839)),
- (unstable, apx_target_feature, "CURRENT_RUSTC_VERSION", Some(139284)),
+ (unstable, apx_target_feature, "1.88.0", Some(139284)),
(unstable, arm_target_feature, "1.27.0", Some(44839)),
(unstable, avx512_target_feature, "1.27.0", Some(44839)),
(unstable, bpf_target_feature, "1.54.0", Some(44839)),
@@ -327,7 +327,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
(unstable, loongarch_target_feature, "1.73.0", Some(44839)),
(unstable, m68k_target_feature, "1.85.0", Some(134328)),
(unstable, mips_target_feature, "1.27.0", Some(44839)),
- (unstable, movrs_target_feature, "CURRENT_RUSTC_VERSION", Some(137976)),
+ (unstable, movrs_target_feature, "1.88.0", Some(137976)),
(unstable, powerpc_target_feature, "1.27.0", Some(44839)),
(unstable, prfchw_target_feature, "1.78.0", Some(44839)),
(unstable, riscv_target_feature, "1.45.0", Some(44839)),
@@ -385,7 +385,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
/// Allows associated type defaults.
(unstable, associated_type_defaults, "1.2.0", Some(29661)),
/// Allows implementing `AsyncDrop`.
- (incomplete, async_drop, "CURRENT_RUSTC_VERSION", Some(126482)),
+ (incomplete, async_drop, "1.88.0", Some(126482)),
/// Allows async functions to be called from `dyn Trait`.
(incomplete, async_fn_in_dyn_trait, "1.85.0", Some(133119)),
/// Allows `#[track_caller]` on async functions.
@@ -395,7 +395,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
/// Allows `async` trait bound modifier.
(unstable, async_trait_bounds, "1.85.0", Some(62290)),
/// Allows using Intel AVX10 target features and intrinsics
- (unstable, avx10_target_feature, "CURRENT_RUSTC_VERSION", Some(138843)),
+ (unstable, avx10_target_feature, "1.88.0", Some(138843)),
/// Allows using C-variadics.
(unstable, c_variadic, "1.34.0", Some(44930)),
/// Allows the use of `#[cfg(contract_checks)` to check if contract checks are enabled.
@@ -483,11 +483,11 @@ pub fn internal(&self, feature: Symbol) -> bool {
/// Allows exhaustive pattern matching on types that contain uninhabited types.
(unstable, exhaustive_patterns, "1.13.0", Some(51085)),
/// Disallows `extern` without an explicit ABI.
- (unstable, explicit_extern_abis, "CURRENT_RUSTC_VERSION", Some(134986)),
+ (unstable, explicit_extern_abis, "1.88.0", Some(134986)),
/// Allows explicit tail calls via `become` expression.
(incomplete, explicit_tail_calls, "1.72.0", Some(112788)),
/// Allows using `#[export_stable]` which indicates that an item is exportable.
- (incomplete, export_stable, "CURRENT_RUSTC_VERSION", Some(139939)),
+ (incomplete, export_stable, "1.88.0", Some(139939)),
/// Allows using `aapcs`, `efiapi`, `sysv64` and `win64` as calling conventions
/// for functions with varargs.
(unstable, extended_varargs_abi_support, "1.65.0", Some(100189)),
@@ -512,7 +512,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
/// Allows impls for the Freeze trait.
(internal, freeze_impls, "1.78.0", Some(121675)),
/// Frontmatter `---` blocks for use by external tools.
- (unstable, frontmatter, "CURRENT_RUSTC_VERSION", Some(136889)),
+ (unstable, frontmatter, "1.88.0", Some(136889)),
/// Allows defining gen blocks and `gen fn`.
(unstable, gen_blocks, "1.75.0", Some(117078)),
/// Infer generic args for both consts and types.
@@ -575,7 +575,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
/// Allows `mut ref` and `mut ref mut` identifier patterns.
(incomplete, mut_ref, "1.79.0", Some(123076)),
/// Allows using `#[naked]` on `extern "Rust"` functions.
- (unstable, naked_functions_rustic_abi, "CURRENT_RUSTC_VERSION", Some(138997)),
+ (unstable, naked_functions_rustic_abi, "1.88.0", Some(138997)),
/// Allows using `#[target_feature(enable = "...")]` on `#[naked]` on functions.
(unstable, naked_functions_target_feature, "1.86.0", Some(138568)),
/// Allows specifying the as-needed link modifier
@@ -641,7 +641,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
/// Allows string patterns to dereference values to match them.
(unstable, string_deref_patterns, "1.67.0", Some(87121)),
/// Allows `super let` statements.
- (unstable, super_let, "CURRENT_RUSTC_VERSION", Some(139076)),
+ (unstable, super_let, "1.88.0", Some(139076)),
/// Allows subtrait items to shadow supertrait items.
(unstable, supertrait_item_shadowing, "1.86.0", Some(89151)),
/// Allows using `#[thread_local]` on `static` items.
diff --git a/compiler/rustc_fluent_macro/src/fluent.rs b/compiler/rustc_fluent_macro/src/fluent.rs
index c96bb48a0368..d58c70674f6a 100644
--- a/compiler/rustc_fluent_macro/src/fluent.rs
+++ b/compiler/rustc_fluent_macro/src/fluent.rs
@@ -25,9 +25,6 @@ fn invocation_relative_path_to_absolute(span: Span, path: &str) -> PathBuf {
path.to_path_buf()
} else {
// `/a/b/c/foo/bar.rs` contains the current macro invocation
- #[cfg(bootstrap)]
- let mut source_file_path = span.source_file().path();
- #[cfg(not(bootstrap))]
let mut source_file_path = span.local_file().unwrap();
// `/a/b/c/foo/`
source_file_path.pop();
diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs
index 98b41187f114..f93b9e5af534 100644
--- a/compiler/rustc_hir/src/definitions.rs
+++ b/compiler/rustc_hir/src/definitions.rs
@@ -309,6 +309,8 @@ pub enum DefPathData {
/// An existential `impl Trait` type node.
/// Argument position `impl Trait` have a `TypeNs` with their pretty-printed name.
OpaqueTy,
+ /// Used for remapped captured lifetimes in an existential `impl Trait` type node.
+ OpaqueLifetime(Symbol),
/// An anonymous associated type from an RPITIT. The symbol refers to the name of the method
/// that defined the type.
AnonAssocTy(Symbol),
@@ -445,7 +447,8 @@ impl DefPathData {
pub fn get_opt_name(&self) -> Option {
use self::DefPathData::*;
match *self {
- TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name),
+ TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name)
+ | OpaqueLifetime(name) => Some(name),
Impl
| ForeignMod
@@ -465,9 +468,8 @@ pub fn get_opt_name(&self) -> Option {
fn hashed_symbol(&self) -> Option {
use self::DefPathData::*;
match *self {
- TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) | AnonAssocTy(name) => {
- Some(name)
- }
+ TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) | AnonAssocTy(name)
+ | OpaqueLifetime(name) => Some(name),
Impl
| ForeignMod
@@ -486,9 +488,8 @@ fn hashed_symbol(&self) -> Option {
pub fn name(&self) -> DefPathDataName {
use self::DefPathData::*;
match *self {
- TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => {
- DefPathDataName::Named(name)
- }
+ TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name)
+ | OpaqueLifetime(name) => DefPathDataName::Named(name),
// Note that this does not show up in user print-outs.
CrateRoot => DefPathDataName::Anon { namespace: kw::Crate },
Impl => DefPathDataName::Anon { namespace: kw::Impl },
diff --git a/compiler/rustc_hir/src/hir/tests.rs b/compiler/rustc_hir/src/hir/tests.rs
index 18f8c523f9d3..8684adee29c9 100644
--- a/compiler/rustc_hir/src/hir/tests.rs
+++ b/compiler/rustc_hir/src/hir/tests.rs
@@ -50,21 +50,14 @@ fn trait_object_roundtrips() {
}
fn trait_object_roundtrips_impl(syntax: TraitObjectSyntax) {
- let unambig = TyKind::TraitObject::<'_, ()>(
- &[],
- TaggedRef::new(
- &const {
- Lifetime {
- hir_id: HirId::INVALID,
- ident: Ident::new(sym::name, DUMMY_SP),
- kind: LifetimeKind::Static,
- source: LifetimeSource::Other,
- syntax: LifetimeSyntax::Hidden,
- }
- },
- syntax,
- ),
- );
+ let lt = Lifetime {
+ hir_id: HirId::INVALID,
+ ident: Ident::new(sym::name, DUMMY_SP),
+ kind: LifetimeKind::Static,
+ source: LifetimeSource::Other,
+ syntax: LifetimeSyntax::Hidden,
+ };
+ let unambig = TyKind::TraitObject::<'_, ()>(&[], TaggedRef::new(<, syntax));
let unambig_to_ambig = unsafe { std::mem::transmute::<_, TyKind<'_, AmbigArg>>(unambig) };
match unambig_to_ambig {
diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs
index 5533920aee4a..7a5ff8906896 100644
--- a/compiler/rustc_hir/src/lib.rs
+++ b/compiler/rustc_hir/src/lib.rs
@@ -4,7 +4,6 @@
// tidy-alphabetical-start
#![allow(internal_features)]
-#![cfg_attr(bootstrap, feature(let_chains))]
#![feature(associated_type_defaults)]
#![feature(box_patterns)]
#![feature(closure_track_caller)]
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 277bb7bd3e15..f7f2b78f0520 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -522,7 +522,7 @@ hir_analysis_trait_object_declared_with_no_traits =
at least one trait is required for an object type
.alias_span = this alias does not contain a trait
-hir_analysis_traits_with_defualt_impl = traits with a default impl, like `{$traits}`, cannot be implemented for {$problematic_kind} `{$self_ty}`
+hir_analysis_traits_with_default_impl = traits with a default impl, like `{$traits}`, cannot be implemented for {$problematic_kind} `{$self_ty}`
.note = a trait object implements `{$traits}` if and only if `{$traits}` is one of the trait object's trait bounds
hir_analysis_transparent_enum_variant = transparent enum needs exactly one variant, but has {$number}
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index bbf36fef1ddb..fb67f2fd2235 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -5,7 +5,7 @@
use hir::def_id::{DefId, DefIdMap, LocalDefId};
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
use rustc_errors::codes::*;
-use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_err};
+use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, pluralize, struct_span_code_err};
use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::VisitorExt;
use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, intravisit};
@@ -14,10 +14,10 @@
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::{
self, BottomUpFolder, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, TypeFolder,
- TypeSuperFoldable, TypeVisitableExt, TypingMode, Upcast,
+ TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Upcast,
};
use rustc_middle::{bug, span_bug};
-use rustc_span::Span;
+use rustc_span::{DUMMY_SP, Span};
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::regions::InferCtxtRegionExt;
@@ -1137,65 +1137,319 @@ fn check_region_bounds_on_impl_item<'tcx>(
// but found 0" it's confusing, because it looks like there
// are zero. Since I don't quite know how to phrase things at
// the moment, give a kind of vague error message.
- if trait_params != impl_params {
- let span = tcx
- .hir_get_generics(impl_m.def_id.expect_local())
- .expect("expected impl item to have generics or else we can't compare them")
- .span;
+ if trait_params == impl_params {
+ return Ok(());
+ }
- let mut generics_span = None;
- let mut bounds_span = vec![];
- let mut where_span = None;
- if let Some(trait_node) = tcx.hir_get_if_local(trait_m.def_id)
- && let Some(trait_generics) = trait_node.generics()
- {
- generics_span = Some(trait_generics.span);
- // FIXME: we could potentially look at the impl's bounds to not point at bounds that
- // *are* present in the impl.
- for p in trait_generics.predicates {
- if let hir::WherePredicateKind::BoundPredicate(pred) = p.kind {
- for b in pred.bounds {
+ if !delay && let Some(guar) = check_region_late_boundedness(tcx, impl_m, trait_m) {
+ return Err(guar);
+ }
+
+ let span = tcx
+ .hir_get_generics(impl_m.def_id.expect_local())
+ .expect("expected impl item to have generics or else we can't compare them")
+ .span;
+
+ let mut generics_span = None;
+ let mut bounds_span = vec![];
+ let mut where_span = None;
+
+ if let Some(trait_node) = tcx.hir_get_if_local(trait_m.def_id)
+ && let Some(trait_generics) = trait_node.generics()
+ {
+ generics_span = Some(trait_generics.span);
+ // FIXME: we could potentially look at the impl's bounds to not point at bounds that
+ // *are* present in the impl.
+ for p in trait_generics.predicates {
+ match p.kind {
+ hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
+ bounds,
+ ..
+ })
+ | hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
+ bounds,
+ ..
+ }) => {
+ for b in *bounds {
if let hir::GenericBound::Outlives(lt) = b {
bounds_span.push(lt.ident.span);
}
}
}
+ _ => {}
}
- if let Some(impl_node) = tcx.hir_get_if_local(impl_m.def_id)
- && let Some(impl_generics) = impl_node.generics()
- {
- let mut impl_bounds = 0;
- for p in impl_generics.predicates {
- if let hir::WherePredicateKind::BoundPredicate(pred) = p.kind {
- for b in pred.bounds {
+ }
+ if let Some(impl_node) = tcx.hir_get_if_local(impl_m.def_id)
+ && let Some(impl_generics) = impl_node.generics()
+ {
+ let mut impl_bounds = 0;
+ for p in impl_generics.predicates {
+ match p.kind {
+ hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
+ bounds,
+ ..
+ })
+ | hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
+ bounds,
+ ..
+ }) => {
+ for b in *bounds {
if let hir::GenericBound::Outlives(_) = b {
impl_bounds += 1;
}
}
}
- }
- if impl_bounds == bounds_span.len() {
- bounds_span = vec![];
- } else if impl_generics.has_where_clause_predicates {
- where_span = Some(impl_generics.where_clause_span);
+ _ => {}
}
}
+ if impl_bounds == bounds_span.len() {
+ bounds_span = vec![];
+ } else if impl_generics.has_where_clause_predicates {
+ where_span = Some(impl_generics.where_clause_span);
+ }
}
- let reported = tcx
- .dcx()
- .create_err(LifetimesOrBoundsMismatchOnTrait {
- span,
- item_kind: impl_m.descr(),
- ident: impl_m.ident(tcx),
- generics_span,
- bounds_span,
- where_span,
- })
- .emit_unless(delay);
- return Err(reported);
}
- Ok(())
+ let reported = tcx
+ .dcx()
+ .create_err(LifetimesOrBoundsMismatchOnTrait {
+ span,
+ item_kind: impl_m.descr(),
+ ident: impl_m.ident(tcx),
+ generics_span,
+ bounds_span,
+ where_span,
+ })
+ .emit_unless(delay);
+
+ Err(reported)
+}
+
+#[allow(unused)]
+enum LateEarlyMismatch<'tcx> {
+ EarlyInImpl(DefId, DefId, ty::Region<'tcx>),
+ LateInImpl(DefId, DefId, ty::Region<'tcx>),
+}
+
+fn check_region_late_boundedness<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ impl_m: ty::AssocItem,
+ trait_m: ty::AssocItem,
+) -> Option {
+ if !impl_m.is_fn() {
+ return None;
+ }
+
+ let (infcx, param_env) = tcx
+ .infer_ctxt()
+ .build_with_typing_env(ty::TypingEnv::non_body_analysis(tcx, impl_m.def_id));
+
+ let impl_m_args = infcx.fresh_args_for_item(DUMMY_SP, impl_m.def_id);
+ let impl_m_sig = tcx.fn_sig(impl_m.def_id).instantiate(tcx, impl_m_args);
+ let impl_m_sig = tcx.liberate_late_bound_regions(impl_m.def_id, impl_m_sig);
+
+ let trait_m_args = infcx.fresh_args_for_item(DUMMY_SP, trait_m.def_id);
+ let trait_m_sig = tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_m_args);
+ let trait_m_sig = tcx.liberate_late_bound_regions(impl_m.def_id, trait_m_sig);
+
+ let ocx = ObligationCtxt::new(&infcx);
+
+ // Equate the signatures so that we can infer whether a late-bound param was present where
+ // an early-bound param was expected, since we replace the late-bound lifetimes with
+ // `ReLateParam`, and early-bound lifetimes with infer vars, so the early-bound args will
+ // resolve to `ReLateParam` if there is a mismatch.
+ let Ok(()) = ocx.eq(
+ &ObligationCause::dummy(),
+ param_env,
+ ty::Binder::dummy(trait_m_sig),
+ ty::Binder::dummy(impl_m_sig),
+ ) else {
+ return None;
+ };
+
+ let errors = ocx.select_where_possible();
+ if !errors.is_empty() {
+ return None;
+ }
+
+ let mut mismatched = vec![];
+
+ let impl_generics = tcx.generics_of(impl_m.def_id);
+ for (id_arg, arg) in
+ std::iter::zip(ty::GenericArgs::identity_for_item(tcx, impl_m.def_id), impl_m_args)
+ {
+ if let ty::GenericArgKind::Lifetime(r) = arg.unpack()
+ && let ty::ReVar(vid) = r.kind()
+ && let r = infcx
+ .inner
+ .borrow_mut()
+ .unwrap_region_constraints()
+ .opportunistic_resolve_var(tcx, vid)
+ && let ty::ReLateParam(ty::LateParamRegion {
+ kind: ty::LateParamRegionKind::Named(trait_param_def_id, _),
+ ..
+ }) = r.kind()
+ && let ty::ReEarlyParam(ebr) = id_arg.expect_region().kind()
+ {
+ mismatched.push(LateEarlyMismatch::EarlyInImpl(
+ impl_generics.region_param(ebr, tcx).def_id,
+ trait_param_def_id,
+ id_arg.expect_region(),
+ ));
+ }
+ }
+
+ let trait_generics = tcx.generics_of(trait_m.def_id);
+ for (id_arg, arg) in
+ std::iter::zip(ty::GenericArgs::identity_for_item(tcx, trait_m.def_id), trait_m_args)
+ {
+ if let ty::GenericArgKind::Lifetime(r) = arg.unpack()
+ && let ty::ReVar(vid) = r.kind()
+ && let r = infcx
+ .inner
+ .borrow_mut()
+ .unwrap_region_constraints()
+ .opportunistic_resolve_var(tcx, vid)
+ && let ty::ReLateParam(ty::LateParamRegion {
+ kind: ty::LateParamRegionKind::Named(impl_param_def_id, _),
+ ..
+ }) = r.kind()
+ && let ty::ReEarlyParam(ebr) = id_arg.expect_region().kind()
+ {
+ mismatched.push(LateEarlyMismatch::LateInImpl(
+ impl_param_def_id,
+ trait_generics.region_param(ebr, tcx).def_id,
+ id_arg.expect_region(),
+ ));
+ }
+ }
+
+ if mismatched.is_empty() {
+ return None;
+ }
+
+ let spans: Vec<_> = mismatched
+ .iter()
+ .map(|param| {
+ let (LateEarlyMismatch::EarlyInImpl(impl_param_def_id, ..)
+ | LateEarlyMismatch::LateInImpl(impl_param_def_id, ..)) = param;
+ tcx.def_span(impl_param_def_id)
+ })
+ .collect();
+
+ let mut diag = tcx
+ .dcx()
+ .struct_span_err(spans, "lifetime parameters do not match the trait definition")
+ .with_note("lifetime parameters differ in whether they are early- or late-bound")
+ .with_code(E0195);
+ for mismatch in mismatched {
+ match mismatch {
+ LateEarlyMismatch::EarlyInImpl(
+ impl_param_def_id,
+ trait_param_def_id,
+ early_bound_region,
+ ) => {
+ let mut multispan = MultiSpan::from_spans(vec![
+ tcx.def_span(impl_param_def_id),
+ tcx.def_span(trait_param_def_id),
+ ]);
+ multispan
+ .push_span_label(tcx.def_span(tcx.parent(impl_m.def_id)), "in this impl...");
+ multispan
+ .push_span_label(tcx.def_span(tcx.parent(trait_m.def_id)), "in this trait...");
+ multispan.push_span_label(
+ tcx.def_span(impl_param_def_id),
+ format!("`{}` is early-bound", tcx.item_name(impl_param_def_id)),
+ );
+ multispan.push_span_label(
+ tcx.def_span(trait_param_def_id),
+ format!("`{}` is late-bound", tcx.item_name(trait_param_def_id)),
+ );
+ if let Some(span) =
+ find_region_in_predicates(tcx, impl_m.def_id, early_bound_region)
+ {
+ multispan.push_span_label(
+ span,
+ format!(
+ "this lifetime bound makes `{}` early-bound",
+ tcx.item_name(impl_param_def_id)
+ ),
+ );
+ }
+ diag.span_note(
+ multispan,
+ format!(
+ "`{}` differs between the trait and impl",
+ tcx.item_name(impl_param_def_id)
+ ),
+ );
+ }
+ LateEarlyMismatch::LateInImpl(
+ impl_param_def_id,
+ trait_param_def_id,
+ early_bound_region,
+ ) => {
+ let mut multispan = MultiSpan::from_spans(vec![
+ tcx.def_span(impl_param_def_id),
+ tcx.def_span(trait_param_def_id),
+ ]);
+ multispan
+ .push_span_label(tcx.def_span(tcx.parent(impl_m.def_id)), "in this impl...");
+ multispan
+ .push_span_label(tcx.def_span(tcx.parent(trait_m.def_id)), "in this trait...");
+ multispan.push_span_label(
+ tcx.def_span(impl_param_def_id),
+ format!("`{}` is late-bound", tcx.item_name(impl_param_def_id)),
+ );
+ multispan.push_span_label(
+ tcx.def_span(trait_param_def_id),
+ format!("`{}` is early-bound", tcx.item_name(trait_param_def_id)),
+ );
+ if let Some(span) =
+ find_region_in_predicates(tcx, trait_m.def_id, early_bound_region)
+ {
+ multispan.push_span_label(
+ span,
+ format!(
+ "this lifetime bound makes `{}` early-bound",
+ tcx.item_name(trait_param_def_id)
+ ),
+ );
+ }
+ diag.span_note(
+ multispan,
+ format!(
+ "`{}` differs between the trait and impl",
+ tcx.item_name(impl_param_def_id)
+ ),
+ );
+ }
+ }
+ }
+
+ Some(diag.emit())
+}
+
+fn find_region_in_predicates<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ def_id: DefId,
+ early_bound_region: ty::Region<'tcx>,
+) -> Option {
+ for (pred, span) in tcx.explicit_predicates_of(def_id).instantiate_identity(tcx) {
+ if pred.visit_with(&mut FindRegion(early_bound_region)).is_break() {
+ return Some(span);
+ }
+ }
+
+ struct FindRegion<'tcx>(ty::Region<'tcx>);
+ impl<'tcx> TypeVisitor> for FindRegion<'tcx> {
+ type Result = ControlFlow<()>;
+ fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result {
+ if r == self.0 { ControlFlow::Break(()) } else { ControlFlow::Continue(()) }
+ }
+ }
+
+ None
}
#[instrument(level = "debug", skip(infcx))]
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 692784bf1714..9fd158ad154d 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -103,10 +103,18 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi
| sym::minnumf32
| sym::minnumf64
| sym::minnumf128
+ | sym::minimumf16
+ | sym::minimumf32
+ | sym::minimumf64
+ | sym::minimumf128
| sym::maxnumf16
| sym::maxnumf32
| sym::maxnumf64
| sym::maxnumf128
+ | sym::maximumf16
+ | sym::maximumf32
+ | sym::maximumf64
+ | sym::maximumf128
| sym::rustc_peek
| sym::type_name
| sym::forget
@@ -374,11 +382,21 @@ pub(crate) fn check_intrinsic_type(
sym::minnumf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
sym::minnumf128 => (0, 0, vec![tcx.types.f128, tcx.types.f128], tcx.types.f128),
+ sym::minimumf16 => (0, 0, vec![tcx.types.f16, tcx.types.f16], tcx.types.f16),
+ sym::minimumf32 => (0, 0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
+ sym::minimumf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
+ sym::minimumf128 => (0, 0, vec![tcx.types.f128, tcx.types.f128], tcx.types.f128),
+
sym::maxnumf16 => (0, 0, vec![tcx.types.f16, tcx.types.f16], tcx.types.f16),
sym::maxnumf32 => (0, 0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
sym::maxnumf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
sym::maxnumf128 => (0, 0, vec![tcx.types.f128, tcx.types.f128], tcx.types.f128),
+ sym::maximumf16 => (0, 0, vec![tcx.types.f16, tcx.types.f16], tcx.types.f16),
+ sym::maximumf32 => (0, 0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
+ sym::maximumf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
+ sym::maximumf128 => (0, 0, vec![tcx.types.f128, tcx.types.f128], tcx.types.f128),
+
sym::copysignf16 => (0, 0, vec![tcx.types.f16, tcx.types.f16], tcx.types.f16),
sym::copysignf32 => (0, 0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
sym::copysignf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index a89160785eb1..709446d09cd2 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -14,7 +14,7 @@
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def::{DefKind, Res};
-use rustc_hir::definitions::DisambiguatorState;
+use rustc_hir::definitions::{DefPathData, DisambiguatorState};
use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt};
use rustc_hir::{
self as hir, AmbigArg, GenericArg, GenericParam, GenericParamKind, HirId, LifetimeKind, Node,
@@ -1470,14 +1470,14 @@ fn remap_opaque_captures(
let mut captures = captures.borrow_mut();
let remapped = *captures.entry(lifetime).or_insert_with(|| {
// `opaque_def_id` is unique to the `BoundVarContext` pass which is executed once
- // per `resolve_bound_vars` query. This is the only location that creates nested
- // lifetime inside a opaque type. `::LifetimeNs(..)` is thus unique
+ // per `resolve_bound_vars` query. This is the only location that creates
+ // `OpaqueLifetime` paths. `::OpaqueLifetime(..)` is thus unique
// to this query and duplicates within the query are handled by `self.disambiguator`.
let feed = self.tcx.create_def(
opaque_def_id,
- Some(ident.name),
- DefKind::LifetimeParam,
None,
+ DefKind::LifetimeParam,
+ Some(DefPathData::OpaqueLifetime(ident.name)),
&mut self.disambiguator,
);
feed.def_span(ident.span);
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 2b1661aaac8f..152714b34073 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -1327,7 +1327,7 @@ pub(crate) struct ImplForTyRequires {
}
#[derive(Diagnostic)]
-#[diag(hir_analysis_traits_with_defualt_impl, code = E0321)]
+#[diag(hir_analysis_traits_with_default_impl, code = E0321)]
#[note]
pub(crate) struct TraitsWithDefaultImpl<'a> {
#[primary_span]
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
index bf91eb1b8fda..4419d5dc7d66 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
@@ -9,8 +9,8 @@
use rustc_hir::{AmbigArg, HirId};
use rustc_middle::bug;
use rustc_middle::ty::{
- self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
- TypeVisitor, Upcast,
+ self as ty, IsSuggestable, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable,
+ TypeVisitableExt, TypeVisitor, Upcast,
};
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, sym};
use rustc_trait_selection::traits;
@@ -996,7 +996,7 @@ struct GenericParamAndBoundVarCollector<'a, 'tcx> {
impl<'tcx> TypeVisitor> for GenericParamAndBoundVarCollector<'_, 'tcx> {
type Result = ControlFlow;
- fn visit_binder>>(
+ fn visit_binder>>(
&mut self,
binder: &ty::Binder<'tcx, T>,
) -> Self::Result {
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 88f745892048..f6e5149bd2b1 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
@@ -172,7 +172,14 @@ pub(super) fn lower_trait_object_ty(
let principal_trait = regular_traits.into_iter().next();
- let mut needed_associated_types = vec![];
+ // A stable ordering of associated types from the principal trait and all its
+ // supertraits. We use this to ensure that different substitutions of a trait
+ // don't result in `dyn Trait` types with different projections lists, which
+ // can be unsound: .
+ // We achieve a stable ordering by walking over the unsubstituted principal
+ // trait ref.
+ let mut ordered_associated_types = vec![];
+
if let Some((principal_trait, ref spans)) = principal_trait {
let principal_trait = principal_trait.map_bound(|trait_pred| {
assert_eq!(trait_pred.polarity, ty::PredicatePolarity::Positive);
@@ -197,16 +204,13 @@ pub(super) fn lower_trait_object_ty(
// FIXME(negative_bounds): Handle this correctly...
let trait_ref =
tcx.anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref));
- needed_associated_types.extend(
+ ordered_associated_types.extend(
tcx.associated_items(pred.trait_ref.def_id)
.in_definition_order()
// We only care about associated types.
.filter(|item| item.is_type())
// No RPITITs -- they're not dyn-compatible for now.
.filter(|item| !item.is_impl_trait_in_trait())
- // If the associated type has a `where Self: Sized` bound,
- // we do not need to constrain the associated type.
- .filter(|item| !tcx.generics_require_sized_self(item.def_id))
.map(|item| (item.def_id, trait_ref)),
);
}
@@ -278,14 +282,26 @@ pub(super) fn lower_trait_object_ty(
}
}
+ // We compute the list of projection bounds taking the ordered associated types,
+ // and check if there was an entry in the collected `projection_bounds`. Those
+ // are computed by first taking the user-written associated types, then elaborating
+ // the principal trait ref, and only using those if there was no user-written.
+ // See note below about how we handle missing associated types with `Self: Sized`,
+ // which are not required to be provided, but are still used if they are provided.
let mut missing_assoc_types = FxIndexSet::default();
- let projection_bounds: Vec<_> = needed_associated_types
+ let projection_bounds: Vec<_> = ordered_associated_types
.into_iter()
.filter_map(|key| {
if let Some(assoc) = projection_bounds.get(&key) {
Some(*assoc)
} else {
- missing_assoc_types.insert(key);
+ // If the associated type has a `where Self: Sized` bound, then
+ // we do not need to provide the associated type. This results in
+ // a `dyn Trait` type that has a different number of projection
+ // bounds, which may lead to type mismatches.
+ if !tcx.generics_require_sized_self(key.0) {
+ missing_assoc_types.insert(key);
+ }
None
}
})
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index 91dde13be550..4937eb73a8be 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -59,7 +59,6 @@
#![allow(internal_features)]
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
-#![cfg_attr(bootstrap, feature(let_chains))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(assert_matches)]
@@ -223,10 +222,6 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
}
_ => (),
}
- });
-
- tcx.par_hir_body_owners(|item_def_id| {
- let def_kind = tcx.def_kind(item_def_id);
// Skip `AnonConst`s because we feed their `type_of`.
if !matches!(def_kind, DefKind::AnonConst) {
tcx.ensure_ok().typeck(item_def_id);
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 09bf84ab64fb..04f9c831b0ac 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -2,7 +2,6 @@
//! the definitions in this file have equivalents in `rustc_ast_pretty`.
// tidy-alphabetical-start
-#![cfg_attr(bootstrap, feature(let_chains))]
#![recursion_limit = "256"]
// tidy-alphabetical-end
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 6cc7e82bbf73..d2cdfe22a3ad 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -2339,7 +2339,7 @@ struct MismatchedParam<'a> {
}
if !mismatched_params.is_empty() {
- // For each mismatched paramter, create a two-way link to each matched parameter
+ // For each mismatched parameter, create a two-way link to each matched parameter
// of the same type.
let mut dependants = IndexVec::::from_fn_n(
|_| SmallVec::<[u32; 4]>::new(),
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 78233a34c461..161f5e981d43 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -1,7 +1,6 @@
// tidy-alphabetical-start
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
-#![cfg_attr(bootstrap, feature(let_chains))]
#![feature(array_windows)]
#![feature(box_patterns)]
#![feature(if_let_guard)]
@@ -32,6 +31,7 @@
mod intrinsicck;
mod method;
mod op;
+mod opaque_types;
mod pat;
mod place_op;
mod rvalue_scopes;
@@ -245,9 +245,7 @@ fn typeck_with_inspect<'tcx>(
let typeck_results = fcx.resolve_type_vars_in_body(body);
- // We clone the defined opaque types during writeback in the new solver
- // because we have to use them during normalization.
- let _ = fcx.infcx.take_opaque_types();
+ fcx.detect_opaque_types_added_during_writeback();
// Consistency check our TypeckResults instance can hold all ItemLocalIds
// it will need to hold.
diff --git a/compiler/rustc_hir_typeck/src/opaque_types.rs b/compiler/rustc_hir_typeck/src/opaque_types.rs
new file mode 100644
index 000000000000..e0224f8c6e1b
--- /dev/null
+++ b/compiler/rustc_hir_typeck/src/opaque_types.rs
@@ -0,0 +1,26 @@
+use super::FnCtxt;
+impl<'tcx> FnCtxt<'_, 'tcx> {
+ /// We may in theory add further uses of an opaque after cloning the opaque
+ /// types storage during writeback when computing the defining uses.
+ ///
+ /// Silently ignoring them is dangerous and could result in ICE or even in
+ /// unsoundness, so we make sure we catch such cases here. There's currently
+ /// no known code where this actually happens, even with the new solver which
+ /// does normalize types in writeback after cloning the opaque type storage.
+ ///
+ /// FIXME(@lcnr): I believe this should be possible in theory and would like
+ /// an actual test here. After playing around with this for an hour, I wasn't
+ /// able to do anything which didn't already try to normalize the opaque before
+ /// then, either allowing compilation to succeed or causing an ambiguity error.
+ pub(super) fn detect_opaque_types_added_during_writeback(&self) {
+ let num_entries = self.checked_opaque_types_storage_entries.take().unwrap();
+ for (key, hidden_type) in
+ self.inner.borrow_mut().opaque_types().opaque_types_added_since(num_entries)
+ {
+ let opaque_type_string = self.tcx.def_path_str(key.def_id);
+ let msg = format!("unexpected cyclic definition of `{opaque_type_string}`");
+ self.dcx().span_delayed_bug(hidden_type.span, msg);
+ }
+ let _ = self.take_opaque_types();
+ }
+}
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index f9502153afdc..17d48184dd97 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -650,14 +650,13 @@ fn calc_adjust_mode(
match &pat.kind {
// Type checking these product-like types successfully always require
// that the expected type be of those types and not reference types.
- PatKind::Tuple(..)
- | PatKind::Range(..)
- | PatKind::Slice(..) => AdjustMode::peel_all(),
+ PatKind::Tuple(..) | PatKind::Range(..) | PatKind::Slice(..) => AdjustMode::peel_all(),
// When checking an explicit deref pattern, only peel reference types.
// FIXME(deref_patterns): If box patterns and deref patterns need to coexist, box
// patterns may want `PeelKind::Implicit`, stopping on encountering a box.
- | PatKind::Box(_)
- | PatKind::Deref(_) => AdjustMode::Peel { kind: PeelKind::ExplicitDerefPat },
+ PatKind::Box(_) | PatKind::Deref(_) => {
+ AdjustMode::Peel { kind: PeelKind::ExplicitDerefPat }
+ }
// A never pattern behaves somewhat like a literal or unit variant.
PatKind::Never => AdjustMode::peel_all(),
// For patterns with paths, how we peel the scrutinee depends on the path's resolution.
@@ -679,7 +678,11 @@ fn calc_adjust_mode(
&& self.tcx.features().deref_patterns()
&& !matches!(lt.kind, PatExprKind::Lit { .. })
{
- span_bug!(lt.span, "FIXME(deref_patterns): adjust mode unimplemented for {:?}", lt.kind);
+ span_bug!(
+ lt.span,
+ "FIXME(deref_patterns): adjust mode unimplemented for {:?}",
+ lt.kind
+ );
}
// Call `resolve_vars_if_possible` here for inline const blocks.
let lit_ty = self.resolve_vars_if_possible(self.check_pat_expr_unadjusted(lt));
@@ -687,17 +690,21 @@ fn calc_adjust_mode(
if self.tcx.features().deref_patterns() {
let mut peeled_ty = lit_ty;
let mut pat_ref_layers = 0;
- while let ty::Ref(_, inner_ty, mutbl) = *peeled_ty.kind() {
+ while let ty::Ref(_, inner_ty, mutbl) =
+ *self.try_structurally_resolve_type(pat.span, peeled_ty).kind()
+ {
// We rely on references at the head of constants being immutable.
debug_assert!(mutbl.is_not());
pat_ref_layers += 1;
peeled_ty = inner_ty;
}
- AdjustMode::Peel { kind: PeelKind::Implicit { until_adt: None, pat_ref_layers } }
+ AdjustMode::Peel {
+ kind: PeelKind::Implicit { until_adt: None, pat_ref_layers },
+ }
} else {
if lit_ty.is_ref() { AdjustMode::Pass } else { AdjustMode::peel_all() }
}
- },
+ }
// Ref patterns are complicated, we handle them in `check_pat_ref`.
PatKind::Ref(..)
@@ -928,6 +935,7 @@ fn check_pat_range(
// be peeled to `str` while ty here is still `&str`, if we don't
// err early here, a rather confusing unification error will be
// emitted instead).
+ let ty = self.try_structurally_resolve_type(expr.span, ty);
let fail =
!(ty.is_numeric() || ty.is_char() || ty.is_ty_var() || ty.references_error());
Some((fail, ty, expr.span))
diff --git a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs
index 56859eef45f7..26be5fc6d190 100644
--- a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs
+++ b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs
@@ -1,10 +1,10 @@
-use std::cell::RefCell;
+use std::cell::{Cell, RefCell};
use std::ops::Deref;
use rustc_data_structures::unord::{UnordMap, UnordSet};
use rustc_hir::def_id::LocalDefId;
use rustc_hir::{self as hir, HirId, HirIdMap, LangItem};
-use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
+use rustc_infer::infer::{InferCtxt, InferOk, OpaqueTypeStorageEntries, TyCtxtInferExt};
use rustc_middle::span_bug;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypingMode};
use rustc_span::Span;
@@ -37,6 +37,11 @@ pub(crate) struct TypeckRootCtxt<'tcx> {
pub(super) fulfillment_cx: RefCell>>>,
+ // Used to detect opaque types uses added after we've already checked them.
+ //
+ // See [FnCtxt::detect_opaque_types_added_during_writeback] for more details.
+ pub(super) checked_opaque_types_storage_entries: Cell