From 696cd98e6b51d657247cd61ee1babcf0ee4b9a8a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 12 Jun 2023 00:35:23 +0000 Subject: [PATCH 1/6] Don't record adjustments twice in note_source_of_type_mismatch_constraint --- compiler/rustc_hir_typeck/src/demand.rs | 7 ++--- .../rustc_hir_typeck/src/method/confirm.rs | 26 +++++++++++++++-- compiler/rustc_hir_typeck/src/method/mod.rs | 21 ++++++++++++++ ...record-adjustments-when-pointing-at-arg.rs | 29 +++++++++++++++++++ ...rd-adjustments-when-pointing-at-arg.stderr | 17 +++++++++++ 5 files changed, 93 insertions(+), 7 deletions(-) create mode 100644 tests/ui/typeck/dont-record-adjustments-when-pointing-at-arg.rs create mode 100644 tests/ui/typeck/dont-record-adjustments-when-pointing-at-arg.stderr diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index b62f689ec6b89..9ce03060e0fe9 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -370,13 +370,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Fudge the receiver, so we can do new inference on it. let possible_rcvr_ty = possible_rcvr_ty.fold_with(&mut fudger); let method = self - .lookup_method( + .lookup_method_for_diagnostic( possible_rcvr_ty, segment, DUMMY_SP, call_expr, binding, - args, ) .ok()?; // Unify the method signature with our incompatible arg, to @@ -435,14 +434,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let Some(rcvr_ty) = self.node_ty_opt(rcvr.hir_id) else { continue; }; let rcvr_ty = rcvr_ty.fold_with(&mut fudger); let Ok(method) = - self.lookup_method(rcvr_ty, segment, DUMMY_SP, parent_expr, rcvr, args) + self.lookup_method_for_diagnostic(rcvr_ty, segment, DUMMY_SP, parent_expr, rcvr) else { continue; }; let ideal_rcvr_ty = rcvr_ty.fold_with(&mut fudger); let ideal_method = self - .lookup_method(ideal_rcvr_ty, segment, DUMMY_SP, parent_expr, rcvr, args) + .lookup_method_for_diagnostic(ideal_rcvr_ty, segment, DUMMY_SP, parent_expr, rcvr) .ok() .and_then(|method| { let _ = self.at(&ObligationCause::dummy(), self.param_env) diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 98529b66602fa..6cd7bd5d196df 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -26,6 +26,7 @@ struct ConfirmContext<'a, 'tcx> { span: Span, self_expr: &'tcx hir::Expr<'tcx>, call_expr: &'tcx hir::Expr<'tcx>, + skip_record_for_diagnostics: bool, } impl<'a, 'tcx> Deref for ConfirmContext<'a, 'tcx> { @@ -59,6 +60,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut confirm_cx = ConfirmContext::new(self, span, self_expr, call_expr); confirm_cx.confirm(unadjusted_self_ty, pick, segment) } + + pub fn confirm_method_for_diagnostic( + &self, + span: Span, + self_expr: &'tcx hir::Expr<'tcx>, + call_expr: &'tcx hir::Expr<'tcx>, + unadjusted_self_ty: Ty<'tcx>, + pick: &probe::Pick<'tcx>, + segment: &hir::PathSegment<'_>, + ) -> ConfirmResult<'tcx> { + let mut confirm_cx = ConfirmContext::new(self, span, self_expr, call_expr); + confirm_cx.skip_record_for_diagnostics = true; + confirm_cx.confirm(unadjusted_self_ty, pick, segment) + } } impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { @@ -68,7 +83,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { self_expr: &'tcx hir::Expr<'tcx>, call_expr: &'tcx hir::Expr<'tcx>, ) -> ConfirmContext<'a, 'tcx> { - ConfirmContext { fcx, span, self_expr, call_expr } + ConfirmContext { fcx, span, self_expr, call_expr, skip_record_for_diagnostics: false } } fn confirm( @@ -219,7 +234,9 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { self.register_predicates(autoderef.into_obligations()); // Write out the final adjustments. - self.apply_adjustments(self.self_expr, adjustments); + if !self.skip_record_for_diagnostics { + self.apply_adjustments(self.self_expr, adjustments); + } target } @@ -453,7 +470,10 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { }); debug!("instantiate_method_substs: user_type_annotation={:?}", user_type_annotation); - self.fcx.write_user_type_annotation(self.call_expr.hir_id, user_type_annotation); + + if !self.skip_record_for_diagnostics { + self.fcx.write_user_type_annotation(self.call_expr.hir_id, user_type_annotation); + } } self.normalize(self.span, substs) diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index 6f4d674ba103b..dabade3658974 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -254,6 +254,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ok(result.callee) } + pub fn lookup_method_for_diagnostic( + &self, + self_ty: Ty<'tcx>, + segment: &hir::PathSegment<'_>, + span: Span, + call_expr: &'tcx hir::Expr<'tcx>, + self_expr: &'tcx hir::Expr<'tcx>, + ) -> Result, MethodError<'tcx>> { + let pick = self.lookup_probe_for_diagnostic( + segment.ident, + self_ty, + call_expr, + ProbeScope::TraitsInScope, + None, + )?; + + Ok(self + .confirm_method_for_diagnostic(span, self_expr, call_expr, self_ty, &pick, segment) + .callee) + } + #[instrument(level = "debug", skip(self, call_expr))] pub fn lookup_probe( &self, diff --git a/tests/ui/typeck/dont-record-adjustments-when-pointing-at-arg.rs b/tests/ui/typeck/dont-record-adjustments-when-pointing-at-arg.rs new file mode 100644 index 0000000000000..0c2d71707c9f0 --- /dev/null +++ b/tests/ui/typeck/dont-record-adjustments-when-pointing-at-arg.rs @@ -0,0 +1,29 @@ +pub trait NSWindow: Sized { + fn frame(self) -> () { + unimplemented!() + } + fn setFrame_display_(self, display: ()) {} +} +impl NSWindow for () {} + +pub struct NSRect {} + +use std::ops::Deref; +struct MainThreadSafe(T); +impl Deref for MainThreadSafe { + type Target = T; + + fn deref(&self) -> &T { + unimplemented!() + } +} + +fn main() { + || { + let ns_window = MainThreadSafe(()); + // Don't record adjustments twice for `*ns_window` + (*ns_window).frame(); + ns_window.setFrame_display_(0); + //~^ ERROR mismatched types + }; +} diff --git a/tests/ui/typeck/dont-record-adjustments-when-pointing-at-arg.stderr b/tests/ui/typeck/dont-record-adjustments-when-pointing-at-arg.stderr new file mode 100644 index 0000000000000..02e87d701b687 --- /dev/null +++ b/tests/ui/typeck/dont-record-adjustments-when-pointing-at-arg.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/dont-record-adjustments-when-pointing-at-arg.rs:26:37 + | +LL | ns_window.setFrame_display_(0); + | ----------------- ^ expected `()`, found integer + | | + | arguments to this method are incorrect + | +note: method defined here + --> $DIR/dont-record-adjustments-when-pointing-at-arg.rs:5:8 + | +LL | fn setFrame_display_(self, display: ()) {} + | ^^^^^^^^^^^^^^^^^ ----------- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From 903b3d36db81cad9d1e23b62f09d655d93aad1ac Mon Sep 17 00:00:00 2001 From: klensy Date: Thu, 15 Jun 2023 18:58:57 +0300 Subject: [PATCH 2/6] cleanup more azure leftovers --- src/bootstrap/util.rs | 2 -- src/ci/docker/run.sh | 2 -- src/tools/build_helper/src/ci.rs | 6 +----- 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index 7e29f671f028b..1ec49f80d632e 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -159,8 +159,6 @@ pub fn symlink_dir(config: &Config, original: &Path, link: &Path) -> io::Result< pub enum CiEnv { /// Not a CI environment. None, - /// The Azure Pipelines environment, for Linux (including Docker), Windows, and macOS builds. - AzurePipelines, /// The GitHub Actions environment, for Linux (including Docker), Windows and macOS builds. GitHubActions, } diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index 2fe3438e0fe8a..0a098467d9493 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -254,8 +254,6 @@ docker \ --env DEPLOY \ --env DEPLOY_ALT \ --env CI \ - --env TF_BUILD \ - --env BUILD_SOURCEBRANCHNAME \ --env GITHUB_ACTIONS \ --env GITHUB_REF \ --env TOOLSTATE_REPO_ACCESS_TOKEN \ diff --git a/src/tools/build_helper/src/ci.rs b/src/tools/build_helper/src/ci.rs index d106e5b339b2f..893195b69c219 100644 --- a/src/tools/build_helper/src/ci.rs +++ b/src/tools/build_helper/src/ci.rs @@ -4,8 +4,6 @@ use std::process::Command; pub enum CiEnv { /// Not a CI environment. None, - /// The Azure Pipelines environment, for Linux (including Docker), Windows, and macOS builds. - AzurePipelines, /// The GitHub Actions environment, for Linux (including Docker), Windows and macOS builds. GitHubActions, } @@ -13,9 +11,7 @@ pub enum CiEnv { impl CiEnv { /// Obtains the current CI environment. pub fn current() -> CiEnv { - if std::env::var("TF_BUILD").map_or(false, |e| e == "True") { - CiEnv::AzurePipelines - } else if std::env::var("GITHUB_ACTIONS").map_or(false, |e| e == "true") { + if std::env::var("GITHUB_ACTIONS").map_or(false, |e| e == "true") { CiEnv::GitHubActions } else { CiEnv::None From 0f7174a02ae1c07576d00933b5ae69ec4a12573f Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 31 May 2023 17:10:34 +0000 Subject: [PATCH 3/6] Re-use the deref-pattern recursion instead of duplicating the logic --- .../src/thir/pattern/const_to_pat.rs | 85 ++++++------------- 1 file changed, 26 insertions(+), 59 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 7976b148f75e2..a2e00d3bfc57d 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -359,6 +359,15 @@ impl<'tcx> ConstToPat<'tcx> { def.non_enum_variant().fields.iter().map(|field| field.ty(self.tcx(), substs)), ))?, }, + ty::Slice(elem_ty) => PatKind::Slice { + prefix: cv + .unwrap_branch() + .iter() + .map(|val| self.recur(*val, *elem_ty, false)) + .collect::>()?, + slice: None, + suffix: Box::new([]), + }, ty::Array(elem_ty, _) => PatKind::Array { prefix: cv .unwrap_branch() @@ -372,58 +381,6 @@ impl<'tcx> ConstToPat<'tcx> { // `&str` is represented as a valtree, let's keep using this // optimization for now. ty::Str => PatKind::Constant { value: mir::ConstantKind::Ty(tcx.mk_const(cv, ty)) }, - // `b"foo"` produces a `&[u8; 3]`, but you can't use constants of array type when - // matching against references, you can only use byte string literals. - // The typechecker has a special case for byte string literals, by treating them - // as slices. This means we turn `&[T; N]` constants into slice patterns, which - // has no negative effects on pattern matching, even if we're actually matching on - // arrays. - ty::Array(elem_ty, _) if !self.treat_byte_string_as_slice => { - let old = self.behind_reference.replace(true); - // References have the same valtree representation as their pointee. - let array = cv; - let val = PatKind::Deref { - subpattern: Box::new(Pat { - kind: PatKind::Array { - prefix: array.unwrap_branch() - .iter() - .map(|val| self.recur(*val, elem_ty, false)) - .collect::>()?, - slice: None, - suffix: Box::new([]), - }, - span, - ty: tcx.mk_slice(elem_ty), - }), - }; - self.behind_reference.set(old); - val - } - ty::Array(elem_ty, _) | - // Cannot merge this with the catch all branch below, because the `const_deref` - // changes the type from slice to array, we need to keep the original type in the - // pattern. - ty::Slice(elem_ty) => { - let old = self.behind_reference.replace(true); - // References have the same valtree representation as their pointee. - let array = cv; - let val = PatKind::Deref { - subpattern: Box::new(Pat { - kind: PatKind::Slice { - prefix: array.unwrap_branch() - .iter() - .map(|val| self.recur(*val, elem_ty, false)) - .collect::>()?, - slice: None, - suffix: Box::new([]), - }, - span, - ty: tcx.mk_slice(elem_ty), - }), - }; - self.behind_reference.set(old); - val - } // Backwards compatibility hack: support references to non-structural types, // but hard error if we aren't behind a double reference. We could just use // the fallback code path below, but that would allow *more* of this fishy @@ -431,11 +388,9 @@ impl<'tcx> ConstToPat<'tcx> { // instead of a hard error. ty::Adt(_, _) if !self.type_marked_structural(*pointee_ty) => { if self.behind_reference.get() { - if !self.saw_const_match_error.get() - && !self.saw_const_match_lint.get() - { - self.saw_const_match_lint.set(true); - tcx.emit_spanned_lint( + if !self.saw_const_match_error.get() && !self.saw_const_match_lint.get() { + self.saw_const_match_lint.set(true); + tcx.emit_spanned_lint( lint::builtin::INDIRECT_STRUCTURAL_MATCH, self.id, span, @@ -456,7 +411,7 @@ impl<'tcx> ConstToPat<'tcx> { // convert the dereferenced constant to a pattern that is the sub-pattern of the // deref pattern. _ => { - if !pointee_ty.is_sized(tcx, param_env) { + if !pointee_ty.is_sized(tcx, param_env) && !pointee_ty.is_slice() { let err = UnsizedPattern { span, non_sm_ty: *pointee_ty }; tcx.sess.emit_err(err); @@ -464,8 +419,20 @@ impl<'tcx> ConstToPat<'tcx> { PatKind::Wild } else { let old = self.behind_reference.replace(true); + // `b"foo"` produces a `&[u8; 3]`, but you can't use constants of array type when + // matching against references, you can only use byte string literals. + // The typechecker has a special case for byte string literals, by treating them + // as slices. This means we turn `&[T; N]` constants into slice patterns, which + // has no negative effects on pattern matching, even if we're actually matching on + // arrays. + let pointee_ty = match *pointee_ty.kind() { + ty::Array(elem_ty, _) if self.treat_byte_string_as_slice => { + tcx.mk_slice(elem_ty) + } + _ => *pointee_ty, + }; // References have the same valtree representation as their pointee. - let subpattern = self.recur(cv, *pointee_ty, false)?; + let subpattern = self.recur(cv, pointee_ty, false)?; self.behind_reference.set(old); PatKind::Deref { subpattern } } From b198589214e5d6e1a7dc40599e61031a0d1a7b1b Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 18 Jun 2023 10:48:09 +1000 Subject: [PATCH 4/6] Don't try to auto-bless 32-bit `mir-opt` tests on ARM Mac hosts Blessing 32-bit tests on 64-bit hosts relies on having a corresponding 32-bit target that can be built "easily" on those hosts. ARM Macs don't have a corresponding 32-bit target, so trying to build one is usually going to fail. --- src/bootstrap/test.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 13a10b0d3a506..59fe57a5872f9 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -44,7 +44,8 @@ const MIR_OPT_BLESS_TARGET_MAPPING: &[(&str, &str)] = &[ ("i686-pc-windows-msvc", "x86_64-pc-windows-msvc"), ("i686-pc-windows-gnu", "x86_64-pc-windows-gnu"), ("i686-apple-darwin", "x86_64-apple-darwin"), - ("i686-apple-darwin", "aarch64-apple-darwin"), + // ARM Macs don't have a corresponding 32-bit target that they can (easily) + // build for, so there is no entry for "aarch64-apple-darwin" here. ]; fn try_run(builder: &Builder<'_>, cmd: &mut Command) -> bool { From d25e8d79a14ebf02df437f0147de592c8ded3ea1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 15 Jun 2023 19:10:45 +0200 Subject: [PATCH 5/6] Test `x.ps1` in `msvc` CI job --- src/bootstrap/mk/Makefile.in | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index 779db9fffa883..d296931580337 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -60,8 +60,11 @@ prepare: ## MSVC native builders # this intentionally doesn't use `$(BOOTSTRAP)` so we can test the shebang on Windows -ci-msvc: - $(Q)$(CFG_SRC_DIR)/x.py test --stage 2 +ci-msvc-py: + $(Q)$(CFG_SRC_DIR)/x.py test --stage 2 tidy +ci-msvc-ps1: + $(Q)$(CFG_SRC_DIR)/x.ps1 test --stage 2 --exclude tidy +ci-msvc: ci-msvc-py ci-msvc-ps1 ## MingW native builders From 894ab2ce7ab15b3bdb1d976aee21ff3157c8779b Mon Sep 17 00:00:00 2001 From: bohan Date: Sun, 18 Jun 2023 20:55:16 +0800 Subject: [PATCH 6/6] refactor(resolve): delete `update_resolution` function --- compiler/rustc_resolve/src/imports.rs | 93 ++++++++++++--------------- 1 file changed, 40 insertions(+), 53 deletions(-) diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 47d8e5993fd82..23ef9bf53a195 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -304,21 +304,23 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let res = binding.res(); self.check_reserved_macro_name(key.ident, res); self.set_binding_parent_module(binding, module); - self.update_resolution(module, key, |this, resolution| { - if let Some(old_binding) = resolution.binding { - if res == Res::Err && old_binding.res() != Res::Err { - // Do not override real bindings with `Res::Err`s from error recovery. - return Ok(()); - } + + let mut resolution = self.resolution(module, key).borrow_mut(); + let old_binding = resolution.binding(); + let mut t = Ok(()); + if let Some(old_binding) = resolution.binding { + if res == Res::Err && old_binding.res() != Res::Err { + // Do not override real bindings with `Res::Err`s from error recovery. + } else { match (old_binding.is_glob_import(), binding.is_glob_import()) { (true, true) => { if res != old_binding.res() { - resolution.binding = Some(this.ambiguity( + resolution.binding = Some(self.ambiguity( AmbiguityKind::GlobVsGlob, old_binding, binding, )); - } else if !old_binding.vis.is_at_least(binding.vis, this.tcx) { + } else if !old_binding.vis.is_at_least(binding.vis, self.tcx) { // We are glob-importing the same item but with greater visibility. resolution.binding = Some(binding); } @@ -330,7 +332,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { && key.ns == MacroNS && nonglob_binding.expansion != LocalExpnId::ROOT { - resolution.binding = Some(this.ambiguity( + resolution.binding = Some(self.ambiguity( AmbiguityKind::GlobVsExpanded, nonglob_binding, glob_binding, @@ -342,12 +344,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let Some(old_binding) = resolution.shadowed_glob { assert!(old_binding.is_glob_import()); if glob_binding.res() != old_binding.res() { - resolution.shadowed_glob = Some(this.ambiguity( + resolution.shadowed_glob = Some(self.ambiguity( AmbiguityKind::GlobVsGlob, old_binding, glob_binding, )); - } else if !old_binding.vis.is_at_least(binding.vis, this.tcx) { + } else if !old_binding.vis.is_at_least(binding.vis, self.tcx) { resolution.shadowed_glob = Some(glob_binding); } } else { @@ -355,53 +357,27 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } (false, false) => { - return Err(old_binding); + t = Err(old_binding); } } - } else { - resolution.binding = Some(binding); } + } else { + resolution.binding = Some(binding); + }; - Ok(()) - }) - } - - fn ambiguity( - &self, - kind: AmbiguityKind, - primary_binding: &'a NameBinding<'a>, - secondary_binding: &'a NameBinding<'a>, - ) -> &'a NameBinding<'a> { - self.arenas.alloc_name_binding(NameBinding { - ambiguity: Some((secondary_binding, kind)), - ..primary_binding.clone() - }) - } - - // Use `f` to mutate the resolution of the name in the module. - // If the resolution becomes a success, define it in the module's glob importers. - fn update_resolution(&mut self, module: Module<'a>, key: BindingKey, f: F) -> T - where - F: FnOnce(&mut Resolver<'a, 'tcx>, &mut NameResolution<'a>) -> T, - { // Ensure that `resolution` isn't borrowed when defining in the module's glob importers, // during which the resolution might end up getting re-defined via a glob cycle. - let (binding, t) = { - let resolution = &mut *self.resolution(module, key).borrow_mut(); - let old_binding = resolution.binding(); - - let t = f(self, resolution); - - match resolution.binding() { - _ if old_binding.is_some() => return t, - None => return t, - Some(binding) => match old_binding { - Some(old_binding) if ptr::eq(old_binding, binding) => return t, - _ => (binding, t), - }, - } + let (binding, t) = match resolution.binding() { + _ if old_binding.is_some() => return t, + None => return t, + Some(binding) => match old_binding { + Some(old_binding) if ptr::eq(old_binding, binding) => return t, + _ => (binding, t), + }, }; + drop(resolution); + // Define `binding` in `module`s glob importers. for import in module.glob_importers.borrow_mut().iter() { let mut ident = key.ident; @@ -420,6 +396,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { t } + fn ambiguity( + &self, + kind: AmbiguityKind, + primary_binding: &'a NameBinding<'a>, + secondary_binding: &'a NameBinding<'a>, + ) -> &'a NameBinding<'a> { + self.arenas.alloc_name_binding(NameBinding { + ambiguity: Some((secondary_binding, kind)), + ..primary_binding.clone() + }) + } + // Define a dummy resolution containing a `Res::Err` as a placeholder for a failed // or indeterminate resolution, also mark such failed imports as used to avoid duplicate diagnostics. fn import_dummy_binding(&mut self, import: &'a Import<'a>, is_indeterminate: bool) { @@ -769,9 +757,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { .emit(); } let key = BindingKey::new(target, ns); - this.update_resolution(parent, key, |_, resolution| { - resolution.single_imports.remove(&Interned::new_unchecked(import)); - }); + let mut resolution = this.resolution(parent, key).borrow_mut(); + resolution.single_imports.remove(&Interned::new_unchecked(import)); } } }